pax_global_header00006660000000000000000000000064151642702410014514gustar00rootroot0000000000000052 comment=670daea7900a9b097b9fb199c392b25bb63af48a libpqxx-8.0.1/000077500000000000000000000000001516427024100132115ustar00rootroot00000000000000libpqxx-8.0.1/.circleci/000077500000000000000000000000001516427024100150445ustar00rootroot00000000000000libpqxx-8.0.1/.circleci/config.yml000066400000000000000000000422651516427024100170450ustar00rootroot00000000000000# CircleCI config for automated test builds triggered from Github. --- version: 2.1 orbs: win: circleci/windows@5.0 jobs: # Run tests against a Linux Docker image. We repeat this for various # distros, but macOS & Windows need separate configs even if they're largely # identical to this one. test-linux: parameters: os: type: string compiler: type: string cxx_ver: type: string docker: - image: << parameters.os >> # The resource_class feature allows configuring CPU and RAM resources for # each job. Different resource classes are available for different # executors. # https://circleci.com/docs/2.0/configuration-reference/#resourceclass resource_class: large steps: - checkout - run: name: Install command: "./tools/install-deps.sh \ << parameters.os >> << parameters.compiler >> >/tmp/vars.sh" max_auto_reruns: 3 - store_artifacts: path: "/tmp/install.log" - store_artifacts: path: "/tmp/vars.sh" - run: name: Autogen command: ". /tmp/vars.sh && autoreconf" - run: name: Configure command: ". /tmp/vars.sh && ./configure \ --enable-maintainer-mode --enable-audit \ --enable-shared --disable-static \ CXX=<< parameters.compiler >> \ CXXFLAGS=\"-O1 -std=<< parameters.cxx_ver >>\"" - store_artifacts: path: config.log - store_artifacts: path: include/pqxx - run: name: Make command: make -j4 - run: name: Start database command: ". /tmp/vars.sh && ./tools/run-test-postgres.sh postgres" - store_artifacts: path: postgres.log - run: name: Test command: . /tmp/vars.sh && make -j4 check - store_artifacts: path: test-suite.log - store_artifacts: path: postgres.log - store_artifacts: path: examples test-macos: parameters: compiler: type: string cxx_ver: type: string macos: # Bummer. We *have* to specify an exact xcode version. And match it up # with a resource class that supports it. Available combinations are # listed here: # # https://circleci.com/docs/guides/execution-managed/using-macos/ # # Without updating these, the macos builds will just stop working when # the XCode/image combo falls out of support. # xcode: "26.2.0" # As of late 2025, this is the default resource class we get for macOS. # But since they include the chip generation, they will eventually fall out # of date. Transient problems can ensue. # resource_class: "m4pro.medium" steps: - checkout - run: name: Install command: "./tools/install-deps.sh macos << parameters.compiler >> \ >/tmp/vars.sh" max_auto_reruns: 3 - store_artifacts: path: "/tmp/install.log" - store_artifacts: path: "/tmp/vars.sh" - run: name: Configure command: ". /tmp/vars.sh && autoreconf && ./configure \ --enable-maintainer-mode --enable-audit \ --enable-shared --disable-static \ CPPFLAGS=\"-I/opt/homebrew/opt/libpq/include/\" \ CXX=<< parameters.compiler >> \ CXXFLAGS=\"-O1 -std=<< parameters.cxx_ver >>\" \ LDFLAGS=\"-L/opt/homebrew/opt/libpq/lib\"" - store_artifacts: path: config.log - store_artifacts: path: include/pqxx - run: name: Make command: make -j4 - run: name: Start database command: ". /tmp/vars.sh && ./tools/run-test-postgres.sh" - store_artifacts: path: postgres.log - run: name: Test command: ". /tmp/vars.sh && make -j4 check" - store_artifacts: path: test-suite.log - store_artifacts: path: postgres.log - store_artifacts: path: examples # Windows builds are very incomplete for now. No MSVC, no gcc, no database. # Couldn't get them working on CircleCI. test-windows: parameters: compiler: type: string cxx_ver: type: string executor: name: win/default size: medium steps: - checkout - run: name: Install command: "./tools/install-deps.sh \ windows << parameters.compiler >> >vars.sh" shell: bash.exe # Installation of dependencies on Windows often times out. max_auto_reruns: 3 - store_artifacts: path: "/tmp/install.log" - store_artifacts: path: "vars.sh" - run: name: Configure # (Run the msys bash, not the one we get from CircleCI.) command: ". vars.sh && bash.exe -c \". vars.sh && \ CXX=<< parameters.compiler >> \ CXXFLAGS='-O1 -std=<< parameters.cxx_ver >>' \ cmake -G Ninja .\"" shell: bash.exe - store_artifacts: path: include/pqxx - run: name: Make command: bash -c ". vars.sh && ninja" shell: bash.exe - run: name: Start database command: ". vars.sh && ./tools/run-test-postgres.sh" shell: bash.exe - store_artifacts: path: postgres.log - store_artifacts: path: postgres-start-stdout.log - store_artifacts: path: postgres-start-stderr.log - run: name: Test command: ". vars.sh && ./test/runner" shell: bash.exe - store_artifacts: path: test-suite.log - store_artifacts: path: postgres.log analyse: parameters: cxx_ver: type: string docker: - image: archlinux resource_class: large steps: - checkout - run: name: Install command: "tools/install-deps.sh archlinux-lint clang++ >/tmp/vars.sh" max_auto_reruns: 3 - store_artifacts: path: "/tmp/install.log" - store_artifacts: path: "/tmp/vars.sh" - run: name: Configure command: "SRC=\"$(pwd)\" && \ . /tmp/vars.sh && \ mkdir -p /tmp/pqxx && \ cd /tmp/pqxx && \ CXX=clang++ CXXFLAGS='-O0 \ -std=<< parameters.cxx_ver >>' cmake \"$SRC\"" - run: name: Analyse # Tricky. I don't really want the pointless stdout output from # run-clang-tidy, except the CI may time out when there's no output # for a while. What we want is the stderr, which we also want to # tee into a file. Bash's "output redirection" solves this neatly, # thanks Nick! # # The actual lint errors seem to go to stdout, with the useless # progress output, not to stderr. command: "SRC=\"$(pwd)\" && \ . /tmp/vars.sh && \ cd /tmp/pqxx && \ ( \"$SRC/tools/lint.sh\" --full > >(tee analyze.txt >&2 ) \ 2>&1 )" # The "tee" holds up output for a long time, causing the CI to call a # timeout after 10 minutes and kill our job. Request an extension. no_output_timeout: 30m - store_artifacts: path: "analyze.txt" - run: name: Summarise # Filter out the useless nonsense in the output: number of warnings # generated for system headers, timings, and number of files. # # Also run a "uniq" to eliminate redundant blank lines. # # Negate the outcome of the final grep so that this will report a # failure if we find any errors. command: "( \ cat analyze.txt | grep -v '^[0-9]\\+ warnings generated\\.$' | \ grep -v '^ *\\[.*\\] .*clang-tidy.*\\.cxx$' | \ grep -v '^Running clang-tidy for [0-9]* files*' | \ sed -e 's/^[[:space:]][[:space:]]*$//' | \ uniq ) >errors.txt || true" - store_artifacts: path: "errors.txt" - run: name: Check for errors # Fails if errors.txt contains actual text. command: "! grep . errors.txt" coverage: parameters: cxx_ver: type: string docker: - image: archlinux steps: - checkout - run: name: Install command: "tools/install-deps.sh archlinux-coverage g++ >/tmp/vars.sh" max_auto_reruns: 3 - store_artifacts: path: "/tmp/install.log" - store_artifacts: path: "/tmp/vars.sh" - run: name: Configure # Default "path coverage limit" is 250k. With that default, we get # a lot of "No path information" messages meaning that gcc saw too # many paths and gave up. In which case we get bogus test coverage # reports. Let's invest a bit of extra compiler work to get the data # we need. # # The profiler seems to default to non-threadsafe operation when not # explicitly linking to pthread, so we explicitly request "atomic" # updates when appropriate. # # We define a macro PQXX_COVERAGE to tell the code not to generate # out-of-line versions of certain inline functions. The out-of-line # code leads gcov to report a lot of lines as uncovered even if they # actually are. command: ". /tmp/vars.sh && autoreconf && \ ./configure \ CXX=g++ \ CXXFLAGS='-O0 -g -std=<< parameters.cxx_ver >> --coverage \ -DPQXX_COVERAGE \ -fpath-coverage-limit=2000000 \ -fprofile-update=prefer-atomic' \ LDFLAGS='--coverage'" - run: name: Compile command: "make -j4 check TESTS=" - run: name: Start database command: ". /tmp/vars.sh && ./tools/run-test-postgres.sh postgres" - run: name: Run command: ". /tmp/vars.sh && make check" - run: name: Lcov command: "lcov \ --config-file=.lcovrc \ --capture --directory src \ --output-file cov.info && \ lcov --remove cov.info '/usr/*' \ --output-file=out.info && \ genhtml \ --config-file=.lcovrc out.info \ --output-directory=coverage_html" - store_artifacts: path: "coverage_html" infer: parameters: cxx_ver: type: string docker: - image: archlinux steps: - checkout - run: name: Install command: "tools/install-deps.sh archlinux-infer g++ >/tmp/vars.sh" max_auto_reruns: 3 - store_artifacts: path: "/tmp/install.log" - store_artifacts: path: "/tmp/vars.sh" - run: name: Configure command: ". /tmp/vars.sh && autoreconf && \ ./configure \ CXX=g++ CXXFLAGS='-O0 -g -std=<< parameters.cxx_ver >>'" - run: name: Capture command: "infer capture -- make -j4 check TESTS=" - run: name: Infer command: "infer analyze --bufferoverrun --datalog --loop-hoisting \ --siof-check-iostreams -- \ make -j4 check TESTS= 1> >(tee infer.log) 2> >(tee stderr.log)" - store_artifacts: path: stderr.log - store_artifacts: path: infer.log - store_artifacts: path: infer-out/report.txt - store_artifacts: path: errors.txt - run: name: Check # Fail if report.txt is nonempty. command: "! test -s infer-out/report.txt" valgrind: # We run this test in Debian because we see what look like false # positives in Arch Linux. The root cause may be what looks like an # internal error in the standard library's charconv implementation for # floating-point types. When running in valgrind, an assertion in there # fails: "output_length == expected_output_length". parameters: compiler: type: string cxx_ver: type: string opt: # Optimisation level. type: integer docker: # ArchLinux seems to hit false positives. # Debian docker image is outdated. - image: ubuntu steps: - checkout - run: name: Install command: "tools/install-deps.sh ubuntu-valgrind \ << parameters.compiler >> >/tmp/vars.sh" max_auto_reruns: 3 - store_artifacts: path: "/tmp/install.log" - store_artifacts: path: "/tmp/vars.sh" - run: name: Configure # Valgrind does not appear to support long double! # # This was breaking std::isinf(), but only with gcc, and # only with -O0 (i.e. no optimisation), and only when running tests # through Valgrind. # # I see no good way around this. So I went with the workaround of # defining a macro for "avoid testing anything that breaks Valgrind." command: ". /tmp/vars.sh && \ CXX='<< parameters.compiler >>' \ CXXFLAGS='-O<< parameters.opt >> \ -std=<< parameters.cxx_ver >> \ -DPQXX_VALGRIND' \ cmake -G Ninja ." - run: name: Build command: "ninja -j4" no_output_timeout: 30m - run: name: Start database command: ". /tmp/vars.sh && ./tools/run-test-postgres.sh postgres" - run: name: Test # Run all the Valgrind tests, in sequence. Might as well get a lot # of use out of the build once we've produced it. command: " ( \ set -Cue ; \ . /tmp/vars.sh && \ for t in \ memcheck cachegrind callgrind helgrind drd massif dhat lackey \ exp-bbv ; do \ echo ; echo ; echo \"*** $t ***\" ; echo ; \ valgrind --trace-children=yes --vgdb=no --track-fds=yes \ --tool=$t test/runner 2>&1 | tee -a test.log || exit 1 ; \ done \ )" - store_artifacts: path: test.log try-make-dist: parameters: compiler: type: string docker: - image: archlinux steps: - checkout - run: name: Install command: "./tools/install-deps.sh \ archlinux << parameters.compiler >> >/tmp/vars.sh" max_auto_reruns: 3 - store_artifacts: path: "/tmp/install.log" - store_artifacts: path: "/tmp/vars.sh" - run: name: Autogen command: ". /tmp/vars.sh && autoreconf" - run: name: Configure command: ". /tmp/vars.sh && \ ./configure CXX=<< parameters.compiler >> CXXFLAGS=-O0" - run: name: Make dist command: ". /tmp/vars.sh && make -j4 dist" - run: name: Extract tarball command: "tar --one-top-level=unpacked -xf libpqxx-*.*.tar*" - run: name: Build from extracted tarball command: ". /tmp/vars.sh && \ cd unpacked/libpqxx-* && \ ./configure CXX=<< parameters.compiler >> CXXFLAGS=-O0 && \ make -j4" workflows: all-tests: jobs: - analyse: matrix: parameters: cxx_ver: ["c++20", "c++23", "c++26"] - coverage: matrix: parameters: cxx_ver: ["c++26"] - infer: matrix: parameters: cxx_ver: ["c++23"] - valgrind: matrix: parameters: compiler: ["g++", "clang++"] cxx_ver: ["c++23"] # I really don't want to test against every conceivable # optimisation level. But -O0 revealed a problem that somehow # wasn't happening when optimising. Can't skip -O2 because it's # the default so it's what everybody is using. And -O3 # restructures code which may reveal problems that don't become # visible at lower levels. So... only level we end up skipping # is -O1. opt: [0, 2, 3] - test-linux: matrix: parameters: os: ["archlinux", "debian", "fedora", "ubuntu"] compiler: ["clang++", "g++"] cxx_ver: ["c++20", "c++23", "c++26"] exclude: - os: "ubuntu" compiler: "g++" cxx_ver: "c++26" - test-macos: matrix: parameters: compiler: ["clang++", "g++"] cxx_ver: ["c++20", "c++23", "c++26"] - test-windows: matrix: parameters: compiler: ["clang++", "g++"] cxx_ver: ["c++20", "c++23", "c++26"] - try-make-dist: matrix: parameters: compiler: ["clang++"] libpqxx-8.0.1/.clang-format000066400000000000000000000040431516427024100155650ustar00rootroot00000000000000--- Language: Cpp AlignAfterOpenBracket: AlwaysBreak # AllowAllArgumentsOnNextLine: true # AllowAllConstructorInitializersOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: true AllowShortCaseLabelsOnASingleLine: true AllowShortFunctionsOnASingleLine: Inline # AllowShortIfStatementsOnASingleLine: WithoutElse # AllowShortLambdasOnASingleLine: All AllowShortLoopsOnASingleLine: true AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: true # AlwaysBreakTemplateDeclarations: No BinPackArguments: true BinPackParameters: true BreakBeforeBraces: Custom BraceWrapping: # AfterCaseLabel: true AfterClass: true AfterControlStatement: true AfterEnum: true AfterExternBlock: true AfterFunction: true AfterNamespace: true AfterStruct: true BeforeCatch: true BeforeElse: true IndentBraces: false SplitEmptyFunction: false SplitEmptyNamespace: false SplitEmptyRecord: false BreakBeforeBinaryOperators: None BreakBeforeTernaryOperators: false BreakConstructorInitializers: AfterColon # BreakInheritanceList: AfterColon BreakStringLiterals: true ColumnLimit: 79 ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerIndentWidth: 8 ContinuationIndentWidth: 2 Cpp11BracedListStyle: true FixNamespaceComments: true IncludeBlocks: Preserve IndentCaseLabels: false IndentPPDirectives: AfterHash IndentWidth: 2 IndentWrappedFunctionNames: false KeepEmptyLinesAtTheStartOfBlocks: false MaxEmptyLinesToKeep: 2 # NamespaceIndentation: All SortIncludes: true SortUsingDeclarations: true SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: false SpaceBeforeAssignmentOperators: true # SpaceBeforeCpp11BracedList: false # SpaceBeforeCtorInitializerColon: true # SpaceBeforeInheritanceColon: true # SpaceBeforeParents: ControlStatements # SpaceBeforeRangedBasedForLoopColon: true SpaceInEmptyParentheses: false SpacesInAngles: false SpacesInCStyleCastParentheses: false SpacesInContainerLiterals: false SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Cpp11 UseTab: Never --- libpqxx-8.0.1/.clang-tidy000066400000000000000000000217441516427024100152550ustar00rootroot00000000000000--- # Somebody decided it would be a good idea to represet a "list of strings" # (a list that can get very long, and the indivdual strings tend to be # relatively long as well) as a single long comma-separated string, with # no tolerance for whitespace. Well done! # # We use clever YAML multiline-string syntax to work around this. Checks: > bugprone-argument-comment, bugprone-assert-side-effect, bugprone-assignment-in-if-condition, bugprone-bad-signal-to-kill-thread, bugprone-bool-pointer-implicit-conversion, bugprone-copy-constructor-init, bugprone-dangling-handle, bugprone-dynamic-static-initializers, bugprone-fold-init-type, bugprone-forward-declaration-namespace, bugprone-forwarding-reference-overload, bugprone-implicit-widening-of-multiplication-result, bugprone-inaccurate-erase, bugprone-incorrect-roundings, bugprone-infinite-loop, bugprone-integer-division, bugprone-lambda-function-name, bugprone-macro-parentheses, bugprone-macro-repeated-side-effects, bugprone-misplaced-operator-in-strlen-in-alloc, bugprone-misplaced-pointer-arithmetic-in-alloc, bugprone-misplaced-widening-cast, bugprone-move-forwarding-reference, bugprone-multiple-statement-macro, bugprone-narrowing-conversions, bugprone-no-escape, bugprone-not-null-terminated-result, bugprone-parent-virtual-call, bugprone-posix-return, bugprone-redundant-branch-condition, bugprone-reserved-identifier, bugprone-shared-ptr-array-mismatch, bugprone-signal-handler, bugprone-signed-char-misuse, bugprone-sizeof-container, bugprone-sizeof-expression, bugprone-spuriously-wake-up-functions, bugprone-standalone-empty, bugprone-string-constructor, bugprone-string-integer-assignment, bugprone-string-literal-with-embedded-nul, bugprone-stringview-nullptr, bugprone-suspicious-enum-usage, bugprone-suspicious-include, bugprone-suspicious-memory-comparison, bugprone-suspicious-memset-usage, bugprone-suspicious-missing-comma, bugprone-suspicious-realloc-usage, bugprone-suspicious-semicolon, bugprone-suspicious-string-compare, bugprone-swapped-arguments, bugprone-terminating-continue, bugprone-throw-keyword-missing, bugprone-too-small-loop-variable, bugprone-unchecked-optional-access, bugprone-undefined-memory-manipulation, bugprone-undelegated-constructor, bugprone-unhandled-exception-at-new, bugprone-unhandled-self-assignment, bugprone-unused-raii, bugprone-unused-return-value, bugprone-use-after-move, bugprone-virtual-near-miss, cert-con36-c, cert-con54-cpp, cert-dcl03-c, cert-dcl16-c, cert-dcl37-c, cert-dcl50-cpp, cert-dcl51-cpp, cert-dcl54-cpp, cert-dcl58-cpp, cert-dcl59-cpp, cert-env33-c, cert-err09-cpp, cert-err33-c, cert-err34-c, cert-err52-cpp, cert-err58-cpp, cert-err60-cpp, cert-err61-cpp, cert-exp42-c, cert-fio38-c, cert-flp30-c, cert-flp37-c, cert-mem57-cpp, cert-msc30-c, cert-msc32-c, cert-msc50-cpp, cert-msc51-cpp, cert-msc54-cpp, cert-oop11-cpp, cert-oop54-cpp, cert-oop57-cpp, cert-oop58-cpp, cert-pos44-c, cert-pos47-c, cert-sig30-c, cert-str34-c, clang-analyzer-*, cppcoreguidelines-avoid-const-or-ref-data-members, cppcoreguidelines-avoid-goto, cppcoreguidelines-avoid-non-const-global-variables, cppcoreguidelines-avoid-reference-coroutine-parameters, cppcoreguidelines-c-copy-assignment-signature, cppcoreguidelines-explicit-virtual-functions, cppcoreguidelines-init-variables, cppcoreguidelines-interfaces-global-init, cppcoreguidelines-narrowing-conversions, cppcoreguidelines-no-malloc, cppcoreguidelines-non-private-member-variables-in-classes, cppcoreguidelines-owning-memory, cppcoreguidelines-prefer-member-initializer, cppcoreguidelines-pro-bounds-array-to-pointer-decay, cppcoreguidelines-pro-bounds-constant-array-index, cppcoreguidelines-pro-type-const-cast, cppcoreguidelines-pro-type-cstyle-cast, cppcoreguidelines-pro-type-member-init, cppcoreguidelines-pro-type-static-cast-downcast, cppcoreguidelines-pro-type-union-access, cppcoreguidelines-slicing, cppcoreguidelines-special-member-functions, cppcoreguidelines-virtual-class-destructor, darwin-dispatch-once-nonstatic, fuchsia-header-anon-namespaces, fuchsia-multiple-inheritance, fuchsia-trailing-return, fuchsia-virtual-inheritance, google-build-explicit-make-pair, google-build-namespaces, google-build-using-namespace, google-default-arguments, google-explicit-constructor, google-global-names-in-headers, google-readability-avoid-underscore-in-googletest-name, google-readability-function-size, google-readability-namespace-comments, google-runtime-operator, google-upgrade-googletest-case, hicpp-avoid-goto, hicpp-deprecated-headers, hicpp-exception-baseclass, hicpp-explicit-conversions, hicpp-function-size, hicpp-invalid-access-moved, hicpp-member-init, hicpp-multiway-paths-covered, hicpp-new-delete-operators, hicpp-no-array-decay, hicpp-no-assembler, hicpp-no-malloc, hicpp-special-member-functions, hicpp-undelegated-constructor, hicpp-use-auto, hicpp-use-emplace, hicpp-use-equals-default, hicpp-use-equals-delete, hicpp-use-noexcept, hicpp-use-nullptr, hicpp-use-override, llvm-header-guard, llvm-include-order, llvm-namespace-comment, llvm-prefer-isa-or-dyn-cast-in-conditionals, llvm-prefer-register-over-unsigned, llvm-twine-local, misc-confusable-identifiers, misc-const-correctness, misc-definitions-in-headers, misc-misleading-bidirectional, misc-misleading-identifier, misc-misplaced-const, misc-new-delete-overloads, misc-non-copyable-objects, misc-non-private-member-variables-in-classes, misc-redundant-expression, misc-throw-by-value-catch-by-reference, misc-unconventional-assign-operator, misc-uniqueptr-reset-release, misc-unused-alias-decls, misc-unused-parameters, misc-unused-using-decls, misc-use-anonymous-namespace, modernize-avoid-bind, modernize-concat-nested-namespaces, modernize-deprecated-headers, modernize-deprecated-ios-base-aliases, modernize-loop-convert, modernize-macro-to-enum, modernize-make-shared, modernize-make-unique, modernize-pass-by-value, modernize-raw-string-literal, modernize-redundant-void-arg, modernize-replace-auto-ptr, modernize-replace-disallow-copy-and-assign-macro, modernize-replace-random-shuffle, modernize-return-braced-init-list, modernize-shrink-to-fit, modernize-unary-static-assert, modernize-use-auto, modernize-use-bool-literals, modernize-use-default-member-init, modernize-use-emplace, modernize-use-equals-default, modernize-use-equals-delete, modernize-use-nodiscard, modernize-use-noexcept, modernize-use-nullptr, modernize-use-override, modernize-use-transparent-functors, modernize-use-uncaught-exceptions, modernize-use-using, performance-faster-string-find, performance-for-range-copy, performance-implicit-conversion-in-loop, performance-inefficient-algorithm, performance-inefficient-string-concatenation, performance-inefficient-vector-operation, performance-move-const-arg, performance-move-constructor-init, performance-no-automatic-move, performance-no-int-to-ptr, performance-trivially-destructible, performance-type-promotion-in-math-fn, performance-unnecessary-copy-initialization, performance-unnecessary-value-param, portability-restrict-system-includes, portability-simd-intrinsics, portability-std-allocator-const, readability-avoid-const-params-in-decls, readability-const-return-type, readability-container-contains, readability-container-data-pointer, readability-container-size-empty, readability-delete-null-pointer, readability-function-size, readability-identifier-naming, readability-inconsistent-declaration-parameter-name, readability-misplaced-array-index, readability-non-const-parameter, readability-redundant-access-specifiers, readability-redundant-control-flow, readability-redundant-declaration, readability-redundant-function-ptr-dereference, readability-redundant-member-init, readability-redundant-preprocessor, readability-redundant-smartptr-get, readability-redundant-string-cstr, readability-redundant-string-init, readability-simplify-boolean-expr, readability-simplify-subscript-expr, readability-static-accessed-through-instance, readability-static-definition-in-anonymous-namespace, readability-string-compare, readability-suspicious-call-argument, readability-uniqueptr-delete-release, readability-use-anyofallof, zircon-temporary-objects libpqxx-8.0.1/.cmake-format000066400000000000000000000216141516427024100155640ustar00rootroot00000000000000--- format: _help_max_prefix_chars: - !!python/unicode 'If the statement spelling length (including space and' - !!python/unicode 'parenthesis) is larger than the tab width by more ' - !!python/unicode 'than this, then force reject un-nested layouts.' max_prefix_chars: 10 _help_dangle_align: - !!python/unicode 'If trailing parenthesis must be ''dangled'' on its own' - !!python/unicode 'line, then align it to this reference: `prefix`: the ' - !!python/unicode 'start of the statement, `prefix-indent`: the start of ' - !!python/unicode 'the statement plus one indentation level, `child`: ' - !!python/unicode 'align to the column of the arguments' dangle_align: !!python/unicode 'prefix' _help_max_subgroups_hwrap: - !!python/unicode 'If an argument group contains more than this many ' - !!python/unicode 'sub-groups (parg or kwarg groups) then force it to a ' - !!python/unicode 'vertical layout.' max_subgroups_hwrap: 2 _help_min_prefix_chars: - !!python/unicode 'If the statement spelling length (including space and' - !!python/unicode 'parenthesis) is less than this, then force reject' - !!python/unicode 'nested layouts.' min_prefix_chars: 4 _help_max_pargs_hwrap: - !!python/unicode 'If a positional argument group contains more than this' - !!python/unicode 'many arguments, then force it to a vertical layout.' max_pargs_hwrap: 6 _help_max_lines_hwrap: - !!python/unicode 'If a candidate layout is wrapped horizontally but ' - !!python/unicode 'exceeds this many lines, then reject the layout.' max_lines_hwrap: 2 _help_autosort: - !!python/unicode 'If true, the parsers may infer whether or not an ' - !!python/unicode 'argument list is sortable (without annotation).' autosort: false _help_line_ending: - !!python/unicode 'What style line endings to use in the output.' line_ending: !!python/unicode 'unix' _help_line_width: - !!python/unicode 'How wide to allow formatted cmake files' line_width: 80 _help_dangle_parens: - !!python/unicode 'If a statement is wrapped to more than one line, then ' - !!python/unicode 'dangle the closing parenthesis on its own line.' dangle_parens: true _help_tab_size: - !!python/unicode 'How many spaces to tab for indent' tab_size: 4 _help_always_wrap: - !!python/unicode 'A list of command names which should always be wrapped' always_wrap: [] _help_require_valid_layout: - !!python/unicode 'By default, if cmake-format cannot successfully fit' - !!python/unicode 'everything into the desired linewidth it will apply ' - !!python/unicode 'the last, most agressive attempt that it made. If ' - !!python/unicode 'this flag is True, however, cmake-format will print ' - !!python/unicode 'error, exit with non-zero status code, and write-out ' - !!python/unicode 'nothing' require_valid_layout: true _help_keyword_case: - !!python/unicode 'Format keywords consistently as ''lower'' or ' - !!python/unicode ' ''upper'' case' keyword_case: !!python/unicode 'unchanged' _help_layout_passes: - !!python/unicode 'A dictionary mapping layout nodes to a list of wrap' - !!python/unicode 'decisions. See the documentation for more information.' layout_passes: {} _help_enable_sort: - !!python/unicode 'If true, the argument lists which are known to be ' - !!python/unicode 'sortable will be sorted lexicographically' enable_sort: true _help_markup: !!python/unicode 'Options affecting comment reflow & formatting.' markup: _help_literal_comment_pattern: - !!python/unicode 'If comment markup is enabled, don''t reflow any ' - !!python/unicode 'comment block which matches this regex. Default is ' - !!python/unicode '`None` (disabled).' literal_comment_pattern: null _help_hashruler_min_length: - !!python/unicode 'If a comment line starts with at least this many ' - !!python/unicode 'consecutive hash characters, then don''t lstrip() ' - !!python/unicode 'them off. This allows for lazy hash rulers where the ' - !!python/unicode 'first hash char is not separated by space' hashruler_min_length: 10 _help_fence_pattern: - !!python/unicode 'Regex to match preformat fences in comments' - !!python/unicode 'default=r''^\s*([`~]{3}[`~]*)(.*)$''' fence_pattern: !!python/unicode '^\s*([`~]{3}[`~]*)(.*)$' _help_canonicalize_hashrulers: - !!python/unicode 'If true, insert a space between first hash char and' - !!python/unicode 'remaining hash chars in a hash ruler, and normalize its' - !!python/unicode 'length to fill the column' canonicalize_hashrulers: true _help_explicit_trailing_pattern: - !!python/unicode 'If a comment line matches starts with this pattern ' - !!python/unicode 'then it is explicitly a trailing comment for the ' - !!python/unicode 'preceding argument. Default is ''#<''' explicit_trailing_pattern: !!python/unicode '#<' _help_first_comment_is_literal: - !!python/unicode 'If comment markup is enabled, don''t reflow first ' - !!python/unicode 'comment block in each listfile. Use to preserve ' - !!python/unicode 'formatting of your copyright/license statements.' first_comment_is_literal: false _help_enable_markup: - !!python/unicode 'enable comment markup parsing and reflow' enable_markup: true _help_ruler_pattern: - !!python/unicode 'Regular expression to match rulers in comments' - !!python/unicode 'default=r''^\s*[^\w\s]{3}.*[^\w\s]{3}$''' ruler_pattern: !!python/unicode '^\s*[^\w\s]{3}.*[^\w\s]{3}$' _help_enum_char: - !!python/unicode 'punctuation character after numerals in an' - !!python/unicode 'enumerated list' enum_char: . _help_bullet_char: - !!python/unicode 'What character to use for bulleted lists' bullet_char: '*' _help_lint: !!python/unicode 'Options affecting the linter' lint: _help_function_pattern: - !!python/unicode 'regex describing valid function names' function_pattern: !!python/unicode '[0-9a-z_]+' _help_disabled_codes: - !!python/unicode 'a list of lint codes to disable' disabled_codes: [] _help_min_statement_spacing: - !!python/unicode 'Require at least this many newlines between statements' min_statement_spacing: 1 _help_macro_pattern: - !!python/unicode 'regular expression pattern describing valid macro names' macro_pattern: !!python/unicode '[0-9A-Z_]+' _help_public_var_pattern: - !!python/unicode 'regular expression pattern describing valid names for' - !!python/unicode 'publicdirectory variables' public_var_pattern: !!python/unicode '[0-9A-Z][0-9A-Z_]+' max_statements: 50 _help_max_conditionals_custom_parser: - !!python/unicode 'In heuristic for C0201, how many conditionals to match' - !!python/unicode 'within a loop in before considering the loop a parser.' max_conditionals_custom_parser: 2 _help_global_var_pattern: - !!python/unicode 'regular expression pattern describing valid names for' - !!python/unicode 'variables with global scope' global_var_pattern: !!python/unicode '[0-9A-Z][0-9A-Z_]+' _help_keyword_pattern: - !!python/unicode 'regular expression pattern describing valid names for' - !!python/unicode 'keywords used in functions or macros' keyword_pattern: !!python/unicode '[0-9A-Z_]+' max_arguments: 5 _help_private_var_pattern: - !!python/unicode 'regular expression pattern describing valid names for' - !!python/unicode 'privatedirectory variables' private_var_pattern: !!python/unicode '_[0-9a-z_]+' max_localvars: 15 max_branches: 12 _help_local_var_pattern: - !!python/unicode 'regular expression pattern describing valid names for' - !!python/unicode 'variables with local scope' local_var_pattern: !!python/unicode '[0-9a-z_]+' _help_max_statement_spacing: - !!python/unicode 'Maximum newlines between statements' max_statement_spacing: 1 _help_internal_var_pattern: - !!python/unicode 'regular expression pattern describing valid names for' - !!python/unicode 'variables with global scope (but internal semantic)' internal_var_pattern: !!python/unicode '_[0-9A-Z][0-9A-Z_]+' max_returns: 6 _help_misc: !!python/unicode 'Miscellaneous configurations options.' misc: _help_per_command: - !!python/unicode 'A dictionary containing any per-command configuration' - !!python/unicode 'overrides. Currently only `command_case` is supported.' per_command: {} _help_parse: !!python/unicode 'Options affecting listfile parsing' parse: _help_additional_commands: - !!python/unicode 'Specify structure for custom cmake functions' additional_commands: !!python/unicode 'foo': !!python/unicode 'flags': - !!python/unicode 'BAR' - !!python/unicode 'BAZ' !!python/unicode 'kwargs': !!python/unicode 'HEADERS': !!python/unicode '*' !!python/unicode 'DEPENDS': !!python/unicode '*' !!python/unicode 'SOURCES': !!python/unicode '*' _help_encode: !!python/unicode 'Options effecting file encoding' libpqxx-8.0.1/.gitattributes000066400000000000000000000006221516427024100161040ustar00rootroot00000000000000aclocal.m4 linguist-generated=true configure linguist-generated=true libpqxx.pc linguist-generated=true libtool linguist-generated=true **/Makefile.in linguist-generated=true cmake/pqxx_cxx_feature_checks.cmake linguist-generated=true config/* linguist-generated=true examples/Makefile.am linguist-generated=true include/CMakeLists.txt linguist-generated=true tests/Makefile.am linguist-generated=true libpqxx-8.0.1/.github/000077500000000000000000000000001516427024100145515ustar00rootroot00000000000000libpqxx-8.0.1/.github/FUNDING.yml000066400000000000000000000015421516427024100163700ustar00rootroot00000000000000# These are supported funding model platforms. --- github: [jtv] patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username # Replace with a single Tidelift platform-name/package-name e.g., npm/babel: tidelift: # Replace with a single Community Bridge project-name e.g., cloud-foundry: community_bridge: liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry: lfx_crowdfunding: polar: # Replace with a single Polar username buy_me_a_coffee: # Replace with a single Buy Me a Coffee username thanks_dev: # Replace with a single thanks.dev username custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] libpqxx-8.0.1/.github/codeql-config.yml000066400000000000000000000010571516427024100200110ustar00rootroot00000000000000--- name: "CodeQL config" query-filters: - exclude: # Matter of taste: when I pass a pointer to an object, I use "*" syntax. # When it's a pointer to an array of objects, I use "[]". Seems clearer, # right? There's no semantic difference. # # But this stupid check thinks I'm passing an array. id: cpp/array-in-interface - exclude: # False positive on test functions, which have their addresses taken # during static initialisation and are then called through those. id: cpp/unused-static-function libpqxx-8.0.1/.github/workflows/000077500000000000000000000000001516427024100166065ustar00rootroot00000000000000libpqxx-8.0.1/.github/workflows/codeql.yml000066400000000000000000000022361516427024100206030ustar00rootroot00000000000000--- name: "CodeQL" "on": push: branches: ["master"] pull_request: branches: ["master"] schedule: - cron: "33 21 * * 6" jobs: analyze: name: Analyze runs-on: ubuntu-latest permissions: actions: read contents: read security-events: write strategy: fail-fast: true matrix: include: - language: cpp build-mode: manual - language: python build-mode: none steps: - name: Checkout uses: actions/checkout@v5 - name: Initialize CodeQL uses: github/codeql-action/init@v4 with: config-file: ./.github/codeql-config.yml languages: ${{ matrix.language }} queries: +security-and-quality - if: ${{ matrix.build-mode == 'manual' }} name: Build run: | ./tools/install-deps.sh ubuntu_codeql clang++ >/tmp/vars.sh . /tmp/vars.sh CXXFLAGS='-O0 -std=c++20' CXX=clang++ cmake . make -j2 - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v4 with: category: "/language:${{ matrix.language }}" libpqxx-8.0.1/.github/workflows/stale.yml000066400000000000000000000013571516427024100204470ustar00rootroot00000000000000--- name: Mark stale issues and pull requests "on": schedule: - cron: "30 1 * * *" permissions: contents: read jobs: stale: permissions: issues: write # for actions/stale to close stale issues pull-requests: write # for actions/stale to close stale PRs runs-on: ubuntu-latest steps: - uses: actions/stale@v1 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: \ There has been no activity on this ticket. Consider closing it. stale-pr-message: \ There has been no activity on this pull request. \ Complete it or drop it. stale-issue-label: 'no-issue-activity' stale-pr-label: 'no-pr-activity' libpqxx-8.0.1/.gitignore000066400000000000000000000004321516427024100152000ustar00rootroot00000000000000autom4te.cache build-*.out CMakeFiles/CMakeTmp confdefs.h config.log config.status configure~ conftest conftest.cpp conftest.err include/pqxx/config.h.in~ libpqxx.pc libpqxx-*.tar.gz libtool pqxx-config win32/common **/*.out **/.*.swp **/.swp **/*.tmp **/*~ **/lint.log **/lint.trs libpqxx-8.0.1/.inferconfig000066400000000000000000000001141516427024100154770ustar00rootroot00000000000000{ "report-block-list-path-regex": [ "/usr/include/c../" ] } libpqxx-8.0.1/.lcovrc000066400000000000000000000006331516427024100145040ustar00rootroot00000000000000# We get mysterious errors about inconsistent coverage data, where it seems # one line might be marked as not executed and then the next line in the same # function is marked as executed. ignore_errors = inconsistent forget_testcase_names = 1 lcov_excl_line = PQXX_DECLARE_ENUM_CONVERSION\(.*\); parallel = 4 genhtml_dark_mode = 1 genhtml_flat_view = 1 genhtml_missed = 1 genhtml_show_function_proportion = 1 libpqxx-8.0.1/.lgtm.yml000066400000000000000000000002241516427024100147530ustar00rootroot00000000000000# Config file for lgtm.com static analysis. --- path_classifiers: test: - test generated: - aclocal.m4 - configure - ltmain.sh libpqxx-8.0.1/.lift/000077500000000000000000000000001516427024100142255ustar00rootroot00000000000000libpqxx-8.0.1/.lift/ignoreFiles000066400000000000000000000001061516427024100164130ustar00rootroot00000000000000# Make Sonatype Lift ignore these generated files. configure config/* libpqxx-8.0.1/.mdl_style.rb000066400000000000000000000015411516427024100156110ustar00rootroot00000000000000all # Allow mixing of header styles, within reason. # I use "setext" style when I can, but have to switch to "atx" (hash marks) # for the more fine-grained sections which setext does not support. rule 'MD003', :style => :setext_with_atx # Multiple consecutive blank lines. Sorry, but I want my Markdown to look # nice. And there does not seem to be an option for "allow a maximum of 2." exclude_rule 'MD012' # What joker came up with this? There may be some sense to warning about # trailing punctuation, but not when it's a question mark or exclamantion mark! rule 'MD026', :punctuation => '.,;:' # In an ordered list, I like to start each item with the right number, not with # "1." rule 'MD029', :style => :ordered # Allow bare URLs. Hate to have to disable this, but mainpage.md has some # special syntax which requires bare URLs. exclude_rule 'MD034' libpqxx-8.0.1/.mdlrc000066400000000000000000000003071516427024100143130ustar00rootroot00000000000000# Markdownlint config. Basically it's code, not config. :-( # Also, it seems all we can really do in this file is point to another file # containing our actual configuration. style '.mdl_style.rb' libpqxx-8.0.1/.readthedocs.yaml000066400000000000000000000017161516427024100164450ustar00rootroot00000000000000# Read the Docs configuration file. # # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details. --- version: 2 build: # Using an old Ubuntu LTS: an apparent bug in Doxygen 1.9.8 "loses" the # documentation for pqxx::transaction and pqxx::work. So for now, stick # with Doxygen 1.9.1. :-( os: "ubuntu-22.04" tools: python: "3.12" apt_packages: - "autoconf" - "automake" - "build-essential" - "graphviz" - "libpq-dev" - "make" jobs: pre_build: - "./configure CXXFLAGS=\"-O0 -std=c++23\" --enable-documentation" - "mkdir -p doc/doxygen-html" - "doxygen doc/Doxyfile" - "mkdir -p -- \"$READTHEDOCS_OUTPUT/html\"" post_build: - "cd -- \"$READTHEDOCS_OUTPUT\" && mv html sphinx-html" - "mv -- doc/doxygen-html \"$READTHEDOCS_OUTPUT/html\"" python: install: - requirements: doc/requirements.txt sphinx: configuration: doc/source/conf.py fail_on_warning: true libpqxx-8.0.1/.yamllint000066400000000000000000000003061516427024100150420ustar00rootroot00000000000000--- pqxx: extends: default rules: # Wish I didn't have to, but accept longer lines. We've got some long # lines that are hard to break without messing up legibility. level: warning libpqxx-8.0.1/AUTHORS000066400000000000000000000002451516427024100142620ustar00rootroot00000000000000Jeroen T. Vermeulen. Wrote the code. Ray Dassen. Did most of the autoconf etc. stuff. We still miss him. Lots of others helped with various other contributions. libpqxx-8.0.1/BUILDING-cmake.md000066400000000000000000000322061516427024100160110ustar00rootroot00000000000000Building using CMake ==================== First of all, the libpqxx build requires the development package for `libpq`, PostgreSQL's C client library. You must have that package installed before you can build libpqxx. It also requires Python 3, which comes pre-installed on many systems. And, you may need various standard Unix or GNU command-line utilities. The instructions will assume that you're working from a command-line shell. If you prefer to work from an IDE, you'll have to know how your IDE likes to do things, and you'll want to follow the shell instructions as a guide. I'm not too familiar with CMake, and this build relies heavily on contributions from users. If you see something wrong here, please file a bug and explain, in simple words, what needs changing and why. There are two ways to use libpqxx in your project with CMake: * _(A)_ copy and build the libpqxx source tree. * Or _(B),_ make use of a separately installed libpqxx. We'll go through both of these. Option (A): Copy and build the libpqxx source tree -------------------------------------------------- This option is nice and portable. If you want others to be able to compile your project on their own systems, this method probably requires a bit less setup than the other option. It's easier to keep compatible compilation options between libpqxx and your project. On the flip side, building your project will take a bit longer, because it will build libpqxx along the way. And of course, you'll need to make sure that there's a copy of the libpqxx tree somewhere. You could do that by having the libpqxx git repo as a submodule inside yours. As mentioned, you'll need to have the PostgreSQL dev libraries installed on your system, including their headers. Let's say you have a copy of the libpqxx source tree inside your source tree as `deps/libpqxx`, and you want to want to build libpqxx in a subdirectory of your build directory called `build-pqxx`. Given that, make sure you have a line like this in your `CMakeLists.txt`: ```cmake add_subdirectory(deps/libpqxx build-pqxx) ``` You'll also need to mention libpqxx in your `target_link_libraries`, so that your code will link with libpqxx. For example, if your project is named `ausom` and links to no other libraries: ```cmake target_link_libraries(ausom PRIVATE pqxx) ``` So a simple working `CMakeLists.txt` might be: ```cmake cmake_minimum_required(VERSION 3.12) project(ausom) set(CMAKE_CXX_STANDARD 20) add_executable(ausom src/ausom.cxx) add_subdirectory(deps/libpqxx build-pqxx) target_link_libraries(ausom PRIVATE pqxx) ``` Option (B): Make use of a separately installed libpqxx ------------------------------------------------------ If libpqxx is already installed, you can just make use of that in your own `CMakeLists.txt`: ```cmake find_package(libpqxx REQUIRED) ``` For this to work, there must be a configuration file `libpqxxConfig.cmake` or `libpqxx-config.cmake` that CMake can find. If this file exists but CMake can't find it, you may have to set `libpqxx_DIR` in your `CMakeLists.txt` to point to a directory containing that configuration file. You'll also need to mention libpqxx in your `target_link_libraries`, so that your code will link with libpqxx. For example, if your project is named `ausom` and links to no other libraries: ```cmake target_link_libraries(ausom PRIVATE pqxx) ``` So a simple working `CMakeLists.txt` might be: ```cmake cmake_minimum_required(VERSION 3.12) project(ausom) set(CMAKE_CXX_STANDARD 20) add_executable(ausom src/ausom.cxx) find_package(libpqxx REQUIRED) target_link_libraries(ausom PRIVATE pqxx) ``` Of course that does mean that you need libpqxx installed on your system. We'll look into that next. Installing a libpqxx OS package ------------------------------- Your operating system provider may have a packaged version of libpqxx ready for you to install. For example, on a Debian or Ubuntu system you might run: ```shell sudo apt-get install libpqxx-dev ``` But the exact name of the package you need may depend on the system. In a Debian-flavoured system, the `-dev` suffix is a convention for saying that you want not just a binary library installed, but its header files as well. You definitely need those. On a RedHat-flavoured system, the convention is a suffix of `-devel` after the name, i.e. `libpqxx-devel`. Other systems may conventionally include the headers with the library package. For example, on macOS using HomeBrew, you would just... ```shell brew install libpqxx ``` Of course if there is no ready-made libpqxx package for your system, or it's not up to date, or it does not provide a `libpqxx-config.cmake` configuration file, another option is to build and install libpqxx using CMake. Building and installing libpqxx yourself ---------------------------------------- If you just want to get libpqxx itself built and installed quickly, run `cmake` from the root of the libpqxx source tree. This configures your build. Then compile libpqxx by running: ```shell cmake --build . ``` To install in the default location: ```shell cmake --install . ``` The rest of this document will go deeper into the details of this, but you may not need it. Stages ------ I'll explain the main build steps in more detail below, but here's a quick rundown: 1. Configure 2. Compile 3. Test 4. Install 5. Use The Test step is optional. Configure --------- Run `cmake` to configure your build. It figures out various parameters, such as where libpq and its headers are, which C++ features your compiler supports, and which options your compiler needs. CMake generates configuration for your build tool: `Makefile`s for `make`, or a Solution (".sln") file for MSVC's `msbuild`, and so on. At this stage you can also override those options yourself. e.g. to instruct the compiler to look for libpq in a non-standard place, or to use a different compiler, or pass different compiler flags. Don't try to specify those while doing the actual compile; set them once when running `cmake`. Let's say `$BUILD` is the directory where you want to build libpqxx, and `$SRC` is where its source code is. So for example, the readme file will be at `$SRC/README.md`. In the simplest case, you just do: ```shell cd $BUILD cmake $SRC ``` Add CMake options as needed. There's more about the options below. I'll also explain the two directories. ### Cheat sheet Here are some popular `cmake` options for libpqxx: * `-DSKIP_BUILD_TEST=on` skips compiling libpqxx's tests. * `-DBUILD_SHARED_LIBS=on` to build a shared library. * `-DBUILD_SHARED_LIBS=off` to build a static library. * `-DBUILD_DOC=on` to build documentation. * `-DINSTALL_TEST=on` to install test executor binary. On Windows, I recommend building libpqxx as a shared library and bundling it with your application. On other platforms I would prefer a static library. Building the documentation requires some tools to be installed. It takes at least Doxygen, but there's no list of requirements. The way to get this set up is to just try it and see what it's missing. ### Generators You can also choose your own build tool by telling CMake to use a particular "generator." For example, here's how to force use of `make`: ```shell cmake -G 'Unix Makefiles' ``` Or if you prefer to build using `ninja` instead: ```shell cmake -G Ninja ``` There are many more options. You may prefer yet a different build tool. ### Finding libpq The CMake step tries to figure out where libpq is, using Cmake's `find_package` function. If that doesn't work, or if you want a libpq in a different location from the one it finds, there are two ways to override it. The first is to set the individual include and link paths. To make the build look for the libpq headers in some directory `$DIR`, add these options: * `-DPostgreSQL_TYPE_INCLUDE_DIR=$DIR` * `-DPostgreSQL_INCLUDE_DIR=$DIR` To make the build look for the libpq library binary in a directory `$DIR`, add this option: * `-DPostgreSQL_LIBRARY_DIR=$DIR` The second, easier way requires CMake 3.12 or better. Here, you specify a path to a full PostgreSQL build tree. You do this (again for some directory `$DIR`) by simply passing this cmake option: `-DPostgreSQL_ROOT=$DIR` ### Source and Build trees Where should you run `cmake`? Two directories matter when building libpqxx: the _source tree_ (where the libpqxx source code is) and the _build tree_ (where you want your build artefacts). Here I will call them `$SRC` and `$BUILD`, but you can call them anything you like. They can be one and the same, if you like. It's convenient, but less clean, as source code and build artefacts will exist in the same directory tree. If you're going to delete the source tree after installing, of course it's fine to make a mess in there. Compile ------- To compile, run: ```shell cmake --build $BUILD ``` (Where `$BUILD` is again the directory where you wish to do the build.) This command will invoke your build tool. Other ways to do the same thing would be... * With Unix Makefiles: `make` * With Ninja: `ninja` * With Visual Studio: `msbuild libpqxx.sln` * etc. Depending on your build tool, you may want to speed this up by adding an option like `-j 16`, where `16` is an example of how many processes you might want to run in parallel. The optimal number depends on your available CPUs and memory. If you have enough memory, usually the number of CPUs will be a good starting point for the right number. Don't use this option with Ninja though. It figures things out for itself. Test ---- Of course libpqxx comes with a test suite, to check that the library is functioning correctly. You can run it, but there's one caveat: you need to give it a database where it can log in, without a password or any other parameters, and try out various things. And when I say you need to "give" it a database, I really mean "give." The test suite will create and drop tables. Those will all have names prefixed with "pqxx", so it's probably safe to use a database you already had, but if any of the items in your database happen to have names starting with `pqxx`, tough luck. They're fair game. Enter this in your shell to build and run the tests: ```shell test/runner ``` ### Configuring the test database But what if you do need a password to log into your test database? Or, what if it's running on a different system so you need to pass that machine's address? What if it's not running on the default port? You can set these parameters for the test suite, or for any other libpq-based application, using the following environment variables. (They only set default values, so they won't override parameters that the application sets in some other way.) * `PGHOST` — the IP address where we can contact the database's socket. Or for a Unix domain socket, its absolute path on the filesystem. * `PGPORT` — TCP port number on which we can connect to the database. * `PGDATABASE` — the name of the database to which you wish to connect. * `PGUSER` — user name under which you wish to log in on the database. * `PGPASSWORD` — user name's password for accessing the database. See the full list at [ https://www.postgresql.org/docs/current/libpq-envars.html ](https://www.postgresql.org/docs/current/libpq-envars.html) **Be careful with passwords,** by the way. Depending on your operating system and configuration, an attacker with access to your machine could try to read your password if you set it on the command line: * Your shell may keep a log of the commands you have entered. * Environment variables may be visible to other users on the system. If at all possible, rely on postgres "peer authentication." Once set up, it is both more secure and more convenient than passwords. Install ------- Once you've built libpqxx, CMake can also help you install the library and headers on your system. The default installation location will vary from one operating system to another, but you can set it explicitly. Let's say you've got your finished build in `$BUILD`, and you want to install it to your system's default install location. The command for this is: ```shell cmake --install $BUILD ``` But you may want to install to some other location. Let's call it `$DEST`. `$DEST` might be something like `/usr/local` on a Unix-like system, or something like `D:\Software` on a Windows system. To install to `$DEST`, run: ```shell cmake --install $BUILD --prefix $DEST ``` Use --- Other projects can include libpqxx in their CMake builds. Here's an example of a `CMakeLists.txt` fragment. You'll probably still need to provide details specific to your project. ```cmake # (First set LIBVERSION to the libpqxx version you have.) set(libpqxxdir "libpqxx-${LIBVERSION}") # You can usually skip building the tests. set(SKIP_BUILD_TEST ON) # On Windows we generally recommend building libpqxx as a shared # library. On other platforms, we recommend a static library. IF (WIN32) set(BUILD_SHARED_LIBS ON) ELSE() set(BUILD_SHARED_LIBS OFF) ENDIF() add_subdirectory(${libpqxxdir}) ``` If you are using shared libraries (which is recommended when building on Windows), you may need to ensure that libpq and the libraries it in turn requires are all in your dynamic link path. libpqxx-8.0.1/BUILDING-configure.md000066400000000000000000000246401516427024100167150ustar00rootroot00000000000000Building using `configure` ========================== The instructions will assume that you're working from a command-line shell. If you prefer to work from an IDE, you'll have to know how your IDE likes to do things, and you'll want to follow the shell instructions as a guide. Prerequisites ------------- Before building and installing the `libpqxx` library, you first need to install the `libpq` library. This is the official C client library for PostgreSQL that allows `libpqxx` to communicate with the database backend server. Methods for installing the `libpq` library will vary depending on your operating system and individual setup. It also requires Python 3, which comes pre-installed on many systems. And, you may need various standard Unix or GNU command-line utilities. Quick start ----------- Once you have downloaded the `libpqxx` source code, you can build and install it quickly by entering the following commands: ```shell ./configure --disable-shared make sudo make install ``` This installation automatically places the `libpqxx` libraries in the appropriate locations for your system. If you wish, you may delete the downloaded folder after the installation process completes. Want more detail? Read on. Stages ------ I'll explain the main build steps in more detail below, but here's a quick overview: 1. Configure 2. Compile 3. Test 4. Install The Test step is optional. Configure --------- The `configure` script configures your build. It figures out various parameters, such as where libpq and its headers are, which C++ features your compiler supports, and which options your compiler needs. It generates Makefiles, which in turn tell the `make` utility how to perform tasks such as compiling libpqxx, running tests, cleaning up after itself, and installing libpqxx. The `configure` step is also where you can set these options, e.g. to instruct the compiler to look for libpq in a non-standard place, or to use a different compiler, or pass different compiler flags. Don't try to specify those while doing the actual compile; set them once when running `configure`. Let's say `$BUILD` is the directory where you want to build libpqxx, and `$SRC` is where its source code is. So for example, the readme file will be at `$SRC/README.md`. In the simplest case, you just do: ```shell cd $BUILD $SRC/configure ``` Add `configure` options as needed. There's more about the options below, or in the output of `configure --help`. I'll also explain the two directories. ### Cheat sheet Here are some popular `configure` options: * `--disable-documentation` skips building of the documentation. * `CXXFLAGS=-O0` disables optimisation. Slower code, but faster build. * `CXXFLAGS=-O3` asks for _more_ optimisation. Faster code, slower build. * `CXX=clang++` compiles with `clang++` as the compiler. * `--enable-maintainer-mode` makes the compiler more pedantic about the code. * `--enable-audit` enables expensive run-time checks for debugging. * `--with-postgres-lib=$DIR` looks for libpq in `$DIR`. * `--with-postgres-include=$DIR` looks for the libpq headers in `$DIR`. * `--prefix=$PATH` prepares to install libpqxx in `$PATH`. * `--enable-shared` enables compilation of libpqxx as a shared library. * `--disable-shared` disbles compilation of libpqxx as a shared library. * `--enable-static` enables compilation of libpqxx as a static library. * `--disable-static` disables compilation of libpqxx as a static library. * `--help` shows you a lot more of the options. So for example, to get a very quick build but produce very inefficient code: ```shell ./configure --disable-documentation CXXFLAGS=-O0 ``` Or if you want to pull out all the stops to find problems in the code: ```shell ./configure --enable-maintainer-mode --enable-audit CXXFLAGS=-O3 ``` (Requesting `-O3` optimisation will make some compilers perform extra analysis which may, as a side effect, cause them to notice and warn about certain kinds of mistakes in the code, such as occasionally-unused variables.) ### Finding libpq One of `configure`'s most important jobs in the libpqxx build is to find the headers and library for libpq. It has three ways of finding those: 1. Asking a popular tool called `pkg-config`, if installed. 2. Asking postgres' deprecated `pg_config` tool, if installed. 3. Through explicit command-line options to `configure`. The explicit command-line options are `--with-postgres-lib` (for the libpq library binary) and `--with-postgres-include` (for the libpq headers). If you want to use a version of libpq that's not installed in a standard location, e.g. if you're cross-compiling to produce a binary for a different CPU architecture than your native system's, use the explicit options. ### Where does the `configure` script come from? I didn't write the `configure` script. It was generated by GNU `autoconf` and related GNU tools. There's a script to re-generate it, called `autogen.sh`. The contents of `configure` are based on a higher-level script called `configure.ac`. This is where I script checks for specific features in libpq or the compiler. The `configure` script adds a lot of built-in items that I don't need to worry about, such as figuring out exactly how your build tools work. Don't try to debug `configure` yourself if you can help it. It's very hard to read, partly because it's automatically generated, but also because it is engineered to work with an extremely broad range of shells, compilers, tools, and operating systems. If you're going to do a "deep dive," try looking at `configure.ac` instead. ### Source and Build trees Where should you run `configure`? Two directories matter when building libpqxx: the _source tree_ (where the libpqxx source code is) and the _build tree_ (where you want your build artefacts). Here I will call them `$SRC` and `$BUILD`, but you can call them anything you like. They can be one and the same, if you like. It's convenient, but less clean, as source code and build artefacts will exist in the same directory tree. If you're going to delete the source tree after installing, of course it's fine to make a mess in there. Compile ------- To start the compile, run the `make` tool. It will go through all the steps to produce a libpqxx library binary. Beware though, it only runs _one_ compiler process at a time. That could take a while. Use the `-j` option to make it run concurrent processes, e.g.: ```shell make -j8 ``` Very roughly speaking, it's probably fastest if you run one process per CPU core in your system. If you have the `nproc` utility installed: ```shell make -j$(nproc) ``` If you want a very fast build and don't mind missing out on efficient code or documentation, tweak the Configure step above by adding `configure` options like `CXXFLAGS=-O0` and `--disable-documentation`. Test ---- Of course libpqxx comes with a test suite, to check that the library is functioning correctly. You can run it, but there's one caveat: you need to give it a database where it can log in, without a password or any other parameters, and try out various things. And when I say you need to "give" it a database, I really mean "give." The test suite will create and drop tables. Those will all have names prefixed with "pqxx", so it's probably safe to use a database you already had, but if any of the items in your database happen to have names starting with `pqxx`, tough luck. They're fair game. Enter this in your shell to build and run the tests: ```shell make check ``` As with compiling, use the `-j` option to make better use of your CPUs. For example: ```shell make check -j$(nproc) ``` ### Configuring the test database But what if you do need a password to log into your test database? Or, what if it's running on a different system so you need to pass that machine's address? What if it's not running on the default port? You can set these parameters for the test suite, or for any other libpq-based application, using the following environment variables. (They only set default values, so they won't override parameters that the application sets in some other way.) * `PGHOST` — the IP address where we can contact the database's socket. Or for a Unix domain socket, its absolute path on the filesystem. * `PGPORT` — * `PGDATABASE` — the name of the database to which you wish to connect. * `PGUSER` — user name under which you wish to log in on the database. * `PGPASSWORD` — user name's password for accessing the database. See the full list at [ https://www.postgresql.org/docs/current/libpq-envars.html ](https://www.postgresql.org/docs/current/libpq-envars.html). **Be careful with passwords,** by the way. Depending on your operating system and configuration, an attacker with access to your machine could try to read your password if you set it on the command line: * Your shell may keep a log of the commands you have entered. * Environment variables may be visible to other users on the system. If at all possible, rely on postgres "peer authentication." Once set up, it is both more secure and more convenient than passwords. Install ------- Installing libpqxx will install the library and headers in a location chosen at the time you can the `configure` script. On some systems it defaults to the `/usr/local/` tree, but it may be different in your environment. Or, use the `configure` script's `--prefix` option to set an install location. (If you want to see exactly what happens, you can run any `make` command line with the `-n` option, which means: don't actually do this, but print all the commands you would execute if you did. It's a lot of output though.) To install, ensure that you have sufficient privileges to write the files to their install locations, and run: ```shell make install ``` Save your build tree somewhere, so that you will be able to undo installation in the future: ```shell make uninstall ``` When using the library, make sure the libpqxx headers are in your compiler's include path. (You will no longer need the libpq headers at that time.) Also, building an application which uses libpqxx, make sure the libpqxx library binary is in your compiler's library search path. And if the library binary is a shared library, you'll also need it in your loader's search path when running your application. This last part goes for libpq as well: when using libpq, make sure you have the libpq library binary in your compiler's library search path, and if it's a shared library, also have it in your loader's search path when running. libpqxx-8.0.1/CMakeLists.txt000066400000000000000000000041131516427024100157500ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.12) file(READ VERSION VER_FILE_CONTENT) string(STRIP ${VER_FILE_CONTENT} VER_FILE_CONTENT) # Remove any release-candidate suffix. string(REGEX MATCH "^[0-9.]+" STRIPPED_VERSION ${VER_FILE_CONTENT}) project( libpqxx VERSION "${STRIPPED_VERSION}" LANGUAGES CXX ) if(NOT "${CMAKE_CXX_STANDARD}") set(CMAKE_CXX_STANDARD 20) endif() set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) # Generate a "compilation database" so we can use run-clang-tidy, to run static # checks in parallel. set(CMAKE_EXPORT_COMPILE_COMMANDS ON) option(BUILD_DOC "Build documentation" OFF) if(NOT SKIP_BUILD_TEST AND CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) option(BUILD_TEST "Build all test cases" ON) endif() # TODO: Enable PQXX_HAVE_STACKTRACE if appropriate. if(NOT SKIP_BUILD_EXAMPLES AND CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR ) option(BUILD_EXAMPLES "Build examples" ON) endif() include(GNUInstallDirs) include(CMakePackageConfigHelpers) include(config) add_subdirectory(src) add_subdirectory(include) if(BUILD_DOC) add_subdirectory(doc) endif() if(BUILD_TEST) add_subdirectory(test) endif() if(BUILD_EXAMPLES) add_subdirectory(examples) endif() # Installation write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/libpqxx-config-version.cmake" VERSION ${VER_FILE_CONTENT} COMPATIBILITY SameMajorVersion ) install(FILES cmake/libpqxx-config.cmake "${CMAKE_CURRENT_BINARY_DIR}/libpqxx-config-version.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libpqxx ) install( EXPORT libpqxx-targets NAMESPACE libpqxx:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libpqxx ) # Build tree export export( EXPORT libpqxx-targets NAMESPACE libpqxx:: FILE ${CMAKE_CURRENT_BINARY_DIR}/libpqxx-targets.cmake ) configure_file( cmake/libpqxx-config.cmake ${CMAKE_CURRENT_BINARY_DIR}/libpqxx-config.cmake COPYONLY ) # Package generation set(CPACK_GENERATOR TGZ) set(CPACK_PACKAGE_VERSION ${VER_FILE_CONTENT}) include(CPack) libpqxx-8.0.1/COPYING000066400000000000000000000027261516427024100142530ustar00rootroot00000000000000Copyright (c) 2000-2026 Jeroen T. Vermeulen. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author, nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. libpqxx-8.0.1/ChangeLog000066400000000000000000000001731516427024100147640ustar00rootroot00000000000000To produce a change log, run this in the git repo: git log --stat --name-only --date=short --abbrev-commit >ChangeLog libpqxx-8.0.1/INSTALL000066400000000000000000000002061516427024100142400ustar00rootroot00000000000000For installation instructions, see `BUILDING-configure.md` (for the `configure` build) and `BUILDING-cmake.md` (for the CMake build). libpqxx-8.0.1/Makefile.am000066400000000000000000000173721516427024100152570ustar00rootroot00000000000000# ############################################################################## # AUTOMATICALLY GENERATED FILE -- DO NOT EDIT. # # This file is generated automatically by libpqxx's template2mak.py script, and # will be rewritten from time to time. # # If you modify this file, chances are your modifications will be lost. # # The template2mak.py script should be available in the tools directory of the # libpqxx source archive. # # Generated from template './Makefile.am.template'. # ############################################################################## # Template for generating the root Makefile.am. # # We do all the compiling from this central root-level Makefile.am, even # though the actual source files are distributed across several subdirectories. # This way we don't waste time waiting to start on the next build target while # the ongoing target is still being built in its own subdirectory. # subdir-objects: store the object files in their source file's respective # subdirectories. # # serial-tests: Use the serial test runner, so tests don't get run in parallel. # Otherwise, output from test failures will be hidden away in log files where # we can't see them when running in a build slave. AUTOMAKE_OPTIONS = subdir-objects serial-tests # We should probably get all the targets in this Makefile.am built (".") before # doing anything like installing the headers. I'm not sure it matters. SUBDIRS = . include EXTRA_DIST = autogen.sh configitems Makefile.am.template README.md VERSION \ requirements.json .clang-format .clang-tidy .cmake-format \ .inferconfig .lcovrc .lgtm.yml .lift .mdlrc .mdl_style.rb .yamllint \ doc/Doxyfile \ src/pqxx-source.hxx \ test/helpers.hxx test/sample_types.hxx \ tools/deprecations.sh \ tools/extract_version.sh \ tools/format.sh \ tools/idock.sh \ tools/install-deps.sh \ tools/lint.sh \ tools/run-test-postgres.sh \ tools/todo.sh \ tools/update-copyright.sh \ tools/check_ascii.py \ tools/compiler_flags.py \ tools/extract_version.py \ tools/filter_config.py \ tools/generate_check_config.py \ tools/generate_cxx_checks.py \ tools/m4esc.py \ tools/template2mak.py \ config/flags/audit-mode.txt \ config/flags/maintainer-mode.txt \ config/flags/suggest-mode.txt \ # (End of list) noinst_HEADERS = test/helpers.hxx DISTCLEANFILES = include/pqxx/config-compiler.h MAINTAINERCLEANFILES = \ Makefile.in aclocal.m4 config.h.in config.log configure stamp-h.in \ config/config.guess config/config.sub config/install-sh config/ltmain.sh \ config/missing config/mkinstalldirs \ include/pqxx/Makefile.in include/pqxx/stamp-h.in pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libpqxx.pc PQXX_TEST_PROGS = test/runner # We use README.md, but automake expects plain README. README: README.md ln -s $< $@ AM_CPPFLAGS = \ -I$(top_srcdir)/include -I$(top_builddir)/include ${POSTGRES_INCLUDE} # Override automatically generated list of default includes. It contains only # unnecessary entries, and incorrectly mentions include/pqxx directly. DEFAULT_INCLUDES= lib_LTLIBRARIES = src/libpqxx.la src_libpqxx_la_SOURCES = \ src/array.cxx \ src/blob.cxx \ src/connection.cxx \ src/cursor.cxx \ src/encodings.cxx \ src/errorhandler.cxx \ src/except.cxx \ src/field.cxx \ src/largeobject.cxx \ src/notification.cxx \ src/params.cxx \ src/pipeline.cxx \ src/result.cxx \ src/robusttransaction.cxx \ src/sql_cursor.cxx \ src/strconv.cxx \ src/stream_from.cxx \ src/stream_to.cxx \ src/subtransaction.cxx \ src/time.cxx \ src/transaction.cxx \ src/transaction_base.cxx \ src/row.cxx \ src/types.cxx \ src/util.cxx \ src/wait.cxx libpqxx_version = -release $(PQXX_ABI) src_libpqxx_la_LDFLAGS = $(libpqxx_version) \ -rpath $(libdir) \ ${POSTGRES_LIB} test_runner_SOURCES = \ test/test00.cxx \ test/test01.cxx \ test/test02.cxx \ test/test07.cxx \ test/test10.cxx \ test/test11.cxx \ test/test13.cxx \ test/test18.cxx \ test/test20.cxx \ test/test21.cxx \ test/test26.cxx \ test/test29.cxx \ test/test30.cxx \ test/test32.cxx \ test/test37.cxx \ test/test39.cxx \ test/test46.cxx \ test/test56.cxx \ test/test60.cxx \ test/test61.cxx \ test/test62.cxx \ test/test70.cxx \ test/test71.cxx \ test/test72.cxx \ test/test74.cxx \ test/test75.cxx \ test/test76.cxx \ test/test77.cxx \ test/test82.cxx \ test/test84.cxx \ test/test88.cxx \ test/test89.cxx \ test/test90.cxx \ test/test_array.cxx \ test/test_blob.cxx \ test/test_cancel_query.cxx \ test/test_column.cxx \ test/test_composite.cxx \ test/test_connection.cxx \ test/test_connection_string.cxx \ test/test_cursor.cxx \ test/test_encodings.cxx \ test/test_error_verbosity.cxx \ test/test_errorhandler.cxx \ test/test_escape.cxx \ test/test_exceptions.cxx \ test/test_field.cxx \ test/test_float.cxx \ test/test_helpers.cxx \ test/test_largeobject.cxx \ test/test_nonblocking_connect.cxx \ test/test_notice_handler.cxx \ test/test_notification.cxx \ test/test_params.cxx \ test/test_pipeline.cxx \ test/test_prepared_statement.cxx \ test/test_range.cxx \ test/test_read_transaction.cxx \ test/test_result_iteration.cxx \ test/test_row.cxx \ test/test_separated_list.cxx \ test/test_simultaneous_transactions.cxx \ test/test_sql_cursor.cxx \ test/test_stateless_cursor.cxx \ test/test_strconv.cxx \ test/test_stream_from.cxx \ test/test_stream_query.cxx \ test/test_stream_to.cxx \ test/test_string_conversion.cxx \ test/test_subtransaction.cxx \ test/test_thread_safety_model.cxx \ test/test_time.cxx \ test/test_transaction.cxx \ test/test_transaction_base.cxx \ test/test_transaction_focus.cxx \ test/test_transactor.cxx \ test/test_type_name.cxx \ test/test_util.cxx \ test/test_zview.cxx \ test/runner.cxx test_runner_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} PQXX_EXAMPLES = \ examples/complete_example \ examples/faster_data \ examples/from_readme \ examples/getting_started_1 \ examples/getting_started_2 \ examples/quick_example \ examples/simple_queries \ # (End of list) noinst_PROGRAMS = $(PQXX_EXAMPLES) examples_complete_example_SOURCES = examples/complete_example.cxx examples_complete_example_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} examples_faster_data_SOURCES = examples/faster_data.cxx examples_faster_data_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} examples_from_readme_SOURCES = examples/from_readme.cxx examples_from_readme_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} examples_getting_started_1_SOURCES = examples/getting_started_1.cxx examples_getting_started_1_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} examples_getting_started_2_SOURCES = examples/getting_started_2.cxx examples_getting_started_2_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} examples_quick_example_SOURCES = examples/quick_example.cxx examples_quick_example_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} examples_simple_queries_SOURCES = examples/simple_queries.cxx examples_simple_queries_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} TESTS = $(PQXX_TEST_PROGS) tools/lint.sh $(PQXX_EXAMPLES) check_PROGRAMS = ${PQXX_TEST_PROGS} maintainer-clean-local: $(RM) -rf doc/doxygen-html $(MKDIR) doc/doxygen-html all-local: docs if BUILD_DOCS DOXYGEN = doxygen # Doxygen config needs the source files in its local tree. That means the # build tree. If that differs from the source tree, copy the files. docs: if ! [ "$(top_srcdir)/src" -ef src ]; \ then \ cp "$(top_srcdir)"/src/*.[ch]xx src/ ; \ cp -r "$(top_srcdir)"/include/pqxx/* include/pqxx/ ; \ cp -r "$(top_srcdir)"/test test/ ; \ fi $(DOXYGEN) "$(top_srcdir)/doc/Doxyfile" else docs: endif dist-hook: if [ -d doc/doxygen-html ]; \ then \ cp -pR doc/doxygen-html $(top_distdir)/doc/html ; \ fi libpqxx-8.0.1/Makefile.am.template000066400000000000000000000103041516427024100170550ustar00rootroot00000000000000# Template for generating the root Makefile.am. # # We do all the compiling from this central root-level Makefile.am, even # though the actual source files are distributed across several subdirectories. # This way we don't waste time waiting to start on the next build target while # the ongoing target is still being built in its own subdirectory. # subdir-objects: store the object files in their source file's respective # subdirectories. # # serial-tests: Use the serial test runner, so tests don't get run in parallel. # Otherwise, output from test failures will be hidden away in log files where # we can't see them when running in a build slave. AUTOMAKE_OPTIONS = subdir-objects serial-tests # We should probably get all the targets in this Makefile.am built (".") before # doing anything like installing the headers. I'm not sure it matters. SUBDIRS = . include EXTRA_DIST = autogen.sh configitems Makefile.am.template README.md VERSION \ requirements.json .clang-format .clang-tidy .cmake-format \ .inferconfig .lcovrc .lgtm.yml .lift .mdlrc .mdl_style.rb .yamllint \ doc/Doxyfile \ src/pqxx-source.hxx \ test/helpers.hxx test/sample_types.hxx \ ###MAKTEMPLATE:FOREACH tools/*.sh tools/###BASENAME###.sh \ ###MAKTEMPLATE:ENDFOREACH ###MAKTEMPLATE:FOREACH tools/*.py tools/###BASENAME###.py \ ###MAKTEMPLATE:ENDFOREACH ###MAKTEMPLATE:FOREACH config/flags/*.txt config/flags/###BASENAME###.txt \ ###MAKTEMPLATE:ENDFOREACH # (End of list) noinst_HEADERS = test/helpers.hxx DISTCLEANFILES = include/pqxx/config-compiler.h MAINTAINERCLEANFILES = \ Makefile.in aclocal.m4 config.h.in config.log configure stamp-h.in \ config/config.guess config/config.sub config/install-sh config/ltmain.sh \ config/missing config/mkinstalldirs \ include/pqxx/Makefile.in include/pqxx/stamp-h.in pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libpqxx.pc PQXX_TEST_PROGS = test/runner # We use README.md, but automake expects plain README. README: README.md ln -s $< $@ AM_CPPFLAGS = \ -I$(top_srcdir)/include -I$(top_builddir)/include ${POSTGRES_INCLUDE} # Override automatically generated list of default includes. It contains only # unnecessary entries, and incorrectly mentions include/pqxx directly. DEFAULT_INCLUDES= lib_LTLIBRARIES = src/libpqxx.la src_libpqxx_la_SOURCES = \ src/array.cxx \ src/blob.cxx \ src/connection.cxx \ src/cursor.cxx \ src/encodings.cxx \ src/errorhandler.cxx \ src/except.cxx \ src/field.cxx \ src/largeobject.cxx \ src/notification.cxx \ src/params.cxx \ src/pipeline.cxx \ src/result.cxx \ src/robusttransaction.cxx \ src/sql_cursor.cxx \ src/strconv.cxx \ src/stream_from.cxx \ src/stream_to.cxx \ src/subtransaction.cxx \ src/time.cxx \ src/transaction.cxx \ src/transaction_base.cxx \ src/row.cxx \ src/types.cxx \ src/util.cxx \ src/wait.cxx libpqxx_version = -release $(PQXX_ABI) src_libpqxx_la_LDFLAGS = $(libpqxx_version) \ -rpath $(libdir) \ ${POSTGRES_LIB} test_runner_SOURCES = \ ###MAKTEMPLATE:FOREACH test/test*.cxx test/###BASENAME###.cxx \ ###MAKTEMPLATE:ENDFOREACH test/runner.cxx test_runner_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} PQXX_EXAMPLES = \ ###MAKTEMPLATE:FOREACH examples/*.cxx examples/###BASENAME### \ ###MAKTEMPLATE:ENDFOREACH # (End of list) noinst_PROGRAMS = $(PQXX_EXAMPLES) ###MAKTEMPLATE:FOREACH examples/*.cxx examples_###BASENAME###_SOURCES = examples/###BASENAME###.cxx examples_###BASENAME###_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} ###MAKTEMPLATE:ENDFOREACH TESTS = $(PQXX_TEST_PROGS) tools/lint.sh $(PQXX_EXAMPLES) check_PROGRAMS = ${PQXX_TEST_PROGS} maintainer-clean-local: $(RM) -rf doc/doxygen-html $(MKDIR) doc/doxygen-html all-local: docs if BUILD_DOCS DOXYGEN = doxygen # Doxygen config needs the source files in its local tree. That means the # build tree. If that differs from the source tree, copy the files. docs: if ! [ "$(top_srcdir)/src" -ef src ]; \ then \ cp "$(top_srcdir)"/src/*.[ch]xx src/ ; \ cp -r "$(top_srcdir)"/include/pqxx/* include/pqxx/ ; \ cp -r "$(top_srcdir)"/test test/ ; \ fi $(DOXYGEN) "$(top_srcdir)/doc/Doxyfile" else docs: endif dist-hook: if [ -d doc/doxygen-html ]; \ then \ cp -pR doc/doxygen-html $(top_distdir)/doc/html ; \ fi libpqxx-8.0.1/Makefile.in000066400000000000000000002547061516427024100152740ustar00rootroot00000000000000# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # ############################################################################## # AUTOMATICALLY GENERATED FILE -- DO NOT EDIT. # # This file is generated automatically by libpqxx's template2mak.py script, and # will be rewritten from time to time. # # If you modify this file, chances are your modifications will be lost. # # The template2mak.py script should be available in the tools directory of the # libpqxx source archive. # # Generated from template './Makefile.am.template'. # ############################################################################## # Template for generating the root Makefile.am. # # We do all the compiling from this central root-level Makefile.am, even # though the actual source files are distributed across several subdirectories. # This way we don't waste time waiting to start on the next build target while # the ongoing target is still being built in its own subdirectory. VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ noinst_PROGRAMS = $(am__EXEEXT_2) TESTS = $(am__EXEEXT_1) tools/lint.sh $(am__EXEEXT_2) check_PROGRAMS = $(am__EXEEXT_1) subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \ $(top_srcdir)/config/m4/ltoptions.m4 \ $(top_srcdir)/config/m4/ltsugar.m4 \ $(top_srcdir)/config/m4/ltversion.m4 \ $(top_srcdir)/config/m4/lt~obsolete.m4 \ $(top_srcdir)/pqxx_cxx_feature_checks.ac \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(noinst_HEADERS) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/pqxx/config.h CONFIG_CLEAN_FILES = libpqxx.pc compile_flags CONFIG_CLEAN_VPATH_FILES = am__EXEEXT_1 = test/runner$(EXEEXT) am__EXEEXT_2 = examples/complete_example$(EXEEXT) \ examples/faster_data$(EXEEXT) examples/from_readme$(EXEEXT) \ examples/getting_started_1$(EXEEXT) \ examples/getting_started_2$(EXEEXT) \ examples/quick_example$(EXEEXT) \ examples/simple_queries$(EXEEXT) PROGRAMS = $(noinst_PROGRAMS) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" LTLIBRARIES = $(lib_LTLIBRARIES) src_libpqxx_la_LIBADD = am__dirstamp = $(am__leading_dot)dirstamp am_src_libpqxx_la_OBJECTS = src/array.lo src/blob.lo src/connection.lo \ src/cursor.lo src/encodings.lo src/errorhandler.lo \ src/except.lo src/field.lo src/largeobject.lo \ src/notification.lo src/params.lo src/pipeline.lo \ src/result.lo src/robusttransaction.lo src/sql_cursor.lo \ src/strconv.lo src/stream_from.lo src/stream_to.lo \ src/subtransaction.lo src/time.lo src/transaction.lo \ src/transaction_base.lo src/row.lo src/types.lo src/util.lo \ src/wait.lo src_libpqxx_la_OBJECTS = $(am_src_libpqxx_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = src_libpqxx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(AM_CXXFLAGS) $(CXXFLAGS) $(src_libpqxx_la_LDFLAGS) \ $(LDFLAGS) -o $@ am_examples_complete_example_OBJECTS = \ examples/complete_example.$(OBJEXT) examples_complete_example_OBJECTS = \ $(am_examples_complete_example_OBJECTS) examples_complete_example_DEPENDENCIES = \ $(top_builddir)/src/libpqxx.la am_examples_faster_data_OBJECTS = examples/faster_data.$(OBJEXT) examples_faster_data_OBJECTS = $(am_examples_faster_data_OBJECTS) examples_faster_data_DEPENDENCIES = $(top_builddir)/src/libpqxx.la am_examples_from_readme_OBJECTS = examples/from_readme.$(OBJEXT) examples_from_readme_OBJECTS = $(am_examples_from_readme_OBJECTS) examples_from_readme_DEPENDENCIES = $(top_builddir)/src/libpqxx.la am_examples_getting_started_1_OBJECTS = \ examples/getting_started_1.$(OBJEXT) examples_getting_started_1_OBJECTS = \ $(am_examples_getting_started_1_OBJECTS) examples_getting_started_1_DEPENDENCIES = \ $(top_builddir)/src/libpqxx.la am_examples_getting_started_2_OBJECTS = \ examples/getting_started_2.$(OBJEXT) examples_getting_started_2_OBJECTS = \ $(am_examples_getting_started_2_OBJECTS) examples_getting_started_2_DEPENDENCIES = \ $(top_builddir)/src/libpqxx.la am_examples_quick_example_OBJECTS = examples/quick_example.$(OBJEXT) examples_quick_example_OBJECTS = $(am_examples_quick_example_OBJECTS) examples_quick_example_DEPENDENCIES = $(top_builddir)/src/libpqxx.la am_examples_simple_queries_OBJECTS = \ examples/simple_queries.$(OBJEXT) examples_simple_queries_OBJECTS = \ $(am_examples_simple_queries_OBJECTS) examples_simple_queries_DEPENDENCIES = $(top_builddir)/src/libpqxx.la am_test_runner_OBJECTS = test/test00.$(OBJEXT) test/test01.$(OBJEXT) \ test/test02.$(OBJEXT) test/test07.$(OBJEXT) \ test/test10.$(OBJEXT) test/test11.$(OBJEXT) \ test/test13.$(OBJEXT) test/test18.$(OBJEXT) \ test/test20.$(OBJEXT) test/test21.$(OBJEXT) \ test/test26.$(OBJEXT) test/test29.$(OBJEXT) \ test/test30.$(OBJEXT) test/test32.$(OBJEXT) \ test/test37.$(OBJEXT) test/test39.$(OBJEXT) \ test/test46.$(OBJEXT) test/test56.$(OBJEXT) \ test/test60.$(OBJEXT) test/test61.$(OBJEXT) \ test/test62.$(OBJEXT) test/test70.$(OBJEXT) \ test/test71.$(OBJEXT) test/test72.$(OBJEXT) \ test/test74.$(OBJEXT) test/test75.$(OBJEXT) \ test/test76.$(OBJEXT) test/test77.$(OBJEXT) \ test/test82.$(OBJEXT) test/test84.$(OBJEXT) \ test/test88.$(OBJEXT) test/test89.$(OBJEXT) \ test/test90.$(OBJEXT) test/test_array.$(OBJEXT) \ test/test_blob.$(OBJEXT) test/test_cancel_query.$(OBJEXT) \ test/test_column.$(OBJEXT) test/test_composite.$(OBJEXT) \ test/test_connection.$(OBJEXT) \ test/test_connection_string.$(OBJEXT) \ test/test_cursor.$(OBJEXT) test/test_encodings.$(OBJEXT) \ test/test_error_verbosity.$(OBJEXT) \ test/test_errorhandler.$(OBJEXT) test/test_escape.$(OBJEXT) \ test/test_exceptions.$(OBJEXT) test/test_field.$(OBJEXT) \ test/test_float.$(OBJEXT) test/test_helpers.$(OBJEXT) \ test/test_largeobject.$(OBJEXT) \ test/test_nonblocking_connect.$(OBJEXT) \ test/test_notice_handler.$(OBJEXT) \ test/test_notification.$(OBJEXT) test/test_params.$(OBJEXT) \ test/test_pipeline.$(OBJEXT) \ test/test_prepared_statement.$(OBJEXT) \ test/test_range.$(OBJEXT) test/test_read_transaction.$(OBJEXT) \ test/test_result_iteration.$(OBJEXT) test/test_row.$(OBJEXT) \ test/test_separated_list.$(OBJEXT) \ test/test_simultaneous_transactions.$(OBJEXT) \ test/test_sql_cursor.$(OBJEXT) \ test/test_stateless_cursor.$(OBJEXT) \ test/test_strconv.$(OBJEXT) test/test_stream_from.$(OBJEXT) \ test/test_stream_query.$(OBJEXT) test/test_stream_to.$(OBJEXT) \ test/test_string_conversion.$(OBJEXT) \ test/test_subtransaction.$(OBJEXT) \ test/test_thread_safety_model.$(OBJEXT) \ test/test_time.$(OBJEXT) test/test_transaction.$(OBJEXT) \ test/test_transaction_base.$(OBJEXT) \ test/test_transaction_focus.$(OBJEXT) \ test/test_transactor.$(OBJEXT) test/test_type_name.$(OBJEXT) \ test/test_util.$(OBJEXT) test/test_zview.$(OBJEXT) \ test/runner.$(OBJEXT) test_runner_OBJECTS = $(am_test_runner_OBJECTS) test_runner_DEPENDENCIES = $(top_builddir)/src/libpqxx.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = examples/$(DEPDIR)/complete_example.Po \ examples/$(DEPDIR)/faster_data.Po \ examples/$(DEPDIR)/from_readme.Po \ examples/$(DEPDIR)/getting_started_1.Po \ examples/$(DEPDIR)/getting_started_2.Po \ examples/$(DEPDIR)/quick_example.Po \ examples/$(DEPDIR)/simple_queries.Po src/$(DEPDIR)/array.Plo \ src/$(DEPDIR)/blob.Plo src/$(DEPDIR)/connection.Plo \ src/$(DEPDIR)/cursor.Plo src/$(DEPDIR)/encodings.Plo \ src/$(DEPDIR)/errorhandler.Plo src/$(DEPDIR)/except.Plo \ src/$(DEPDIR)/field.Plo src/$(DEPDIR)/largeobject.Plo \ src/$(DEPDIR)/notification.Plo src/$(DEPDIR)/params.Plo \ src/$(DEPDIR)/pipeline.Plo src/$(DEPDIR)/result.Plo \ src/$(DEPDIR)/robusttransaction.Plo src/$(DEPDIR)/row.Plo \ src/$(DEPDIR)/sql_cursor.Plo src/$(DEPDIR)/strconv.Plo \ src/$(DEPDIR)/stream_from.Plo src/$(DEPDIR)/stream_to.Plo \ src/$(DEPDIR)/subtransaction.Plo src/$(DEPDIR)/time.Plo \ src/$(DEPDIR)/transaction.Plo \ src/$(DEPDIR)/transaction_base.Plo src/$(DEPDIR)/types.Plo \ src/$(DEPDIR)/util.Plo src/$(DEPDIR)/wait.Plo \ test/$(DEPDIR)/runner.Po test/$(DEPDIR)/test00.Po \ test/$(DEPDIR)/test01.Po test/$(DEPDIR)/test02.Po \ test/$(DEPDIR)/test07.Po test/$(DEPDIR)/test10.Po \ test/$(DEPDIR)/test11.Po test/$(DEPDIR)/test13.Po \ test/$(DEPDIR)/test18.Po test/$(DEPDIR)/test20.Po \ test/$(DEPDIR)/test21.Po test/$(DEPDIR)/test26.Po \ test/$(DEPDIR)/test29.Po test/$(DEPDIR)/test30.Po \ test/$(DEPDIR)/test32.Po test/$(DEPDIR)/test37.Po \ test/$(DEPDIR)/test39.Po test/$(DEPDIR)/test46.Po \ test/$(DEPDIR)/test56.Po test/$(DEPDIR)/test60.Po \ test/$(DEPDIR)/test61.Po test/$(DEPDIR)/test62.Po \ test/$(DEPDIR)/test70.Po test/$(DEPDIR)/test71.Po \ test/$(DEPDIR)/test72.Po test/$(DEPDIR)/test74.Po \ test/$(DEPDIR)/test75.Po test/$(DEPDIR)/test76.Po \ test/$(DEPDIR)/test77.Po test/$(DEPDIR)/test82.Po \ test/$(DEPDIR)/test84.Po test/$(DEPDIR)/test88.Po \ test/$(DEPDIR)/test89.Po test/$(DEPDIR)/test90.Po \ test/$(DEPDIR)/test_array.Po test/$(DEPDIR)/test_blob.Po \ test/$(DEPDIR)/test_cancel_query.Po \ test/$(DEPDIR)/test_column.Po test/$(DEPDIR)/test_composite.Po \ test/$(DEPDIR)/test_connection.Po \ test/$(DEPDIR)/test_connection_string.Po \ test/$(DEPDIR)/test_cursor.Po test/$(DEPDIR)/test_encodings.Po \ test/$(DEPDIR)/test_error_verbosity.Po \ test/$(DEPDIR)/test_errorhandler.Po \ test/$(DEPDIR)/test_escape.Po \ test/$(DEPDIR)/test_exceptions.Po test/$(DEPDIR)/test_field.Po \ test/$(DEPDIR)/test_float.Po test/$(DEPDIR)/test_helpers.Po \ test/$(DEPDIR)/test_largeobject.Po \ test/$(DEPDIR)/test_nonblocking_connect.Po \ test/$(DEPDIR)/test_notice_handler.Po \ test/$(DEPDIR)/test_notification.Po \ test/$(DEPDIR)/test_params.Po test/$(DEPDIR)/test_pipeline.Po \ test/$(DEPDIR)/test_prepared_statement.Po \ test/$(DEPDIR)/test_range.Po \ test/$(DEPDIR)/test_read_transaction.Po \ test/$(DEPDIR)/test_result_iteration.Po \ test/$(DEPDIR)/test_row.Po \ test/$(DEPDIR)/test_separated_list.Po \ test/$(DEPDIR)/test_simultaneous_transactions.Po \ test/$(DEPDIR)/test_sql_cursor.Po \ test/$(DEPDIR)/test_stateless_cursor.Po \ test/$(DEPDIR)/test_strconv.Po \ test/$(DEPDIR)/test_stream_from.Po \ test/$(DEPDIR)/test_stream_query.Po \ test/$(DEPDIR)/test_stream_to.Po \ test/$(DEPDIR)/test_string_conversion.Po \ test/$(DEPDIR)/test_subtransaction.Po \ test/$(DEPDIR)/test_thread_safety_model.Po \ test/$(DEPDIR)/test_time.Po test/$(DEPDIR)/test_transaction.Po \ test/$(DEPDIR)/test_transaction_base.Po \ test/$(DEPDIR)/test_transaction_focus.Po \ test/$(DEPDIR)/test_transactor.Po \ test/$(DEPDIR)/test_type_name.Po test/$(DEPDIR)/test_util.Po \ test/$(DEPDIR)/test_zview.Po am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(src_libpqxx_la_SOURCES) \ $(examples_complete_example_SOURCES) \ $(examples_faster_data_SOURCES) \ $(examples_from_readme_SOURCES) \ $(examples_getting_started_1_SOURCES) \ $(examples_getting_started_2_SOURCES) \ $(examples_quick_example_SOURCES) \ $(examples_simple_queries_SOURCES) $(test_runner_SOURCES) DIST_SOURCES = $(src_libpqxx_la_SOURCES) \ $(examples_complete_example_SOURCES) \ $(examples_faster_data_SOURCES) \ $(examples_from_readme_SOURCES) \ $(examples_getting_started_1_SOURCES) \ $(examples_getting_started_2_SOURCES) \ $(examples_quick_example_SOURCES) \ $(examples_simple_queries_SOURCES) $(test_runner_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgconfig_DATA) HEADERS = $(noinst_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir distdir-am dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/compile_flags.in \ $(srcdir)/libpqxx.pc.in $(top_srcdir)/config/compile \ $(top_srcdir)/config/config.guess \ $(top_srcdir)/config/config.sub $(top_srcdir)/config/depcomp \ $(top_srcdir)/config/install-sh $(top_srcdir)/config/ltmain.sh \ $(top_srcdir)/config/missing \ $(top_srcdir)/config/mkinstalldirs \ $(top_srcdir)/include/pqxx/config.h.in AUTHORS COPYING \ ChangeLog INSTALL NEWS README README.md config/compile \ config/config.guess config/config.sub config/depcomp \ config/install-sh config/ltmain.sh config/missing \ config/mkinstalldirs DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip # Exists only to be overridden by the user if desired. AM_DISTCHECK_DVI_TARGET = dvi distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FILECMD = @FILECMD@ GREP = @GREP@ HAVE_CXX20 = @HAVE_CXX20@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR = @MKDIR@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PG_CONFIG = @PG_CONFIG@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_INCLUDE = @POSTGRES_INCLUDE@ PQXXVERSION = @PQXXVERSION@ PQXX_ABI = @PQXX_ABI@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_postgres_lib = @with_postgres_lib@ # subdir-objects: store the object files in their source file's respective # subdirectories. # # serial-tests: Use the serial test runner, so tests don't get run in parallel. # Otherwise, output from test failures will be hidden away in log files where # we can't see them when running in a build slave. AUTOMAKE_OPTIONS = subdir-objects serial-tests # We should probably get all the targets in this Makefile.am built (".") before # doing anything like installing the headers. I'm not sure it matters. SUBDIRS = . include EXTRA_DIST = autogen.sh configitems Makefile.am.template README.md VERSION \ requirements.json .clang-format .clang-tidy .cmake-format \ .inferconfig .lcovrc .lgtm.yml .lift .mdlrc .mdl_style.rb .yamllint \ doc/Doxyfile \ src/pqxx-source.hxx \ test/helpers.hxx test/sample_types.hxx \ tools/deprecations.sh \ tools/extract_version.sh \ tools/format.sh \ tools/idock.sh \ tools/install-deps.sh \ tools/lint.sh \ tools/run-test-postgres.sh \ tools/todo.sh \ tools/update-copyright.sh \ tools/check_ascii.py \ tools/compiler_flags.py \ tools/extract_version.py \ tools/filter_config.py \ tools/generate_check_config.py \ tools/generate_cxx_checks.py \ tools/m4esc.py \ tools/template2mak.py \ config/flags/audit-mode.txt \ config/flags/maintainer-mode.txt \ config/flags/suggest-mode.txt \ # (End of list) noinst_HEADERS = test/helpers.hxx DISTCLEANFILES = include/pqxx/config-compiler.h MAINTAINERCLEANFILES = \ Makefile.in aclocal.m4 config.h.in config.log configure stamp-h.in \ config/config.guess config/config.sub config/install-sh config/ltmain.sh \ config/missing config/mkinstalldirs \ include/pqxx/Makefile.in include/pqxx/stamp-h.in pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libpqxx.pc PQXX_TEST_PROGS = test/runner AM_CPPFLAGS = \ -I$(top_srcdir)/include -I$(top_builddir)/include ${POSTGRES_INCLUDE} # Override automatically generated list of default includes. It contains only # unnecessary entries, and incorrectly mentions include/pqxx directly. DEFAULT_INCLUDES = lib_LTLIBRARIES = src/libpqxx.la src_libpqxx_la_SOURCES = \ src/array.cxx \ src/blob.cxx \ src/connection.cxx \ src/cursor.cxx \ src/encodings.cxx \ src/errorhandler.cxx \ src/except.cxx \ src/field.cxx \ src/largeobject.cxx \ src/notification.cxx \ src/params.cxx \ src/pipeline.cxx \ src/result.cxx \ src/robusttransaction.cxx \ src/sql_cursor.cxx \ src/strconv.cxx \ src/stream_from.cxx \ src/stream_to.cxx \ src/subtransaction.cxx \ src/time.cxx \ src/transaction.cxx \ src/transaction_base.cxx \ src/row.cxx \ src/types.cxx \ src/util.cxx \ src/wait.cxx libpqxx_version = -release $(PQXX_ABI) src_libpqxx_la_LDFLAGS = $(libpqxx_version) \ -rpath $(libdir) \ ${POSTGRES_LIB} test_runner_SOURCES = \ test/test00.cxx \ test/test01.cxx \ test/test02.cxx \ test/test07.cxx \ test/test10.cxx \ test/test11.cxx \ test/test13.cxx \ test/test18.cxx \ test/test20.cxx \ test/test21.cxx \ test/test26.cxx \ test/test29.cxx \ test/test30.cxx \ test/test32.cxx \ test/test37.cxx \ test/test39.cxx \ test/test46.cxx \ test/test56.cxx \ test/test60.cxx \ test/test61.cxx \ test/test62.cxx \ test/test70.cxx \ test/test71.cxx \ test/test72.cxx \ test/test74.cxx \ test/test75.cxx \ test/test76.cxx \ test/test77.cxx \ test/test82.cxx \ test/test84.cxx \ test/test88.cxx \ test/test89.cxx \ test/test90.cxx \ test/test_array.cxx \ test/test_blob.cxx \ test/test_cancel_query.cxx \ test/test_column.cxx \ test/test_composite.cxx \ test/test_connection.cxx \ test/test_connection_string.cxx \ test/test_cursor.cxx \ test/test_encodings.cxx \ test/test_error_verbosity.cxx \ test/test_errorhandler.cxx \ test/test_escape.cxx \ test/test_exceptions.cxx \ test/test_field.cxx \ test/test_float.cxx \ test/test_helpers.cxx \ test/test_largeobject.cxx \ test/test_nonblocking_connect.cxx \ test/test_notice_handler.cxx \ test/test_notification.cxx \ test/test_params.cxx \ test/test_pipeline.cxx \ test/test_prepared_statement.cxx \ test/test_range.cxx \ test/test_read_transaction.cxx \ test/test_result_iteration.cxx \ test/test_row.cxx \ test/test_separated_list.cxx \ test/test_simultaneous_transactions.cxx \ test/test_sql_cursor.cxx \ test/test_stateless_cursor.cxx \ test/test_strconv.cxx \ test/test_stream_from.cxx \ test/test_stream_query.cxx \ test/test_stream_to.cxx \ test/test_string_conversion.cxx \ test/test_subtransaction.cxx \ test/test_thread_safety_model.cxx \ test/test_time.cxx \ test/test_transaction.cxx \ test/test_transaction_base.cxx \ test/test_transaction_focus.cxx \ test/test_transactor.cxx \ test/test_type_name.cxx \ test/test_util.cxx \ test/test_zview.cxx \ test/runner.cxx test_runner_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} PQXX_EXAMPLES = \ examples/complete_example \ examples/faster_data \ examples/from_readme \ examples/getting_started_1 \ examples/getting_started_2 \ examples/quick_example \ examples/simple_queries \ # (End of list) examples_complete_example_SOURCES = examples/complete_example.cxx examples_complete_example_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} examples_faster_data_SOURCES = examples/faster_data.cxx examples_faster_data_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} examples_from_readme_SOURCES = examples/from_readme.cxx examples_from_readme_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} examples_getting_started_1_SOURCES = examples/getting_started_1.cxx examples_getting_started_1_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} examples_getting_started_2_SOURCES = examples/getting_started_2.cxx examples_getting_started_2_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} examples_quick_example_SOURCES = examples/quick_example.cxx examples_quick_example_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} examples_simple_queries_SOURCES = examples/simple_queries.cxx examples_simple_queries_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} @BUILD_DOCS_TRUE@DOXYGEN = doxygen all: all-recursive .SUFFIXES: .SUFFIXES: .cxx .lo .o .obj am--refresh: Makefile @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): include/pqxx/config.h: include/pqxx/stamp-h1 @test -f $@ || rm -f include/pqxx/stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) include/pqxx/stamp-h1 include/pqxx/stamp-h1: $(top_srcdir)/include/pqxx/config.h.in $(top_builddir)/config.status @rm -f include/pqxx/stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status include/pqxx/config.h $(top_srcdir)/include/pqxx/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f include/pqxx/stamp-h1 touch $@ distclean-hdr: -rm -f include/pqxx/config.h include/pqxx/stamp-h1 libpqxx.pc: $(top_builddir)/config.status $(srcdir)/libpqxx.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ compile_flags: $(top_builddir)/config.status $(srcdir)/compile_flags.in cd $(top_builddir) && $(SHELL) ./config.status $@ clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } src/$(am__dirstamp): @$(MKDIR_P) src @: > src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/$(DEPDIR) @: > src/$(DEPDIR)/$(am__dirstamp) src/array.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/blob.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/connection.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/cursor.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/encodings.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/errorhandler.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/except.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/field.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/largeobject.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/notification.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/params.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/pipeline.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/result.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/robusttransaction.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/sql_cursor.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/strconv.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/stream_from.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/stream_to.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/subtransaction.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/time.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/transaction.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/transaction_base.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/row.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/types.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/util.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/wait.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/libpqxx.la: $(src_libpqxx_la_OBJECTS) $(src_libpqxx_la_DEPENDENCIES) $(EXTRA_src_libpqxx_la_DEPENDENCIES) src/$(am__dirstamp) $(AM_V_CXXLD)$(src_libpqxx_la_LINK) -rpath $(libdir) $(src_libpqxx_la_OBJECTS) $(src_libpqxx_la_LIBADD) $(LIBS) examples/$(am__dirstamp): @$(MKDIR_P) examples @: > examples/$(am__dirstamp) examples/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) examples/$(DEPDIR) @: > examples/$(DEPDIR)/$(am__dirstamp) examples/complete_example.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/complete_example$(EXEEXT): $(examples_complete_example_OBJECTS) $(examples_complete_example_DEPENDENCIES) $(EXTRA_examples_complete_example_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/complete_example$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(examples_complete_example_OBJECTS) $(examples_complete_example_LDADD) $(LIBS) examples/faster_data.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/faster_data$(EXEEXT): $(examples_faster_data_OBJECTS) $(examples_faster_data_DEPENDENCIES) $(EXTRA_examples_faster_data_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/faster_data$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(examples_faster_data_OBJECTS) $(examples_faster_data_LDADD) $(LIBS) examples/from_readme.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/from_readme$(EXEEXT): $(examples_from_readme_OBJECTS) $(examples_from_readme_DEPENDENCIES) $(EXTRA_examples_from_readme_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/from_readme$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(examples_from_readme_OBJECTS) $(examples_from_readme_LDADD) $(LIBS) examples/getting_started_1.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/getting_started_1$(EXEEXT): $(examples_getting_started_1_OBJECTS) $(examples_getting_started_1_DEPENDENCIES) $(EXTRA_examples_getting_started_1_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/getting_started_1$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(examples_getting_started_1_OBJECTS) $(examples_getting_started_1_LDADD) $(LIBS) examples/getting_started_2.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/getting_started_2$(EXEEXT): $(examples_getting_started_2_OBJECTS) $(examples_getting_started_2_DEPENDENCIES) $(EXTRA_examples_getting_started_2_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/getting_started_2$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(examples_getting_started_2_OBJECTS) $(examples_getting_started_2_LDADD) $(LIBS) examples/quick_example.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/quick_example$(EXEEXT): $(examples_quick_example_OBJECTS) $(examples_quick_example_DEPENDENCIES) $(EXTRA_examples_quick_example_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/quick_example$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(examples_quick_example_OBJECTS) $(examples_quick_example_LDADD) $(LIBS) examples/simple_queries.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/simple_queries$(EXEEXT): $(examples_simple_queries_OBJECTS) $(examples_simple_queries_DEPENDENCIES) $(EXTRA_examples_simple_queries_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/simple_queries$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(examples_simple_queries_OBJECTS) $(examples_simple_queries_LDADD) $(LIBS) test/$(am__dirstamp): @$(MKDIR_P) test @: > test/$(am__dirstamp) test/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) test/$(DEPDIR) @: > test/$(DEPDIR)/$(am__dirstamp) test/test00.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test01.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test02.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test07.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test10.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test11.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test13.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test18.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test20.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test21.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test26.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test29.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test30.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test32.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test37.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test39.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test46.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test56.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test60.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test61.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test62.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test70.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test71.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test72.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test74.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test75.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test76.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test77.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test82.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test84.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test88.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test89.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test90.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_array.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_blob.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_cancel_query.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_column.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_composite.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_connection.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_connection_string.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_cursor.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_encodings.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_error_verbosity.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_errorhandler.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_escape.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_exceptions.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_field.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_float.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_helpers.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_largeobject.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_nonblocking_connect.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_notice_handler.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_notification.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_params.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_pipeline.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_prepared_statement.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_range.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_read_transaction.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_result_iteration.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_row.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_separated_list.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_simultaneous_transactions.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_sql_cursor.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_stateless_cursor.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_strconv.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_stream_from.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_stream_query.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_stream_to.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_string_conversion.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_subtransaction.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_thread_safety_model.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_time.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_transaction.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_transaction_base.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_transaction_focus.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_transactor.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_type_name.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_util.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/test_zview.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/runner.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/runner$(EXEEXT): $(test_runner_OBJECTS) $(test_runner_DEPENDENCIES) $(EXTRA_test_runner_DEPENDENCIES) test/$(am__dirstamp) @rm -f test/runner$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(test_runner_OBJECTS) $(test_runner_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f examples/*.$(OBJEXT) -rm -f src/*.$(OBJEXT) -rm -f src/*.lo -rm -f test/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/complete_example.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/faster_data.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/from_readme.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/getting_started_1.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/getting_started_2.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/quick_example.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/simple_queries.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/array.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/blob.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/connection.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/cursor.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/encodings.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/errorhandler.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/except.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/field.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/largeobject.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/notification.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/params.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pipeline.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/result.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/robusttransaction.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/row.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/sql_cursor.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/strconv.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/stream_from.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/stream_to.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/subtransaction.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/time.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/transaction.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/transaction_base.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/types.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/util.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/wait.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/runner.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test00.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test01.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test02.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test07.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test10.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test11.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test13.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test18.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test20.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test21.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test26.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test29.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test30.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test32.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test37.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test39.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test46.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test56.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test60.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test61.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test62.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test70.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test71.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test72.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test74.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test75.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test76.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test77.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test82.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test84.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test88.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test89.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test90.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_array.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_blob.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_cancel_query.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_column.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_composite.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_connection.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_connection_string.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_cursor.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_encodings.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_error_verbosity.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_errorhandler.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_escape.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_exceptions.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_field.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_float.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_helpers.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_largeobject.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_nonblocking_connect.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_notice_handler.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_notification.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_params.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_pipeline.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_prepared_statement.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_range.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_read_transaction.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_result_iteration.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_row.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_separated_list.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_simultaneous_transactions.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_sql_cursor.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_stateless_cursor.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_strconv.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_stream_from.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_stream_query.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_stream_to.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_string_conversion.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_subtransaction.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_thread_safety_model.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_time.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_transaction.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_transaction_base.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_transaction_focus.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_transactor.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_type_name.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_util.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/test_zview.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .cxx.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cxx.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cxx.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf examples/.libs examples/_libs -rm -rf src/.libs src/_libs -rm -rf test/.libs test/_libs distclean-libtool: -rm -f libtool config.lt install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ done uninstall-pkgconfigDATA: @$(NORMAL_UNINSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files check-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list=' $(TESTS) '; \ $(am__tty_colors); \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ col=$$red; res=XPASS; \ ;; \ *) \ col=$$grn; res=PASS; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xfail=`expr $$xfail + 1`; \ col=$$lgn; res=XFAIL; \ ;; \ *) \ failed=`expr $$failed + 1`; \ col=$$red; res=FAIL; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ col=$$blu; res=SKIP; \ fi; \ echo "$${col}$$res$${std}: $$tst"; \ done; \ if test "$$all" -eq 1; then \ tests="test"; \ All=""; \ else \ tests="tests"; \ All="All "; \ fi; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="$$All$$all $$tests passed"; \ else \ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all $$tests failed"; \ else \ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ if test "$$skip" -eq 1; then \ skipped="($$skip test was not run)"; \ else \ skipped="($$skip tests were not run)"; \ fi; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ if test "$$failed" -eq 0; then \ col="$$grn"; \ else \ col="$$red"; \ fi; \ echo "$${col}$$dashes$${std}"; \ echo "$${col}$$banner$${std}"; \ test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ test -z "$$report" || echo "$${col}$$report$${std}"; \ echo "$${col}$$dashes$${std}"; \ test "$$failed" -eq 0; \ else :; fi distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-zstd: distdir tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ *.tar.zst*) \ zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-recursive all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(DATA) $(HEADERS) \ all-local install-checkPROGRAMS: install-libLTLIBRARIES installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f examples/$(DEPDIR)/$(am__dirstamp) -rm -f examples/$(am__dirstamp) -rm -f src/$(DEPDIR)/$(am__dirstamp) -rm -f src/$(am__dirstamp) -rm -f test/$(DEPDIR)/$(am__dirstamp) -rm -f test/$(am__dirstamp) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-recursive clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool clean-noinstPROGRAMS mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f examples/$(DEPDIR)/complete_example.Po -rm -f examples/$(DEPDIR)/faster_data.Po -rm -f examples/$(DEPDIR)/from_readme.Po -rm -f examples/$(DEPDIR)/getting_started_1.Po -rm -f examples/$(DEPDIR)/getting_started_2.Po -rm -f examples/$(DEPDIR)/quick_example.Po -rm -f examples/$(DEPDIR)/simple_queries.Po -rm -f src/$(DEPDIR)/array.Plo -rm -f src/$(DEPDIR)/blob.Plo -rm -f src/$(DEPDIR)/connection.Plo -rm -f src/$(DEPDIR)/cursor.Plo -rm -f src/$(DEPDIR)/encodings.Plo -rm -f src/$(DEPDIR)/errorhandler.Plo -rm -f src/$(DEPDIR)/except.Plo -rm -f src/$(DEPDIR)/field.Plo -rm -f src/$(DEPDIR)/largeobject.Plo -rm -f src/$(DEPDIR)/notification.Plo -rm -f src/$(DEPDIR)/params.Plo -rm -f src/$(DEPDIR)/pipeline.Plo -rm -f src/$(DEPDIR)/result.Plo -rm -f src/$(DEPDIR)/robusttransaction.Plo -rm -f src/$(DEPDIR)/row.Plo -rm -f src/$(DEPDIR)/sql_cursor.Plo -rm -f src/$(DEPDIR)/strconv.Plo -rm -f src/$(DEPDIR)/stream_from.Plo -rm -f src/$(DEPDIR)/stream_to.Plo -rm -f src/$(DEPDIR)/subtransaction.Plo -rm -f src/$(DEPDIR)/time.Plo -rm -f src/$(DEPDIR)/transaction.Plo -rm -f src/$(DEPDIR)/transaction_base.Plo -rm -f src/$(DEPDIR)/types.Plo -rm -f src/$(DEPDIR)/util.Plo -rm -f src/$(DEPDIR)/wait.Plo -rm -f test/$(DEPDIR)/runner.Po -rm -f test/$(DEPDIR)/test00.Po -rm -f test/$(DEPDIR)/test01.Po -rm -f test/$(DEPDIR)/test02.Po -rm -f test/$(DEPDIR)/test07.Po -rm -f test/$(DEPDIR)/test10.Po -rm -f test/$(DEPDIR)/test11.Po -rm -f test/$(DEPDIR)/test13.Po -rm -f test/$(DEPDIR)/test18.Po -rm -f test/$(DEPDIR)/test20.Po -rm -f test/$(DEPDIR)/test21.Po -rm -f test/$(DEPDIR)/test26.Po -rm -f test/$(DEPDIR)/test29.Po -rm -f test/$(DEPDIR)/test30.Po -rm -f test/$(DEPDIR)/test32.Po -rm -f test/$(DEPDIR)/test37.Po -rm -f test/$(DEPDIR)/test39.Po -rm -f test/$(DEPDIR)/test46.Po -rm -f test/$(DEPDIR)/test56.Po -rm -f test/$(DEPDIR)/test60.Po -rm -f test/$(DEPDIR)/test61.Po -rm -f test/$(DEPDIR)/test62.Po -rm -f test/$(DEPDIR)/test70.Po -rm -f test/$(DEPDIR)/test71.Po -rm -f test/$(DEPDIR)/test72.Po -rm -f test/$(DEPDIR)/test74.Po -rm -f test/$(DEPDIR)/test75.Po -rm -f test/$(DEPDIR)/test76.Po -rm -f test/$(DEPDIR)/test77.Po -rm -f test/$(DEPDIR)/test82.Po -rm -f test/$(DEPDIR)/test84.Po -rm -f test/$(DEPDIR)/test88.Po -rm -f test/$(DEPDIR)/test89.Po -rm -f test/$(DEPDIR)/test90.Po -rm -f test/$(DEPDIR)/test_array.Po -rm -f test/$(DEPDIR)/test_blob.Po -rm -f test/$(DEPDIR)/test_cancel_query.Po -rm -f test/$(DEPDIR)/test_column.Po -rm -f test/$(DEPDIR)/test_composite.Po -rm -f test/$(DEPDIR)/test_connection.Po -rm -f test/$(DEPDIR)/test_connection_string.Po -rm -f test/$(DEPDIR)/test_cursor.Po -rm -f test/$(DEPDIR)/test_encodings.Po -rm -f test/$(DEPDIR)/test_error_verbosity.Po -rm -f test/$(DEPDIR)/test_errorhandler.Po -rm -f test/$(DEPDIR)/test_escape.Po -rm -f test/$(DEPDIR)/test_exceptions.Po -rm -f test/$(DEPDIR)/test_field.Po -rm -f test/$(DEPDIR)/test_float.Po -rm -f test/$(DEPDIR)/test_helpers.Po -rm -f test/$(DEPDIR)/test_largeobject.Po -rm -f test/$(DEPDIR)/test_nonblocking_connect.Po -rm -f test/$(DEPDIR)/test_notice_handler.Po -rm -f test/$(DEPDIR)/test_notification.Po -rm -f test/$(DEPDIR)/test_params.Po -rm -f test/$(DEPDIR)/test_pipeline.Po -rm -f test/$(DEPDIR)/test_prepared_statement.Po -rm -f test/$(DEPDIR)/test_range.Po -rm -f test/$(DEPDIR)/test_read_transaction.Po -rm -f test/$(DEPDIR)/test_result_iteration.Po -rm -f test/$(DEPDIR)/test_row.Po -rm -f test/$(DEPDIR)/test_separated_list.Po -rm -f test/$(DEPDIR)/test_simultaneous_transactions.Po -rm -f test/$(DEPDIR)/test_sql_cursor.Po -rm -f test/$(DEPDIR)/test_stateless_cursor.Po -rm -f test/$(DEPDIR)/test_strconv.Po -rm -f test/$(DEPDIR)/test_stream_from.Po -rm -f test/$(DEPDIR)/test_stream_query.Po -rm -f test/$(DEPDIR)/test_stream_to.Po -rm -f test/$(DEPDIR)/test_string_conversion.Po -rm -f test/$(DEPDIR)/test_subtransaction.Po -rm -f test/$(DEPDIR)/test_thread_safety_model.Po -rm -f test/$(DEPDIR)/test_time.Po -rm -f test/$(DEPDIR)/test_transaction.Po -rm -f test/$(DEPDIR)/test_transaction_base.Po -rm -f test/$(DEPDIR)/test_transaction_focus.Po -rm -f test/$(DEPDIR)/test_transactor.Po -rm -f test/$(DEPDIR)/test_type_name.Po -rm -f test/$(DEPDIR)/test_util.Po -rm -f test/$(DEPDIR)/test_zview.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-libtool distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-pkgconfigDATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f examples/$(DEPDIR)/complete_example.Po -rm -f examples/$(DEPDIR)/faster_data.Po -rm -f examples/$(DEPDIR)/from_readme.Po -rm -f examples/$(DEPDIR)/getting_started_1.Po -rm -f examples/$(DEPDIR)/getting_started_2.Po -rm -f examples/$(DEPDIR)/quick_example.Po -rm -f examples/$(DEPDIR)/simple_queries.Po -rm -f src/$(DEPDIR)/array.Plo -rm -f src/$(DEPDIR)/blob.Plo -rm -f src/$(DEPDIR)/connection.Plo -rm -f src/$(DEPDIR)/cursor.Plo -rm -f src/$(DEPDIR)/encodings.Plo -rm -f src/$(DEPDIR)/errorhandler.Plo -rm -f src/$(DEPDIR)/except.Plo -rm -f src/$(DEPDIR)/field.Plo -rm -f src/$(DEPDIR)/largeobject.Plo -rm -f src/$(DEPDIR)/notification.Plo -rm -f src/$(DEPDIR)/params.Plo -rm -f src/$(DEPDIR)/pipeline.Plo -rm -f src/$(DEPDIR)/result.Plo -rm -f src/$(DEPDIR)/robusttransaction.Plo -rm -f src/$(DEPDIR)/row.Plo -rm -f src/$(DEPDIR)/sql_cursor.Plo -rm -f src/$(DEPDIR)/strconv.Plo -rm -f src/$(DEPDIR)/stream_from.Plo -rm -f src/$(DEPDIR)/stream_to.Plo -rm -f src/$(DEPDIR)/subtransaction.Plo -rm -f src/$(DEPDIR)/time.Plo -rm -f src/$(DEPDIR)/transaction.Plo -rm -f src/$(DEPDIR)/transaction_base.Plo -rm -f src/$(DEPDIR)/types.Plo -rm -f src/$(DEPDIR)/util.Plo -rm -f src/$(DEPDIR)/wait.Plo -rm -f test/$(DEPDIR)/runner.Po -rm -f test/$(DEPDIR)/test00.Po -rm -f test/$(DEPDIR)/test01.Po -rm -f test/$(DEPDIR)/test02.Po -rm -f test/$(DEPDIR)/test07.Po -rm -f test/$(DEPDIR)/test10.Po -rm -f test/$(DEPDIR)/test11.Po -rm -f test/$(DEPDIR)/test13.Po -rm -f test/$(DEPDIR)/test18.Po -rm -f test/$(DEPDIR)/test20.Po -rm -f test/$(DEPDIR)/test21.Po -rm -f test/$(DEPDIR)/test26.Po -rm -f test/$(DEPDIR)/test29.Po -rm -f test/$(DEPDIR)/test30.Po -rm -f test/$(DEPDIR)/test32.Po -rm -f test/$(DEPDIR)/test37.Po -rm -f test/$(DEPDIR)/test39.Po -rm -f test/$(DEPDIR)/test46.Po -rm -f test/$(DEPDIR)/test56.Po -rm -f test/$(DEPDIR)/test60.Po -rm -f test/$(DEPDIR)/test61.Po -rm -f test/$(DEPDIR)/test62.Po -rm -f test/$(DEPDIR)/test70.Po -rm -f test/$(DEPDIR)/test71.Po -rm -f test/$(DEPDIR)/test72.Po -rm -f test/$(DEPDIR)/test74.Po -rm -f test/$(DEPDIR)/test75.Po -rm -f test/$(DEPDIR)/test76.Po -rm -f test/$(DEPDIR)/test77.Po -rm -f test/$(DEPDIR)/test82.Po -rm -f test/$(DEPDIR)/test84.Po -rm -f test/$(DEPDIR)/test88.Po -rm -f test/$(DEPDIR)/test89.Po -rm -f test/$(DEPDIR)/test90.Po -rm -f test/$(DEPDIR)/test_array.Po -rm -f test/$(DEPDIR)/test_blob.Po -rm -f test/$(DEPDIR)/test_cancel_query.Po -rm -f test/$(DEPDIR)/test_column.Po -rm -f test/$(DEPDIR)/test_composite.Po -rm -f test/$(DEPDIR)/test_connection.Po -rm -f test/$(DEPDIR)/test_connection_string.Po -rm -f test/$(DEPDIR)/test_cursor.Po -rm -f test/$(DEPDIR)/test_encodings.Po -rm -f test/$(DEPDIR)/test_error_verbosity.Po -rm -f test/$(DEPDIR)/test_errorhandler.Po -rm -f test/$(DEPDIR)/test_escape.Po -rm -f test/$(DEPDIR)/test_exceptions.Po -rm -f test/$(DEPDIR)/test_field.Po -rm -f test/$(DEPDIR)/test_float.Po -rm -f test/$(DEPDIR)/test_helpers.Po -rm -f test/$(DEPDIR)/test_largeobject.Po -rm -f test/$(DEPDIR)/test_nonblocking_connect.Po -rm -f test/$(DEPDIR)/test_notice_handler.Po -rm -f test/$(DEPDIR)/test_notification.Po -rm -f test/$(DEPDIR)/test_params.Po -rm -f test/$(DEPDIR)/test_pipeline.Po -rm -f test/$(DEPDIR)/test_prepared_statement.Po -rm -f test/$(DEPDIR)/test_range.Po -rm -f test/$(DEPDIR)/test_read_transaction.Po -rm -f test/$(DEPDIR)/test_result_iteration.Po -rm -f test/$(DEPDIR)/test_row.Po -rm -f test/$(DEPDIR)/test_separated_list.Po -rm -f test/$(DEPDIR)/test_simultaneous_transactions.Po -rm -f test/$(DEPDIR)/test_sql_cursor.Po -rm -f test/$(DEPDIR)/test_stateless_cursor.Po -rm -f test/$(DEPDIR)/test_strconv.Po -rm -f test/$(DEPDIR)/test_stream_from.Po -rm -f test/$(DEPDIR)/test_stream_query.Po -rm -f test/$(DEPDIR)/test_stream_to.Po -rm -f test/$(DEPDIR)/test_string_conversion.Po -rm -f test/$(DEPDIR)/test_subtransaction.Po -rm -f test/$(DEPDIR)/test_thread_safety_model.Po -rm -f test/$(DEPDIR)/test_time.Po -rm -f test/$(DEPDIR)/test_transaction.Po -rm -f test/$(DEPDIR)/test_transaction_base.Po -rm -f test/$(DEPDIR)/test_transaction_focus.Po -rm -f test/$(DEPDIR)/test_transactor.Po -rm -f test/$(DEPDIR)/test_type_name.Po -rm -f test/$(DEPDIR)/test_util.Po -rm -f test/$(DEPDIR)/test_zview.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic \ maintainer-clean-local mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-libLTLIBRARIES uninstall-pkgconfigDATA .MAKE: $(am__recursive_targets) check-am install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am all-local \ am--depfiles am--refresh check check-TESTS check-am clean \ clean-checkPROGRAMS clean-cscope clean-generic \ clean-libLTLIBRARIES clean-libtool clean-noinstPROGRAMS cscope \ cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ dist-gzip dist-hook dist-lzip dist-shar dist-tarZ dist-xz \ dist-zip dist-zstd distcheck distclean distclean-compile \ distclean-generic distclean-hdr distclean-libtool \ distclean-tags distcleancheck distdir distuninstallcheck dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-man install-pdf install-pdf-am install-pkgconfigDATA \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic maintainer-clean-local mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-libLTLIBRARIES uninstall-pkgconfigDATA .PRECIOUS: Makefile # We use README.md, but automake expects plain README. README: README.md ln -s $< $@ maintainer-clean-local: $(RM) -rf doc/doxygen-html $(MKDIR) doc/doxygen-html all-local: docs # Doxygen config needs the source files in its local tree. That means the # build tree. If that differs from the source tree, copy the files. @BUILD_DOCS_TRUE@docs: @BUILD_DOCS_TRUE@ if ! [ "$(top_srcdir)/src" -ef src ]; \ @BUILD_DOCS_TRUE@ then \ @BUILD_DOCS_TRUE@ cp "$(top_srcdir)"/src/*.[ch]xx src/ ; \ @BUILD_DOCS_TRUE@ cp -r "$(top_srcdir)"/include/pqxx/* include/pqxx/ ; \ @BUILD_DOCS_TRUE@ cp -r "$(top_srcdir)"/test test/ ; \ @BUILD_DOCS_TRUE@ fi @BUILD_DOCS_TRUE@ $(DOXYGEN) "$(top_srcdir)/doc/Doxyfile" @BUILD_DOCS_FALSE@docs: dist-hook: if [ -d doc/doxygen-html ]; \ then \ cp -pR doc/doxygen-html $(top_distdir)/doc/html ; \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: libpqxx-8.0.1/NEWS000066400000000000000000001760301516427024100137170ustar00rootroot000000000000008.0.1 - A lot more constructors are now `explicit`. - Update GNU attributes to use standard `[[attribute]]` syntax. (#1199) - Fix mistake in check for GNU "pure" attribute. - Fix potential 1-byte buffer overrun in `stream_to`. (#1203) 8.0.0 - C++20 is now the oldest C++ version that libpqxx supports. - Requires PostgreSQL 11 or better. - **Exception class hierarchy has changed.** See `UPGRADING.md`. - **Result/row iterators have changed.** Instead of `i[n]` do `(*i)[n]`. - **Result equality now only compares identity, not the data inside.** - **Row/field equality now only compares identity, not the data inside.** - **Row/field lifetimes have changed: see `row_ref` and `field_ref`.** - **`pqxx::bytes` is now a vector of bytes, not a string of bytes.** (#924) - All libpqxx exceptions are now derived from `pqxx::failure`. - Libpqxx exceptions now have a C++26 `std::stacktrace`, if available. - Use `pqxx::bytes::data()` instead of `pqxx::bytes::c_str()`. - The string conversion API has changed! (Old API should still work). (#948) - "String conversion" to `std::string_view` etc. is now supported. (#694) - Simpler to use: `pqxx::from_string()`, `pqxx::to_buf()`, `pqxx::into_buf()`. - `to_buf()` and `into_buf()` functions will no longer zero-terminate. - **Beware lifetime** when "converting" a string to `std::string_view`! - Binary data can be any `std::contiguous_range` of `std::byte`. (#925) - Generic `quote()` takes `always_null` into account. - You can now convert strings to `pqxx::array` types. - You can now parse SQL arrays straight into `std::vector` and such. - There are fewer raw pointers in the API, for safety & verifiability. - The libpqxx exceptions now have a `std::source_location`. (#923) - Result & row iterators are now proper random access iterators. - More getters are now `noexcept`. - Retired `binarystring` and its headers. Use `blob` instead. - Retired `connection_base` type alias. Use `connection`. - Retired `pqxx::encrypt_password()`. Use the ones in `pqxx::connection`. - Retired `pqxx::prepare::dynamic_params`. Use `pqxx::params`. - Retired deprecated `stream_to` constructors. Use factory functions. - Retired `transaction_base::unesc_raw()`. Use `unesc_bin()`. - Retired `transaction_base::quote_raw()`. Use `quote()` with `bytes_view`. - Deprecated `field` constructors are no longer publicly accessible. - Assume compiler supports concepts. - Assume compiler supports integral conversions in `charconv`. - Assume compiler supports spans, ranges, and `cmp_less` etc. - Retired result row slicing. - Assume compiler supports `std::remove_cvref_t` etc. - Assume compiler supports `[[likely]]` & `[[unlikely]]`. - Assume compiler supports `ssize()`. - Assume compiler supports `std::source_location`. - Assume compiler supports ISO-646 without needing `` header. - Feel free to use `pqxx::encoding_group`. It's no longer "internal." - There's now an `unknown` encoding group. It's the only fully safe default. - Dropping JOHAB encoding. Never fully worked on the server anyway. - Array parsing will refuse to work if the encoding group is `UNKNOWN`. - You can now combine connection string & option pairs on connections! (#1133) - Encodings support code got smaller, simpler, more efficient. - Tests are now in a single directory (#934) - Added an "examples" directory: tested, maintained sample code. - `check_cast()` supports infinities and NaNs. - Now supporting CMake "unity builds." - Stop trying to figure out link options for filesystem library. - You can now set `PQXX_LINT=skip` to skip lint checks during test build. - Header/binary version compatibility check now tolerates patch upgrades. - New helper functions to query a type's nullness properties. - More SQL statements can now be `std::string_view` instead of `pqxx::zview`. - Work around broken multidim `operator[]` support in MSVC 2022. - Build fix for MSVC 2026. (#1160) - Nicer replacement for `pqxx::connection::port()`: `port_number()`. - `pqxx::out_of_memory` is now `pqxx::server_out_of_memory` for clarity. - `pqxx::protocol_violation` is now an `sql_error`, not a `broken_connection`. - Use C++26 reflection, if available, for finding types' names. - Export `source_loc()` function: render a `std::source_location` into text. - Allow tests to run even on ASCII-only databases. - `composite_into_buf()` now returns a `zview`. - Optionally pass `encoding_group` (or connection/transaction) into `params`. - `pqxx::zview` no longer accepts null pointer. - `pqxx::zview` is now `final`. - Replace all generated config headers with just `config-compiler.h`. (#1152) - CMake build now filters `config-compiler.h`, like the autotools build does. - For `stream()`, a type must be convertible and move-constructible. (#1168) - Build defaults to C++20 minimum. - Deprecated `extract_version.sh`; use `extract_version.py`. - Retired tools: `rmlo`, `pqxxthreadsafety`, `test_all.py`. - Shell scripts now have "`.sh`" suffix. Saves hand-coding names. 7.10.5 - Fix missing types in Doxygen docs (by downgrading Doxygen :-/ ). - Tweak `README.md`. (#1111) - Skip YAML lint checks; it's all fixed up in the 8.0 release branch. 7.10.4 - Logic for controlling non-blocking mode was inverted (non-Windows). (#1057) - Pass SQL error code when throwing `pqxx::insufficient_privilege`. (#1077) - Deprecated the unnamed prepared statement. 7.10.3 - Fix Microsoft Visual Studio C++17 build. (#1036, #1037) - Run Appveyor & CircleCI tests against multiple C++ versions at once. 7.10.2 - CMake: Drop unneeded, broken `PostgreSQL_INCLUDE_DIRS` definition. (#981) - Handle spaces and single quotes in `connection::connection_string()` (#992) - _I said,_ can't pass parameters to streaming query. Remove support. (#997) - Fix pkgconfig for static linkage; use config module `libpq`. (#999) - Made `row::as_tuple()` public. (#1003) - Avoid garbage at end of demangled names. (#1007) - Fix build when `std::free` is not `noexcept`, such as Mac. (#1010) - Document: generally `pqxx::type_name` should be a `std::string_view`. (#1009) - Fix float-to-text conversion workaround when `charconv` is missing. - Fix `result::affected_rows()` for empty results. (#1018) - Fix error message in `result::expect_columns()`. (#1020) - Fix for compilers that support concepts but not ranges. (#1017) - Avoid deprecation warning for ``. (#1023) 7.10.1 - Fix string conversion buffer budget for arrays containing nulls. (#921) - Remove `-fanalyzer` option again; gcc is still broken. - Oops, no, minimum CMake version is not 3.28, but 3.12! - Fix warnings on compilers that accept `[[assume]]` with a warning. (#928) - Can't pass parameters to streaming query. - CMake build: take libpq path from build target, not absolute path. (#964) - Added explanation to `listen()` of when notifications come in. (#963) 7.10.0 - Deprecate `errorhandler`; replace with lambda-friendly "notice handlers." - Deprecate `notification_receiver`; replace with "notification handlers" - Bump minimum CMake version to 3.12. (#851, #874) - Fixed error message on clashing transaction focuses. (#879) - Don't call`/bin/true`; macOS doesn't have it. Just call `true`. (#885) - Deprecate `exec_prepared()`; just use `exec()` with a `pqxx::prepped`. - Deprecate `exec1()` etc. Use `result::expect_rows()` etc. - Fix error-reporting crash in non-blocking connection constructor. (#894) - Fix buffer overrun when converting array containing nulls to string. (#906) - Fix nullness check for `std::optional` containing a nullable value. (#907) - `connection::process_notice()` no longer appends newline if missing. 7.9.2 - Fix CMake documentation install. (#848) - More CMake build fix. (#869) - Bump gcc/clang/postgres minimum version requirements. - Another fix to the readthedocs documentation build. (#845) - Remove obsolete CMake workaround kludges. (#851, #866, #867) - Remove obscure deprecated `stream_to` constructor that never worked. (#853) - Support reading a field as an SQL array using `as_sql_array()`. (#841) - Make row iterator a _proper_ `random_access_iterator`. (#846) - Downgrade result iterator to "bidirectional"; was never really RA. (#846) 7.9.1 - Fix bad conversion of array of empty strings to string. (#816) - Move `[[likely]]` feature check back to compile time, to speed up configure. - Support `[[assume(...)]]`. - Fix `throw_null_conversion` compile error when converting enums. (#807) - Fix memory leak when failing to connect. - Improve introductory docs for connections and transactions. - Re-do entire documentation build. No more Sphinx in readthedocs. (#802) - No more autodetection of doxygen etc. Run it, or don't. - Docs build now disabled by default; use `--enable-documentation` to change. 7.9.0 - Support standard libraries without `std::basic_string` etc. - `std::basic_string` becomes `bytes_view`. (#726) - Fix assertion failure when streaming row ending in empty string. (#774) - CMake users can `shared_link_libraries(... libpqxx::pqxx)`. (#784) - Support parameterised versions of `query()` etc. (#646) - Put all feature tests back in config header. (#732) - Automate integration of feature tests into both CMake & autoconf. (#747) - Streaming query result implements `std::input_iterator`. (#771) - Fix broken `to_buf()` on `zview`. (#728) - Support `PQfsize()` and `PQfmod()`. (#727) - Implement conversion from `string_view` to string. (#728) - Rename `splitconfig` to `splitconfig.py`. (#763) - Document need for conversions more clearly, link to docs. (#757) - Experimental support for converting `std::span` to SQL arrays. (#769) 7.8.1 - Regenerate build files. Should fix ARM Mac build. (#715) - Reinstate `` that MSVC can't live with or without. (#713) 7.8.0 - Streaming large data sets now benchmarks faster than similar C/libpq code! - New `array` class for easier parsing of SQL arrays. - Deprecating `stream_from`. Use `transaction_base::stream()`. - Use `array_parser` only on comma-separated types, i.e. most of them. (#590) - Bumping requirements versions: need postgres 10. - Fix `array_parser` bug when parsing semicolon in an unquoted string. - Make some `zview` constructors `noexcept` if `string_view` does it. - Handle result status code for starting streaming replication. (#631) - Faster text decoding and escaping in data streaming. (#601) - Deprecate `basic_fieldstream` and `fieldstream`. - Deprecate `<<` operator inserting a field into an `ostream`. - New string conversion fields: `converts_to_string` & `converts_from_string`. - Ran `autoupdate` (because the autotools told me to). - Documentation tweak. (#584) - Typo in README.md. (#586) - Support `std::optional` etc. in `stream_to`. (#596) - Remove support for single-quoted array/composite elements. No such thing! - Optimise out a kink in composite field parser. - Work around build warning in MinGW: include `winsock2.h` before `windows.h`. - Drop some redundant encoding groups. - If CMake can't find libpq, fall back to pkg-config. (#664) - Work around spurious compile error on g++ pre-gcc-10. (#665) - Include `` and `` headers in ``. (#667) - Don't use `std::function` as deleter for smart pointers. - Work around gcc compile error with regex + address sanitizer + analyzers. - Fix "double free" on exit when built as shared library on Debian. (#681) - Stop including ``; should be built into compilers. (#680) - New `broken_connection` exception subclass: `protocol_violation`. (#686) - Retired unused `blob_already_exists` exception class. (#686) - Support for `PQinitOpenSSL()`. (#678) - Slightly more helpful error for unsupported conversions. (#695) - Replace some C++ feature tests with C++20 feature macros. - Support moving of `stream_to`. (#706) - Incorporate `source_location` in exceptions. 7.7.4 - `transaction_base::for_each()` is now called `for_stream()`. (#580) - New `transaction_base::for_query()` is similar, but non-streaming. (#580) - Query data and iterate directly as client-side types: `query()`. (#580) - New ways to query a single row! `query01()` and `query1()`. (#580) - We now have 3 kinds of execution: "exec", "query", and "stream" functions. - Use C++23 `std::unreachable()` where available. - `result::iter()` return value now keeps its `result` alive. 7.7.3 - Fix up more damage done by auto-formatting. - New `result::for_each()`: simple iteration and conversion of rows. (#528) - Add some missing headers in ``. (#551) - More strictness in `header-pre.hxx`/`header-post.hxx` checking. - Disallow nesting of `ignore-deprecated` blocks. - Deprecate `exec` functions' `desc` parameter. - Fix `placeholders` documentation. (#557) - Strip `const` and references from `value_type`. (#558) - Get tests running on appveyor. (#560) - Fix broken nonblocking connection on Windows. (#560) 7.7.2 - Fix up damage done by auto-formatting. 7.7.1 - When you build libpqxx, configure the compiler's C++ version yourself! - Finally fix a long-standing silly warning in autogen. - Fix `digit_to_number` not being found on some comilers. (#518, #519) - In audit mode, define `_FORTIFY_SOURCE` to enable some extra checks. - Make more functions `constexpr`. Nothing particularly useful though. - Make more functions `noexcept`. - Move constructor & assignment for `result`. - Support LGTM.com and Facebook "infer" static analysis. - Deprecated `set_variable`/`get_variable` on `transaction_base`. - (Design unearthed warts in SQL variables, which were then fixed.) - Set/get session variables on `connection`: `set_session_var`/`get_var`. - Set/get local variables: execute SQL statements. - When using `select()`, include `` if available. 7.7.0 - Fix `stream_to` for differing table/client encodings. (#473) - Use `[[likely]]` & `[[unlikely]]` only in C++20, to silence warnings. - Fix clang "not a const expression" error in Windows. (#472) - Fix warnings about `[[likely]]` in `if constexpr`. (#475) - Clearer error for ambiguous string conversion of `char` type. (#481) - Pseudo-statement in `prepare()` error was for the wrong statement. (#488) - New class, `connecting` for nonblocking connection to the database. (#487) - New class, `range` for SQL range types. (#490) - Replace `std::isdigit` with a safer alternative. - Support string conversions for `std::chrono::year_month_day`. (#492) - Helper for implementing string traits: `generic_to_buf`. - Support `result::at(row_num, col_num)`. - Support `result[row_num, col_num]` if the compiler allows it. - Work around broken `std::filesystem::path` in MinGW. (#498) - Fix leak when getting client encoding fails. (#500) - Use `std::cmp_greater` etc. when available. Saves some ugly casts. - Move `result_iterator.hxx` into `pqxx/include/internal/`. - Move `compiler-public.hxx` into `pqxx/include/internal/`. - Add script for updating copyright strings. - Make `tools/lint` figure out source directory by itself. - Pass the actual C++ version to `tools/lint`, not the baseline one. - Re-enable pyflakes testing in `tools/lint`. - Make more functions `[[nodiscard]]`. - Qualified some member functions as lvalue or rvalue. - Don't run clang-tidy by default. Compatibility issues with gcc options. - Describe version requirements in a JSON file, `requirements.json`. - Doxygen documentation now uses the (Doxygen-extended) Markdown format. - Build docs in `doc/html/`, no longer in `doc/html/Reference/`. - Disable some `std::filesystem` features on Windows. - Shut up stupid Visual Studio warnings. - On gcc, mark rarely-used functions as "cold," to be optimised for size. - Glyph scanning for GB18030 encoding was utterly broken. (#517) 7.6.0 - Removed bad string conversion to `std::basic_string_view`. (#463) - Add C++20 concepts: `binary`, `char_string`, `char_strings`. - Generalise binary strings to any contiguous range of `std::byte`. - Mark `zview` as a view and as a borrowed range. - Save a copy step on string fields in `stream_to`. - New helper: `pqxx::value_type`. - New helper: `pqxx::binary_cast`. (#450) - Some escaping functions now have "into my buffer" variants. - More generic escaping functions, supporting more types of binary. - In C++20, accept generic columns list for `stream_to`. (#447) - Renamed `` to ``. - Deprecated `dynamic_params` in favour of `params`. - `pqxx::params::append_multi()` now calls `reserve()` if possible. - `pqxx::params::size()` is now `noexcept` (but sadly, `ssize()` is not). - Helper for generating parameter placeholders `$1`, `$2`, etc. (#443) - Now requires support for C++14 `[[deprecated]]` attribute. - Deprecated `unesc_raw()` with `unesc_bin()` variants. - Once `unesc_raw()` is gone, we'll support only the hex escape format. - Work around broken `thread_local` in MinGW gcc < 11.1. - `pqxx::blob` now supports `std::filesystem::path`. - Fixed check against header/lib version mismatch: `check_pqxx_version_7_6` - Deprecated result slicing. Expect `row::slice()` to disappear. - More complete documentation, of cursors in particular. 7.5.2 - **Actual serious bug.** `blob::read(std::vector<...>)` was broken. 7.5.1 - Fixed some Visual Studio warnings. - Missed a bit in working around MinGW's broken ``. - Deprecated more obsolete representations of binary data. Use `std::byte`. - New script `tools/deprecations` lists files that use deprecated code. - Added automake-generated `config/compile` to revision control. 7.5.0 - Now requires `std::variant` support! No longer works with gcc7. - When implementing a string conversion, consider specialising `param_format`. - Stop "aborting" nontransaction on closing. (#419) - Silence an overzealous Visual C++ warning. (#418) - Starting support for C++20 `std::span`. - New `blob::read()` using `std::span`. (#429) - New `params` class lets you build parameter lists incrementally. (#387) - Pass `std::vector` params in binary format. - Dropped legacy tests 31 and 49 to work around clang C++20 bug. - Fixed `stream_to` test failure in non-English locales. (#440) - Clarify `transaction_base::stream` documentation. (#423) - Avoid `` on MinGW; it's broken there. (#336, #398, #424, #441) 7.4.1 - Missing includes; broke macOS clang build. (#416) 7.4.0 - Work around Visual Studio 2017 bug with `[[deprecated]]`. (#405, #406) - Work around eternal Windows bug with `max` macro yet again. (#101) - Prepare for C++20 `std::ssize()`. - Dropped test12, which didn't add much and tried to read null strings. - Support string conversion for `std::monostate`. (#409) - Consistent "named constructors" for `stream_to` and `stream_from`. - New `table_path` type. - New `connection` methods `quote_table` and `quote_columns`. - Lots of deprecated stream constructors. - `pqxx::row::swap()` now finally has the `deprecated` attribute. - Finally deprecated a bunch of `field`, `row`, and `result` constructors. - Exposed `transaction_focus` marker class. 7.3.1 - New, simpler API for large objects: `blob` ("binary large object"). - `largeobject` and friends are now deprecated. - Fix visibility issue on gcc/clang, especially on macOS. (#395) - Use "pure" & "visibility" attributes if they work, regardless of compiler. - More deprecated items now have the `[[deprecated]]` attribute. - Document the concept of transaction focus. - Error messages more often report query description, if given. - Suppress spurious deprecation messages on Visual Studio. (#402) - Correct error when prepared/param statement clashes with tx focus. (#401) - `from_stream` with `from_query` now has a convenient factory function. - Removed some obsolete scripts from the `tools/` directory. 7.3.0 - `stream_to` now quotes and escapes its table name. - Removed `transaction_base::classname()`. Did anyone ever use it? - Internal reorg of the `transaction` and `transactionfocus` hierarchies. - Removed the only case of virtual inheritance, related to `namedclass`. - Internal `concat()` for faster, simpler string concatentation. - Fix compile omission in string conversions for `nullptr_t`. - `pqxx::size_buffer()` can now size multiple values at once. - `multi_to_string()` to convert multiple values into one `std::string`. - Implicit `zview` constructor from `char const *`. (#389) - Many `std::string&` parameters are now `zview` or `std::string_view`. - Now checking statement parameter lengths for overflow. - `#include ` in connection.cxx. (#394) 7.2.1 - Fix infinite loop in converting `char *` to string. (#377) - Deprecated `namedclass`. - Convert an entire row using `row::as()`. - Internal rework of `field::to()` and `field::as()` functions. - Some more warning options in maintainer mode. - Removed the old, DocBook-based tutorial. - Fixed wrong `query` and SQLSTATE params to some exceptions. (#378) 7.2.0 - You can now implicitly convert a `const std::string &` to `zview`. - Replaced some overloads for C strings and C++ strings with `zview`. - Deprecating `binarystring`. Use `std::basic_string` instead! - Array parser did not recognise escaping in unquoted values. - gcc10 test build fix: a result iterator is not the same thing as a `row`. - Doc fix: field size does _not_ include terminating zero. (#356) - Fix error message in `demangle_type_name`: printed result, not raw name. - Fix compile warning in `demangle_type_name` on GNU systems. - Document that string conversions assume non-null values. - Start playing with C++20 _concepts._ - Sketch out concepts-based `PQconnectdbParams` support. (#343) - Add missing link to "datatypes" documentation. (#346) - Supports `to_string`, `stream_to`, etc. for `binarystring`. (#312) - Fixed infinite recursion when using `std::optional` in `stream_to`. (#364) - Home-rolled hex-escaping. Saves an allocation. - Catch floating-point negative overflow in `check_cast`, not underflow. - Bit more work on CMake build doc. (#318) - Typo in `datatypes.md`: `nullness`, not `nullness_traits`. (#353) - Fixed test names map in `tests/runner.cxx`. (#354) - Integral `from_string` now accept leading whitespace, as in composite types. - Experimental support basics for composite types. (#355) - Use `stream_from` without knowing the number of fields. (#357) - Global `size_buffer` function. - `quote()` now works for always-null types without conversions defined. - `std::nullopt` now converts to an SQL null. - Skip quoting and escaping array/composite fields of "safe" types. - New type trait: `is_unquoted_safe`. - Forbid invalid specialisations of `query_value`. - Fixed `mktemp` invocation that broke on FreeBSD. - Avoid unneeded encode/decode step on more binary data. - If `__cxa_demangle` fails, fall back on raw type name. (#361) 7.1.2 - Document build in `BUILDING-configure.md` / `BUILDING-cmake.md`. - Work around silly clang warning in `test_errorhandler.cxx`. - Fix install error with some internal headers. (#322) - Fix "No object selected" error message in large objects. (#324) - If error has no SQLSTATE, throw `broken_connection`. (#280) - Fix argument order in `encrypt_password`. (#333, #334) - Fix underestimate of buffer size for `to_string` for floats. (#328) 7.1.1 - Compile fix for Visual Studio. - Warning fix for clang. - Also install `transaction_focus.hxx`. (#320) 7.1.0 - Query tuples straight into `std::tuple` using `transaction::stream()`! - And, `stream_from` now supports more or less arbitrary queries. - Instead of a tuple of fields, you can pass `stream_to` a container as well. - `string_traits::size_buffer()` must now be `noexcept`. - New `nullness` member: `always_null`. - There is now `to_buf` support for string literals. - Streaming data is now more efficient. - The table name in `stream_from` is now escaped. - You can now "convert" strings to `std::string_view`. Mind your lifetimes! - A `std::variant` will now convert to string, if its member types do. - If a `stream_from` row fails to convert, you can no longer retry it. - `from_string(field const &)` now handles null values properly. - Obsolete Windows build docs are gone. - Added `row::to(std::tuple<...>)`. - Unified the test suites. We no longer need `test/unit/unit_runner`. - New helper: `strip_t<...>` to remove a type's constness and reference. - Replace custom templating with CMake glob in `src/CMakeLists.txt`. - Replace custom templating with CMake glob in `doc/CMakeLists.txt`. - Replace custom templating with CMake glob in `test/unit/CMakeLists.txt`. 7.0.8 - Inline `type_name` in `PQXX_DECLARE_ENUM_CONVERSION`. 7.0.7 - Fix broken `--with-postgres-lib` option in `configure` script (#311) - Should now build even if neither `pkg-config` nor `pg_config` is available. - CMake accepts `PostgreSQL_ROOT`, if it's a sufficiently recent version. 7.0.6 - Prefer `pg_config` over `pkg-config` for include path (#291). - Try to plod on if we don't know the PostgreSQL include path. - Fix error message when starting overlapping transactions and such (#303). - Fix potential crashes when converting invalid strings to floats (#307, #308). 7.0.5 - Compile fix for g++ 10: include `` (#292). - Cleaned up error-checking of PG results. (#280). - The `esc()` methods now also take `std::string_view` (#295). 7.0.4 - Fix possible crash in `connection::connection_string` (#290). - Fix filtering of default values in `connection::connection_string` (#288). - Deprecate `row::swap` and public inheritance of iterators from `row`. - More copy/move/default constructors/assignments on result iterators. - More copy/move/default constructors/assignments on row iterators. 7.0.3 - Fixed misreporting of broken connection as `sql_error` (#280). - Replaced non-ASCII test texts with escape codes (#282, #283). - `ilostream` could truncate at `0xff` byte at buffer boundary (#284, #286). 7.0.2 - New query function: `query_value`, queries and converts a single value. - A `stream_from` stream can now be iterated. - More callable types qualify as transactors, thanks to `std::invoke`. 7.0.1 - Windows build fixes. - Documentation for writing your own string conversions. - `transaction_rollback` and children are now `sql_error`, not just `failure`. 7.0.0 - Bumped minimum required C++ version to C++17. - Everything has changed. If you're porting from older versions, be careful! - There is now only one connection class: `connection`. - Removed tablereader/tablewriter, replaced by stream_from/stream_to. - Removed obsolete transactor framework, replaced by post-C++11 one. - Removed old ways of invoking parameterised and prepared statements. - Session variables are no longer cached. - If you do weird stuff with setting/getting variables, it may break. - Reading a variable written from raw SQL, procedures, etc, will now work. - Prepared statements are now registered immediately. - If you do weird stuff with preparing/unpreparing statements, it may break. - Changed exceptions and errors for many error situations. - Mishandling prepared statements will now break the connection. - Many string references and const char pointers are now `std::string_view`. - New `zview` class wraps `string_view` for string with terminating zero. - The `stream_base` abstract base class is gone. - Transactions no longer have an `isolation_tag` nested type. - The `isolation_traits` type is gone. - There's no more `pqxx_exception`. Complicated things too much. - `pqxx::string_traits<>::name()` has been replaced with `pqxx::type_name`. - `to_string()` can now handle `std::vector` (to produce an SQL array). - All `from_string()` that took a C string now take a `std::string_view`. - There are now separate `string_traits` and `null_traits` templates. - Enums outside classes are now scoped enums. - `error_verbosity` is no longer nested in connection. - `connection::get_verbosity` is gone. - Some enums have changed names: `accesspolicy` to `access_policy`, and so on. - `dynamic_params` now accepts an accessor. - Fixed "const" support in arguments to parameterised/prepared statements. - Connection objects can now be moved. - `connections::options()` has been replaced by `connection_string()`. - Replaced pqxx-fulltest with `test_all.py`. - Some `size_type` have changed to different types, to match current libpq. - Internal overflows are more consistently caught and reported. - Deprecated items have been removed. - Large objects now require backend version 9.3 or better. - Seeking inside large objects now supports 64-bit sizes. - Visual Studio project files and sample headers are gone. Use CMake. - MinGW Makefiles are gone. Use `configure` or CMake. - Need PostgreSQL 10 to use robusttransaction. - `robusttransaction` no longer uses a log table. Feel free to drop it. 6.4.4 - Use pkg-config if pg-config is not available. - In CMake build, prefer CMake's config headers over any found in source tree. 6.4.3 - Updated copyright strings. - Added missing "stream" headers to autotools-based install. - Added stream headers to pqxx/pqxx header. 6.4.2 - Fix mistake for Windows in 6.4.1: use PQfreemem, not std::free. - Easily enable runtime checks in configure: "--enable-audit". - Enable optimisation in CircleCI build. 6.4.1 - Fixed more memory leaks. 6.4.0 - Half fix, half work around nasty notice processor life time bug. - Fix selective running of tests: "test/unit/runner test_infinities". - Added some missing `std::` qualifications. 6.3.3 - Throw more appropriate error when unable to read client encoding. - CMake build fixes. 6.3.2 - Conversion errors no longer throw pqxx::failure; always conversion_error! - Use C++17's built-in numeric string conversions, if available. - Query numeric precision in a more sensible, standard way. - Avoid "dead code" warning. - Replace obsolete autoconf macros. - Remove all "using namespace std". - CMake build fixes. 6.3.1 - Windows compile fix (CALLBACK is a macro there). - Work around Visual Studio 2017 not supporting ISO 646. 6.3.0 - New "table stream" classes by Joseph Durel: stream_from/stream_to. - Support weird characters in more identifiers: cursors, notifcations, etc. - Connection policies are deprecated. It'll all be one class in 7.0! - Connection deactivation/reactivation is deprecated. - Some items that were documented as deprecated are now also declared as such. - Fix Windows bug where WSAPoll was never used. Thanks dpolunin. - Fix Windows CMake build to link to socket libraries. Thanks dpolunin. - Various other changes to the CMake build. - Fix failure when doing multiple string conversions with Visual C++. - Fix nested project builds in CMake. Thanks Andrew Brownsword. - In Visual Studio, build for host architecture, not "x64". - Fix string conversion link error in Visual Studio. Thanks Ivan Poiakov. - Fix string conversion to bool for "1". Thanks Amaracs. - Fix in escaping of strings in arrays. Thanks smirql. - Faster copying of results of large queries. Thanks Vsevolod Strukchinsky. - Starting to handle encodings properly! Thanks to Joseph Durel. - No longer using std::iterator (deprecated in C++17). 6.2.5 - Removed deprecated pqxx-config. - Build fix on Visual C++ when not defining NOMINMAX. - Reduce setup code for string conversions, hopefully improving speed. - Allow nul bytes in tablereader. - Support defining string conversions for enum types. - Fixed const/pure attributes warning in gcc 8. - Updated build documentation to mention CMake option. - Fixed a floating-point string conversion failure with Visual Studio 2017. 6.2.4 - Fix builds in paths containing non-ASCII characters. - New macro: PQXX_HIDE_EXP_OPTIONAL (to work around a client build error). 6.2.3 - Build fixes. 6.2.2 - Variable number of arguments to prepared or parameterised statement (#75). - Windows build fix (#76). 6.2.1 - Compile fixes. 6.2.0 - At last! A check against version mismatch between library and headers. - Small compile fixes. 6.1.1 - Small compile fixes. - A particular error string would always come out empty. 6.1.0 - Dependencies among headers have changed. You may need extra includes. - Library headers now include "*.hxx" directly, not the user-level headers. - Supports parsing of SQL arrays, when using "ASCII-like" encodings. 6.0.0 - C++11 is now required. Your compiler must have shared_ptr, noexcept, etc. - Removed configure.ac.in; we now use configure.ac directly. - Removed pqxx::items. Use the new C++11 initialiser syntax. - Removed maketemporary. We weren't using it. - Can now be built outside the source tree. - New, simpler, lambda-friendly transactor framework. - New, simpler, prepared statements and parameterised statements. - Result rows can be passed around independently. - New exec0(): perform query, expect zero rows of data. - New exec1(): perform query, expect (and return) a single row of data. - New exec_n(): perform query, expect exactly n rows of data. - No longer defines Visual Studio's NOMINMAX in headers. - Much faster configure script. - Most configuration items are gone. - Retired all existing capability flags. - Uses WSAPoll() on Windows. - Documentation on readthedocs.org, thanks Tim Sheerman-Chase. 5.1.0 - Releases after this will require C++11! - Internal simplification to pqxx::result. - A row object now keeps its result object alive. - New exec() variants: "expect & return 1 row," "expect no rows," "expect n." - ChangeLog is gone. It was a drag on maintenance. 5.0.1 - Exposed sqlstate in sql_error exception class. 5.0 - The PGSTD namespace alias is gone. Use the std namespace directly. - pqxx::tuple is now pqxx::row, to avoid clashes with std::tuple. - Deprecated escape_binary functions dropped. - Deprecated notify_listener class dropped. - Support for many old compilers dropped. - Support for "long long" and "long double" types is always enabled. - No longer uses obsolete std::tr1 namespace; use plain std instead. - Now requires libpq 9.1 or better. - Requires server version 9.1 or better. - Support for REPEATABLE READ isolation level added. - Makefile fixes for Visual Studio 2013. - Supports C++11 and C++14. - No longer has obsolete debian & RPM packaging built in. - Fixed failure to abort uncommitted subtransactions on destruction. - Fixed failure to detect some integer overflows during conversion. - Build tooling uses /usr/bin/env python instead of /usr/bin/python. - New configure options: --with-postgres-include and --with-postgres-lib. - In g++ or compatible compilers, non-exported items are no longer accessible. - Many build fixes for various platforms and compilers. 4.0 - API change: noticers are gone! Use errorhandlers to capture error output. - API change: tablereaders and tablewriters are gone; they weren't safe. - API change: prepared statements are now weakly-typed, and much simpler. - API change: fields and tuples are now stand-alone classes in ::pqxx. - API change: thread-safety field have_strerror_r is now have_safe_strerror. - API change: notify_listener has been replaced with notification_receiver. - notification_receiver takes a payload parameter. - Easier Visual C++ setup. - Absolutely requires a libpq version with PQescapeStringConn. - Absolutely requires libpq 8.0 or better. - Changes for C++0x. - Supports clang++. - Visual C++ makefiles now support new-style unit tests. - Sample headers for more recent Visual Studio versions. - Fixes binary-data escaping problems with postgres 9.0. - Fixes problems with binary-string handling and escaping. - Fixes compatibility problems between 9.x libpq and 7.x backend. - quote_name to escape SQL identifiers for use in queries. - syntax_error reports error's approximate location in the query. - On Windows, now uses ws2_32 instead of wsock32. - Various Windows build fixes. - Updated for gcc 4.6.0. - configure script supports --enable-documentation/--disable-documentation. - Streamlined test/release toolchain. 3.1 - Shared libraries are now versioned by ABI: 3.1 instead of 3.1.0 etc. - Threading behaviour is now documented, and can be queried. - Version information available at compile time. - Supports parameterized statements. - Result tuples now support slicing. - Configure with --with-tr1=boost to use BOOST shared_ptr. - String conversion now has its own header file. - Supports read-only transactions. - Fixed breakage with Solaris "make". - Uses shared_ptr if available. - binarystring::str() is no longer cached; no longer returns reference. - Fixed problems in Visual C++ Makefile for test suite. - Fixed problems with RPM packaging. - Fixed build problem on RedHat/CentOS 5. - Lets you check whether a prepared statement has been defined. - "Varargs" prepared statements. - Unnamed prepared statements now supported. - Results have iterator as well as const_iterator. - Rewrite of robusttransaction logic; may actually do its job now. - Connections support async query cancel from signal handler or thread. - More documentation for performance features. 3.0 - Website is now at http://pqxx.org/ (no redirects) - Completely replaced cursor classes - More helpful error messages on failed connections - More detailed hierarchy of constraint-violation exception classes - trigger is now called notify_listener, trigger header is now notify-listen - New mixin base class pqxx_exception distinguishes libpqxx exception types - Quoting is back! transaction_base::quote() & connection_base::quote() - Several build & documentation problems with Visual C++ fixed - Compile fixes for gcc 4.2, 4.3 - Compile fixes for Sun Studio Express 5.9 - Uses strlcpy() where available, instead of strncpy() - Keeps better track of applicable text encodings - Fixed bug with prepared statement parameters in separate C++ statements - robusttransaction now works for multiple users - Pipeline lets you cancel ongoing queries, e.g. because they run for too long - Fixed broken escaping of binary values in tablewriter - Floating-point types now represented with full precision - Proper unit tests for new functionality - New traits-based system for adding data types - Floating-point infinities now supported - Flushing/completing a pipeline now frees up the transaction for other use - Completely reworked test suite, builds and runs much faster - tablewriter supports writing of raw lines 2.6.9 - Removed old 1.x API (that means all identifiers with capital letters!) - Tested with all current libpq versions and oldest/newest supported backends - No longer have old OnCommit()/OnAbort()/OnDoubt() callbacks in transactor! - Fixes failure when closing cursors with upper-case letters in their names - Fixes bug when adding triggers to connections that aren't open yet - Fixes bug when removing triggers - Fixes small memory leak when preparing statements - Fixes many problems with older backends - Fixes bug in result::swap(): protocol versions were not swapped - Some errors went undetected when using certain libpq versions - Fixes prepared statements on new libpq versions talking to old backends - Can estimate server version if libpq does not know how to obtain it - Greatly reduced memory usage while escaping strings - With Visual C++, creates lib/ directory if not already present - Useful error messages when preparing statements - Allows prepared statements to be registered explicitly - Support for "long long" types; enable with PQXX_ALLOW_LONG_LONG macro - Compilation errors for older libpq versions fixed - Some new small utility classes for disabling notice processing etc. - Result sets remember the queries that yielded them - New test script, pqxx-fulltest, tests against all current postgres versions - Connections can simulate failure - Adds password encryption function 2.6.8 - Fixes bug: binary parameters to prepared statements truncated at nul bytes - New, more specific exception types to distinguish errors from server - Resolved serious problems with generated reference documentation - Automatically detect Windows socket library with MinGW - Windows "make" fixed to run from main directory, not win32 - Fixes "mktemp" problems on some BSD-based platforms - pqxx-config is deprecated; use pkg-config instead - On GNU/Linux, uses poll() instead of select() to avoid file descriptor limit - Will provide server and protocol version information where available - New cursor class, absolute_cursor 2.6.7 - New escape functions for binary data: transaction_base::esc_raw() - Improved detection of socket libraries, especially for MinGW - Works around bug in some versions of GNU grep 2.5.1 - Fixes problem with configuration headers - Fixes PQprepare() detection - Fixes incomplete Visual C++ Makefile - Fixes compile error in workaround for older libpq versions - Removes "rpath" link option 2.6.6 - New, encoding-safe string-escaping functions - Upper-case letters now allowed in prepared-statement names - Fixes crash in test005 - More Visual C++ improvements - Removed collaboration diagrams from reference docs - New templating system for generating Windows Makefiles etc. 2.6.5 - Visual C++ users: copy win32/common-sample to win32/common before editing it - Should fix problems finding socket library on MinGW - Even more work on Visual C++ problems - Updated documentation for Visual C++ users - Fixed bug in prepared statements (mostly visible on Visual C++) - Nested transactions work harder to detect backend support 2.6.4 - Massively improved compatibility with Windows and Visual C++ - Fixed late initialization of "direct" connection state - Fixed problem with initialization of connection capabilities - Fixed configuration bug for libpq in nonstandard locations - Sample configuration header for libpq found in PostgreSQL 8.1 2.6.3 - Radical rework of prepared statements; INCOMPATIBLE INTERFACE CHANGE! - Dropped support for g++ 2.95 - Emulate prepared statements support on old libpq or old backend - Bug fix: missing tutorial (release script now tests for this) - Automatically links in socket library on Windows or Solaris, if needed - Bug fix: check for std namespace didn't work - Fixes for Cygwin/MSYS/MinGW 2.6.2 - Bug fix: connection state was not set up properly in some common cases - Bug fix: headers were installed in "include" instead of "include/pqxx" - Bug fix: sqlesc(string) broke with multibyte or multiple encodings - namedclass is now used as a virtual base; affects all subclass constructors - Initial implementation of subtransactions - Detect more connection capabilities - Standard library namespace can be set from configure script's command line - Completely reworked connection hierarchy, with separate policy objects - Clients can now define their own connection policies - Paved the way for client-defined thread synchronization - Now lives at http://thaiopensource.org/development/libpqxx/ 2.6.1 - Hugely improved recognition of different strerror_r() versions - Resolved link problems with gcc 4.0 and shared library 2.6.0 - New macro PQXX_SHARED defines whether to use/build libpqxx as shared library - Robusttransaction compatible with PostgreSQL 8.1 - Infrastructure for querying connection/backend capabilities at runtime - Greatly improved cursor support - Connection reactivation can be inhibited explicitly - Tries even harder to make sense of conflicting strerror_r() definitions - Detects connection failures that libpq glosses over - Reference documentation grouped into more coherent sections - Assumes strerror() is threadsafe on systems that have no strerror_r() - Now allows connection's socket number to be queried - New internal_error class for libpqxx-internal errors - With Visual C++, doesn't redefine NOMINMAX if it is defined already - Several compatibility improvements for Visual C++ - Fixes and workarounds for HP-UX and HP aCC compiler - Phased old cursor interface out of test suite; tests ported to new interface - Added documentation on thread safety - New thread safety model - Large objects have functions to tell current position - Minor updates to tutorial (somebody pay me and I'll do more :) - No longer needs libpq-fs.h header - Meaningful error messages for ambiguous string conversions fixed 2.5.6 - Support null parameters to prepared statements (use C-style char pointers) 2.5.5 - Diagnoses connection failure during result transfer - Fixes invalid -R link option in pqxx-config 2.5.4 - Fix workaround code for older libpq versions without PQunescapeBytea() - Work around grep bug in Fedora Core 4 that broke configure in UTF-8 locales - In Visual C++, assume libpqxx is a DLL when linking to std library as DLL - Missing documentation in distribution archive is back again - Export fewer symbols from library binary with gcc 4.0 - Releases now automatically tested against gcc 4.0 - Meaningful link errors for additional ambiguous string conversions - DLL symbol exports now automatically tested before each release 2.5.3 - Greatly improved builds on MinGW with MSYS - All known problems with MinGW fixed - Fix bugs in stream classes that caused failures and crashes with STLport - Detects and uses STLport automatically 2.5.2 - Fix memory leaks - Fix problems with NaN (not-a-number values) on some compilers 2.5.1 - Fix configure script; broke when very recent libpqxx was already installed - Fix cursor breakage when "long" is more than 32 bits - Fix cases where new-style abort/doubt handlers are used - Fix for division-by-zero error in Visual C++ (changed sample headers) - Improved checking for strerror_r in configure script - Fix for problem MinGW has with configure script - Fix spurious failure of Oid check in configure script 2.5.0 - Fix race condition in removing triggers - Fix binary string conversion with older libpq - Fix some error strings that may previously have come out wrong - No longer includes any libpq headers while compiling client code - Improved thread safety: avoid strerror() where possible - Prepared statements - Translate more error conditions to std::bad_alloc exception - Clearer and more specific explanations for configuration failures - Improved documentation - Looks for standard library in global namespace as well as std - Accepts standard C library in std namespace - Release script automatically tests with a range of compilers, not just one - Compatible with g++ 2.95 again; this time it's tested automatically 2.4.4 - Fix problems building shared library in Visual C++ - Fix autobuild in Debian, which was broken by mistake in BSD grep workaround - Fix conversion of string to floating-point type NaN - Remove stray CVS directories from distribution archive - Workaround for Visual C++ problem when issuing messages from destructors - Yet more workarounds for Visual C++ bugs - Fix situation where connection state might not be restored after failure - Fix configuration problem on SunOS - Network speedup in connection setup with pending variables and/or triggers 2.4.3 - Yet more workarounds for bugs in Visual C++ .NET 2003 - Fixes for SunC++ 5.5 - On Visual C++, now defines NOMINMAX, fixing large object support - Workaround for BSD grep - Improvements for builds from CVS - Sample config headers for Sun ONE Studio 8 2.4.2 - Fix minor problems with Apple's version of g++ 3.3 - Fix problem with MingW on Windows - Workarounds and fixes for Visual C++.NET 2003 - Renewed compatibility with g++ 2.95 - More sample configuration headers - Updated reference documentation - Removed assert code 2.4.1 - Several bugs in icursor_iterator fixed; incompatible interface changes - Tightens throw specifications on begin(), end(), size(), capacity() - Containers define reference and pointer types - Implements swap() in all container types - Implements == and != in all container types - Stabilizes new (but still limited) cursor interface - icursor_iterator thinks purely in stride granularity - Introduces />= comparisons for icursor_iterators - Allows "adopted SQL cursors" in new cursor interface - Reference-counting in binarystrings, so they can be copied (and efficiently) - Fixes reference-to-temporary problem with std::reverse_iterator in results - Result/tuple reverse_iterators no longer require std::reverse_iterator - Includes some sample config headers (in config/sample-headers) - Replaces iffy autoconf checks (avoid failures with maintainer mode's -Werror) - Fixes incompatibility with some implementations of Unix "cut" program (again) 2.4.0 - Fixes incompatibility with some implementations of Unix "cut" program - Fixes "ptrdiff_t redefinition" problem in some environments - More container-like tuples, so fields can be iterated - All size_type types are now unsigned - More conservative robusttransaction--thanks Tom Lane - Stream-like extraction operator for result field conversion - Warnings about deprecated headers now suppressed while compiling library - Iterator constructors and copy assignments now have empty throw specs 2.3.0 - Generates MinGW Makefile automatically - Documents MinGW build - Workaround for missing prepared-statement support - Potential bug fixed in closing of connections - Fixed incompatibility between new cursor streams and older backends - Removed pqxxbench 2.2.9 - Bugfix in removing trigger - Added "failed connection" to regression test - Some changes to throw specifications - Putting libpq in its own namespace is optional 2.2.8 - Moved libpq into pqxx::internal::pq namespace - New config system separates compiler-related items from libpq-related ones - Auto-generates Visual C++ Makefile, should always remain up-to-date now 2.2.7 - Bugfix: from_string() didn't handle LONG_MIN--thanks Yannick Boivin 2.2.6 - Complete "pipeline" rewrite, for better exception safety - New garbage collection scheme for "result;" constructors now exception-free 2.2.5 - First new cursor classes! - Fixed strange failure in tablewriter during large insertions - Updated tutorial 2.2.4 - New utility class template, items<> for easy container initialization - New utility function template, separated_list() - Error handling bugfix in tablewriter - Fixed tablereader handling of lines ending in empty fields - tablereader lines no longer end in newline with old libpq versions 2.2.3 - Trigger names no longer need to be proper identifiers - Compile fixes for g++ 3.4.0 and other modern compilers - Tablestreams may specify column lists - Deprecated Quote() in favour of sqlesc(); improved quoting - Fixed generation of libpqxx.spec 2.2.2 - Bugfix in fieldstream w.r.t. reading strings on some systems - Renamed config.h to internalconfig.h to avoid confusion - New connection functions allow client to sleep until notification arrives - Notification functions return number of notifications received - Even fewer client-visible macros exported by libconfig.h 2.2.1 - New, 2.x-style string conversions without locale problem - Documentation improvements - Implemented result::swap() 2.2.0 - Installs to /usr/local by default, NOT to /usr/local/pqxx like before! - Uses Postgres-provided script to find Postgres (thanks Peter Eisentraut) - Which means no more configure arguments required on Irix (thanks Arjen Baart) - Fixes long-standing bug in result class! - New pipeline class for throughput optimization - New field stream class: read result field as C++ stream - Separate namespace pqxx::internal for definitions not relevant to the user - More Windows compilation fixes - SUN Workshop 6 compile fixes and workarounds (thanks Jon Meinecke) - Implemented reverse_iterator for result class - Checks for functional std::reverse_iterator template - Preliminary Makefile for MinGW compiler (thanks Pasquale Fersini) - Changed the way unique<> works - Checks for functional std::count_if() - Bugs fixed & test programs added 2.1.3 - Makefile fixes for Visual C++, thanks Paresh Patel - Library ABI versioning implemented, thanks Roger Leigh - Uses old SQL isolation level syntax for compatibility, thanks koun@sina.com - tablestreams can explicitly complete() before destructor - Bugfix in robusttransaction: forgot to set isolation level - Fixed off-by-ones in tablewriter escape code - tablestreams now use \n-style escape sequences - tablestreams support octal numbers - Freely definable "null" strings in tablestreams, as originally intended - Improved Debian packaging, thanks Roger Leigh - tablestreams use libpq's new-style COPY functions, if available - Extended automation of build/release procedure - tablewriter writes in nonblocking mode to help hide communication latency - Can get backend variables as well as set them - More configuration macro cleanups - Workaround for missing clear() in standard string - Merry Christmas! 2.1.2 - Compile fix for gcc libstdc++ 2.9, thanks Jaroslaw Staniek - Moved deprecated functions below current ones - Cleanups for Debian packaging (thanks Roger Leigh, new Debian maintainer!) - Updated authors listings - Bumped ABI version number for the first time (now 2:0:1) 2.1.1 - More workarounds for gcc 2.95 - Automated tools keep test makefiles up to date 2.1.0 - Asynchronous connections - Fixed configure --includedir option (thanks Ray Dassen!) - Compile fixes for SUN Workshop 6, and one for gcc on FreeBSD 4.8 2.0.0 - New stable release! - Includes all changes since 1.5 release. - Workarounds for Microsoft Visual C++ 7 problems. Thanks Costin Musteata! - No longer need to define PQXX_NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION - Integrated Windows configuration into regular configuration - Only uses #warning if preprocessor supports it - Works on libpq versions without PQ[un]escapeBytea() 1.9.9 - Minor documentation changes 1.9.8 - Workaround for compile problem with postgres 7.3 - Convenience typedef for transaction<>: "work" 1.9.7 - binarystring rewritten and moved to its own file - binarystring::size() does not include terminating null byte! - Implemented escaping of binary strings - Fix in workaround for missing numeric_limits on some compilers - String conversion supported for unsigned char * - More helpful link errors for unsupported string conversions - Complete test coverage 1.9.6 - Fixes in "field table" support - Improved coexistence with client program's config.h, if any - Prefixed autoconf macros used in headers with "PQXX_" 1.9.5 - Header file contents moved to .hxx files for editor filetype recognition - Fixes wrong timestamp for include/pqxx/result in 1.9.4 distribution 1.9.4 - Fixes Visual C++ build problem when compiling as library 1.9.3 - Quick release for various minor changes 1.9.2 - Renamed most public member functions to all-lower-case names - (previously is now called 1.9.1 - tablestream destructor crashed if table didn't exist (thanks Sean [Rogers?]) - Renamed all header files to remove ".h" suffix - Tables created by regression test now prefixed with "pqxx" for safety - Large objects now considered stable - Migrated tutorial from SGML to DocBook XML (thanks Wichert Akkerman) - Added tests 57-59 - Fixed compile error in largeobject - Updated Windows makefiles 1.9.0 - EVERYTHING HAS CHANGED. Read the list or run into trouble! - CURSOR HAS INCOMPATIBLE CHANGES AND MAY BE REPLACED COMPLETELY - CACHEDRESULT HAS INCOMPATIBLE CHANGES (won't compile without changes) - REVISE YOUR TRANSACTORS; now templatized on transaction type - Finally got license file in order - Incompatible change in setting transactor quality of service - Cursors require serializable isolation level (checked at link time) - Renamed Connection_base to connection_base, Connection to connection, LazyConnection to lazyconnection - Renamed LargeObject to largeobject, LargeObjectAccess to largeobjectaccess - Renamed Noticer to noticer - Renamed Trigger to trigger - Renamed Result to result, Tuple to tuple, Field to field - Renamed Unique<> to unique<> - Renamed CachedResult to cachedresult - Transformed Transaction Taxonomy (TTT): - Renamed Transaction_base to transaction_base - Renamed Transaction to transaction - Renamed Transactor to transactor<> (now a template) - Implemented transaction isolation levels as compile-time static properties - transaction and robusttransaction now templatized on their isolation levels - cachedresult requires serializable isolation level (checked at link time) - Now need to include pqxx/transactor.h yourself if you need transactors - Large objects require real backend transaction at compile time - New type oid and constant oid_none for row identifiers resp. null oid - Added some forgotten PQXX_LIBEXPORTs - Tweaked documentation in many places 1.8.1 - By popular request: more convenient way to read field values - Documented locale sensitivity of ToString(), FromString(), Field::to() 1.8.0 - Compiles on gcc 2.95 again (heavy streambuf workarounds in largeobject.h) - ConnectionItf renamed to Connection_base, TransactionItf to Transaction_base - connectionitf.h is now connection_base.h, transactionitf.h connection_base.h 1.7.8 - BinaryString class for unescaping bytea strings - PQAlloc template keeps track of libpq-allocated objects - Removed some consts in Unique<>, ConnectionItf, sorry! - Can now set session variables on connections, transactions 1.7.7 - ./configure also looks for postgres in /usr/local/pgsql - test007 now uses SQL_ASCII as its test encoding - integrated Greg Hookey's Debian packaging 1.7.6 - added postgres library (libpq) to dynamic link path 1.7.5 - added test052 - test055 - added Result::Tuple::ColumnNumber() - also test setting of client encodings - removed superfluous versions of to_file() from large object classes 1.7.4 - new exception class, sql_error, remembers query text - moved exception classes to new file include/pqxx/except.h - test cases report texts of any failed queries - added tools/rmlo.cxx 1.7.3 - default constructors for connection classes - revamped seeking operations on large objects - better error messages in large objects - added test050, test051 1.7.2 - more workarounds for Sun CC 5.1, thanks Jeroen van Erp! - preliminary support for "named" queries - can now Quote() string constants - included Doxyfile in distribution archive - helps avoid Windows memory allocation problem in DLLs - allows setting of client character set encoding 1.7.1 - regenerated documentation 1.7.0 - removed all deprecated features - connection string documentation in README - separate Connection, LazyConnection classes - made test001 more concise - added test049 1.6.4 - configure script now respects different std namespace 1.6.3 - olostream, lostream now flush themselves before closing - fixed compilation problems when using ToString<>() on a plain char * - compilation fixes for Sun compiler (thanks Jeroen van Erp!) - added .pc file for pkgconfig (thanks Ray Dassen!) 1.6.2 - Debian packaging added to distribution archive - new ilostream, olostream, lostream classes 1.6.1 - large object's cunlink() replaced by remove() - default constructor for LargeObject 1.6.0 - new large objects interface - added test048 1.5.0 - allow result fields to be written to streams - removed confusing CachedResult::clear() - minor documentation updates - added test046, test047 - added convenience header 1.4.5 - fixed crash CachedResult that was less shallow than I thought - fixed quoting problem with adopted SQL cursors 1.4.4 - (forgot to save cursor.cxx with new constructor in 1.4.4, sorry) 1.4.3 - all tests now have three-digit numbers - Cursor can adopt SQL cursor returned by a function 1.4.2 - bugfix in CachedResult when accessing empty Results - minor documentation improvements 1.4.1 - documents new homepage: http://pqxx.tk/ - Connection constructor accepts null connect string - Exec() now also takes queries as C++ strings 1.4.0 - Connection::IsOpen() renamed to is_open() - NoticeProcessor replaced by Noticer (with C++ linkage) 1.3.7: - detects nasty rare problem case with Cursors in unknown positions 1.3.6: - fixed detection of missing PQescapeString(). Thanks David Wright! v1.3.5: - documented Windows build procedure - fixed problem with upper-case letters in cursor names. Thanks key88! 2003-01-19 16:00, v1.3.4: - support long double type - clarified some error messages 2003-01-08 18:45, v1.3.3: - fix missing include in test13 2003-01-07 02:30, v1.3.2: - configure looks for postgres includes/library in more places, thanks Ray! 2003-01-02 23:00, v1.3.1: - bugfix in Cursor positioning 2003-01-02 20:30, v1.3.0: - absolute positioning for Cursor - better documentation on cursors - reduced, but improved test suite output 2002-12-23 17:30, v1.2.8: - Cursor::Move() returns number of rows skipped - new typedef Cursor::size_type 2002-12-14 23:30, v1.2.7: - test suite now distinguishes expected errors from unexpected ones 2002-12-09 20:00, v1.2.6: - fixed some Cursor test cases for change in postgres 7.3 - added important warning to Cursor 2002-12-09 02:00, v1.2.5: - added important warning to CachedResult 2002-12-08 14:14, v1.2.4: - fixed compile error on some systems in include/pqxx/util.h 2002-12-04 12:00, v1.2.3: - workaround for broken on some systems - fixed Quote() bug 2002-12-03 01:30, v1.2.2: - fixed serious CachedResult bug - added test41 2002-12-02 17:00, v1.2.1: - hopefully fixed cursor bug with PostgreSQL 7.3 2002-12-01 22:00, v1.2.0: - new CachedResult class 2002-11-07 13:15, v1.1.4: - workaround for missing InvalidOid definition 2002-10-23 16:00, v1.1.3: - Cursor & TableStream hierarchy now work on any transaction type - get no. of affected rows & oid of inserted row from Result - increased test coverage 2002-10-21 01:30, v1.1.2: - updated build procedure - Debian packaging improvements 2002-09-25 03:00, v1.1.1: - supports activating/deactivating of connections - various Connection getters now activate deferred connection first 2002-09-23 01:00, v1.1.0: - supports lazy connections (added 19 test cases just for these) - greatly reduced performance overhead for RobustTransaction - removed id field from RobustTransaction's transaction log tables 2002-09-14 20:00, v1.0.1: - now lives on GBorg - various packaging updates 2002-06-12 17:30, v0.5.1: - no longer have to destroy one transaction before creating the next 2002-06-07 17:15, v0.5.0: - "make install" now finally installs headers! - distribution now includes SGML (DocBook) version of tutorial 2002-06-04 15:00, v0.4.4: - may now have multiple triggers with same name on single connection 2002-06-02 23:00, v0.4.3: - fixed TableReader problem with \t and \n 2002-06-01 21:00, v0.4.2: - hopefully fixes compile problem with broken std::iterator - configure no longer requires --with-postgres-include=/usr/include/postgresql 2002-05-29 22:00, v0.4.1: - can now also handle bool, unsigned char, short field types 2002-05-27 22:30, v0.4.0: - RENAMED Transactor::TRANSACTIONTYPE to argument_type for STL conformance - RENAMED Result::Field::name() to Name() - documentation improvements - minor optimizations 2002-05-18 00:00, v0.3.1: - removed broken postgres_fe.h dependency (hopefully permanent fix) 2002-05-12 22:45, v0.3.0: - also looks for postgres_fe.h in postgres' internal/ directory (tmp fix) 2002-05-05 01:30, v0.2.3: - extensive build instructions in README - make check now controlled through PG environment variables 2002-05-04 19:30, v0.2.2: - more STL conformance - fixed regression test - test6 now copies "orgevents" to "events" by default 2002-04-28 23:45 Version bumped to 0.2 2002-04-28 23:45 Self-generated distribution archive 2002-04-27 14:20 Replaced automake symlinks with actual files 2002-04-07 02:30 Released with configure script 2002-03-29 01:15 Not yet released. Still integrating autogen stuff... libpqxx-8.0.1/README.md000066400000000000000000000271001516427024100144700ustar00rootroot00000000000000libpqxx ======= Welcome to libpqxx, the C++ API to the PostgreSQL database management system. Home page: [ http://pqxx.org/development/libpqxx ](http://pqxx.org/development/libpqxx/) Find libpqxx on Github: [ https://github.com/jtv/libpqxx ](https://github.com/jtv/libpqxx) Documentation on Read The Docs: [ https://libpqxx.readthedocs.io ](https://libpqxx.readthedocs.io) Compiling this package requires PostgreSQL to be installed -- or at least the C headers and library for client development. The library builds on top of PostgreSQL's standard C API, libpq, though your code won't notice. If you're getting the code straight from the Git repo, the head of the `master` branch represents the current _development version._ Releases are tags on commits in `master`. For example, to get version 7.1.1: ```sh git checkout 7.1.1 ``` Thank you! ---------- Somebody who deserves special mention here: our first Donor-level sponsor is Klaus ([@klaussilveira](https://github.com/klaussilveira)). Thank you, Klaus! Upgrade notes ------------- **The 8.x versions require at least C++20.** Make sure your compiler is up to date. Building libpqxx ---------------- There are two different ways of building libpqxx from the command line: 1. Using CMake, on any system which supports it. 2. On Unix-like systems, using a `configure` script. "Unix-like" systems include GNU/Linux, Apple macOS and the BSD family, AIX, HP-UX, Irix, Solaris, etc. Even on Microsoft Windows, a Unix-like environment such as WSL, Cygwin, or MinGW should work. You'll find detailed build and install instructions in [`BUILDING-configure.md`](./BUILDING-configure.md) and [`BUILDING-cmake.md`](./BUILDING-cmake.md), respectively. And if you're working with Microsoft Visual Studio, have a look at Gordon Elliott's [ Easy-PQXX Build for Windows Visual Studio ](https://github.com/GordonLElliott/Easy-PQXX-Build-for-Windows-Visual-Studio) project. Documentation ------------- Building the library, if you have the right tools installed, generates HTML documentation in the `doc/` directory. It is based on the headers in `include/pqxx/` and text in `include/pqxx/doc/`. This documentation is also available online at [readthedocs](https://libpqxx.readthedocs.io). Programming with libpqxx ------------------------ Your first program will involve the libpqxx classes `connection` (see the `pqxx/connection.hxx` header), and `work` (a convenience alias for `transaction<>`). There are various transaction classes, but they all conform to the interface defined in the `transaction_base` class (in the `` header). These `*.hxx` headers are not the ones you include in your program. Instead, include the versions without filename suffix (e.g. `pqxx/connection`). Those will include the actual .hxx files for you. This was done so that includes are in standard C++ style (as in `` etc.), but an editor will still recognize them as files containing C++ code. Unless you care a lot about compilation speed, you'll probably just want to include everything: ```cxx #include ``` Continuing the list of classes, you may also need the `pqxx::result` class (`pqxx/result.hxx`). In a nutshell, you create a `pqxx::connection` based on a PostgreSQL connection string (see below), create a pqxx::work (a transaction object) in the context of that connection, and run one or more queries or other SQL commands on that. Depending on how you execute a query, it can return a stream of `std::tuple` (each representing one row); or just one tuple or field; or a `pqxx::result` object which holds both the result data and additional metadata. The metadata includes details like how many rows your query returned or modified, what the column names are, and so on. A `pqxx::result` acts as a container of `pqxx::row_ref` objects, and a `pqxx::row_ref` in turn acts as a container of `pqxx::field_ref` objects. (They aren't _really_ containers; all these classes are essentially references to the real data returned by libpq.) Here's an example with all the basics to get you going: ```c++ #include #include int main() { try { // Connect to the database. You can have multiple connections open // at the same time, even to the same database. pqxx::connection cx; std::cout << "Connected to " << cx.dbname() << '\n'; // Start a transaction. A connection can only have one transaction // open at the same time, but after you finish a transaction, you // can start a new one on the same connection. pqxx::work tx{cx}; // Query data of two columns, converting them to std::string and // int respectively. Iterate the rows. for (auto [name, salary] : tx.query( "SELECT name, salary FROM employee ORDER BY name")) { std::cout << name << " earns " << salary << ".\n"; } // For large amounts of data, "streaming" the results is more // efficient. It does not work for all types of queries though. // // You can read fields as std::string_view here, which is not // something you can do in most places. A string_view becomes // meaningless when the underlying string ceases to exist. In this // particular situation, you can convert a field to string_view and // it will be valid for just that one iteration of the loop. The // next iteration may overwrite or deallocate its buffer space. for (auto [name, salary] : tx.stream( "SELECT name, salary FROM employee")) { std::cout << name << " earns " << salary << ".\n"; } // Execute a statement, and check that it returns 0 rows of data. // This will throw pqxx::unexpected_rows if the query returns rows. std::cout << "Doubling all employees' salaries...\n"; tx.exec("UPDATE employee SET salary = salary*2").no_rows(); // Shorthand: conveniently query a single value from the database, // and convert it to an `int`. int my_salary = tx.query_value( "SELECT salary FROM employee WHERE name = 'Me'"); std::cout << "I now earn " << my_salary << ".\n"; // Or, query one whole row. This function will throw an exception // unless the result contains exactly 1 row. auto [top_name, top_salary] = tx.query1( R"( SELECT name, salary FROM employee WHERE salary = (SELECT max(salary) FROM employee) LIMIT 1 )"); std::cout << "Top earner is " << top_name << " with a salary of " << top_salary << ".\n"; // If you need to access the result metadata, not just the actual // field values, use `exec()`. It returns a pqxx::result object. pqxx::result res = tx.exec("SELECT * FROM employee"); std::cout << "Columns:\n"; for (pqxx::row_size_type col = 0; col < res.columns(); ++col) std::cout << res.column_name(col) << '\n'; // Commit the transaction. If you don't do this, the database will // undo any changes you made in the transaction. std::cout << "Making changes definite: "; tx.commit(); std::cout << "OK.\n"; } catch (std::exception const &e) { std::cerr << "ERROR: " << e.what() << '\n'; return 1; } return 0; } ``` Connection strings ------------------ Postgres connection strings state which database server you wish to connect to, under which username, using which password, and so on. Their format is defined in the documentation for libpq, the C client interface for PostgreSQL. Alternatively, these values may be defined by setting certain environment variables as documented in e.g. the manual for psql, the command line interface to PostgreSQL. Again the definitions are the same for libpqxx-based programs. The connection strings and variables are not fully and definitively documented here; this document will tell you just enough to get going. Check the PostgreSQL documentation for authoritative information. The connection string consists of attribute=value pairs separated by spaces, e.g. "user=john password=1x2y3z4". The valid attributes include: * `host` — Name of server to connect to, or the full file path (beginning with a slash) to a Unix-domain socket on the local machine. Defaults to "/tmp". Equivalent to (but overrides) environment variable PGHOST. * `hostaddr` — IP address of a server to connect to; mutually exclusive with "host". * `port` — Port number at the server host to connect to, or socket file name extension for Unix-domain connections. Equivalent to (but overrides) environment variable PGPORT. * `dbname` — Name of the database to connect to. A single server may host multiple databases. Defaults to the same name as the current user's name. Equivalent to (but overrides) environment variable PGDATABASE. * `user` — User name to connect under. This defaults to the name of the current user, although PostgreSQL users are not necessarily the same thing as system users. * `requiressl` — If set to 1, demands an encrypted SSL connection (and fails if no SSL connection can be created). Settings in the connection strings override the environment variables, which in turn override the default, on a variable-by-variable basis. You only need to define those variables that require non-default values. Linking with libpqxx -------------------- To link your final program, make sure you link to both libpqxx and the underlying C-level library, libpq, in that order. With most Unix-style compilers, you'd do this using these options while linking: `-lpqxx -lpq` Both libraries must be in your link path, so the linker knows where to find them. Any dynamic libraries you use must also be in a place where the loader can find them when loading your program at runtime. Sometimes people run into trouble with this when they have more than one lipqxx binary on their system. If you get massive link errors, try removing the "-lpqxx" argument from the command line and replacing it with the name of the libpqxx library binary instead. That's typically libpqxx.a, but you'll have to add the path to its location as well, e.g. `/usr/local/pqxx/lib/libpqxx.a`. This will ensure that the linker will use that exact version of the library rather than one found elsewhere on the system, and eliminate worries about the exact right version of the library being installed with your program.. If you get a moderate number fo link errors which include a missing symbol `check_pqxx_version_X_Y` (where `X` and `Y` are numbers), that's typically a sign that you're linking to a different version of libpqxx than the one whose headers your compiler used while compiling. And Visual Studio users in particular, beware: when linking object files and libraries, _do not mix Release artefacts with Debug artefacts._ This can be especially confusing when you install libpqxx from a pre-built package. Which kind of binary did you get? Actually the same thing _can_ happen with other compilers: most compilers have options that change the code they produce in incompatible ways. Mixing files from different kinds of builds can lead to link errors, or worse, crashes. libpqxx-8.0.1/UPGRADING.md000066400000000000000000000454361516427024100150670ustar00rootroot00000000000000Changes in 8.0 ============== Many things have changed. Most code written against 7.x will still work, but there may now be nicer ways of doing things. Some of your code may need updating, and I'm sorry about that! But I hope you'll be happy overall. Let's go through the main things. C++20 ----- You will need at least C++20 to compile libpqxx. Compiler support for C++20 does not need to be absolutely complete, but the basics must be there: concepts, ranges, spans, various utility functions in the standard library, the new object lifetime rules, and so on. Thanks to `std::span`, there are now very few raw pointers in the API (or even internally). This makes libpqxx not only safer, but also easier to _prove_ safe. It is important to be able to run static analysis tools that may detect bugs and vulnerabilities. But, in the C++ tradition, it shouldn't cost us anything in terms of speed. PostgreSQL & libpq versions --------------------------- When you connect to a database, libpqxx checks that it is compatible with the PostgreSQL server version. If not, it refuses to connect in order to avoid nasty surprises later. This wasn't very noticeable before because the minimum version was set to 8.0 and I never remembered to update it. Now I've bumped it up. This will happen from time to time. If the bump causes you problems, please seriously consider upgrading your server. Retiring deprecated items ------------------------- Some types and functions were already deprecated and are now gone: * `binarystring`. Use `blob` instead. * `connection_base` was an alias. Use just regular `connection`. * `encrypt_password()`. Use the equivalent member functions in `connection`. * `dynamic_params`. Use `params`. * `stream_from`. Use `transaction_base::stream()` instead. * Some `stream_to` constructors. Use static "factory" member functions. * `transaction_base::unesc_raw()`. Use `unesc_bin()`. * `transaction_base::quote_raw()`. Use `quote()`, passing a `bytes_view`. * Some `field` constructors. * Result row splicing. I don't think anyone ever used it. Result iterators ---------------- _Lifetimes:_ `result` and `row` iterators no longer reference-count their `result` object. In libpqxx 7, a `result` object's data would stay alive in memory for as long as you had an iterator referring to it. It seemed like a good idea once, many years ago, but it made iteration staggeringly inefficient. So, that's changed now. Just like any other iterator in C++, `result` and `row` iterators no longer keep your container alive. It's your own problem to ensure that. However `result` objects are still reference-counted smart pointers to the underlying data, so copying them is relatively cheap. _Semantics:_ Iterators for the `result` and `row` classes have never fully complied with the standard requirements for iterators. There was a good reason for this: I wanted these iterators to be convenient and work a lot like C pointers. I wanted you to be able to dereference them as if a `result` object were just an array of pointers to arrays. But it really started getting in the way. Much as I hate it, the standard requirements say that for any iterator `i`, `i[n]` should mean `*(i + n)`. In libpqxx, if you had a `result` iterator `i`, `i[n]` meant "field `n` in the row to which `i` points." Really convenient, but not compliant with the standard. So, that is no longer the case. If you want "field `n` in the row to which `i` points," say `(*i)[n]`, or `i->at(n)`. By the way, these changes mean that result and row iterators are now proper, standard random-access iterators. Some algorithms from the standard library may magically become more efficient when they detect this. Comparing results, rows, and fields ----------------------------------- When you compare two `result`, `row`, or `field` objects with `==` or `!=`, it now only checks whether they refer to (the same row/field in) the same underlying data object. It does not look at the data inside. These comparisons were meant to be helpful but they were never very well defined. And if you don't know exactly what you're getting, why would you want to invest the compute time? Row and field references ------------------------ The `row` and `field` classes were cumbersome, inefficient, and hopelessly intertwined with iterators. To avoid all that, use `row_ref` instead of `row` and `field_ref` instead of `field`. These assume that you keep the original `result` around, and in a stable location in memory. Unlike `row` and `field`, they do not keep the underlying data object alive through reference-counting. But neither do any of the standard C++ containers, so I hope you'll find this intuitive. It's certainly more efficient. _The indexing operations now return `row_ref` and `field_ref` instead of `row` and `field` respectively._ It probably won't affect your code, but you're running static analysis and instrumented builds to check for these things, right? Exceptions ---------- The exception hierarchy has changed radically. An exception no longer tries to tell your application everything it needs to know through its _type;_ there are _functions_ to tell you things like "can I still use my connection after this?" and "what should I call this type of exception?" That comes with a reorganisation of the hierarchy itself. It used to be that an exception that breaks your connection was always derived from `broken_connection`. _That is no longer the case._ There is now a single base class for all libpqxx exceptions, and it comes with all the properties that any of the libpqxx exceptions might need. Some of them will be irrelevant for some exceptions, in which case they return an empty string. So what should your `catch` code look like now? In some situations you'll need to catch a very specific error. That's where you still have the individual libpqxx exception classes, which you can catch individually or through inheritance grouping. But for a more general `try` block, write `catch` clauses in this order: 1. Any non-libpqxx exceptions, most specific ones first. 2. If needed, any _specific_ libpqxx exceptions that you want to separate out. 3. A single `catch` block on `pqxx::failure`. That final block can sort out the details by calling the exception's member functions, and checking its type using `typeid` and `dynamic_cast` if needed. What do I tell the user? What do I log? What SQL were we executing when this happened? Where in my application did it happen? Can I find more background on this SQL problem? Should I continue my transaction? Is it even worth trying to recover using the same connection? Handling exceptions can be messy and unclear at the best of times, but the new exception arrangement tries to give you something reasonable to work with. Binary data ----------- As the documentation predicted, the alias `pqxx::bytes` has changed to stand for `std::vector`. It used to be `std::basic_string`. And `pqxx::bytes_view` is now an alias for `std::span`. This may require changes to your code. The APIs for `std::basic_string` and `std::vector` differ, perhaps in more places than they should. Do not read the data using the `c_str()` member function; use `data()` instead. Hate to do this to you. However there were real problems with using `std::basic_string` the way we did. The `basic_string` template wasn't built for binary data, and there was no guarantee that it would work with any given compiler. Even where it did, we had to work around differences between compilers and compiler versions. That's not healthy. But there's also good news! Thanks to C++20's Concepts, most functions that previously only accepted a `pqxx::bytes` argument will now accept just about _any_ block of binary data, such as `std::array` or a C-style array. String conversion API --------------------- This is a whole chapter in itself. If you were specialising `pqxx::type_name` or `pqxx::string_traits`, things just got simpler, safer, and more efficient. But there's also a change in lifetime rules. This can be important for writing safe and correct code, so read on! ### Type names Let's get the easiest part out of the way first: `type_name` is now deprecated. Instead of specialising `type_name`, you now specialise a _function_ called `name_type()`. It returns a `std::string_view`, so the underlying data can be a string literal instead of a `std::string`. Some static analysis tools would report false positives about static deallocation of the `type_name` strings. ### Defining a string conversion Then there's `pqxx::string_traits`. Several changes here. If you were defining your own conversions to/from SQL strings, the 8.x API is... 1. _leaner,_ losing several members but mainly `into_string()`. 2. _safer,_ using views and spans rather than raw C-style pointers. 3. _simpler,_ dropping the terminating zero at the end of various strings. 4. _friendlier,_ accepting `std::source_location` for better error reporting. 5. _richer,_ capable of dealing with different text encodings. 6. _faster,_ because of the lifetime rule changes (described below). Your existing conversions may still work without changes, but that's only thanks to some specific compatibility shims. These will go away in libpqxx 9 at the latest, so I urge you to update your code. ### Lifetime rule changes In libpqxx 7.x, when you converted a C++ value to an SQL string or _vice versa,_ you could count on having a valid output for at least as long as you kept the object in which you stored it. The details depend on the type, e.g. `pqxx::string_traits::to_string()` returns a string constant, either "`true`" or "`false`". We're tightening that up in 8.x. Now, the output remains valid for at least as long as you keep the object in which you stored it, _and also keep the original in place._ This streamlines some trivial conversions. For example, converting a `std::string_view` or a C-style string to SQL is now just a matter of returning a view on that same data. It's just the same data in both C++ and SQL. It also enables some conversions that weren't possible before. You can now convert an SQL string to a `std::string_view` or a C-style string pointer, because the conversion is allowed to refer to its input data. Most code won't need to care about this change. A calling function is usually either done very quickly with its converted value, or it immediately arranges for more permanent storage. If you call `pqxx::to_string()` for example, you get a `std::string` containing the SQL string. All that changes in that case is the conversion process skipping an internal copy step, making it a bit faster. ### Using conversions There is now a richer, more complete set of global conversion functions. This means you can convert C++ values to SQL strings without calling their `pqxx::string_traits` functions yourself. The options are, from easiest to most efficient: * `pqxx::to_string()` returns the SQL value as a `std::string`. * `pqxx::into_buf()` renders the SQL value into a buffer you provide. * `pqxx::to_buf()` returns the SQL value, in a location of its own choosing. The `to_buf()` variant can make use of optimisations such as returning a view or pointer referring to the input you give it, or returning a string constant (e.g. "`true`" or "`false`"). That concludes the changes to the string conversion API. On to the new features that won't require you to change your code, but may improve your life. SQL Arrays ---------- You can now generate and parse SQL arrays, just like you can convert so many other types between their C++ representations and their SQL representations. The C++ type for this is the `pqxx::array` class template. You can parse an array from its SQL string representation in the same way you'd parse any other type of value: `my_array = pqxx::from_string>(text)`. Which means that a `result` field's `as()` member function will also support array parsing, just as you would expect. And in the other direction, you can use `pqxx::to_string(my_array)` to generate the SQL representation string for your `array` object. The `to_string()` direction will also work for other containers, by the way. So you can just convert a `std::vector` or a `std::array` in the same way and get their SQL array representations. You'll need to know what those template parameters in `array<...>` are: 1. The type for the elements inside the array. 2. The number of dimensions. A simple array has 1 dimension, which is the default, but multi-dimensional arrays also work. 3. The separator character between the elements in the SQL array. It defaults to whatever the default is for the element type, but you can override it. However it must be a single ASCII byte. A `pqxx::array` is mostly useful for loading SQL values into C++. it does not not support changing or manipulating the array's contents once you've got it. When going in the other direction however, you can use the standard C++ container or range types: `std::vector`, `std::array`, `std::range`, `std::view`, and so on. Nest these inside each other to form multi-dimensional SQL arrays. Composite types --------------- These are syntactically similar to arrays, but a bit more work. An SQL composite type is like a C++ `struct` of your own. You define it in SQL (whether through libpqxx or in some other way), and also a corresponding C++ type for the client side. You can then convert these between their C++ form and their SQL form, just like other types. To make that work, you'll have to define its `pqxx::string_traits` and `pqxx::nullness` traits types. The `composite.hxx` header contains some functions that you can call to handle most of the work that the conversions in the `string_traits` need to do. Source locations ---------------- Most of the functions in the libpqxx API now accept a `std::source_location` as a final argument. They will default to the location from where you call them. (To keep them from getting in the way, I abbreviated the type name to `pqxx::sl`. In most functions it just shows up as `sl`.) In many cases where libpqxx throws an exception, the error message will now include a reference to that source location to help you debug the error. Where possible, this will be the most precise location where you called into libpqxx. In places where libpqxx functions call other libpqxx functions, they will (where possible) pass the original source location along, so you're not left with a source reference that has no meaning to you and is nothing to do with your application. By default the source location will show the boundary where execution went from your code into libpqxx, even if the actual error happened many layers further down. You can also override this and pass your own source location in the call. In some situations it is not possible to pass a source location, but libpqxx will try to give you at least some useful location, such as the location where you created the object on which the error occurred. Expect this whole mechanism to change again in the future as C++ moves towards full traceback support. Text encodings -------------- PostgreSQL lets you communicate with the database in a choice of _client encodings._ SQL and data that go back and forth between your client and the server will be represented in this encoding. For a lot of purposes your code will not need to be aware of the encoding. For example, all SQL keywords themselves as well as all special characters such as quotes and commas and various field separators will all be in ASCII. There are cases where libpqxx needs to know what kind of encoding it's getting. For example, when you create a `pqxx::params` to pass parameters to an SQL statement, in some cases it will need to be aware. You can provide the information by passing your connection, transaction, or "ecnoding group" (see below) as the first constructor argument, before any actual parameters. The encodings machinery doesn't actually care about the _exact_ encoding of the text it's handling, but it needs to know where each character begins and ends, so that it can detect special characters (e.g. closing quotes) reliably. Without this, things can get a little dangerous when e.g. a multi-byte character inside a string happens to contain a byte that looks just like an ASCII quote character. Knowing where character values begin and end tells libpqxx which kind it is. This information is now also available to string conversions, to help them parse SQL data that may contain text in the client encoding. In some cases you may need to pass it yourself. Null pointers and `zview` ------------------------- It is no longer valid to create a `pqxx::zview` from a `nullptr`. This eliminates a little wart in the class' API that made it very different from `std::string_view`. If a `std::string_view` has a null pointer, so long as its length is zero, it can't cause any harm because there are no contents that you might attempt to access. (It was always invalid to construct a `string_view` from _just_ a null pointer, without a length, but that's another story.) A `zview`, however, normally promises that you can access the byte at its `end()`, and get a zero byte. Of course that wouldn't work with a null pointer! And so, the fine print for `zview` _used_ to say that a `zview` guaranteed a terminating zero byte _unless the pointer was null._ But that introduces too much complication and risk of mistakes. So from now on, unlike `string_view`, `zview` completely forbids null pointers. (You may be wondering what happens to the default constructor. When you default-construct a `zview`, it will point to a zero-terminated empty string. Its pointer will not be null.) Build changes ------------- The build has improved in many ways. As before, you get a choice of CMake or the `configure` script. The CMake build now also supports "unity builds." All shell scripts now have a `.sh` suffix. It takes some getting used to, but it simplifies some things such as running lint checkers on all of them without having to name each one of them individually. The build no longer tries to figure out whether you need to link a standard C++ filesystems library. In most cases this seems to be part of the regular standard library now, and at any rate libpqxx itself does not use it. If you do need to add a link option to get `std::filesystem` to work, you'll have to pass that option yourself. In the lint script (now called `tools/lint.sh`), set `PQXX_LINT=skip` to skip lint checks. This can speed up `make check` runs, and enable them to run without network access. Both the CMake build and the autotools built now default to C++20 (at minimum, I think) if you don't specify a version. This means that you no longer need to set a compiler option yourself just so your C++ compiler doesn't default to an older dialect. (Of course you may still want a _specific_ version, in which case you still do need to pass the option of your choice.) libpqxx-8.0.1/VERSION000066400000000000000000000000061516427024100142550ustar00rootroot000000000000008.0.1 libpqxx-8.0.1/aclocal.m4000066400000000000000000001774011516427024100150630ustar00rootroot00000000000000# generated automatically by aclocal 1.16.5 -*- Autoconf -*- # Copyright (C) 1996-2021 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],, [m4_warning([this file was generated for autoconf 2.71. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html # =========================================================================== # # SYNOPSIS # # AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) # # DESCRIPTION # # Check for baseline language coverage in the compiler for the specified # version of the C++ standard. If necessary, add switches to CXX and # CXXCPP to enable support. VERSION may be '11', '14', '17', or '20' for # the respective C++ standard version. # # The second argument, if specified, indicates whether you insist on an # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. # -std=c++11). If neither is specified, you get whatever works, with # preference for no added switch, and then for an extended mode. # # The third argument, if specified 'mandatory' or if left unspecified, # indicates that baseline support for the specified C++ standard is # required and that the macro should error out if no mode with that # support is found. If specified 'optional', then configuration proceeds # regardless, after defining HAVE_CXX${VERSION} if and only if a # supporting mode is found. # # LICENSE # # Copyright (c) 2008 Benjamin Kosnik # Copyright (c) 2012 Zack Weinberg # Copyright (c) 2013 Roy Stogner # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov # Copyright (c) 2015 Paul Norman # Copyright (c) 2015 Moritz Klammler # Copyright (c) 2016, 2018 Krzesimir Nowak # Copyright (c) 2019 Enji Cooper # Copyright (c) 2020 Jason Merrill # Copyright (c) 2021 Jörn Heusipp # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 15 dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro dnl (serial version number 13). AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], [$1], [14], [ax_cxx_compile_alternatives="14 1y"], [$1], [17], [ax_cxx_compile_alternatives="17 1z"], [$1], [20], [ax_cxx_compile_alternatives="20"], [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$2], [], [], [$2], [ext], [], [$2], [noext], [], [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], [$3], [optional], [ax_cxx_compile_cxx$1_required=false], [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) AC_LANG_PUSH([C++])dnl ac_success=no m4_if([$2], [], [dnl AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, ax_cv_cxx_compile_cxx$1, [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [ax_cv_cxx_compile_cxx$1=yes], [ax_cv_cxx_compile_cxx$1=no])]) if test x$ax_cv_cxx_compile_cxx$1 = xyes; then ac_success=yes fi]) m4_if([$2], [noext], [], [dnl if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do switch="-std=gnu++${alternative}" cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, [ac_save_CXX="$CXX" CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done fi]) m4_if([$2], [ext], [], [dnl if test x$ac_success = xno; then dnl HP's aCC needs +std=c++11 according to: dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf dnl Cray's crayCC needs "-h std=c++11" for alternative in ${ax_cxx_compile_alternatives}; do for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, [ac_save_CXX="$CXX" CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done if test x$ac_success = xyes; then break fi done fi]) AC_LANG_POP([C++]) if test x$ax_cxx_compile_cxx$1_required = xtrue; then if test x$ac_success = xno; then AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) fi fi if test x$ac_success = xno; then HAVE_CXX$1=0 AC_MSG_NOTICE([No compiler with C++$1 support was found]) else HAVE_CXX$1=1 AC_DEFINE(HAVE_CXX$1,1, [define if the compiler supports basic C++$1 syntax]) fi AC_SUBST(HAVE_CXX$1) ]) dnl Test body for checking C++11 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 ) dnl Test body for checking C++14 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 ) dnl Test body for checking C++17 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 ) dnl Test body for checking C++20 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 _AX_CXX_COMPILE_STDCXX_testbody_new_in_20 ) dnl Tests for new features in C++11 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ // If the compiler admits that it is not ready for C++11, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" // MSVC always sets __cplusplus to 199711L in older versions; newer versions // only set it correctly if /Zc:__cplusplus is specified as well as a // /std:c++NN switch: // https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ #elif __cplusplus < 201103L && !defined _MSC_VER #error "This is not a C++11 compiler" #else namespace cxx11 { namespace test_static_assert { template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; } namespace test_final_override { struct Base { virtual ~Base() {} virtual void f() {} }; struct Derived : public Base { virtual ~Derived() override {} virtual void f() override {} }; } namespace test_double_right_angle_brackets { template < typename T > struct check {}; typedef check single_type; typedef check> double_type; typedef check>> triple_type; typedef check>>> quadruple_type; } namespace test_decltype { int f() { int a = 1; decltype(a) b = 2; return a + b; } } namespace test_type_deduction { template < typename T1, typename T2 > struct is_same { static const bool value = false; }; template < typename T > struct is_same { static const bool value = true; }; template < typename T1, typename T2 > auto add(T1 a1, T2 a2) -> decltype(a1 + a2) { return a1 + a2; } int test(const int c, volatile int v) { static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == false, ""); auto ac = c; auto av = v; auto sumi = ac + av + 'x'; auto sumf = ac + av + 1.0; static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == true, ""); return (sumf > 0.0) ? sumi : add(c, v); } } namespace test_noexcept { int f() { return 0; } int g() noexcept { return 0; } static_assert(noexcept(f()) == false, ""); static_assert(noexcept(g()) == true, ""); } namespace test_constexpr { template < typename CharT > unsigned long constexpr strlen_c_r(const CharT *const s, const unsigned long acc) noexcept { return *s ? strlen_c_r(s + 1, acc + 1) : acc; } template < typename CharT > unsigned long constexpr strlen_c(const CharT *const s) noexcept { return strlen_c_r(s, 0UL); } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("1") == 1UL, ""); static_assert(strlen_c("example") == 7UL, ""); static_assert(strlen_c("another\0example") == 7UL, ""); } namespace test_rvalue_references { template < int N > struct answer { static constexpr int value = N; }; answer<1> f(int&) { return answer<1>(); } answer<2> f(const int&) { return answer<2>(); } answer<3> f(int&&) { return answer<3>(); } void test() { int i = 0; const int c = 0; static_assert(decltype(f(i))::value == 1, ""); static_assert(decltype(f(c))::value == 2, ""); static_assert(decltype(f(0))::value == 3, ""); } } namespace test_uniform_initialization { struct test { static const int zero {}; static const int one {1}; }; static_assert(test::zero == 0, ""); static_assert(test::one == 1, ""); } namespace test_lambdas { void test1() { auto lambda1 = [](){}; auto lambda2 = lambda1; lambda1(); lambda2(); } int test2() { auto a = [](int i, int j){ return i + j; }(1, 2); auto b = []() -> int { return '0'; }(); auto c = [=](){ return a + b; }(); auto d = [&](){ return c; }(); auto e = [a, &b](int x) mutable { const auto identity = [](int y){ return y; }; for (auto i = 0; i < a; ++i) a += b--; return x + identity(a + b); }(0); return a + b + c + d + e; } int test3() { const auto nullary = [](){ return 0; }; const auto unary = [](int x){ return x; }; using nullary_t = decltype(nullary); using unary_t = decltype(unary); const auto higher1st = [](nullary_t f){ return f(); }; const auto higher2nd = [unary](nullary_t f1){ return [unary, f1](unary_t f2){ return f2(unary(f1())); }; }; return higher1st(nullary) + higher2nd(nullary)(unary); } } namespace test_variadic_templates { template struct sum; template struct sum { static constexpr auto value = N0 + sum::value; }; template <> struct sum<> { static constexpr auto value = 0; }; static_assert(sum<>::value == 0, ""); static_assert(sum<1>::value == 1, ""); static_assert(sum<23>::value == 23, ""); static_assert(sum<1, 2>::value == 3, ""); static_assert(sum<5, 5, 11>::value == 21, ""); static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); } // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function // because of this. namespace test_template_alias_sfinae { struct foo {}; template using member = typename T::member_type; template void func(...) {} template void func(member*) {} void test(); void test() { func(0); } } } // namespace cxx11 #endif // __cplusplus >= 201103L ]]) dnl Tests for new features in C++14 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ // If the compiler admits that it is not ready for C++14, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201402L && !defined _MSC_VER #error "This is not a C++14 compiler" #else namespace cxx14 { namespace test_polymorphic_lambdas { int test() { const auto lambda = [](auto&&... args){ const auto istiny = [](auto x){ return (sizeof(x) == 1UL) ? 1 : 0; }; const int aretiny[] = { istiny(args)... }; return aretiny[0]; }; return lambda(1, 1L, 1.0f, '1'); } } namespace test_binary_literals { constexpr auto ivii = 0b0000000000101010; static_assert(ivii == 42, "wrong value"); } namespace test_generalized_constexpr { template < typename CharT > constexpr unsigned long strlen_c(const CharT *const s) noexcept { auto length = 0UL; for (auto p = s; *p; ++p) ++length; return length; } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("x") == 1UL, ""); static_assert(strlen_c("test") == 4UL, ""); static_assert(strlen_c("another\0test") == 7UL, ""); } namespace test_lambda_init_capture { int test() { auto x = 0; const auto lambda1 = [a = x](int b){ return a + b; }; const auto lambda2 = [a = lambda1(x)](){ return a; }; return lambda2(); } } namespace test_digit_separators { constexpr auto ten_million = 100'000'000; static_assert(ten_million == 100000000, ""); } namespace test_return_type_deduction { auto f(int& x) { return x; } decltype(auto) g(int& x) { return x; } template < typename T1, typename T2 > struct is_same { static constexpr auto value = false; }; template < typename T > struct is_same { static constexpr auto value = true; }; int test() { auto x = 0; static_assert(is_same::value, ""); static_assert(is_same::value, ""); return x; } } } // namespace cxx14 #endif // __cplusplus >= 201402L ]]) dnl Tests for new features in C++17 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ // If the compiler admits that it is not ready for C++17, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201703L && !defined _MSC_VER #error "This is not a C++17 compiler" #else #include #include #include namespace cxx17 { namespace test_constexpr_lambdas { constexpr int foo = [](){return 42;}(); } namespace test::nested_namespace::definitions { } namespace test_fold_expression { template int multiply(Args... args) { return (args * ... * 1); } template bool all(Args... args) { return (args && ...); } } namespace test_extended_static_assert { static_assert (true); } namespace test_auto_brace_init_list { auto foo = {5}; auto bar {5}; static_assert(std::is_same, decltype(foo)>::value); static_assert(std::is_same::value); } namespace test_typename_in_template_template_parameter { template typename X> struct D; } namespace test_fallthrough_nodiscard_maybe_unused_attributes { int f1() { return 42; } [[nodiscard]] int f2() { [[maybe_unused]] auto unused = f1(); switch (f1()) { case 17: f1(); [[fallthrough]]; case 42: f1(); } return f1(); } } namespace test_extended_aggregate_initialization { struct base1 { int b1, b2 = 42; }; struct base2 { base2() { b3 = 42; } int b3; }; struct derived : base1, base2 { int d; }; derived d1 {{1, 2}, {}, 4}; // full initialization derived d2 {{}, {}, 4}; // value-initialized bases } namespace test_general_range_based_for_loop { struct iter { int i; int& operator* () { return i; } const int& operator* () const { return i; } iter& operator++() { ++i; return *this; } }; struct sentinel { int i; }; bool operator== (const iter& i, const sentinel& s) { return i.i == s.i; } bool operator!= (const iter& i, const sentinel& s) { return !(i == s); } struct range { iter begin() const { return {0}; } sentinel end() const { return {5}; } }; void f() { range r {}; for (auto i : r) { [[maybe_unused]] auto v = i; } } } namespace test_lambda_capture_asterisk_this_by_value { struct t { int i; int foo() { return [*this]() { return i; }(); } }; } namespace test_enum_class_construction { enum class byte : unsigned char {}; byte foo {42}; } namespace test_constexpr_if { template int f () { if constexpr(cond) { return 13; } else { return 42; } } } namespace test_selection_statement_with_initializer { int f() { return 13; } int f2() { if (auto i = f(); i > 0) { return 3; } switch (auto i = f(); i + 4) { case 17: return 2; default: return 1; } } } namespace test_template_argument_deduction_for_class_templates { template struct pair { pair (T1 p1, T2 p2) : m1 {p1}, m2 {p2} {} T1 m1; T2 m2; }; void f() { [[maybe_unused]] auto p = pair{13, 42u}; } } namespace test_non_type_auto_template_parameters { template struct B {}; B<5> b1; B<'a'> b2; } namespace test_structured_bindings { int arr[2] = { 1, 2 }; std::pair pr = { 1, 2 }; auto f1() -> int(&)[2] { return arr; } auto f2() -> std::pair& { return pr; } struct S { int x1 : 2; volatile double y1; }; S f3() { return {}; } auto [ x1, y1 ] = f1(); auto& [ xr1, yr1 ] = f1(); auto [ x2, y2 ] = f2(); auto& [ xr2, yr2 ] = f2(); const auto [ x3, y3 ] = f3(); } namespace test_exception_spec_type_system { struct Good {}; struct Bad {}; void g1() noexcept; void g2(); template Bad f(T*, T*); template Good f(T1*, T2*); static_assert (std::is_same_v); } namespace test_inline_variables { template void f(T) {} template inline T g(T) { return T{}; } template<> inline void f<>(int) {} template<> int g<>(int) { return 5; } } } // namespace cxx17 #endif // __cplusplus < 201703L && !defined _MSC_VER ]]) dnl Tests for new features in C++20 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[ #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 202002L && !defined _MSC_VER #error "This is not a C++20 compiler" #else #include namespace cxx20 { // As C++20 supports feature test macros in the standard, there is no // immediate need to actually test for feature availability on the // Autoconf side. } // namespace cxx20 #endif // __cplusplus < 202002L && !defined _MSC_VER ]]) # Copyright (C) 2002-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.16.5], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.16.5])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. AS_CASE([$CONFIG_FILES], [*\'*], [eval set x "$CONFIG_FILES"], [*], [set x $CONFIG_FILES]) shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`AS_DIRNAME(["$am_mf"])` am_filepart=`AS_BASENAME(["$am_mf"])` AM_RUN_LOG([cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles]) || am_rc=$? done if test $am_rc -ne 0; then AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE="gmake" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking).]) fi AS_UNSET([am_dirpart]) AS_UNSET([am_filepart]) AS_UNSET([am_mf]) AS_UNSET([am_rc]) rm -f conftest-deps.mk } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking is enabled. # This creates each '.Po' and '.Plo' makefile fragment that we'll need in # order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl m4_ifdef([_$0_ALREADY_INIT], [m4_fatal([$0 expanded multiple times ]m4_defn([_$0_ALREADY_INIT]))], [m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) # Variables for tags utilities; see am/tags.am if test -z "$CTAGS"; then CTAGS=ctags fi AC_SUBST([CTAGS]) if test -z "$ETAGS"; then ETAGS=etags fi AC_SUBST([ETAGS]) if test -z "$CSCOPE"; then CSCOPE=cscope fi AC_SUBST([CSCOPE]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering # Copyright (C) 1996-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAINTAINER_MODE([DEFAULT-MODE]) # ---------------------------------- # Control maintainer-specific portions of Makefiles. # Default is to disable them, unless 'enable' is passed literally. # For symmetry, 'disable' may be passed as well. Anyway, the user # can override the default with the --enable/--disable switch. AC_DEFUN([AM_MAINTAINER_MODE], [m4_case(m4_default([$1], [disable]), [enable], [m4_define([am_maintainer_other], [disable])], [disable], [m4_define([am_maintainer_other], [enable])], [m4_define([am_maintainer_other], [enable]) m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) dnl maintainer-mode's default is 'disable' unless 'enable' is passed AC_ARG_ENABLE([maintainer-mode], [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], am_maintainer_other[ make rules and dependencies not useful (and sometimes confusing) to the casual installer])], [USE_MAINTAINER_MODE=$enableval], [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE AC_SUBST([MAINT])dnl ] ) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check whether make has an 'include' directive that can support all # the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], [AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) AS_CASE([$?:`cat confinc.out 2>/dev/null`], ['0:this is the am__doit target'], [AS_CASE([$s], [BSD], [am__include='.include' am__quote='"'], [am__include='include' am__quote=''])]) if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* AC_MSG_RESULT([${_am_result}]) AC_SUBST([am__include])]) AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([config/m4/libtool.m4]) m4_include([config/m4/ltoptions.m4]) m4_include([config/m4/ltsugar.m4]) m4_include([config/m4/ltversion.m4]) m4_include([config/m4/lt~obsolete.m4]) libpqxx-8.0.1/appveyor.yml000066400000000000000000000033711516427024100156050ustar00rootroot00000000000000--- # Configuration for test runs in Appveyor. version: "1.0.{build}" image: "Visual Studio 2022" shallow_clone: true # AppVeyor seems to build every push to a branch with a PR twice: once for the # branch, once for the PR. Suppress that. Especially when combining with # rolling builds, because it means that one of those gets instantly cancelled, # which means a "build failure" because it didn't complete. branches: only: - master # Set up to run the build across multiple C++ language versions. environment: # PostgreSQL version. We need it in several places. PGVERSION: 15 matrix: - CXX_VERSION: 20 - CXX_VERSION: 23 MSVC: "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC" services: postgresql%PGVERSION% install: - net start postgresql-x64-%PGVERSION% # Run CMake to build libpqxx.sln. # # 7z's -bsp0 option is supposed to suppress its progress bar. before_build: - cmd: "call \"%MSVC%\\Auxiliary\\Build\\vcvars64.bat\"\n\ cmake -DBUILD_SHARED_LIBS=1 -DCMAKE_CXX_STANDARD=%CXX_VERSION% \ -DCMAKE_CXX_FLAGS=\"/analyze /EHsc /Wall /sdl /options:strict /MP \ /wd4514 /wd4702 /wd4800 /wd4820 /wd4866 /wd4868 /wd5031 /wd5032 \ /wd5045 /wd5246 /wd5264 /wd6924\" \ .\n\ 7z a -bsp0 config-headers.zip \ \"%APPVEYOR_BUILD_FOLDER%/include/pqxx/config-*.h*\"\n\ appveyor PushArtifact config-headers.zip" configuration: Debug build: parallel: true project: libpqxx.sln verbosity: minimal test_script: - ps: $env:Path += ";.\\src\\Debug;C:\\Program Files\\PostgreSQL\\$env:PGVERSION\\bin" ; $env:PGUSER = "postgres" ; $env:PGPASSWORD = "Password12!" ; .\\test\\Debug\\runner.exe # Don't notify. The Github PR will have a status indicator. notifications: libpqxx-8.0.1/autogen.sh000077500000000000000000000034631516427024100152200ustar00rootroot00000000000000#! /bin/bash # Run this to generate the configure script etc. set -Cue -o pipefail PQXXVERSION=$(./tools/extract_version.py) PQXX_ABI=$(./tools/extract_version.py --abi) PQXX_MAJOR=$(./tools/extract_version.py --major) PQXX_MINOR=$(./tools/extract_version.py --minor) PQXX_PATCH=$(./tools/extract_version.py --patch-num) echo "libpqxx version $PQXXVERSION" echo "libpqxx ABI version $PQXX_ABI" # Substitute version information into special placeholders. # This is fully custom stuff and I'd love to get rid of it. substitute() { # (If this were bash, we'd make these locals.) infile="$1" outfile="$2" sed -e "s/@PQXXVERSION@/$PQXXVERSION/g" \ -e "s/@PQXX_MAJOR@/$PQXX_MAJOR/g" \ -e "s/@PQXX_MINOR@/$PQXX_MINOR/g" \ -e "s/@PQXX_PATCH@/$PQXX_PATCH/g" \ -e "s/@PQXX_ABI@/$PQXX_ABI/g" \ "$infile" >|"$outfile.tmp" mv "$outfile.tmp" "$outfile" } # Use templating system to generate various Makefiles. expand_templates() { for template in "$@" do ./tools/template2mak.py "$template" "${template%.template}" done } # We have two kinds of templates. One uses our custom templating tool. And # a few others simply have some substitutions done. readarray -t < <(find . -name \*.template) templates expand_templates "${templates[@]}" substitute include/pqxx/version.hxx.template include/pqxx/version.hxx substitute include/pqxx/doc/mainpage.md.template include/pqxx/doc/mainpage.md # Generate feature test snippets for C++ features that we simply detect by # checking a C++ feature test macro. ./tools/generate_cxx_checks.py # Generate autoconf and CMake configuration for our feature test snippets. ./tools/generate_check_config.py autoheader libtoolize --force --automake --copy aclocal -I . -I config/m4 automake --add-missing --copy autoconf echo "Done." libpqxx-8.0.1/cmake/000077500000000000000000000000001516427024100142715ustar00rootroot00000000000000libpqxx-8.0.1/cmake/config.cmake000066400000000000000000000041671516427024100165500ustar00rootroot00000000000000include(CheckFunctionExists) include(CMakeFindDependencyMacro) if(NOT PostgreSQL_FOUND) find_package(PostgreSQL) endif() if(NOT PostgreSQL_FOUND) find_package(PkgConfig REQUIRED) pkg_check_modules(PostgreSQL REQUIRED libpq) endif() check_function_exists("poll" PQXX_HAVE_POLL) # Incorporate feature checks based on C++ feature test macros. include(pqxx_cxx_feature_checks) # Check for std::stacktrace support. We can't just generate this like other # tests because some compilers require an extra library to support # std::stacktrace. try_compile( PQXX_HAVE_STACKTRACE ${PROJECT_BINARY_DIR} SOURCES ${PROJECT_SOURCE_DIR}/config-tests/stacktrace_support.cxx ) set(AC_CONFIG_H_IN "${PROJECT_SOURCE_DIR}/include/pqxx/config.h.in") set(CM_CONFIG_H_IN "${PROJECT_BINARY_DIR}/include/pqxx/config_cmake.h.in") set(CONFIG_H "${PROJECT_BINARY_DIR}/include/pqxx/config.h") set(CONFIG_H_COM "${PROJECT_BINARY_DIR}/include/pqxx/config-compiler.h") message(STATUS "Generating configuration headers") # First we write config_cmake.h.in based on autoconf's config.h.in. file(WRITE "${CM_CONFIG_H_IN}" "") file(STRINGS "${AC_CONFIG_H_IN}" lines) foreach(line ${lines}) string(REGEX REPLACE "^#undef" "#cmakedefine" l "${line}") file(APPEND "${CM_CONFIG_H_IN}" "${l}\n") endforeach() # Now have CMake write config.h based on that config_cmake.h.in. This makes the # process look as much like the autoconf one as we can. configure_file("${CM_CONFIG_H_IN}" "${CONFIG_H}" @ONLY) find_package(Python3 REQUIRED COMPONENTS Interpreter) # Then grab the PQXX macros from config.h and write them to config-compiler.h. execute_process( WORKING_DIRECTORY ${CMAKE_BINARY_DIR} RESULT_VARIABLE filter_result ERROR_VARIABLE filter_stderr COMMAND ${Python3_EXECUTABLE} "${PROJECT_SOURCE_DIR}/tools/filter_config.py" "${CONFIG_H}" "${CONFIG_H_COM}" ) # Staggering: execute_process() will fail *silently* on error... if(NOT filter_result STREQUAL "0") message( FATAL_ERROR "Filtering config failed (${filter_result}): ${filter_stderr}" ) endif() message(STATUS "Generating configuration headers - done") libpqxx-8.0.1/cmake/libpqxx-config.cmake000066400000000000000000000001711516427024100202240ustar00rootroot00000000000000include(CMakeFindDependencyMacro) find_dependency(PostgreSQL) include("${CMAKE_CURRENT_LIST_DIR}/libpqxx-targets.cmake") libpqxx-8.0.1/cmake/pqxx_cxx_feature_checks.cmake000066400000000000000000000036401516427024100222130ustar00rootroot00000000000000# Configuration for feature checks. Generated by generate_check_config.py. try_compile( PQXX_HAVE_ASSUME ${PROJECT_BINARY_DIR} SOURCES ${PROJECT_SOURCE_DIR}/config-tests/PQXX_HAVE_ASSUME.cxx ) try_compile( PQXX_HAVE_CHARCONV_FLOAT ${PROJECT_BINARY_DIR} SOURCES ${PROJECT_SOURCE_DIR}/config-tests/PQXX_HAVE_CHARCONV_FLOAT.cxx ) try_compile( PQXX_HAVE_CXA_DEMANGLE ${PROJECT_BINARY_DIR} SOURCES ${PROJECT_SOURCE_DIR}/config-tests/PQXX_HAVE_CXA_DEMANGLE.cxx ) try_compile( PQXX_HAVE_GCC_PURE ${PROJECT_BINARY_DIR} SOURCES ${PROJECT_SOURCE_DIR}/config-tests/PQXX_HAVE_GCC_PURE.cxx ) try_compile( PQXX_HAVE_GCC_VISIBILITY ${PROJECT_BINARY_DIR} SOURCES ${PROJECT_SOURCE_DIR}/config-tests/PQXX_HAVE_GCC_VISIBILITY.cxx ) try_compile( PQXX_HAVE_MULTIDIM ${PROJECT_BINARY_DIR} SOURCES ${PROJECT_SOURCE_DIR}/config-tests/PQXX_HAVE_MULTIDIM.cxx ) try_compile( PQXX_HAVE_POLL ${PROJECT_BINARY_DIR} SOURCES ${PROJECT_SOURCE_DIR}/config-tests/PQXX_HAVE_POLL.cxx ) try_compile( PQXX_HAVE_RANGES ${PROJECT_BINARY_DIR} SOURCES ${PROJECT_SOURCE_DIR}/config-tests/PQXX_HAVE_RANGES.cxx ) try_compile( PQXX_HAVE_SLEEP_FOR ${PROJECT_BINARY_DIR} SOURCES ${PROJECT_SOURCE_DIR}/config-tests/PQXX_HAVE_SLEEP_FOR.cxx ) try_compile( PQXX_HAVE_STRERROR_R ${PROJECT_BINARY_DIR} SOURCES ${PROJECT_SOURCE_DIR}/config-tests/PQXX_HAVE_STRERROR_R.cxx ) try_compile( PQXX_HAVE_STRERROR_S ${PROJECT_BINARY_DIR} SOURCES ${PROJECT_SOURCE_DIR}/config-tests/PQXX_HAVE_STRERROR_S.cxx ) try_compile( PQXX_HAVE_TYPE_DISPLAY ${PROJECT_BINARY_DIR} SOURCES ${PROJECT_SOURCE_DIR}/config-tests/PQXX_HAVE_TYPE_DISPLAY.cxx ) try_compile( PQXX_HAVE_YEAR_MONTH_DAY ${PROJECT_BINARY_DIR} SOURCES ${PROJECT_SOURCE_DIR}/config-tests/PQXX_HAVE_YEAR_MONTH_DAY.cxx ) try_compile( PQXX_HAVE_ZARGS ${PROJECT_BINARY_DIR} SOURCES ${PROJECT_SOURCE_DIR}/config-tests/PQXX_HAVE_ZARGS.cxx ) # End of config. libpqxx-8.0.1/compile_flags.in000066400000000000000000000000261516427024100163430ustar00rootroot00000000000000@CPPFLAGS@ @CXXFLAGS@ libpqxx-8.0.1/config-tests/000077500000000000000000000000001516427024100156165ustar00rootroot00000000000000libpqxx-8.0.1/config-tests/PQXX_HAVE_ASSUME.cxx000066400000000000000000000002621516427024100210220ustar00rootroot00000000000000#if !__has_cpp_attribute(assume) # error "No support for [[assume]] attribute." #endif #include void foo(int i) { [[assume(i > 0)]]; std::cout << i << '\n'; } libpqxx-8.0.1/config-tests/PQXX_HAVE_CHARCONV_FLOAT.cxx000066400000000000000000000006251516427024100221600ustar00rootroot00000000000000// Test for std::to_string/std::from_string for floating-point types. #include #include int main() { char z[100]; auto rt = std::to_chars(std::begin(z), std::end(z), 3.14159L); if (rt.ec != std::errc{}) return 1; long double n; auto rf = std::from_chars(std::cbegin(z), std::cend(z), n); if (rf.ec != std::errc{}) return 2; return (n > 3 and n < 4) ? 0 : 1; } libpqxx-8.0.1/config-tests/PQXX_HAVE_CXA_DEMANGLE.cxx000066400000000000000000000006521516427024100216770ustar00rootroot00000000000000// Test for cross-vendor C++ ABI's __cxa_demangle function. #include #include #include #include #include int main() { int status = 0; char *name = abi::__cxa_demangle(typeid(10).name(), nullptr, nullptr, &status); if (status != 0) throw std::runtime_error("Demangle failed!"); int result = std::strcmp(name, "int"); std::free(name); return result; } libpqxx-8.0.1/config-tests/PQXX_HAVE_GCC_PURE.cxx000066400000000000000000000003231516427024100212520ustar00rootroot00000000000000// Test for gcc-style "pure" attribute. #if !__has_cpp_attribute(gnu::pure) # error "Compiler does not support gnu::pure attribute." #endif [[gnu::pure]] int f() { return 0; } int main() { return f(); } libpqxx-8.0.1/config-tests/PQXX_HAVE_GCC_VISIBILITY.cxx000066400000000000000000000004251516427024100221710ustar00rootroot00000000000000// Test for gcc-style "visibility" attribute. #if !__has_cpp_attribute(gnu::visibility) # error "Compiler does not support gnu::visibility attribute." #endif struct [[gnu::visibility("hidden")]] D { D() {} int f() { return 0; } }; int main() { D d; return d.f(); } libpqxx-8.0.1/config-tests/PQXX_HAVE_MULTIDIM.cxx000066400000000000000000000011121516427024100212440ustar00rootroot00000000000000// Feature check for 'PQXX_HAVE_MULTIDIM'. // Generated by generate_cxx_checks.py. #include #if !defined(__cpp_multidimensional_subscript) # error "No PQXX_HAVE_MULTIDIM: __cpp_multidimensional_subscript is not set." #endif #if !__cpp_multidimensional_subscript # error "No PQXX_HAVE_MULTIDIM: __cpp_multidimensional_subscript is false." #endif #include struct foo { int operator[](int i) const { return i; } int operator[](int i, std::source_location) const { return i - 1; } }; int main() { return foo{}[1, std::source_location::current()]; } libpqxx-8.0.1/config-tests/PQXX_HAVE_POLL.cxx000066400000000000000000000001241516427024100205700ustar00rootroot00000000000000// Test for poll(). #include int main() { return poll(nullptr, 0, 0); } libpqxx-8.0.1/config-tests/PQXX_HAVE_RANGES.cxx000066400000000000000000000004561516427024100210110ustar00rootroot00000000000000// Feature check for 'PQXX_HAVE_RANGES'. // Generated by generate_cxx_checks.py. #include #if !defined(__cpp_lib_ranges) # error "No PQXX_HAVE_RANGES: __cpp_lib_ranges is not set." #endif #if !__cpp_lib_ranges # error "No PQXX_HAVE_RANGES: __cpp_lib_ranges is false." #endif int main() {} libpqxx-8.0.1/config-tests/PQXX_HAVE_SLEEP_FOR.cxx000066400000000000000000000015611516427024100214060ustar00rootroot00000000000000// Test for std::this_thread::sleep_for(). /* For some reason MinGW's header seems to be broken. * * But it gets worse. It looks as if we can include without problems * in this configuration test. Why does it break when MinGW users try to build * the library, but succeed when we try it here? * * To try and get close to the situation in the library code itself, we try * including some standard headers and OS headers that we don't strictly need * here. */ #include #include #include #include #include #include #include #if __has_include() # include #endif #if __has_include() # include #endif #if __has_include() # include #endif int main() { std::this_thread::sleep_for(std::chrono::microseconds{10u}); } libpqxx-8.0.1/config-tests/PQXX_HAVE_STRERROR_R.cxx000066400000000000000000000005271516427024100215740ustar00rootroot00000000000000// Check for strerror_r. // It can be either the POSIX version (which returns int) or the GNU version // (which returns char *). #include #include int main() { char buffer[200]; auto res{strerror_r(1, buffer, 200)}; // Sidestep type differences. We don't really care what the value is. return not not res; } libpqxx-8.0.1/config-tests/PQXX_HAVE_STRERROR_S.cxx000066400000000000000000000003411516427024100215670ustar00rootroot00000000000000// Test for strerror_s, as defined in Windows and C11. // Presumably this'll be part of the C++ standard some day. #include int main() { using namespace std; char buf[200]; return strerror_s(buf, 200, 1); } libpqxx-8.0.1/config-tests/PQXX_HAVE_TYPE_DISPLAY.cxx000066400000000000000000000002571516427024100217770ustar00rootroot00000000000000#include template constexpr std::string_view name_type() { return display_string_of(^^T); } int main() { static_assert(name_type() == "int"); } libpqxx-8.0.1/config-tests/PQXX_HAVE_YEAR_MONTH_DAY.cxx000066400000000000000000000001631516427024100222270ustar00rootroot00000000000000// Test for std::chrono::year_month_day etc. #include int main() { return int(std::chrono::year{1}); } libpqxx-8.0.1/config-tests/PQXX_HAVE_ZARGS.cxx000066400000000000000000000004541516427024100207160ustar00rootroot00000000000000#include #if !__has_cpp_attribute(gnu::null_terminated_string_arg) # error "This compiler does not support gnu::null_terminated_string_arg." #endif [[gnu::null_terminated_string_arg]] void print(char const *msg) { std::cout << msg << '\n'; } int main() { print("zargs works."); } libpqxx-8.0.1/config-tests/README.md000066400000000000000000000032631516427024100171010ustar00rootroot00000000000000Configuration tests =================== Libpqxx comes with support for two different build systems: the GNU autotools, and CMake. We need to teach both of these to test things like "does this compiler environment support `std::to_chars` for floating-point types?" In both build systems we test these things by trying to compile a particular snippet of code, found in this directry, and seeing whether that succeeds. These are the snippets with names like `PQXX_*.cxx`. To avoid duplicating those snippets for multiple build systems, we put them here. Both the autotools configuration and the CMake configuration can refer to them that way. We generate autoconf and cmake configuration automatically to inject those checks, avoiding tedious repetition. Some of the checks are based on C++20 feature test macros. We generate those automatically using `tools/generate_cxx_checks.py`. It took a bit of nasty magic to read a C++ source file into m4 for the autoconf side and treat it as a string literal, without macro expansion. There is every chance that I missed something, so be prepared for tests failing for unexpected reasons! Some C++ syntax may end up having an unforeseen meaning in m4, and screw up the handling of the code snippet. Re-configure, and read your logs carefully after editing these snippets. There are also a few other files here, used for other related purposes. For example, `minimal.cxx` is a nearly-blank input just to check whether th compiler will accept various options. And `stacktrace_support.cxx` is used not for an automated check, but for a manual one in each of the builds (because it needs to be not just compiled, but linked as well for the check to be effective.) libpqxx-8.0.1/config-tests/minimal.cxx000066400000000000000000000000331516427024100177640ustar00rootroot00000000000000int main() { return 0; } libpqxx-8.0.1/config-tests/stacktrace_support.cxx000066400000000000000000000002121516427024100222550ustar00rootroot00000000000000#include #include #include int main() { std::cout << std::format("{}", std::stacktrace::current()); } libpqxx-8.0.1/config/000077500000000000000000000000001516427024100144565ustar00rootroot00000000000000libpqxx-8.0.1/config/compile000077500000000000000000000163501516427024100160410ustar00rootroot00000000000000#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1999-2021 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN* | MSYS*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/* | msys/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: libpqxx-8.0.1/config/config.guess000077500000000000000000001405121516427024100170010ustar00rootroot00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2022 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale timestamp='2022-01-09' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # https://git.savannah.gnu.org/cgit/config.git/plain/config.guess # # Please send patches to . # The "shellcheck disable" line above the timestamp inhibits complaints # about features and limitations of the classic Bourne shell that were # superseded or lifted in POSIX. However, this script identifies a wide # variety of pre-POSIX systems that do not have POSIX shells at all, and # even some reasonably current systems (Solaris 10 as case-in-point) still # have a pre-POSIX /bin/sh. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2022 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi # Just in case it came from the environment. GUESS= # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. tmp= # shellcheck disable=SC2172 trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 set_cc_for_build() { # prevent multiple calls if $tmp is already set test "$tmp" && return 0 : "${TMPDIR=/tmp}" # shellcheck disable=SC2039,SC3028 { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } dummy=$tmp/dummy case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in ,,) echo "int x;" > "$dummy.c" for driver in cc gcc c89 c99 ; do if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD=$driver break fi done if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac } # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case $UNAME_SYSTEM in Linux|GNU|GNU/*) LIBC=unknown set_cc_for_build cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #elif defined(__GLIBC__) LIBC=gnu #else #include /* First heuristic to detect musl libc. */ #ifdef __DEFINED_va_list LIBC=musl #endif #endif EOF cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` eval "$cc_set_libc" # Second heuristic to detect musl libc. if [ "$LIBC" = unknown ] && command -v ldd >/dev/null && ldd --version 2>&1 | grep -q ^musl; then LIBC=musl fi # If the system lacks a compiler, then just pick glibc. # We could probably try harder. if [ "$LIBC" = unknown ]; then LIBC=gnu fi ;; esac # Note: order is significant - the case branches are not exclusive. case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ /sbin/sysctl -n hw.machine_arch 2>/dev/null || \ /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \ echo unknown)` case $UNAME_MACHINE_ARCH in aarch64eb) machine=aarch64_be-unknown ;; armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` machine=${arch}${endian}-unknown ;; *) machine=$UNAME_MACHINE_ARCH-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. case $UNAME_MACHINE_ARCH in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # Determine ABI tags. case $UNAME_MACHINE_ARCH in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case $UNAME_VERSION in Debian*) release='-gnu' ;; *) release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. GUESS=$machine-${os}${release}${abi-} ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE ;; *:SecBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE ;; *:MidnightBSD:*:*) GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE ;; *:ekkoBSD:*:*) GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE ;; *:SolidBSD:*:*) GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE ;; *:OS108:*:*) GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE ;; macppc:MirBSD:*:*) GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE ;; *:MirBSD:*:*) GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE ;; *:Sortix:*:*) GUESS=$UNAME_MACHINE-unknown-sortix ;; *:Twizzler:*:*) GUESS=$UNAME_MACHINE-unknown-twizzler ;; *:Redox:*:*) GUESS=$UNAME_MACHINE-unknown-redox ;; mips:OSF1:*.*) GUESS=mips-dec-osf1 ;; alpha:OSF1:*:*) # Reset EXIT trap before exiting to avoid spurious non-zero exit code. trap '' 0 case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case $ALPHA_CPU_TYPE in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") UNAME_MACHINE=alpha ;; "EV5 (21164)") UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` GUESS=$UNAME_MACHINE-dec-osf$OSF_REL ;; Amiga*:UNIX_System_V:4.0:*) GUESS=m68k-unknown-sysv4 ;; *:[Aa]miga[Oo][Ss]:*:*) GUESS=$UNAME_MACHINE-unknown-amigaos ;; *:[Mm]orph[Oo][Ss]:*:*) GUESS=$UNAME_MACHINE-unknown-morphos ;; *:OS/390:*:*) GUESS=i370-ibm-openedition ;; *:z/VM:*:*) GUESS=s390-ibm-zvmoe ;; *:OS400:*:*) GUESS=powerpc-ibm-os400 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) GUESS=arm-acorn-riscix$UNAME_RELEASE ;; arm*:riscos:*:*|arm*:RISCOS:*:*) GUESS=arm-unknown-riscos ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) GUESS=hppa1.1-hitachi-hiuxmpp ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. case `(/bin/universe) 2>/dev/null` in att) GUESS=pyramid-pyramid-sysv3 ;; *) GUESS=pyramid-pyramid-bsd ;; esac ;; NILE*:*:*:dcosx) GUESS=pyramid-pyramid-svr4 ;; DRS?6000:unix:4.0:6*) GUESS=sparc-icl-nx6 ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) GUESS=sparc-icl-nx7 ;; esac ;; s390x:SunOS:*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL ;; sun4H:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-hal-solaris2$SUN_REL ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-sun-solaris2$SUN_REL ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) GUESS=i386-pc-auroraux$UNAME_RELEASE ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 fi fi SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=$SUN_ARCH-pc-solaris2$SUN_REL ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-sun-solaris3$SUN_REL ;; sun4*:SunOS:*:*) case `/usr/bin/arch -k` in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` GUESS=sparc-sun-sunos$SUN_REL ;; sun3*:SunOS:*:*) GUESS=m68k-sun-sunos$UNAME_RELEASE ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case `/bin/arch` in sun3) GUESS=m68k-sun-sunos$UNAME_RELEASE ;; sun4) GUESS=sparc-sun-sunos$UNAME_RELEASE ;; esac ;; aushp:SunOS:*:*) GUESS=sparc-auspex-sunos$UNAME_RELEASE ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) GUESS=m68k-milan-mint$UNAME_RELEASE ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) GUESS=m68k-hades-mint$UNAME_RELEASE ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) GUESS=m68k-unknown-mint$UNAME_RELEASE ;; m68k:machten:*:*) GUESS=m68k-apple-machten$UNAME_RELEASE ;; powerpc:machten:*:*) GUESS=powerpc-apple-machten$UNAME_RELEASE ;; RISC*:Mach:*:*) GUESS=mips-dec-mach_bsd4.3 ;; RISC*:ULTRIX:*:*) GUESS=mips-dec-ultrix$UNAME_RELEASE ;; VAX*:ULTRIX*:*:*) GUESS=vax-dec-ultrix$UNAME_RELEASE ;; 2020:CLIX:*:* | 2430:CLIX:*:*) GUESS=clipper-intergraph-clix$UNAME_RELEASE ;; mips:*:*:UMIPS | mips:*:*:RISCos) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } GUESS=mips-mips-riscos$UNAME_RELEASE ;; Motorola:PowerMAX_OS:*:*) GUESS=powerpc-motorola-powermax ;; Motorola:*:4.3:PL8-*) GUESS=powerpc-harris-powermax ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) GUESS=powerpc-harris-powermax ;; Night_Hawk:Power_UNIX:*:*) GUESS=powerpc-harris-powerunix ;; m88k:CX/UX:7*:*) GUESS=m88k-harris-cxux7 ;; m88k:*:4*:R4*) GUESS=m88k-motorola-sysv4 ;; m88k:*:3*:R3*) GUESS=m88k-motorola-sysv3 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 then if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ test "$TARGET_BINARY_INTERFACE"x = x then GUESS=m88k-dg-dgux$UNAME_RELEASE else GUESS=m88k-dg-dguxbcs$UNAME_RELEASE fi else GUESS=i586-dg-dgux$UNAME_RELEASE fi ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) GUESS=m88k-dolphin-sysv3 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 GUESS=m88k-motorola-sysv3 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) GUESS=m88k-tektronix-sysv3 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) GUESS=m68k-tektronix-bsd ;; *:IRIX*:*:*) IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'` GUESS=mips-sgi-irix$IRIX_REL ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) GUESS=i386-ibm-aix ;; ia64:AIX:*:*) if test -x /usr/bin/oslevel ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then GUESS=$SYSTEM_NAME else GUESS=rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then GUESS=rs6000-ibm-aix3.2.4 else GUESS=rs6000-ibm-aix3.2 fi ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if test -x /usr/bin/lslpp ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi GUESS=$IBM_ARCH-ibm-aix$IBM_REV ;; *:AIX:*:*) GUESS=rs6000-ibm-aix ;; ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) GUESS=romp-ibm-bsd4.4 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) GUESS=rs6000-bull-bosx ;; DPX/2?00:B.O.S.:*:*) GUESS=m68k-bull-sysv3 ;; 9000/[34]??:4.3bsd:1.*:*) GUESS=m68k-hp-bsd ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) GUESS=m68k-hp-bsd4.4 ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` case $UNAME_MACHINE in 9000/31?) HP_ARCH=m68000 ;; 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if test -x /usr/bin/getconf; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case $sc_cpu_version in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case $sc_kernel_bits in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi if test "$HP_ARCH" = ""; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if test "$HP_ARCH" = hppa2.0w then set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH=hppa2.0w else HP_ARCH=hppa64 fi fi GUESS=$HP_ARCH-hp-hpux$HPUX_REV ;; ia64:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` GUESS=ia64-hp-hpux$HPUX_REV ;; 3050*:HI-UX:*:*) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } GUESS=unknown-hitachi-hiuxwe2 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) GUESS=hppa1.1-hp-bsd ;; 9000/8??:4.3bsd:*:*) GUESS=hppa1.0-hp-bsd ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) GUESS=hppa1.0-hp-mpeix ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) GUESS=hppa1.1-hp-osf ;; hp8??:OSF1:*:*) GUESS=hppa1.0-hp-osf ;; i*86:OSF1:*:*) if test -x /usr/sbin/sysversion ; then GUESS=$UNAME_MACHINE-unknown-osf1mk else GUESS=$UNAME_MACHINE-unknown-osf1 fi ;; parisc*:Lites*:*:*) GUESS=hppa1.1-hp-lites ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) GUESS=c1-convex-bsd ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) GUESS=c34-convex-bsd ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) GUESS=c38-convex-bsd ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) GUESS=c4-convex-bsd ;; CRAY*Y-MP:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=ymp-cray-unicos$CRAY_REL ;; CRAY*[A-Z]90:*:*:*) echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=t90-cray-unicos$CRAY_REL ;; CRAY*T3E:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=alphaev5-cray-unicosmk$CRAY_REL ;; CRAY*SV1:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=sv1-cray-unicos$CRAY_REL ;; *:UNICOS/mp:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=craynv-cray-unicosmp$CRAY_REL ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE ;; sparc*:BSD/OS:*:*) GUESS=sparc-unknown-bsdi$UNAME_RELEASE ;; *:BSD/OS:*:*) GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE ;; arm:FreeBSD:*:*) UNAME_PROCESSOR=`uname -p` set_cc_for_build if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi else FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf fi ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case $UNAME_PROCESSOR in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL ;; i*:CYGWIN*:*) GUESS=$UNAME_MACHINE-pc-cygwin ;; *:MINGW64*:*) GUESS=$UNAME_MACHINE-pc-mingw64 ;; *:MINGW*:*) GUESS=$UNAME_MACHINE-pc-mingw32 ;; *:MSYS*:*) GUESS=$UNAME_MACHINE-pc-msys ;; i*:PW*:*) GUESS=$UNAME_MACHINE-pc-pw32 ;; *:SerenityOS:*:*) GUESS=$UNAME_MACHINE-pc-serenity ;; *:Interix*:*) case $UNAME_MACHINE in x86) GUESS=i586-pc-interix$UNAME_RELEASE ;; authenticamd | genuineintel | EM64T) GUESS=x86_64-unknown-interix$UNAME_RELEASE ;; IA64) GUESS=ia64-unknown-interix$UNAME_RELEASE ;; esac ;; i*:UWIN*:*) GUESS=$UNAME_MACHINE-pc-uwin ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) GUESS=x86_64-pc-cygwin ;; prep*:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=powerpcle-unknown-solaris2$SUN_REL ;; *:GNU:*:*) # the GNU system GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'` GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'` GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL ;; *:GNU/*:*:*) # other systems with GNU libc and userland GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"` GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC ;; *:Minix:*:*) GUESS=$UNAME_MACHINE-unknown-minix ;; aarch64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; arm*:Linux:*:*) set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then GUESS=$UNAME_MACHINE-unknown-linux-$LIBC else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi else GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf fi fi ;; avr32*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; cris:Linux:*:*) GUESS=$UNAME_MACHINE-axis-linux-$LIBC ;; crisv32:Linux:*:*) GUESS=$UNAME_MACHINE-axis-linux-$LIBC ;; e2k:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; frv:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; hexagon:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; i*86:Linux:*:*) GUESS=$UNAME_MACHINE-pc-linux-$LIBC ;; ia64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; k1om:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; m32r*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; m68*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; mips:Linux:*:* | mips64:Linux:*:*) set_cc_for_build IS_GLIBC=0 test x"${LIBC}" = xgnu && IS_GLIBC=1 sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef mips #undef mipsel #undef mips64 #undef mips64el #if ${IS_GLIBC} && defined(_ABI64) LIBCABI=gnuabi64 #else #if ${IS_GLIBC} && defined(_ABIN32) LIBCABI=gnuabin32 #else LIBCABI=${LIBC} #endif #endif #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 CPU=mipsisa64r6 #else #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 CPU=mipsisa32r6 #else #if defined(__mips64) CPU=mips64 #else CPU=mips #endif #endif #endif #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) MIPS_ENDIAN=el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) MIPS_ENDIAN= #else MIPS_ENDIAN= #endif #endif EOF cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'` eval "$cc_set_vars" test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } ;; mips64el:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; openrisc*:Linux:*:*) GUESS=or1k-unknown-linux-$LIBC ;; or32:Linux:*:* | or1k*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; padre:Linux:*:*) GUESS=sparc-unknown-linux-$LIBC ;; parisc64:Linux:*:* | hppa64:Linux:*:*) GUESS=hppa64-unknown-linux-$LIBC ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;; PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;; *) GUESS=hppa-unknown-linux-$LIBC ;; esac ;; ppc64:Linux:*:*) GUESS=powerpc64-unknown-linux-$LIBC ;; ppc:Linux:*:*) GUESS=powerpc-unknown-linux-$LIBC ;; ppc64le:Linux:*:*) GUESS=powerpc64le-unknown-linux-$LIBC ;; ppcle:Linux:*:*) GUESS=powerpcle-unknown-linux-$LIBC ;; riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; s390:Linux:*:* | s390x:Linux:*:*) GUESS=$UNAME_MACHINE-ibm-linux-$LIBC ;; sh64*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; sh*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; sparc:Linux:*:* | sparc64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; tile*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; vax:Linux:*:*) GUESS=$UNAME_MACHINE-dec-linux-$LIBC ;; x86_64:Linux:*:*) set_cc_for_build LIBCABI=$LIBC if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_X32 >/dev/null then LIBCABI=${LIBC}x32 fi fi GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI ;; xtensa*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. GUESS=i386-sequent-sysv4 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. GUESS=$UNAME_MACHINE-pc-os2-emx ;; i*86:XTS-300:*:STOP) GUESS=$UNAME_MACHINE-unknown-stop ;; i*86:atheos:*:*) GUESS=$UNAME_MACHINE-unknown-atheos ;; i*86:syllable:*:*) GUESS=$UNAME_MACHINE-pc-syllable ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) GUESS=i386-unknown-lynxos$UNAME_RELEASE ;; i*86:*DOS:*:*) GUESS=$UNAME_MACHINE-pc-msdosdjgpp ;; i*86:*:4.*:*) UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL else GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL fi ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL else GUESS=$UNAME_MACHINE-pc-sysv32 fi ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. GUESS=i586-pc-msdosdjgpp ;; Intel:Mach:3*:*) GUESS=i386-pc-mach3 ;; paragon:*:*:*) GUESS=i860-intel-osf1 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4 fi ;; mini*:CTIX:SYS*5:*) # "miniframe" GUESS=m68010-convergent-sysv ;; mc68k:UNIX:SYSTEM5:3.51m) GUESS=m68k-convergent-sysv ;; M680?0:D-NIX:5.3:*) GUESS=m68k-diab-dnix ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) GUESS=m68k-unknown-lynxos$UNAME_RELEASE ;; mc68030:UNIX_System_V:4.*:*) GUESS=m68k-atari-sysv4 ;; TSUNAMI:LynxOS:2.*:*) GUESS=sparc-unknown-lynxos$UNAME_RELEASE ;; rs6000:LynxOS:2.*:*) GUESS=rs6000-unknown-lynxos$UNAME_RELEASE ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) GUESS=powerpc-unknown-lynxos$UNAME_RELEASE ;; SM[BE]S:UNIX_SV:*:*) GUESS=mips-dde-sysv$UNAME_RELEASE ;; RM*:ReliantUNIX-*:*:*) GUESS=mips-sni-sysv4 ;; RM*:SINIX-*:*:*) GUESS=mips-sni-sysv4 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` GUESS=$UNAME_MACHINE-sni-sysv4 else GUESS=ns32k-sni-sysv fi ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says GUESS=i586-unisys-sysv4 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm GUESS=hppa1.1-stratus-sysv4 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. GUESS=i860-stratus-sysv4 ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. GUESS=$UNAME_MACHINE-stratus-vos ;; *:VOS:*:*) # From Paul.Green@stratus.com. GUESS=hppa1.1-stratus-vos ;; mc68*:A/UX:*:*) GUESS=m68k-apple-aux$UNAME_RELEASE ;; news*:NEWS-OS:6*:*) GUESS=mips-sony-newsos6 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if test -d /usr/nec; then GUESS=mips-nec-sysv$UNAME_RELEASE else GUESS=mips-unknown-sysv$UNAME_RELEASE fi ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. GUESS=powerpc-be-beos ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. GUESS=powerpc-apple-beos ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. GUESS=i586-pc-beos ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. GUESS=i586-pc-haiku ;; x86_64:Haiku:*:*) GUESS=x86_64-unknown-haiku ;; SX-4:SUPER-UX:*:*) GUESS=sx4-nec-superux$UNAME_RELEASE ;; SX-5:SUPER-UX:*:*) GUESS=sx5-nec-superux$UNAME_RELEASE ;; SX-6:SUPER-UX:*:*) GUESS=sx6-nec-superux$UNAME_RELEASE ;; SX-7:SUPER-UX:*:*) GUESS=sx7-nec-superux$UNAME_RELEASE ;; SX-8:SUPER-UX:*:*) GUESS=sx8-nec-superux$UNAME_RELEASE ;; SX-8R:SUPER-UX:*:*) GUESS=sx8r-nec-superux$UNAME_RELEASE ;; SX-ACE:SUPER-UX:*:*) GUESS=sxace-nec-superux$UNAME_RELEASE ;; Power*:Rhapsody:*:*) GUESS=powerpc-apple-rhapsody$UNAME_RELEASE ;; *:Rhapsody:*:*) GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE ;; arm64:Darwin:*:*) GUESS=aarch64-apple-darwin$UNAME_RELEASE ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` case $UNAME_PROCESSOR in unknown) UNAME_PROCESSOR=powerpc ;; esac if command -v xcode-select > /dev/null 2> /dev/null && \ ! xcode-select --print-path > /dev/null 2> /dev/null ; then # Avoid executing cc if there is no toolchain installed as # cc will be a stub that puts up a graphical alert # prompting the user to install developer tools. CC_FOR_BUILD=no_compiler_found else set_cc_for_build fi if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_PPC >/dev/null then UNAME_PROCESSOR=powerpc fi elif test "$UNAME_PROCESSOR" = i386 ; then # uname -m returns i386 or x86_64 UNAME_PROCESSOR=$UNAME_MACHINE fi GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE ;; *:QNX:*:4*) GUESS=i386-pc-qnx ;; NEO-*:NONSTOP_KERNEL:*:*) GUESS=neo-tandem-nsk$UNAME_RELEASE ;; NSE-*:NONSTOP_KERNEL:*:*) GUESS=nse-tandem-nsk$UNAME_RELEASE ;; NSR-*:NONSTOP_KERNEL:*:*) GUESS=nsr-tandem-nsk$UNAME_RELEASE ;; NSV-*:NONSTOP_KERNEL:*:*) GUESS=nsv-tandem-nsk$UNAME_RELEASE ;; NSX-*:NONSTOP_KERNEL:*:*) GUESS=nsx-tandem-nsk$UNAME_RELEASE ;; *:NonStop-UX:*:*) GUESS=mips-compaq-nonstopux ;; BS2000:POSIX*:*:*) GUESS=bs2000-siemens-sysv ;; DS/*:UNIX_System_V:*:*) GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "${cputype-}" = 386; then UNAME_MACHINE=i386 elif test "x${cputype-}" != x; then UNAME_MACHINE=$cputype fi GUESS=$UNAME_MACHINE-unknown-plan9 ;; *:TOPS-10:*:*) GUESS=pdp10-unknown-tops10 ;; *:TENEX:*:*) GUESS=pdp10-unknown-tenex ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) GUESS=pdp10-dec-tops20 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) GUESS=pdp10-xkl-tops20 ;; *:TOPS-20:*:*) GUESS=pdp10-unknown-tops20 ;; *:ITS:*:*) GUESS=pdp10-unknown-its ;; SEI:*:*:SEIUX) GUESS=mips-sei-seiux$UNAME_RELEASE ;; *:DragonFly:*:*) DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case $UNAME_MACHINE in A*) GUESS=alpha-dec-vms ;; I*) GUESS=ia64-dec-vms ;; V*) GUESS=vax-dec-vms ;; esac ;; *:XENIX:*:SysV) GUESS=i386-pc-xenix ;; i*86:skyos:*:*) SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'` GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL ;; i*86:rdos:*:*) GUESS=$UNAME_MACHINE-pc-rdos ;; i*86:Fiwix:*:*) GUESS=$UNAME_MACHINE-pc-fiwix ;; *:AROS:*:*) GUESS=$UNAME_MACHINE-unknown-aros ;; x86_64:VMkernel:*:*) GUESS=$UNAME_MACHINE-unknown-esx ;; amd64:Isilon\ OneFS:*:*) GUESS=x86_64-unknown-onefs ;; *:Unleashed:*:*) GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE ;; esac # Do we have a guess based on uname results? if test "x$GUESS" != x; then echo "$GUESS" exit fi # No uname command or uname output not recognized. set_cc_for_build cat > "$dummy.c" < #include #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #include #if defined(_SIZE_T_) || defined(SIGLOST) #include #endif #endif #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) #if !defined (ultrix) #include #if defined (BSD) #if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); #else #if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); #else printf ("vax-dec-bsd\n"); exit (0); #endif #endif #else printf ("vax-dec-bsd\n"); exit (0); #endif #else #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname un; uname (&un); printf ("vax-dec-ultrix%s\n", un.release); exit (0); #else printf ("vax-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname *un; uname (&un); printf ("mips-dec-ultrix%s\n", un.release); exit (0); #else printf ("mips-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } echo "$0: unable to guess system type" >&2 case $UNAME_MACHINE:$UNAME_SYSTEM in mips:Linux | mips64:Linux) # If we got here on MIPS GNU/Linux, output extra information. cat >&2 <&2 <&2 </dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = "$UNAME_MACHINE" UNAME_RELEASE = "$UNAME_RELEASE" UNAME_SYSTEM = "$UNAME_SYSTEM" UNAME_VERSION = "$UNAME_VERSION" EOF fi exit 1 # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: libpqxx-8.0.1/config/config.sub000077500000000000000000001051161516427024100164450ustar00rootroot00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2022 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale timestamp='2022-01-03' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # https://git.savannah.gnu.org/cgit/config.git/plain/config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. # The "shellcheck disable" line above the timestamp inhibits complaints # about features and limitations of the classic Bourne shell that were # superseded or lifted in POSIX. However, this script identifies a wide # variety of pre-POSIX systems that do not have POSIX shells at all, and # even some reasonably current systems (Solaris 10 as case-in-point) still # have a pre-POSIX /bin/sh. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2022 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; *local*) # First pass through any local machine types. echo "$1" exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Split fields of configuration type # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read field1 field2 field3 field4 <&2 exit 1 ;; *-*-*-*) basic_machine=$field1-$field2 basic_os=$field3-$field4 ;; *-*-*) # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two # parts maybe_os=$field2-$field3 case $maybe_os in nto-qnx* | linux-* | uclinux-uclibc* \ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ | storm-chaos* | os2-emx* | rtmk-nova*) basic_machine=$field1 basic_os=$maybe_os ;; android-linux) basic_machine=$field1-unknown basic_os=linux-android ;; *) basic_machine=$field1-$field2 basic_os=$field3 ;; esac ;; *-*) # A lone config we happen to match not fitting any pattern case $field1-$field2 in decstation-3100) basic_machine=mips-dec basic_os= ;; *-*) # Second component is usually, but not always the OS case $field2 in # Prevent following clause from handling this valid os sun*os*) basic_machine=$field1 basic_os=$field2 ;; zephyr*) basic_machine=$field1-unknown basic_os=$field2 ;; # Manufacturers dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ | unicom* | ibm* | next | hp | isi* | apollo | altos* \ | convergent* | ncr* | news | 32* | 3600* | 3100* \ | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ | ultra | tti* | harris | dolphin | highlevel | gould \ | cbm | ns | masscomp | apple | axis | knuth | cray \ | microblaze* | sim | cisco \ | oki | wec | wrs | winbond) basic_machine=$field1-$field2 basic_os= ;; *) basic_machine=$field1 basic_os=$field2 ;; esac ;; esac ;; *) # Convert single-component short-hands not valid as part of # multi-component configurations. case $field1 in 386bsd) basic_machine=i386-pc basic_os=bsd ;; a29khif) basic_machine=a29k-amd basic_os=udi ;; adobe68k) basic_machine=m68010-adobe basic_os=scout ;; alliant) basic_machine=fx80-alliant basic_os= ;; altos | altos3068) basic_machine=m68k-altos basic_os= ;; am29k) basic_machine=a29k-none basic_os=bsd ;; amdahl) basic_machine=580-amdahl basic_os=sysv ;; amiga) basic_machine=m68k-unknown basic_os= ;; amigaos | amigados) basic_machine=m68k-unknown basic_os=amigaos ;; amigaunix | amix) basic_machine=m68k-unknown basic_os=sysv4 ;; apollo68) basic_machine=m68k-apollo basic_os=sysv ;; apollo68bsd) basic_machine=m68k-apollo basic_os=bsd ;; aros) basic_machine=i386-pc basic_os=aros ;; aux) basic_machine=m68k-apple basic_os=aux ;; balance) basic_machine=ns32k-sequent basic_os=dynix ;; blackfin) basic_machine=bfin-unknown basic_os=linux ;; cegcc) basic_machine=arm-unknown basic_os=cegcc ;; convex-c1) basic_machine=c1-convex basic_os=bsd ;; convex-c2) basic_machine=c2-convex basic_os=bsd ;; convex-c32) basic_machine=c32-convex basic_os=bsd ;; convex-c34) basic_machine=c34-convex basic_os=bsd ;; convex-c38) basic_machine=c38-convex basic_os=bsd ;; cray) basic_machine=j90-cray basic_os=unicos ;; crds | unos) basic_machine=m68k-crds basic_os= ;; da30) basic_machine=m68k-da30 basic_os= ;; decstation | pmax | pmin | dec3100 | decstatn) basic_machine=mips-dec basic_os= ;; delta88) basic_machine=m88k-motorola basic_os=sysv3 ;; dicos) basic_machine=i686-pc basic_os=dicos ;; djgpp) basic_machine=i586-pc basic_os=msdosdjgpp ;; ebmon29k) basic_machine=a29k-amd basic_os=ebmon ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson basic_os=ose ;; gmicro) basic_machine=tron-gmicro basic_os=sysv ;; go32) basic_machine=i386-pc basic_os=go32 ;; h8300hms) basic_machine=h8300-hitachi basic_os=hms ;; h8300xray) basic_machine=h8300-hitachi basic_os=xray ;; h8500hms) basic_machine=h8500-hitachi basic_os=hms ;; harris) basic_machine=m88k-harris basic_os=sysv3 ;; hp300 | hp300hpux) basic_machine=m68k-hp basic_os=hpux ;; hp300bsd) basic_machine=m68k-hp basic_os=bsd ;; hppaosf) basic_machine=hppa1.1-hp basic_os=osf ;; hppro) basic_machine=hppa1.1-hp basic_os=proelf ;; i386mach) basic_machine=i386-mach basic_os=mach ;; isi68 | isi) basic_machine=m68k-isi basic_os=sysv ;; m68knommu) basic_machine=m68k-unknown basic_os=linux ;; magnum | m3230) basic_machine=mips-mips basic_os=sysv ;; merlin) basic_machine=ns32k-utek basic_os=sysv ;; mingw64) basic_machine=x86_64-pc basic_os=mingw64 ;; mingw32) basic_machine=i686-pc basic_os=mingw32 ;; mingw32ce) basic_machine=arm-unknown basic_os=mingw32ce ;; monitor) basic_machine=m68k-rom68k basic_os=coff ;; morphos) basic_machine=powerpc-unknown basic_os=morphos ;; moxiebox) basic_machine=moxie-unknown basic_os=moxiebox ;; msdos) basic_machine=i386-pc basic_os=msdos ;; msys) basic_machine=i686-pc basic_os=msys ;; mvs) basic_machine=i370-ibm basic_os=mvs ;; nacl) basic_machine=le32-unknown basic_os=nacl ;; ncr3000) basic_machine=i486-ncr basic_os=sysv4 ;; netbsd386) basic_machine=i386-pc basic_os=netbsd ;; netwinder) basic_machine=armv4l-rebel basic_os=linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony basic_os=newsos ;; news1000) basic_machine=m68030-sony basic_os=newsos ;; necv70) basic_machine=v70-nec basic_os=sysv ;; nh3000) basic_machine=m68k-harris basic_os=cxux ;; nh[45]000) basic_machine=m88k-harris basic_os=cxux ;; nindy960) basic_machine=i960-intel basic_os=nindy ;; mon960) basic_machine=i960-intel basic_os=mon960 ;; nonstopux) basic_machine=mips-compaq basic_os=nonstopux ;; os400) basic_machine=powerpc-ibm basic_os=os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson basic_os=ose ;; os68k) basic_machine=m68k-none basic_os=os68k ;; paragon) basic_machine=i860-intel basic_os=osf ;; parisc) basic_machine=hppa-unknown basic_os=linux ;; psp) basic_machine=mipsallegrexel-sony basic_os=psp ;; pw32) basic_machine=i586-unknown basic_os=pw32 ;; rdos | rdos64) basic_machine=x86_64-pc basic_os=rdos ;; rdos32) basic_machine=i386-pc basic_os=rdos ;; rom68k) basic_machine=m68k-rom68k basic_os=coff ;; sa29200) basic_machine=a29k-amd basic_os=udi ;; sei) basic_machine=mips-sei basic_os=seiux ;; sequent) basic_machine=i386-sequent basic_os= ;; sps7) basic_machine=m68k-bull basic_os=sysv2 ;; st2000) basic_machine=m68k-tandem basic_os= ;; stratus) basic_machine=i860-stratus basic_os=sysv4 ;; sun2) basic_machine=m68000-sun basic_os= ;; sun2os3) basic_machine=m68000-sun basic_os=sunos3 ;; sun2os4) basic_machine=m68000-sun basic_os=sunos4 ;; sun3) basic_machine=m68k-sun basic_os= ;; sun3os3) basic_machine=m68k-sun basic_os=sunos3 ;; sun3os4) basic_machine=m68k-sun basic_os=sunos4 ;; sun4) basic_machine=sparc-sun basic_os= ;; sun4os3) basic_machine=sparc-sun basic_os=sunos3 ;; sun4os4) basic_machine=sparc-sun basic_os=sunos4 ;; sun4sol2) basic_machine=sparc-sun basic_os=solaris2 ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun basic_os= ;; sv1) basic_machine=sv1-cray basic_os=unicos ;; symmetry) basic_machine=i386-sequent basic_os=dynix ;; t3e) basic_machine=alphaev5-cray basic_os=unicos ;; t90) basic_machine=t90-cray basic_os=unicos ;; toad1) basic_machine=pdp10-xkl basic_os=tops20 ;; tpf) basic_machine=s390x-ibm basic_os=tpf ;; udi29k) basic_machine=a29k-amd basic_os=udi ;; ultra3) basic_machine=a29k-nyu basic_os=sym1 ;; v810 | necv810) basic_machine=v810-nec basic_os=none ;; vaxv) basic_machine=vax-dec basic_os=sysv ;; vms) basic_machine=vax-dec basic_os=vms ;; vsta) basic_machine=i386-pc basic_os=vsta ;; vxworks960) basic_machine=i960-wrs basic_os=vxworks ;; vxworks68) basic_machine=m68k-wrs basic_os=vxworks ;; vxworks29k) basic_machine=a29k-wrs basic_os=vxworks ;; xbox) basic_machine=i686-pc basic_os=mingw32 ;; ymp) basic_machine=ymp-cray basic_os=unicos ;; *) basic_machine=$1 basic_os= ;; esac ;; esac # Decode 1-component or ad-hoc basic machines case $basic_machine in # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) cpu=hppa1.1 vendor=winbond ;; op50n) cpu=hppa1.1 vendor=oki ;; op60c) cpu=hppa1.1 vendor=oki ;; ibm*) cpu=i370 vendor=ibm ;; orion105) cpu=clipper vendor=highlevel ;; mac | mpw | mac-mpw) cpu=m68k vendor=apple ;; pmac | pmac-mpw) cpu=powerpc vendor=apple ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) cpu=m68000 vendor=att ;; 3b*) cpu=we32k vendor=att ;; bluegene*) cpu=powerpc vendor=ibm basic_os=cnk ;; decsystem10* | dec10*) cpu=pdp10 vendor=dec basic_os=tops10 ;; decsystem20* | dec20*) cpu=pdp10 vendor=dec basic_os=tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) cpu=m68k vendor=motorola ;; dpx2*) cpu=m68k vendor=bull basic_os=sysv3 ;; encore | umax | mmax) cpu=ns32k vendor=encore ;; elxsi) cpu=elxsi vendor=elxsi basic_os=${basic_os:-bsd} ;; fx2800) cpu=i860 vendor=alliant ;; genix) cpu=ns32k vendor=ns ;; h3050r* | hiux*) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) cpu=m68000 vendor=hp ;; hp9k3[2-9][0-9]) cpu=m68k vendor=hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) cpu=hppa1.1 vendor=hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; i*86v32) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv32 ;; i*86v4*) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv4 ;; i*86v) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv ;; i*86sol2) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=solaris2 ;; j90 | j90-cray) cpu=j90 vendor=cray basic_os=${basic_os:-unicos} ;; iris | iris4d) cpu=mips vendor=sgi case $basic_os in irix*) ;; *) basic_os=irix4 ;; esac ;; miniframe) cpu=m68000 vendor=convergent ;; *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) cpu=m68k vendor=atari basic_os=mint ;; news-3600 | risc-news) cpu=mips vendor=sony basic_os=newsos ;; next | m*-next) cpu=m68k vendor=next case $basic_os in openstep*) ;; nextstep*) ;; ns2*) basic_os=nextstep2 ;; *) basic_os=nextstep3 ;; esac ;; np1) cpu=np1 vendor=gould ;; op50n-* | op60c-*) cpu=hppa1.1 vendor=oki basic_os=proelf ;; pa-hitachi) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; pbd) cpu=sparc vendor=tti ;; pbb) cpu=m68k vendor=tti ;; pc532) cpu=ns32k vendor=pc532 ;; pn) cpu=pn vendor=gould ;; power) cpu=power vendor=ibm ;; ps2) cpu=i386 vendor=ibm ;; rm[46]00) cpu=mips vendor=siemens ;; rtpc | rtpc-*) cpu=romp vendor=ibm ;; sde) cpu=mipsisa32 vendor=sde basic_os=${basic_os:-elf} ;; simso-wrs) cpu=sparclite vendor=wrs basic_os=vxworks ;; tower | tower-32) cpu=m68k vendor=ncr ;; vpp*|vx|vx-*) cpu=f301 vendor=fujitsu ;; w65) cpu=w65 vendor=wdc ;; w89k-*) cpu=hppa1.1 vendor=winbond basic_os=proelf ;; none) cpu=none vendor=none ;; leon|leon[3-9]) cpu=sparc vendor=$basic_machine ;; leon-*|leon[3-9]-*) cpu=sparc vendor=`echo "$basic_machine" | sed 's/-.*//'` ;; *-*) # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read cpu vendor <&2 exit 1 ;; esac ;; esac # Here we canonicalize certain aliases for manufacturers. case $vendor in digital*) vendor=dec ;; commodore*) vendor=cbm ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if test x$basic_os != x then # First recognize some ad-hoc cases, or perhaps split kernel-os, or else just # set os. case $basic_os in gnu/linux*) kernel=linux os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'` ;; os2-emx) kernel=os2 os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'` ;; nto-qnx*) kernel=nto os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'` ;; *-*) # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read kernel os <&2 exit 1 ;; esac # As a final step for OS-related things, validate the OS-kernel combination # (given a valid OS), if there is a kernel. case $kernel-$os in linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ | linux-musl* | linux-relibc* | linux-uclibc* ) ;; uclinux-uclibc* ) ;; -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* ) # These are just libc implementations, not actual OSes, and thus # require a kernel. echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 exit 1 ;; kfreebsd*-gnu* | kopensolaris*-gnu*) ;; vxworks-simlinux | vxworks-simwindows | vxworks-spe) ;; nto-qnx*) ;; os2-emx) ;; *-eabi* | *-gnueabi*) ;; -*) # Blank kernel with real OS is always fine. ;; *-*) echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 exit 1 ;; esac # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. case $vendor in unknown) case $cpu-$os in *-riscix*) vendor=acorn ;; *-sunos*) vendor=sun ;; *-cnk* | *-aix*) vendor=ibm ;; *-beos*) vendor=be ;; *-hpux*) vendor=hp ;; *-mpeix*) vendor=hp ;; *-hiux*) vendor=hitachi ;; *-unos*) vendor=crds ;; *-dgux*) vendor=dg ;; *-luna*) vendor=omron ;; *-genix*) vendor=ns ;; *-clix*) vendor=intergraph ;; *-mvs* | *-opened*) vendor=ibm ;; *-os400*) vendor=ibm ;; s390-* | s390x-*) vendor=ibm ;; *-ptx*) vendor=sequent ;; *-tpf*) vendor=ibm ;; *-vxsim* | *-vxworks* | *-windiss*) vendor=wrs ;; *-aux*) vendor=apple ;; *-hms*) vendor=hitachi ;; *-mpw* | *-macos*) vendor=apple ;; *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) vendor=atari ;; *-vos*) vendor=stratus ;; esac ;; esac echo "$cpu-$vendor-${kernel:+$kernel-}$os" exit # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: libpqxx-8.0.1/config/depcomp000077500000000000000000000560201516427024100160360ustar00rootroot00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2018-03-07.03; # UTC # Copyright (C) 1999-2021 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: libpqxx-8.0.1/config/flags/000077500000000000000000000000001516427024100155525ustar00rootroot00000000000000libpqxx-8.0.1/config/flags/audit-mode.txt000066400000000000000000000017141516427024100203460ustar00rootroot00000000000000# Compiler flags for "audit mode." # # We run these through compiler_flags.py to figure out which ones the compiler # actually supports. It's a case of "more is better," but it's not a problem # if only some compilers support only some of these flags. -fno-sanitize-recover=all -fsanitize=address -fsanitize-address-use-after-scope -fsanitize=alignment -fsanitize=bool -fsanitize=bounds -fsanitize=bounds-strict -fsanitize=builtin -fsanitize=enum -fsanitize=float-cast-overflow -fsanitize=float-divide-by-zero -fsanitize=integer-divide-by-zero -fsanitize=leak -fsanitize=nonnull-attribute -fsanitize=null -fsanitize=object-size -fsanitize=pointer-compare -fsanitize=pointer-overflow -fsanitize=pointer-subtract -fsanitize=return -fsanitize=returns-nonnull-attribute -fsanitize=shift -fsanitize=shift-base -fsanitize=shift-exponent -fsanitize=signed-integer-overflow -fsanitize=undefined -fsanitize=unreachable -fsanitize=vla-bound -fsanitize=vptr -fstack-protector-all libpqxx-8.0.1/config/flags/maintainer-mode.txt000066400000000000000000000025451516427024100213720ustar00rootroot00000000000000# Compiler flags for "maintainer mode". # # We run these through compiler_flags.py to figure out which ones the compiler # actually supports. It's a case of "more is better," but it's not a problem # if only some compilers support only some of these flags. # # There's also -fanalyzer, which is a macro for many of these options, but as # of gcc 13.2.0 it still causes a lot of errors for the standard library. -fnothrow-opt -Wanalyzer-double-fclose -Wanalyzer-double-free -Wanalyzer-exposure-through-output-file -Wanalyzer-file-leak -Wanalyzer-free-of-non-heap -Wanalyzer-malloc-leak -Wanalyzer-possible-null-dereference -Wanalyzer-mismatching-deallocation -Wanalyzer-null-dereference -Wanalyzer-null-argument -Wanalyzer-possible-null-argument -Wanalyzer-shift-count-negative -Wanalyzer-overflow -Wanalyzer-stale-setjmp-buffer -Wanalyzer-tainted-array-index -Wanalyzer-unsafe-call-within-signal-handler -Wanalyzer-use-after-free -Wanalyzer-use-of-pointer-in-stale-stack-frame -Wanalyzer-use-of-uninitialized-value -Wanalyzer-write-to-const -Wanalyzer-write-to-string-literal -Warray-bounds=2 -Wattribute-alias=2 -Wdangling-gsl -Wdangling-reference -Wdeprecated-literal-operator -Wduplicated-branches -Wduplicated-cond -Wlogical-op -Wmismatched-tags -Wredundant-tags -Wrestrict -Wstringop-overflow -Wsuggest-attribute=noreturn -Wsuggest-override -Wtrampolines -Wunreachable-code libpqxx-8.0.1/config/flags/suggest-mode.txt000066400000000000000000000006251516427024100207210ustar00rootroot00000000000000# Compiler flags for "suggest mode". # # We run these through compiler_flags.py to figure out which ones the compiler # actually supports. It's a case of "more is better," but it's not a problem # if only some compilers support only some of these flags. -Wsuggest-attribute=cold -Wsuggest-attribute=const -Wsuggest-attribute=malloc -Wsuggest-attribute=pure -Wsuggest-final-types -Wsuggest-final-methods libpqxx-8.0.1/config/install-sh000077500000000000000000000357761516427024100165040ustar00rootroot00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2020-11-14.01; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_mkdir= # Desired mode of installed file. mode=0755 # Create dirs (including intermediate dirs) using mode 755. # This is like GNU 'install' as of coreutils 8.32 (2020). mkdir_umask=22 backupsuffix= chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -p pass -p to $cpprog. -s $stripprog installed files. -S SUFFIX attempt to back up existing files, with suffix SUFFIX. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG By default, rm is invoked with -f; when overridden with RMPROG, it's up to you to specify -f if you want it. If -S is not specified, no backups are attempted. Email bug reports to bug-automake@gnu.org. Automake home page: https://www.gnu.org/software/automake/ " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -p) cpprog="$cpprog -p";; -s) stripcmd=$stripprog;; -S) backupsuffix="$2" shift;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? # Don't chown directories that already exist. if test $dstdir_status = 0; then chowncmd="" fi else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dstbase=`basename "$src"` case $dst in */) dst=$dst$dstbase;; *) dst=$dst/$dstbase;; esac dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi case $dstdir in */) dstdirslash=$dstdir;; *) dstdirslash=$dstdir/;; esac obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false # The $RANDOM variable is not portable (e.g., dash). Use it # here however when possible just to lower collision chance. tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap ' ret=$? rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null exit $ret ' 0 # Because "mkdir -p" follows existing symlinks and we likely work # directly in world-writeable /tmp, make sure that the '$tmpdir' # directory is successfully created first before we actually test # 'mkdir -p'. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac oIFS=$IFS IFS=/ set -f set fnord $dstdir shift set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=${dstdirslash}_inst.$$_ rmtmp=${dstdirslash}_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && { test -z "$stripcmd" || { # Create $dsttmp read-write so that cp doesn't create it read-only, # which would cause strip to fail. if test -z "$doit"; then : >"$dsttmp" # No need to fork-exec 'touch'. else $doit touch "$dsttmp" fi } } && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # If $backupsuffix is set, and the file being installed # already exists, attempt a backup. Don't worry if it fails, # e.g., if mv doesn't support -f. if test -n "$backupsuffix" && test -f "$dst"; then $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null fi # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: libpqxx-8.0.1/config/ltmain.sh000077500000000000000000012123751516427024100163140ustar00rootroot00000000000000#! /usr/bin/env sh ## DO NOT EDIT - This file generated from ./build-aux/ltmain.in ## by inline-source v2019-02-19.15 # libtool (GNU libtool) 2.4.7 # Provide generalized library-building support services. # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996-2019, 2021-2022 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . PROGRAM=libtool PACKAGE=libtool VERSION="2.4.7 Debian-2.4.7-7build1" package_revision=2.4.7 ## ------ ## ## Usage. ## ## ------ ## # Run './libtool --help' for help with using this script from the # command line. ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # After configure completes, it has a better idea of some of the # shell tools we need than the defaults used by the functions shared # with bootstrap, so set those here where they can still be over- # ridden by the user, but otherwise take precedence. : ${AUTOCONF="autoconf"} : ${AUTOMAKE="automake"} ## -------------------------- ## ## Source external libraries. ## ## -------------------------- ## # Much of our low-level functionality needs to be sourced from external # libraries, which are installed to $pkgauxdir. # Set a version string for this script. scriptversion=2019-02-19.15; # UTC # General shell script boiler plate, and helper functions. # Written by Gary V. Vaughan, 2004 # This is free software. There is NO warranty; not even for # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # Copyright (C) 2004-2019, 2021 Bootstrap Authors # # This file is dual licensed under the terms of the MIT license # , and GPL version 2 or later # . You must apply one of # these licenses when using or redistributing this software or any of # the files within it. See the URLs above, or the file `LICENSE` # included in the Bootstrap distribution for the full license texts. # Please report bugs or propose patches to: # ## ------ ## ## Usage. ## ## ------ ## # Evaluate this file near the top of your script to gain access to # the functions and variables defined here: # # . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh # # If you need to override any of the default environment variable # settings, do that before evaluating this file. ## -------------------- ## ## Shell normalisation. ## ## -------------------- ## # Some shells need a little help to be as Bourne compatible as possible. # Before doing anything else, make sure all that help has been provided! DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # NLS nuisances: We save the old values in case they are required later. _G_user_locale= _G_safe_locale= for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test set = \"\${$_G_var+set}\"; then save_$_G_var=\$$_G_var $_G_var=C export $_G_var _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" fi" done # These NLS vars are set unconditionally (bootstrap issue #24). Unset those # in case the environment reset is needed later and the $save_* variant is not # defined (see the code above). LC_ALL=C LANGUAGE=C export LANGUAGE LC_ALL # Make sure IFS has a sensible default sp=' ' nl=' ' IFS="$sp $nl" # There are apparently some retarded systems that use ';' as a PATH separator! if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # func_unset VAR # -------------- # Portably unset VAR. # In some shells, an 'unset VAR' statement leaves a non-zero return # status if VAR is already unset, which might be problematic if the # statement is used at the end of a function (thus poisoning its return # value) or when 'set -e' is active (causing even a spurious abort of # the script in this case). func_unset () { { eval $1=; (eval unset $1) >/dev/null 2>&1 && eval unset $1 || : ; } } # Make sure CDPATH doesn't cause `cd` commands to output the target dir. func_unset CDPATH # Make sure ${,E,F}GREP behave sanely. func_unset GREP_OPTIONS ## ------------------------- ## ## Locate command utilities. ## ## ------------------------- ## # func_executable_p FILE # ---------------------- # Check that FILE is an executable regular file. func_executable_p () { test -f "$1" && test -x "$1" } # func_path_progs PROGS_LIST CHECK_FUNC [PATH] # -------------------------------------------- # Search for either a program that responds to --version with output # containing "GNU", or else returned by CHECK_FUNC otherwise, by # trying all the directories in PATH with each of the elements of # PROGS_LIST. # # CHECK_FUNC should accept the path to a candidate program, and # set $func_check_prog_result if it truncates its output less than # $_G_path_prog_max characters. func_path_progs () { _G_progs_list=$1 _G_check_func=$2 _G_PATH=${3-"$PATH"} _G_path_prog_max=0 _G_path_prog_found=false _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} for _G_dir in $_G_PATH; do IFS=$_G_save_IFS test -z "$_G_dir" && _G_dir=. for _G_prog_name in $_G_progs_list; do for _exeext in '' .EXE; do _G_path_prog=$_G_dir/$_G_prog_name$_exeext func_executable_p "$_G_path_prog" || continue case `"$_G_path_prog" --version 2>&1` in *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; *) $_G_check_func $_G_path_prog func_path_progs_result=$func_check_prog_result ;; esac $_G_path_prog_found && break 3 done done done IFS=$_G_save_IFS test -z "$func_path_progs_result" && { echo "no acceptable sed could be found in \$PATH" >&2 exit 1 } } # We want to be able to use the functions in this file before configure # has figured out where the best binaries are kept, which means we have # to search for them ourselves - except when the results are already set # where we skip the searches. # Unless the user overrides by setting SED, search the path for either GNU # sed, or the sed that truncates its output the least. test -z "$SED" && { _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for _G_i in 1 2 3 4 5 6 7; do _G_sed_script=$_G_sed_script$nl$_G_sed_script done echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed _G_sed_script= func_check_prog_sed () { _G_path_prog=$1 _G_count=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo '' >> conftest.nl "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "sed gsed" func_check_prog_sed "$PATH:/usr/xpg4/bin" rm -f conftest.sed SED=$func_path_progs_result } # Unless the user overrides by setting GREP, search the path for either GNU # grep, or the grep that truncates its output the least. test -z "$GREP" && { func_check_prog_grep () { _G_path_prog=$1 _G_count=0 _G_path_prog_max=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo 'GREP' >> conftest.nl "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "grep ggrep" func_check_prog_grep "$PATH:/usr/xpg4/bin" GREP=$func_path_progs_result } ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # All uppercase variable names are used for environment variables. These # variables can be overridden by the user before calling a script that # uses them if a suitable command of that name is not already available # in the command search PATH. : ${CP="cp -f"} : ${ECHO="printf %s\n"} : ${EGREP="$GREP -E"} : ${FGREP="$GREP -F"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} ## -------------------- ## ## Useful sed snippets. ## ## -------------------- ## sed_dirname='s|/[^/]*$||' sed_basename='s|^.*/||' # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='s|\([`"$\\]\)|\\\1|g' # Same as above, but do not quote variable references. sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' # Sed substitution that converts a w32 file name or path # that contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-'\' parameter expansions in output of sed_double_quote_subst that # were '\'-ed in input to the same. If an odd number of '\' preceded a # '$' in input to sed_double_quote_subst, that '$' was protected from # expansion. Since each input '\' is now two '\'s, look for any number # of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. _G_bs='\\' _G_bs2='\\\\' _G_bs4='\\\\\\\\' _G_dollar='\$' sed_double_backslash="\ s/$_G_bs4/&\\ /g s/^$_G_bs2$_G_dollar/$_G_bs&/ s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g s/\n//g" # require_check_ifs_backslash # --------------------------- # Check if we can use backslash as IFS='\' separator, and set # $check_ifs_backshlash_broken to ':' or 'false'. require_check_ifs_backslash=func_require_check_ifs_backslash func_require_check_ifs_backslash () { _G_save_IFS=$IFS IFS='\' _G_check_ifs_backshlash='a\\b' for _G_i in $_G_check_ifs_backshlash do case $_G_i in a) check_ifs_backshlash_broken=false ;; '') break ;; *) check_ifs_backshlash_broken=: break ;; esac done IFS=$_G_save_IFS require_check_ifs_backslash=: } ## ----------------- ## ## Global variables. ## ## ----------------- ## # Except for the global variables explicitly listed below, the following # functions in the '^func_' namespace, and the '^require_' namespace # variables initialised in the 'Resource management' section, sourcing # this file will not pollute your global namespace with anything # else. There's no portable way to scope variables in Bourne shell # though, so actually running these functions will sometimes place # results into a variable named after the function, and often use # temporary variables in the '^_G_' namespace. If you are careful to # avoid using those namespaces casually in your sourcing script, things # should continue to work as you expect. And, of course, you can freely # overwrite any of the functions or variables defined here before # calling anything to customize them. EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. # Allow overriding, eg assuming that you follow the convention of # putting '$debug_cmd' at the start of all your functions, you can get # bash to show function call trace with: # # debug_cmd='echo "${FUNCNAME[0]} $*" >&2' bash your-script-name debug_cmd=${debug_cmd-":"} exit_cmd=: # By convention, finish your script with: # # exit $exit_status # # so that you can set exit_status to non-zero if you want to indicate # something went wrong during execution without actually bailing out at # the point of failure. exit_status=$EXIT_SUCCESS # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath=$0 # The name of this program. progname=`$ECHO "$progpath" |$SED "$sed_basename"` # Make sure we have an absolute progpath for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` progdir=`cd "$progdir" && pwd` progpath=$progdir/$progname ;; *) _G_IFS=$IFS IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS=$_G_IFS test -x "$progdir/$progname" && break done IFS=$_G_IFS test -n "$progdir" || progdir=`pwd` progpath=$progdir/$progname ;; esac ## ----------------- ## ## Standard options. ## ## ----------------- ## # The following options affect the operation of the functions defined # below, and should be set appropriately depending on run-time para- # meters passed on the command line. opt_dry_run=false opt_quiet=false opt_verbose=false # Categories 'all' and 'none' are always available. Append any others # you will pass as the first argument to func_warning from your own # code. warning_categories= # By default, display warnings according to 'opt_warning_types'. Set # 'warning_func' to ':' to elide all warnings, or func_fatal_error to # treat the next displayed warning as a fatal error. warning_func=func_warn_and_continue # Set to 'all' to display all warnings, 'none' to suppress all # warnings, or a space delimited list of some subset of # 'warning_categories' to display only the listed warnings. opt_warning_types=all ## -------------------- ## ## Resource management. ## ## -------------------- ## # This section contains definitions for functions that each ensure a # particular resource (a file, or a non-empty configuration variable for # example) is available, and if appropriate to extract default values # from pertinent package files. Call them using their associated # 'require_*' variable to ensure that they are executed, at most, once. # # It's entirely deliberate that calling these functions can set # variables that don't obey the namespace limitations obeyed by the rest # of this file, in order that that they be as useful as possible to # callers. # require_term_colors # ------------------- # Allow display of bold text on terminals that support it. require_term_colors=func_require_term_colors func_require_term_colors () { $debug_cmd test -t 1 && { # COLORTERM and USE_ANSI_COLORS environment variables take # precedence, because most terminfo databases neglect to describe # whether color sequences are supported. test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} if test 1 = "$USE_ANSI_COLORS"; then # Standard ANSI escape sequences tc_reset='' tc_bold=''; tc_standout='' tc_red=''; tc_green='' tc_blue=''; tc_cyan='' else # Otherwise trust the terminfo database after all. test -n "`tput sgr0 2>/dev/null`" && { tc_reset=`tput sgr0` test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` tc_standout=$tc_bold test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` } fi } require_term_colors=: } ## ----------------- ## ## Function library. ## ## ----------------- ## # This section contains a variety of useful functions to call in your # scripts. Take note of the portable wrappers for features provided by # some modern shells, which will fall back to slower equivalents on # less featureful shells. # func_append VAR VALUE # --------------------- # Append VALUE onto the existing contents of VAR. # _G_HAVE_PLUSEQ_OP # Can be empty, in which case the shell is probed, "yes" if += is # useable or anything else if it does not work. if test -z "$_G_HAVE_PLUSEQ_OP" && \ __PLUSEQ_TEST="a" && \ __PLUSEQ_TEST+=" b" 2>/dev/null && \ test "a b" = "$__PLUSEQ_TEST"; then _G_HAVE_PLUSEQ_OP=yes fi if test yes = "$_G_HAVE_PLUSEQ_OP" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_append () { $debug_cmd eval "$1+=\$2" }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_append () { $debug_cmd eval "$1=\$$1\$2" } fi # func_append_quoted VAR VALUE # ---------------------------- # Quote VALUE and append to the end of shell variable VAR, separated # by a space. if test yes = "$_G_HAVE_PLUSEQ_OP"; then eval 'func_append_quoted () { $debug_cmd func_quote_arg pretty "$2" eval "$1+=\\ \$func_quote_arg_result" }' else func_append_quoted () { $debug_cmd func_quote_arg pretty "$2" eval "$1=\$$1\\ \$func_quote_arg_result" } fi # func_append_uniq VAR VALUE # -------------------------- # Append unique VALUE onto the existing contents of VAR, assuming # entries are delimited by the first character of VALUE. For example: # # func_append_uniq options " --another-option option-argument" # # will only append to $options if " --another-option option-argument " # is not already present somewhere in $options already (note spaces at # each end implied by leading space in second argument). func_append_uniq () { $debug_cmd eval _G_current_value='`$ECHO $'$1'`' _G_delim=`expr "$2" : '\(.\)'` case $_G_delim$_G_current_value$_G_delim in *"$2$_G_delim"*) ;; *) func_append "$@" ;; esac } # func_arith TERM... # ------------------ # Set func_arith_result to the result of evaluating TERMs. test -z "$_G_HAVE_ARITH_OP" \ && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ && _G_HAVE_ARITH_OP=yes if test yes = "$_G_HAVE_ARITH_OP"; then eval 'func_arith () { $debug_cmd func_arith_result=$(( $* )) }' else func_arith () { $debug_cmd func_arith_result=`expr "$@"` } fi # func_basename FILE # ------------------ # Set func_basename_result to FILE with everything up to and including # the last / stripped. if test yes = "$_G_HAVE_XSI_OPS"; then # If this shell supports suffix pattern removal, then use it to avoid # forking. Hide the definitions single quotes in case the shell chokes # on unsupported syntax... _b='func_basename_result=${1##*/}' _d='case $1 in */*) func_dirname_result=${1%/*}$2 ;; * ) func_dirname_result=$3 ;; esac' else # ...otherwise fall back to using sed. _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` if test "X$func_dirname_result" = "X$1"; then func_dirname_result=$3 else func_append func_dirname_result "$2" fi' fi eval 'func_basename () { $debug_cmd '"$_b"' }' # func_dirname FILE APPEND NONDIR_REPLACEMENT # ------------------------------------------- # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. eval 'func_dirname () { $debug_cmd '"$_d"' }' # func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT # -------------------------------------------------------- # Perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # For efficiency, we do not delegate to the functions above but instead # duplicate the functionality here. eval 'func_dirname_and_basename () { $debug_cmd '"$_b"' '"$_d"' }' # func_echo ARG... # ---------------- # Echo program name prefixed message. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname: $_G_line" done IFS=$func_echo_IFS } # func_echo_all ARG... # -------------------- # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_echo_infix_1 INFIX ARG... # ------------------------------ # Echo program name, followed by INFIX on the first line, with any # additional lines not showing INFIX. func_echo_infix_1 () { $debug_cmd $require_term_colors _G_infix=$1; shift _G_indent=$_G_infix _G_prefix="$progname: $_G_infix: " _G_message=$* # Strip color escape sequences before counting printable length for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" do test -n "$_G_tc" && { _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` } done _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes func_echo_infix_1_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_infix_1_IFS $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 _G_prefix=$_G_indent done IFS=$func_echo_infix_1_IFS } # func_error ARG... # ----------------- # Echo program name prefixed message to standard error. func_error () { $debug_cmd $require_term_colors func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 } # func_fatal_error ARG... # ----------------------- # Echo program name prefixed message to standard error, and exit. func_fatal_error () { $debug_cmd func_error "$*" exit $EXIT_FAILURE } # func_grep EXPRESSION FILENAME # ----------------------------- # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $debug_cmd $GREP "$1" "$2" >/dev/null 2>&1 } # func_len STRING # --------------- # Set func_len_result to the length of STRING. STRING may not # start with a hyphen. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_len () { $debug_cmd func_len_result=${#1} }' else func_len () { $debug_cmd func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` } fi # func_mkdir_p DIRECTORY-PATH # --------------------------- # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { $debug_cmd _G_directory_path=$1 _G_dir_list= if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then # Protect directory names starting with '-' case $_G_directory_path in -*) _G_directory_path=./$_G_directory_path ;; esac # While some portion of DIR does not yet exist... while test ! -d "$_G_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. _G_dir_list=$_G_directory_path:$_G_dir_list # If the last portion added has no slash in it, the list is done case $_G_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` done _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` func_mkdir_p_IFS=$IFS; IFS=: for _G_dir in $_G_dir_list; do IFS=$func_mkdir_p_IFS # mkdir can fail with a 'File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$_G_dir" 2>/dev/null || : done IFS=$func_mkdir_p_IFS # Bail out if we (or some other process) failed to create a directory. test -d "$_G_directory_path" || \ func_fatal_error "Failed to create '$1'" fi } # func_mktempdir [BASENAME] # ------------------------- # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, BASENAME is the basename for that directory. func_mktempdir () { $debug_cmd _G_template=${TMPDIR-/tmp}/${1-$progname} if test : = "$opt_dry_run"; then # Return a directory name, but don't create it in dry-run mode _G_tmpdir=$_G_template-$$ else # If mktemp works, use that first and foremost _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` if test ! -d "$_G_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race _G_tmpdir=$_G_template-${RANDOM-0}$$ func_mktempdir_umask=`umask` umask 0077 $MKDIR "$_G_tmpdir" umask $func_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$_G_tmpdir" || \ func_fatal_error "cannot create temporary directory '$_G_tmpdir'" fi $ECHO "$_G_tmpdir" } # func_normal_abspath PATH # ------------------------ # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. func_normal_abspath () { $debug_cmd # These SED scripts presuppose an absolute path with a trailing slash. _G_pathcar='s|^/\([^/]*\).*$|\1|' _G_pathcdr='s|^/[^/]*||' _G_removedotparts=':dotsl s|/\./|/|g t dotsl s|/\.$|/|' _G_collapseslashes='s|/\{1,\}|/|g' _G_finalslash='s|/*$|/|' # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` while :; do # Processed it all yet? if test / = "$func_normal_abspath_tpath"; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result"; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_notquiet ARG... # -------------------- # Echo program name prefixed message only when not in quiet mode. func_notquiet () { $debug_cmd $opt_quiet || func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_relative_path SRCDIR DSTDIR # -------------------------------- # Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. func_relative_path () { $debug_cmd func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=$func_dirname_result if test -z "$func_relative_path_tlibdir"; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test -n "$func_stripname_result"; then func_append func_relative_path_result "/$func_stripname_result" fi # Normalisation. If bindir is libdir, return '.' else relative path. if test -n "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result" func_relative_path_result=$func_stripname_result fi test -n "$func_relative_path_result" || func_relative_path_result=. : } # func_quote_portable EVAL ARG # ---------------------------- # Internal function to portably implement func_quote_arg. Note that we still # keep attention to performance here so we as much as possible try to avoid # calling sed binary (so far O(N) complexity as long as func_append is O(1)). func_quote_portable () { $debug_cmd $require_check_ifs_backslash func_quote_portable_result=$2 # one-time-loop (easy break) while true do if $1; then func_quote_portable_result=`$ECHO "$2" | $SED \ -e "$sed_double_quote_subst" -e "$sed_double_backslash"` break fi # Quote for eval. case $func_quote_portable_result in *[\\\`\"\$]*) # Fallback to sed for $func_check_bs_ifs_broken=:, or when the string # contains the shell wildcard characters. case $check_ifs_backshlash_broken$func_quote_portable_result in :*|*[\[\*\?]*) func_quote_portable_result=`$ECHO "$func_quote_portable_result" \ | $SED "$sed_quote_subst"` break ;; esac func_quote_portable_old_IFS=$IFS for _G_char in '\' '`' '"' '$' do # STATE($1) PREV($2) SEPARATOR($3) set start "" "" func_quote_portable_result=dummy"$_G_char$func_quote_portable_result$_G_char"dummy IFS=$_G_char for _G_part in $func_quote_portable_result do case $1 in quote) func_append func_quote_portable_result "$3$2" set quote "$_G_part" "\\$_G_char" ;; start) set first "" "" func_quote_portable_result= ;; first) set quote "$_G_part" "" ;; esac done done IFS=$func_quote_portable_old_IFS ;; *) ;; esac break done func_quote_portable_unquoted_result=$func_quote_portable_result case $func_quote_portable_result in # double-quote args containing shell metacharacters to delay # word splitting, command substitution and variable expansion # for a subsequent eval. # many bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_portable_result=\"$func_quote_portable_result\" ;; esac } # func_quotefast_eval ARG # ----------------------- # Quote one ARG (internal). This is equivalent to 'func_quote_arg eval ARG', # but optimized for speed. Result is stored in $func_quotefast_eval. if test xyes = `(x=; printf -v x %q yes; echo x"$x") 2>/dev/null`; then printf -v _GL_test_printf_tilde %q '~' if test '\~' = "$_GL_test_printf_tilde"; then func_quotefast_eval () { printf -v func_quotefast_eval_result %q "$1" } else # Broken older Bash implementations. Make those faster too if possible. func_quotefast_eval () { case $1 in '~'*) func_quote_portable false "$1" func_quotefast_eval_result=$func_quote_portable_result ;; *) printf -v func_quotefast_eval_result %q "$1" ;; esac } fi else func_quotefast_eval () { func_quote_portable false "$1" func_quotefast_eval_result=$func_quote_portable_result } fi # func_quote_arg MODEs ARG # ------------------------ # Quote one ARG to be evaled later. MODEs argument may contain zero or more # specifiers listed below separated by ',' character. This function returns two # values: # i) func_quote_arg_result # double-quoted (when needed), suitable for a subsequent eval # ii) func_quote_arg_unquoted_result # has all characters that are still active within double # quotes backslashified. Available only if 'unquoted' is specified. # # Available modes: # ---------------- # 'eval' (default) # - escape shell special characters # 'expand' # - the same as 'eval'; but do not quote variable references # 'pretty' # - request aesthetic output, i.e. '"a b"' instead of 'a\ b'. This might # be used later in func_quote to get output like: 'echo "a b"' instead # of 'echo a\ b'. This is slower than default on some shells. # 'unquoted' # - produce also $func_quote_arg_unquoted_result which does not contain # wrapping double-quotes. # # Examples for 'func_quote_arg pretty,unquoted string': # # string | *_result | *_unquoted_result # ------------+-----------------------+------------------- # " | \" | \" # a b | "a b" | a b # "a b" | "\"a b\"" | \"a b\" # * | "*" | * # z="${x-$y}" | "z=\"\${x-\$y}\"" | z=\"\${x-\$y}\" # # Examples for 'func_quote_arg pretty,unquoted,expand string': # # string | *_result | *_unquoted_result # --------------+---------------------+-------------------- # z="${x-$y}" | "z=\"${x-$y}\"" | z=\"${x-$y}\" func_quote_arg () { _G_quote_expand=false case ,$1, in *,expand,*) _G_quote_expand=: ;; esac case ,$1, in *,pretty,*|*,expand,*|*,unquoted,*) func_quote_portable $_G_quote_expand "$2" func_quote_arg_result=$func_quote_portable_result func_quote_arg_unquoted_result=$func_quote_portable_unquoted_result ;; *) # Faster quote-for-eval for some shells. func_quotefast_eval "$2" func_quote_arg_result=$func_quotefast_eval_result ;; esac } # func_quote MODEs ARGs... # ------------------------ # Quote all ARGs to be evaled later and join them into single command. See # func_quote_arg's description for more info. func_quote () { $debug_cmd _G_func_quote_mode=$1 ; shift func_quote_result= while test 0 -lt $#; do func_quote_arg "$_G_func_quote_mode" "$1" if test -n "$func_quote_result"; then func_append func_quote_result " $func_quote_arg_result" else func_append func_quote_result "$func_quote_arg_result" fi shift done } # func_stripname PREFIX SUFFIX NAME # --------------------------------- # strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_stripname () { $debug_cmd # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary variable first. func_stripname_result=$3 func_stripname_result=${func_stripname_result#"$1"} func_stripname_result=${func_stripname_result%"$2"} }' else func_stripname () { $debug_cmd case $2 in .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; esac } fi # func_show_eval CMD [FAIL_EXP] # ----------------------------- # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} func_quote_arg pretty,expand "$_G_cmd" eval "func_notquiet $func_quote_arg_result" $opt_dry_run || { eval "$_G_cmd" _G_status=$? if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_show_eval_locale CMD [FAIL_EXP] # ------------------------------------ # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} $opt_quiet || { func_quote_arg expand,pretty "$_G_cmd" eval "func_echo $func_quote_arg_result" } $opt_dry_run || { eval "$_G_user_locale $_G_cmd" _G_status=$? eval "$_G_safe_locale" if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_tr_sh # ---------- # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { $debug_cmd case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_verbose ARG... # ------------------- # Echo program name prefixed message in verbose mode only. func_verbose () { $debug_cmd $opt_verbose && func_echo "$*" : } # func_warn_and_continue ARG... # ----------------------------- # Echo program name prefixed warning message to standard error. func_warn_and_continue () { $debug_cmd $require_term_colors func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 } # func_warning CATEGORY ARG... # ---------------------------- # Echo program name prefixed warning message to standard error. Warning # messages can be filtered according to CATEGORY, where this function # elides messages where CATEGORY is not listed in the global variable # 'opt_warning_types'. func_warning () { $debug_cmd # CATEGORY must be in the warning_categories list! case " $warning_categories " in *" $1 "*) ;; *) func_internal_error "invalid warning category '$1'" ;; esac _G_category=$1 shift case " $opt_warning_types " in *" $_G_category "*) $warning_func ${1+"$@"} ;; esac } # func_sort_ver VER1 VER2 # ----------------------- # 'sort -V' is not generally available. # Note this deviates from the version comparison in automake # in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a # but this should suffice as we won't be specifying old # version formats or redundant trailing .0 in bootstrap.conf. # If we did want full compatibility then we should probably # use m4_version_compare from autoconf. func_sort_ver () { $debug_cmd printf '%s\n%s\n' "$1" "$2" \ | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n } # func_lt_ver PREV CURR # --------------------- # Return true if PREV and CURR are in the correct order according to # func_sort_ver, otherwise false. Use it like this: # # func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." func_lt_ver () { $debug_cmd test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: #! /bin/sh # A portable, pluggable option parser for Bourne shell. # Written by Gary V. Vaughan, 2010 # This is free software. There is NO warranty; not even for # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # Copyright (C) 2010-2019, 2021 Bootstrap Authors # # This file is dual licensed under the terms of the MIT license # , and GPL version 2 or later # . You must apply one of # these licenses when using or redistributing this software or any of # the files within it. See the URLs above, or the file `LICENSE` # included in the Bootstrap distribution for the full license texts. # Please report bugs or propose patches to: # # Set a version string for this script. scriptversion=2019-02-19.15; # UTC ## ------ ## ## Usage. ## ## ------ ## # This file is a library for parsing options in your shell scripts along # with assorted other useful supporting features that you can make use # of too. # # For the simplest scripts you might need only: # # #!/bin/sh # . relative/path/to/funclib.sh # . relative/path/to/options-parser # scriptversion=1.0 # func_options ${1+"$@"} # eval set dummy "$func_options_result"; shift # ...rest of your script... # # In order for the '--version' option to work, you will need to have a # suitably formatted comment like the one at the top of this file # starting with '# Written by ' and ending with '# Copyright'. # # For '-h' and '--help' to work, you will also need a one line # description of your script's purpose in a comment directly above the # '# Written by ' line, like the one at the top of this file. # # The default options also support '--debug', which will turn on shell # execution tracing (see the comment above debug_cmd below for another # use), and '--verbose' and the func_verbose function to allow your script # to display verbose messages only when your user has specified # '--verbose'. # # After sourcing this file, you can plug in processing for additional # options by amending the variables from the 'Configuration' section # below, and following the instructions in the 'Option parsing' # section further down. ## -------------- ## ## Configuration. ## ## -------------- ## # You should override these variables in your script after sourcing this # file so that they reflect the customisations you have added to the # option parser. # The usage line for option parsing errors and the start of '-h' and # '--help' output messages. You can embed shell variables for delayed # expansion at the time the message is displayed, but you will need to # quote other shell meta-characters carefully to prevent them being # expanded when the contents are evaled. usage='$progpath [OPTION]...' # Short help message in response to '-h' and '--help'. Add to this or # override it after sourcing this library to reflect the full set of # options your script accepts. usage_message="\ --debug enable verbose shell tracing -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -v, --verbose verbosely report processing --version print version information and exit -h, --help print short or long help message and exit " # Additional text appended to 'usage_message' in response to '--help'. long_help_message=" Warning categories include: 'all' show all warnings 'none' turn off all the warnings 'error' warnings are treated as fatal errors" # Help message printed before fatal option parsing errors. fatal_help="Try '\$progname --help' for more information." ## ------------------------- ## ## Hook function management. ## ## ------------------------- ## # This section contains functions for adding, removing, and running hooks # in the main code. A hook is just a list of function names that can be # run in order later on. # func_hookable FUNC_NAME # ----------------------- # Declare that FUNC_NAME will run hooks added with # 'func_add_hook FUNC_NAME ...'. func_hookable () { $debug_cmd func_append hookable_fns " $1" } # func_add_hook FUNC_NAME HOOK_FUNC # --------------------------------- # Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must # first have been declared "hookable" by a call to 'func_hookable'. func_add_hook () { $debug_cmd case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not accept hook functions." ;; esac eval func_append ${1}_hooks '" $2"' } # func_remove_hook FUNC_NAME HOOK_FUNC # ------------------------------------ # Remove HOOK_FUNC from the list of hook functions to be called by # FUNC_NAME. func_remove_hook () { $debug_cmd eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' } # func_propagate_result FUNC_NAME_A FUNC_NAME_B # --------------------------------------------- # If the *_result variable of FUNC_NAME_A _is set_, assign its value to # *_result variable of FUNC_NAME_B. func_propagate_result () { $debug_cmd func_propagate_result_result=: if eval "test \"\${${1}_result+set}\" = set" then eval "${2}_result=\$${1}_result" else func_propagate_result_result=false fi } # func_run_hooks FUNC_NAME [ARG]... # --------------------------------- # Run all hook functions registered to FUNC_NAME. # It's assumed that the list of hook functions contains nothing more # than a whitespace-delimited list of legal shell function names, and # no effort is wasted trying to catch shell meta-characters or preserve # whitespace. func_run_hooks () { $debug_cmd _G_rc_run_hooks=false case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not support hook functions." ;; esac eval _G_hook_fns=\$$1_hooks; shift for _G_hook in $_G_hook_fns; do func_unset "${_G_hook}_result" eval $_G_hook '${1+"$@"}' func_propagate_result $_G_hook func_run_hooks if $func_propagate_result_result; then eval set dummy "$func_run_hooks_result"; shift fi done } ## --------------- ## ## Option parsing. ## ## --------------- ## # In order to add your own option parsing hooks, you must accept the # full positional parameter list from your hook function. You may remove # or edit any options that you action, and then pass back the remaining # unprocessed options in '_result', escaped # suitably for 'eval'. # # The '_result' variable is automatically unset # before your hook gets called; for best performance, only set the # *_result variable when necessary (i.e. don't call the 'func_quote' # function unnecessarily because it can be an expensive operation on some # machines). # # Like this: # # my_options_prep () # { # $debug_cmd # # # Extend the existing usage message. # usage_message=$usage_message' # -s, --silent don'\''t print informational messages # ' # # No change in '$@' (ignored completely by this hook). Leave # # my_options_prep_result variable intact. # } # func_add_hook func_options_prep my_options_prep # # # my_silent_option () # { # $debug_cmd # # args_changed=false # # # Note that, for efficiency, we parse as many options as we can # # recognise in a loop before passing the remainder back to the # # caller on the first unrecognised argument we encounter. # while test $# -gt 0; do # opt=$1; shift # case $opt in # --silent|-s) opt_silent=: # args_changed=: # ;; # # Separate non-argument short options: # -s*) func_split_short_opt "$_G_opt" # set dummy "$func_split_short_opt_name" \ # "-$func_split_short_opt_arg" ${1+"$@"} # shift # args_changed=: # ;; # *) # Make sure the first unrecognised option "$_G_opt" # # is added back to "$@" in case we need it later, # # if $args_changed was set to 'true'. # set dummy "$_G_opt" ${1+"$@"}; shift; break ;; # esac # done # # # Only call 'func_quote' here if we processed at least one argument. # if $args_changed; then # func_quote eval ${1+"$@"} # my_silent_option_result=$func_quote_result # fi # } # func_add_hook func_parse_options my_silent_option # # # my_option_validation () # { # $debug_cmd # # $opt_silent && $opt_verbose && func_fatal_help "\ # '--silent' and '--verbose' options are mutually exclusive." # } # func_add_hook func_validate_options my_option_validation # # You'll also need to manually amend $usage_message to reflect the extra # options you parse. It's preferable to append if you can, so that # multiple option parsing hooks can be added safely. # func_options_finish [ARG]... # ---------------------------- # Finishing the option parse loop (call 'func_options' hooks ATM). func_options_finish () { $debug_cmd func_run_hooks func_options ${1+"$@"} func_propagate_result func_run_hooks func_options_finish } # func_options [ARG]... # --------------------- # All the functions called inside func_options are hookable. See the # individual implementations for details. func_hookable func_options func_options () { $debug_cmd _G_options_quoted=false for my_func in options_prep parse_options validate_options options_finish do func_unset func_${my_func}_result func_unset func_run_hooks_result eval func_$my_func '${1+"$@"}' func_propagate_result func_$my_func func_options if $func_propagate_result_result; then eval set dummy "$func_options_result"; shift _G_options_quoted=: fi done $_G_options_quoted || { # As we (func_options) are top-level options-parser function and # nobody quoted "$@" for us yet, we need to do it explicitly for # caller. func_quote eval ${1+"$@"} func_options_result=$func_quote_result } } # func_options_prep [ARG]... # -------------------------- # All initialisations required before starting the option parse loop. # Note that when calling hook functions, we pass through the list of # positional parameters. If a hook function modifies that list, and # needs to propagate that back to rest of this script, then the complete # modified list must be put in 'func_run_hooks_result' before returning. func_hookable func_options_prep func_options_prep () { $debug_cmd # Option defaults: opt_verbose=false opt_warning_types= func_run_hooks func_options_prep ${1+"$@"} func_propagate_result func_run_hooks func_options_prep } # func_parse_options [ARG]... # --------------------------- # The main option parsing loop. func_hookable func_parse_options func_parse_options () { $debug_cmd _G_parse_options_requote=false # this just eases exit handling while test $# -gt 0; do # Defer to hook functions for initial option parsing, so they # get priority in the event of reusing an option name. func_run_hooks func_parse_options ${1+"$@"} func_propagate_result func_run_hooks func_parse_options if $func_propagate_result_result; then eval set dummy "$func_parse_options_result"; shift # Even though we may have changed "$@", we passed the "$@" array # down into the hook and it quoted it for us (because we are in # this if-branch). No need to quote it again. _G_parse_options_requote=false fi # Break out of the loop if we already parsed every option. test $# -gt 0 || break # We expect that one of the options parsed in this function matches # and thus we remove _G_opt from "$@" and need to re-quote. _G_match_parse_options=: _G_opt=$1 shift case $_G_opt in --debug|-x) debug_cmd='set -x' func_echo "enabling shell trace mode" >&2 $debug_cmd ;; --no-warnings|--no-warning|--no-warn) set dummy --warnings none ${1+"$@"} shift ;; --warnings|--warning|-W) if test $# = 0 && func_missing_arg $_G_opt; then _G_parse_options_requote=: break fi case " $warning_categories $1" in *" $1 "*) # trailing space prevents matching last $1 above func_append_uniq opt_warning_types " $1" ;; *all) opt_warning_types=$warning_categories ;; *none) opt_warning_types=none warning_func=: ;; *error) opt_warning_types=$warning_categories warning_func=func_fatal_error ;; *) func_fatal_error \ "unsupported warning category: '$1'" ;; esac shift ;; --verbose|-v) opt_verbose=: ;; --version) func_version ;; -\?|-h) func_usage ;; --help) func_help ;; # Separate optargs to long options (plugins may need this): --*=*) func_split_equals "$_G_opt" set dummy "$func_split_equals_lhs" \ "$func_split_equals_rhs" ${1+"$@"} shift ;; # Separate optargs to short options: -W*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "$func_split_short_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-v*|-x*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) _G_parse_options_requote=: ; break ;; -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; *) set dummy "$_G_opt" ${1+"$@"}; shift _G_match_parse_options=false break ;; esac if $_G_match_parse_options; then _G_parse_options_requote=: fi done if $_G_parse_options_requote; then # save modified positional parameters for caller func_quote eval ${1+"$@"} func_parse_options_result=$func_quote_result fi } # func_validate_options [ARG]... # ------------------------------ # Perform any sanity checks on option settings and/or unconsumed # arguments. func_hookable func_validate_options func_validate_options () { $debug_cmd # Display all warnings if -W was not given. test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" func_run_hooks func_validate_options ${1+"$@"} func_propagate_result func_run_hooks func_validate_options # Bail if the options were screwed! $exit_cmd $EXIT_FAILURE } ## ----------------- ## ## Helper functions. ## ## ----------------- ## # This section contains the helper functions used by the rest of the # hookable option parser framework in ascii-betical order. # func_fatal_help ARG... # ---------------------- # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { $debug_cmd eval \$ECHO \""Usage: $usage"\" eval \$ECHO \""$fatal_help"\" func_error ${1+"$@"} exit $EXIT_FAILURE } # func_help # --------- # Echo long help message to standard output and exit. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message" exit 0 } # func_missing_arg ARGNAME # ------------------------ # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $debug_cmd func_error "Missing argument for '$1'." exit_cmd=exit } # func_split_equals STRING # ------------------------ # Set func_split_equals_lhs and func_split_equals_rhs shell variables # after splitting STRING at the '=' sign. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_equals () { $debug_cmd func_split_equals_lhs=${1%%=*} func_split_equals_rhs=${1#*=} if test "x$func_split_equals_lhs" = "x$1"; then func_split_equals_rhs= fi }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_equals () { $debug_cmd func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` func_split_equals_rhs= test "x$func_split_equals_lhs=" = "x$1" \ || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` } fi #func_split_equals # func_split_short_opt SHORTOPT # ----------------------------- # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_short_opt () { $debug_cmd func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"} }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_short_opt () { $debug_cmd func_split_short_opt_name=`expr "x$1" : 'x\(-.\)'` func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` } fi #func_split_short_opt # func_usage # ---------- # Echo short help message to standard output and exit. func_usage () { $debug_cmd func_usage_message $ECHO "Run '$progname --help |${PAGER-more}' for full usage" exit 0 } # func_usage_message # ------------------ # Echo short help message to standard output. func_usage_message () { $debug_cmd eval \$ECHO \""Usage: $usage"\" echo $SED -n 's|^# || /^Written by/{ x;p;x } h /^Written by/q' < "$progpath" echo eval \$ECHO \""$usage_message"\" } # func_version # ------------ # Echo version message to standard output and exit. # The version message is extracted from the calling file's header # comments, with leading '# ' stripped: # 1. First display the progname and version # 2. Followed by the header comment line matching /^# Written by / # 3. Then a blank line followed by the first following line matching # /^# Copyright / # 4. Immediately followed by any lines between the previous matches, # except lines preceding the intervening completely blank line. # For example, see the header comments of this file. func_version () { $debug_cmd printf '%s\n' "$progname $scriptversion" $SED -n ' /^# Written by /!b s|^# ||; p; n :fwd2blnk /./ { n b fwd2blnk } p; n :holdwrnt s|^# || s|^# *$|| /^Copyright /!{ /./H n b holdwrnt } s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| G s|\(\n\)\n*|\1|g p; q' < "$progpath" exit $? } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "30/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: # Set a version string. scriptversion='(GNU libtool) 2.4.7' # func_echo ARG... # ---------------- # Libtool also displays the current mode in messages, so override # funclib.sh func_echo with this custom definition. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" done IFS=$func_echo_IFS } # func_warning ARG... # ------------------- # Libtool warnings are not categorized, so override funclib.sh # func_warning with this simpler definition. func_warning () { $debug_cmd $warning_func ${1+"$@"} } ## ---------------- ## ## Options parsing. ## ## ---------------- ## # Hook in the functions to make sure our own options are parsed during # the option parsing loop. usage='$progpath [OPTION]... [MODE-ARG]...' # Short help message in response to '-h'. usage_message="Options: --config show all configuration variables --debug enable verbose shell tracing -n, --dry-run display commands without modifying any files --features display basic configuration information and exit --mode=MODE use operation mode MODE --no-warnings equivalent to '-Wnone' --preserve-dup-deps don't remove duplicate dependency libraries --quiet, --silent don't print informational messages --tag=TAG use configuration variables from tag TAG -v, --verbose print more informational messages than default --version print version information -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -h, --help, --help-all print short, long, or detailed help message " # Additional text appended to 'usage_message' in response to '--help'. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message MODE must be one of the following: clean remove files from the build directory compile compile a source file into a libtool object execute automatically set library path, then run a program finish complete the installation of libtool libraries install install libraries or executables link create a library or an executable uninstall remove libraries from an installed directory MODE-ARGS vary depending on the MODE. When passed as first option, '--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. Try '$progname --help --mode=MODE' for a more detailed description of MODE. When reporting a bug, please describe a test case to reproduce it and include the following information: host-triplet: $host shell: $SHELL compiler: $LTCC compiler flags: $LTCFLAGS linker: $LD (gnu? $with_gnu_ld) version: $progname $scriptversion Debian-2.4.7-7build1 automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` Report bugs to . GNU libtool home page: . General help using GNU software: ." exit 0 } # func_lo2o OBJECT-NAME # --------------------- # Transform OBJECT-NAME from a '.lo' suffix to the platform specific # object suffix. lo2o=s/\\.lo\$/.$objext/ o2lo=s/\\.$objext\$/.lo/ if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_lo2o () { case $1 in *.lo) func_lo2o_result=${1%.lo}.$objext ;; * ) func_lo2o_result=$1 ;; esac }' # func_xform LIBOBJ-OR-SOURCE # --------------------------- # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) # suffix to a '.lo' libtool-object suffix. eval 'func_xform () { func_xform_result=${1%.*}.lo }' else # ...otherwise fall back to using sed. func_lo2o () { func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` } func_xform () { func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` } fi # func_fatal_configuration ARG... # ------------------------------- # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func_fatal_error ${1+"$@"} \ "See the $PACKAGE documentation for more information." \ "Fatal configuration error." } # func_config # ----------- # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # ------------- # Display the features supported by this script. func_features () { echo "host: $host" if test yes = "$build_libtool_libs"; then echo "enable shared libraries" else echo "disable shared libraries" fi if test yes = "$build_old_libs"; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag TAGNAME # ----------------------- # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname=$1 re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf=/$re_begincf/,/$re_endcf/p # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # ------------------------ # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # libtool_options_prep [ARG]... # ----------------------------- # Preparation for options parsed by libtool. libtool_options_prep () { $debug_mode # Option defaults: opt_config=false opt_dlopen= opt_dry_run=false opt_help=false opt_mode= opt_preserve_dup_deps=false opt_quiet=false nonopt= preserve_args= _G_rc_lt_options_prep=: _G_rc_lt_options_prep=: # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; *) _G_rc_lt_options_prep=false ;; esac if $_G_rc_lt_options_prep; then # Pass back the list of options. func_quote eval ${1+"$@"} libtool_options_prep_result=$func_quote_result fi } func_add_hook func_options_prep libtool_options_prep # libtool_parse_options [ARG]... # --------------------------------- # Provide handling for libtool specific options. libtool_parse_options () { $debug_cmd _G_rc_lt_parse_options=false # Perform our own loop to consume as many options as possible in # each iteration. while test $# -gt 0; do _G_match_lt_parse_options=: _G_opt=$1 shift case $_G_opt in --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) func_config ;; --dlopen|-dlopen) opt_dlopen="${opt_dlopen+$opt_dlopen }$1" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) func_features ;; --finish) set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $_G_opt && break opt_mode=$1 case $1 in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $_G_opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_quiet=false func_append preserve_args " $_G_opt" ;; --no-warnings|--no-warning|--no-warn) opt_warning=false func_append preserve_args " $_G_opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $_G_opt" ;; --silent|--quiet) opt_quiet=: opt_verbose=false func_append preserve_args " $_G_opt" ;; --tag) test $# = 0 && func_missing_arg $_G_opt && break opt_tag=$1 func_append preserve_args " $_G_opt $1" func_enable_tag "$1" shift ;; --verbose|-v) opt_quiet=false opt_verbose=: func_append preserve_args " $_G_opt" ;; # An option not handled by this hook function: *) set dummy "$_G_opt" ${1+"$@"} ; shift _G_match_lt_parse_options=false break ;; esac $_G_match_lt_parse_options && _G_rc_lt_parse_options=: done if $_G_rc_lt_parse_options; then # save modified positional parameters for caller func_quote eval ${1+"$@"} libtool_parse_options_result=$func_quote_result fi } func_add_hook func_parse_options libtool_parse_options # libtool_validate_options [ARG]... # --------------------------------- # Perform any sanity checks on option settings and/or unconsumed # arguments. libtool_validate_options () { # save first non-option argument if test 0 -lt $#; then nonopt=$1 shift fi # preserve --debug test : = "$debug_cmd" || func_append preserve_args " --debug" case $host in # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match test yes != "$build_libtool_libs" \ && test yes != "$build_old_libs" \ && func_fatal_configuration "not configured to build any kind of library" # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test execute != "$opt_mode"; then func_error "unrecognized option '-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help=$help help="Try '$progname --help --mode=$opt_mode' for more information." } # Pass back the unparsed argument list func_quote eval ${1+"$@"} libtool_validate_options_result=$func_quote_result } func_add_hook func_validate_options libtool_validate_options # Process options as early as possible so that --help and --version # can return quickly. func_options ${1+"$@"} eval set dummy "$func_options_result"; shift ## ----------- ## ## Main. ## ## ----------- ## magic='%%%MAGIC variable%%%' magic_exe='%%%MAGIC EXE variable%%%' # Global variables. extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # func_generated_by_libtool # True iff stdin has been generated by Libtool. This function is only # a basic sanity check; it will hardly flush out determined imposters. func_generated_by_libtool_p () { $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p } # func_lalib_unsafe_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if 'file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case $lalib_p_line in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test yes = "$lalib_p" } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { test -f "$1" && $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $debug_cmd save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # 'FILE.' does not work on cygwin managed mounts. func_source () { $debug_cmd case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case $lt_sysroot:$1 in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result='='$func_stripname_result ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $debug_cmd if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with '--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=$1 if test yes = "$build_libtool_libs"; then write_lobj=\'$2\' else write_lobj=none fi if test yes = "$build_old_libs"; then write_oldobj=\'$3\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $debug_cmd # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result= if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result"; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $debug_cmd if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $debug_cmd # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $debug_cmd if test -z "$2" && test -n "$1"; then func_error "Could not determine host file name corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result=$1 fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $debug_cmd if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " '$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result=$3 fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $debug_cmd case $4 in $1 ) func_to_host_path_result=$3$func_to_host_path_result ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via '$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $debug_cmd $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $debug_cmd case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result=$1 } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result=$func_convert_core_msys_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result=$func_convert_core_file_wine_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via '$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $debug_cmd if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd=func_convert_path_$func_stripname_result fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $debug_cmd func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result=$1 } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_msys_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_path_wine_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_dll_def_p FILE # True iff FILE is a Windows DLL '.def' file. # Keep in sync with _LT_DLL_DEF_P in libtool.m4 func_dll_def_p () { $debug_cmd func_dll_def_p_tmp=`$SED -n \ -e 's/^[ ]*//' \ -e '/^\(;.*\)*$/d' \ -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ -e q \ "$1"` test DEF = "$func_dll_def_p_tmp" } # func_mode_compile arg... func_mode_compile () { $debug_cmd # Get the compilation command and the source file. base_compile= srcfile=$nonopt # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg=$arg arg_mode=normal ;; target ) libobj=$arg arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify '-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs=$IFS; IFS=, for arg in $args; do IFS=$save_ifs func_append_quoted lastarg "$arg" done IFS=$save_ifs func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg=$srcfile srcfile=$arg ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with '-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj=$func_basename_result } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from '$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test yes = "$build_libtool_libs" \ || func_fatal_configuration "cannot build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_arg pretty "$libobj" test "X$libobj" != "X$func_quote_arg_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name '$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname=$func_basename_result xdir=$func_dirname_result lobj=$xdir$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test yes = "$build_old_libs"; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test no = "$compiler_c_o"; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext lockfile=$output_obj.lock else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test yes = "$need_locks"; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test warn = "$need_locks"; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_arg pretty "$srcfile" qsrcfile=$func_quote_arg_result # Only build a PIC object if we are building libtool libraries. if test yes = "$build_libtool_libs"; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test no != "$pic_mode"; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test yes = "$suppress_opt"; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test yes = "$build_old_libs"; then if test yes != "$pic_mode"; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test yes = "$compiler_c_o"; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test no != "$need_locks"; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test compile = "$opt_mode" && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a '.o' file suitable for static linking -static only build a '.o' file suitable for static linking -Wc,FLAG -Xcompiler FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a 'standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix '.c' with the library object suffix, '.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to '-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the '--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the 'install' or 'cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE use a list of object files found in FILE to specify objects -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wa,FLAG -Xassembler FLAG pass linker-specific FLAG directly to the assembler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with '-') are ignored. Every other argument is treated as a filename. Files ending in '.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in '.la', then a libtool library is created, only library objects ('.lo' files) may be specified, and '-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created using 'ar' and 'ranlib', or on Windows using 'lib'. If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode '$opt_mode'" ;; esac echo $ECHO "Try '$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test : = "$opt_help"; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | $SED -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | $SED '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $debug_cmd # The first argument is the command name. cmd=$nonopt test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "'$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "'$file' was not linked with '-export-dynamic'" continue fi func_dirname "$file" "" "." dir=$func_dirname_result if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir=$func_dirname_result ;; *) func_warning "'-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir=$absdir # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic=$magic # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file=$progdir/$program elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file=$progdir/$program fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if $opt_dry_run; then # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS else if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd=\$cmd$args fi } test execute = "$opt_mode" && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $debug_cmd libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "'$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument '$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and '=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_quiet && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the '-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the '$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the '$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the '$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test finish = "$opt_mode" && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $debug_cmd # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac then # Aesthetically quote it. func_quote_arg pretty "$nonopt" install_prog="$func_quote_arg_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_arg pretty "$arg" func_append install_prog "$func_quote_arg_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=false stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=: ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test X-m = "X$prev" && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_arg pretty "$arg" func_append install_prog " $func_quote_arg_result" if test -n "$arg2"; then func_quote_arg pretty "$arg2" fi func_append install_shared_prog " $func_quote_arg_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the '$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_arg pretty "$install_override_mode" func_append install_shared_prog " -m $func_quote_arg_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=: if $isdir; then destdir=$dest destname= else func_dirname_and_basename "$dest" "" "." destdir=$func_dirname_result destname=$func_basename_result # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "'$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "'$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir=$func_dirname_result func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking '$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname=$1 shift srcname=$realname test -n "$relink_command" && srcname=${realname}T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme=$stripme case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme= ;; esac ;; os2*) case $realname in *_dll.a) tstripme= ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try 'ln -sf' first, because the 'ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib=$destdir/$realname func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name=$func_basename_result instname=$dir/${name}i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile=$destdir/$destname else func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest=$destfile destfile= ;; *) func_fatal_help "cannot copy a libtool object to '$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test yes = "$build_old_libs"; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile=$destdir/$destname else func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext= case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=.exe fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script '$wrapper'" finalize=: for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` if test -n "$libdir" && test ! -f "$libfile"; then func_warning "'$lib' has not been installed in '$libdir'" finalize=false fi done relink_command= func_source "$wrapper" outputname= if test no = "$fast_install" && test -n "$relink_command"; then $opt_dry_run || { if $finalize; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file=$func_basename_result outputname=$tmpdir/$file # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_quiet || { func_quote_arg expand,pretty "$relink_command" eval "func_echo $func_quote_arg_result" } if eval "$relink_command"; then : else func_error "error: relink '$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file=$outputname else func_warning "cannot relink '$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name=$func_basename_result # Set up the ranlib parameters. oldlib=$destdir/$name func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run '$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test install = "$opt_mode" && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $debug_cmd my_outputname=$1 my_originator=$2 my_pic_p=${3-false} my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms=${my_outputname}S.c else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist=$output_objdir/$my_outputname.nm func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* External symbol declarations for the compiler. */\ " if test yes = "$dlself"; then func_verbose "generating symbol list for '$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from '$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols=$output_objdir/$outputname.exp $opt_dry_run || { $RM $export_symbols eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from '$dlprefile'" func_basename "$dlprefile" name=$func_basename_result case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename= if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname"; then func_basename "$dlprefile_dlname" dlprefile_dlbasename=$func_basename_result else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename"; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi func_show_eval '$RM "${nlist}I"' if test -n "$global_symbol_to_import"; then eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[];\ " if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ static void lt_syminit(void) { LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; for (; symbol->name; ++symbol) {" $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" echo >> "$output_objdir/$my_dlsyms" "\ } }" fi echo >> "$output_objdir/$my_dlsyms" "\ LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = { {\"$my_originator\", (void *) 0}," if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ {\"@INIT@\", (void *) <_syminit}," fi case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) $my_pic_p && pic_flag_for_symtable=" $pic_flag" ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' # Transform the symbol file into the correct name. symfileobj=$output_objdir/${my_outputname}S.$objext case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for '$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $debug_cmd win32_libid_type=unknown win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then case $nm_interface in "MS dumpbin") if func_cygming_ms_implib_p "$1" || func_cygming_gnu_implib_p "$1" then win32_nmres=import else win32_nmres= fi ;; *) func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s|.*|import| p q } }'` ;; esac case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $debug_cmd sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $debug_cmd match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive that possess that section. Heuristic: eliminate # all those that have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $debug_cmd if func_cygming_gnu_implib_p "$1"; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1"; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result= fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $debug_cmd f_ex_an_ar_dir=$1; shift f_ex_an_ar_oldlib=$1 if test yes = "$lock_old_archive_extraction"; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test yes = "$lock_old_archive_extraction"; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $debug_cmd my_gentop=$1; shift my_oldlibs=${1+"$@"} my_oldobjs= my_xlib= my_xabs= my_xdir= for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib=$func_basename_result my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir=$my_gentop/$my_xlib_u func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` func_basename "$darwin_archive" darwin_base_archive=$func_basename_result darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches; do func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" cd "unfat-$$/$darwin_base_archive-$darwin_arch" func_extract_an_archive "`pwd`" "$darwin_base_archive" cd "$darwin_curdir" $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result=$my_oldobjs } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory where it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" func_quote_arg pretty "$ECHO" qECHO=$func_quote_arg_result $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=$qECHO fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ that is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options that match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test yes = "$fast_install"; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else \$ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* declarations of non-ANSI functions */ #if defined __MINGW32__ # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined __CYGWIN__ # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined other_platform || defined ... */ #endif /* portability defines, excluding path handling macros */ #if defined _MSC_VER # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC #elif defined __MINGW32__ # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined __CYGWIN__ # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined other platforms ... */ #endif #if defined PATH_MAX # define LT_PATHMAX PATH_MAX #elif defined MAXPATHLEN # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ defined __OS2__ # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free (stale); stale = 0; } \ } while (0) #if defined LT_DEBUGWRAPPER static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; size_t tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined HAVE_DOS_BASED_FILE_SYSTEM if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined HAVE_DOS_BASED_FILE_SYSTEM } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = (size_t) (q - p); p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (STREQ (str, pat)) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else size_t len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { size_t orig_value_len = strlen (orig_value); size_t add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ size_t len = strlen (new_value); while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[--len] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $debug_cmd case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_suncc_cstd_abi # !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! # Several compiler flags select an ABI that is incompatible with the # Cstd library. Avoid specifying it if any are in CXXFLAGS. func_suncc_cstd_abi () { $debug_cmd case " $compile_command " in *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) suncc_use_cstd_abi=no ;; *) suncc_use_cstd_abi=yes ;; esac } # func_mode_link arg... func_mode_link () { $debug_cmd case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # what system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll that has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= os2dllname= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=false prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module=$wl-single_module func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test yes != "$build_libtool_libs" \ && func_fatal_configuration "cannot build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg=$1 shift func_quote_arg pretty,unquoted "$arg" qarg=$func_quote_arg_unquoted_result func_append libtool_args " $func_quote_arg_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir=$arg prev= continue ;; dlfiles|dlprefiles) $preload || { # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=: } case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test no = "$dlself"; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test dlprefiles = "$prev"; then dlself=yes elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test dlfiles = "$prev"; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols=$arg test -f "$arg" \ || func_fatal_error "symbol file '$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex=$arg prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir=$arg prev= continue ;; mllvm) # Clang does not use LLVM to link, so we can simply discard any # '-mllvm $arg' options when doing the link step. prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result if test none != "$pic_object"; then # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object fi # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file '$arg' does not exist" fi arg=$save_arg prev= continue ;; os2dllname) os2dllname=$arg prev= continue ;; precious_regex) precious_files_regex=$arg prev= continue ;; release) release=-$arg prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test rpath = "$prev"; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds=$arg prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xassembler) func_append compiler_flags " -Xassembler $qarg" prev= func_append compile_command " -Xassembler $qarg" func_append finalize_command " -Xassembler $qarg" continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg=$arg case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "'-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test X-export-symbols = "X$arg"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between '-L' and '$1'" else func_fatal_error "need path for '-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of '$dir'" dir=$absdir ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test X-lc = "X$arg" || test X-lm = "X$arg"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test X-lc = "X$arg" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig* | *-*-midnightbsd*) # Do not include libc due to us having libc/libc_r. test X-lc = "X$arg" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test X-lc = "X$arg" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test X-lc = "X$arg" && continue ;; esac elif test X-lc_r = "X$arg"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig* | *-*-midnightbsd*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -mllvm) prev=mllvm continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; # Solaris ld rejects as of 11.4. Refer to Oracle bug 22985199. -pthread) case $host in *solaris2*) ;; *) case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac ;; esac continue ;; -mt|-mthreads|-kthread|-Kthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module=$wl-multi_module continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "'-no-install' is ignored for $host" func_warning "assuming '-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -os2dllname) prev=os2dllname continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_arg pretty "$flag" func_append arg " $func_quote_arg_result" func_append compiler_flags " $func_quote_arg_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_arg pretty "$flag" func_append arg " $wl$func_quote_arg_result" func_append compiler_flags " $wl$func_quote_arg_result" func_append linker_flags " $func_quote_arg_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xassembler) prev=xassembler continue ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_arg pretty "$arg" arg=$func_quote_arg_result ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # -fstack-protector* stack protector flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization # -specs=* GCC specs files # -stdlib=* select c++ std lib with clang # -fsanitize=* Clang/GCC memory and address sanitizer # -fuse-ld=* Linker select flags for GCC # -static-* direct GCC to link specific libraries statically # -fcilkplus Cilk Plus language extension features for C/C++ # -Wa,* Pass flags directly to the assembler -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ -specs=*|-fsanitize=*|-fuse-ld=*|-static-*|-fcilkplus|-Wa,*) func_quote_arg pretty "$arg" arg=$func_quote_arg_result func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; -Z*) if test os2 = "`expr $host : '.*\(os2\)'`"; then # OS/2 uses -Zxxx to specify OS/2-specific options compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case $arg in -Zlinker | -Zstack) prev=xcompiler ;; esac continue else # Otherwise treat like 'Some other compiler flag' below func_quote_arg pretty "$arg" arg=$func_quote_arg_result fi ;; # Some other compiler flag. -* | +*) func_quote_arg pretty "$arg" arg=$func_quote_arg_result ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result test none = "$pic_object" || { # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object } # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test dlfiles = "$prev"; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test dlprefiles = "$prev"; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_arg pretty "$arg" arg=$func_quote_arg_result ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the '$prevarg' option requires an argument" if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname=$func_basename_result libobjs_save=$libobjs if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" # Definition is injected by LT_CONFIG during libtool generation. func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" func_dirname "$output" "/" "" output_objdir=$func_dirname_result$objdir func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test lib = "$linkmode"; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=false newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test lib,link = "$linkmode,$pass"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs=$tmp_deplibs fi if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass"; then libs=$deplibs deplibs= fi if test prog = "$linkmode"; then case $pass in dlopen) libs=$dlfiles ;; dlpreopen) libs=$dlprefiles ;; link) libs="$deplibs %DEPLIBS%" test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" ;; esac fi if test lib,dlpreopen = "$linkmode,$pass"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs=$dlprefiles fi if test dlopen = "$pass"; then # Collect dlpreopened libraries save_deplibs=$deplibs deplibs= fi for deplib in $libs; do lib= found=false case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test lib != "$linkmode" && test prog != "$linkmode"; then func_warning "'-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test lib = "$linkmode"; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib=$searchdir/lib$name$search_ext if test -f "$lib"; then if test .la = "$search_ext"; then found=: else found=false fi break 2 fi done done if $found; then # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll=$l done if test "X$ll" = "X$old_library"; then # only static version available found=false func_dirname "$lib" "" "." ladir=$func_dirname_result lib=$ladir/$old_library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi else # deplib doesn't seem to be a libtool library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi ;; # -l *.ltframework) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test conv = "$pass" && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi if test scan = "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "'-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test link = "$pass"; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=false case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=: fi ;; pass_all) valid_a_lib=: ;; esac if $valid_a_lib; then echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" else echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." fi ;; esac continue ;; prog) if test link != "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test conv = "$pass"; then deplibs="$deplib $deplibs" elif test prog = "$linkmode"; then if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=: continue ;; esac # case $deplib $found || test -f "$lib" \ || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "'$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir=$func_dirname_result dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass" || { test prog != "$linkmode" && test lib != "$linkmode"; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test conv = "$pass"; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for '$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done elif test prog != "$linkmode" && test lib != "$linkmode"; then func_fatal_error "'$lib' is not a convenience library" fi continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test yes = "$prefer_static_libs" || test built,no = "$prefer_static_libs,$installed"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib=$l done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for '$lib'" fi # This library was specified with -dlopen. if test dlopen = "$pass"; then test -z "$libdir" \ && func_fatal_error "cannot -dlopen a convenience library: '$lib'" if test -z "$dlname" || test yes != "$dlopen_support" || test no = "$build_libtool_libs" then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of '$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir=$ladir fi ;; esac func_basename "$lib" laname=$func_basename_result # Find the relevant object directory and library name. if test yes = "$installed"; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library '$lib' was moved." dir=$ladir absdir=$abs_ladir libdir=$abs_ladir else dir=$lt_sysroot$libdir absdir=$lt_sysroot$libdir fi test yes = "$hardcode_automatic" && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir=$ladir absdir=$abs_ladir # Remove this search path later func_append notinst_path " $abs_ladir" else dir=$ladir/$objdir absdir=$abs_ladir/$objdir # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test dlpreopen = "$pass"; then if test -z "$libdir" && test prog = "$linkmode"; then func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" fi case $host in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test lib = "$linkmode"; then deplibs="$dir/$old_library $deplibs" elif test prog,link = "$linkmode,$pass"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test prog = "$linkmode" && test link != "$pass"; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=false if test no != "$link_all_deplibs" || test -z "$library_names" || test no = "$build_libtool_libs"; then linkalldeplibs=: fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if $linkalldeplibs; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test prog,link = "$linkmode,$pass"; then if test -n "$library_names" && { { test no = "$prefer_static_libs" || test built,yes = "$prefer_static_libs,$installed"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then # Make sure the rpath contains only unique directories. case $temp_rpath: in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if $alldeplibs && { test pass_all = "$deplibs_check_method" || { test yes = "$build_libtool_libs" && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test built = "$use_static_libs" && test yes = "$installed"; then use_static_libs=no fi if test -n "$library_names" && { test no = "$use_static_libs" || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc* | *os2*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test no = "$installed"; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule= for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule=$dlpremoduletest break fi done if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then echo if test prog = "$linkmode"; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test lib = "$linkmode" && test yes = "$hardcode_into_libs"; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname=$1 shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname=$dlname elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc* | *os2*) func_arith $current - $age major=$func_arith_result versuffix=-$major ;; esac eval soname=\"$soname_spec\" else soname=$realname fi # Make a new name for the extract_expsyms_cmds to use soroot=$soname func_basename "$soroot" soname=$func_basename_result func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from '$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for '$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test prog = "$linkmode" || test relink != "$opt_mode"; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test no = "$hardcode_direct"; then add=$dir/$linklib case $host in *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; *-*-sysv4*uw2*) add_dir=-L$dir ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir=-L$dir ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we cannot # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library"; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add=$dir/$old_library fi elif test -n "$old_library"; then add=$dir/$old_library fi fi esac elif test no = "$hardcode_minus_L"; then case $host in *-*-sunos*) add_shlibpath=$dir ;; esac add_dir=-L$dir add=-l$name elif test no = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; relink) if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$dir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$absdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name elif test yes = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; *) lib_linked=no ;; esac if test yes != "$lib_linked"; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test prog = "$linkmode"; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test yes != "$hardcode_direct" && test yes != "$hardcode_minus_L" && test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test prog = "$linkmode" || test relink = "$opt_mode"; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$libdir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$libdir add=-l$name elif test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add=-l$name elif test yes = "$hardcode_automatic"; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib"; then add=$inst_prefix_dir$libdir/$linklib else add=$libdir/$linklib fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir=-L$libdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name fi if test prog = "$linkmode"; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test prog = "$linkmode"; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test unsupported != "$hardcode_direct"; then test -n "$old_library" && linklib=$old_library compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test yes = "$build_libtool_libs"; then # Not a shared library if test pass_all != "$deplibs_check_method"; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system cannot link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test yes = "$module"; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test lib = "$linkmode"; then if test -n "$dependency_libs" && { test yes != "$hardcode_into_libs" || test yes = "$build_old_libs" || test yes = "$link_static"; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs=$temp_deplibs fi func_append newlib_search_path " $absdir" # Link against this library test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test no != "$link_all_deplibs"; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path=$deplib ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of '$dir'" absdir=$dir fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names"; then for tmp in $deplibrary_names; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl"; then depdepl=$absdir/$objdir/$depdepl darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" path= fi fi ;; *) path=-L$absdir/$objdir ;; esac else eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "'$deplib' seems to be moved" path=-L$absdir fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test link = "$pass"; then if test prog = "$linkmode"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs=$newdependency_libs if test dlpreopen = "$pass"; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test dlopen != "$pass"; then test conv = "$pass" || { # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= } if test prog,link = "$linkmode,$pass"; then vars="compile_deplibs finalize_deplibs" else vars=deplibs fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Add Sun CC postdeps if required: test CXX = "$tagname" && { case $host_os in linux*) case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C++ 5.9 func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; solaris*) func_cc_basename "$CC" case $func_cc_basename_result in CC* | sunCC*) func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; esac } # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i= ;; esac if test -n "$i"; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test prog = "$linkmode"; then dlfiles=$newdlfiles fi if test prog = "$linkmode" || test lib = "$linkmode"; then dlprefiles=$newdlprefiles fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "'-R' is ignored for archives" test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "'-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "'-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs=$output func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form 'libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test no = "$module" \ && func_fatal_help "libtool library '$output' must begin with 'lib'" if test no != "$need_lib_prefix"; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test pass_all != "$deplibs_check_method"; then func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test no = "$dlself" \ || func_warning "'-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test 1 -lt "$#" \ && func_warning "ignoring multiple '-rpath's for a libtool library" install_libdir=$1 oldlibs= if test -z "$rpath"; then if test yes = "$build_libtool_libs"; then # Building a libtool convenience library. # Some compilers have problems with a '.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "'-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs=$IFS; IFS=: set dummy $vinfo 0 0 0 shift IFS=$save_ifs test -n "$7" && \ func_fatal_help "too many parameters to '-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major=$1 number_minor=$2 number_revision=$3 # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # that has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|freebsd-elf|linux|midnightbsd-elf|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_revision ;; freebsd-aout|qnx|sunos) current=$number_major revision=$number_minor age=0 ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_minor lt_irix_increment=no ;; *) func_fatal_configuration "$modename: unknown library version type '$version_type'" ;; esac ;; no) current=$1 revision=$2 age=$3 ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT '$current' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION '$revision' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE '$age' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE '$age' is greater than the current interface number '$current'" func_fatal_error "'$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" # On Darwin other compilers case $CC in nagfor*) verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" ;; *) verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; esac ;; freebsd-aout) major=.$current versuffix=.$current.$revision ;; freebsd-elf | midnightbsd-elf) func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; irix | nonstopux) if test no = "$lt_irix_increment"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring=$verstring_prefix$major.$revision # Add in all the interfaces that we are compatible with. loop=$revision while test 0 -ne "$loop"; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring_prefix$major.$iface:$verstring done # Before this point, $major must not contain '.'. major=.$major versuffix=$major.$revision ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=.$current.$age.$revision verstring=$current.$age.$revision # Add in all the interfaces that we are compatible with. loop=$age while test 0 -ne "$loop"; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring:$iface.0 done # Make executables depend on our current version. func_append verstring ":$current.0" ;; qnx) major=.$current versuffix=.$current ;; sco) major=.$current versuffix=.$current ;; sunos) major=.$current versuffix=.$current.$revision ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 file systems. func_arith $current - $age major=$func_arith_result versuffix=-$major ;; *) func_fatal_configuration "unknown library version type '$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring=0.0 ;; esac if test no = "$need_version"; then versuffix= else versuffix=.0.0 fi fi # Remove version info from name if versioning should be avoided if test yes,no = "$avoid_version,$need_version"; then major= versuffix= verstring= fi # Check to see if the archive will have undefined symbols. if test yes = "$allow_undefined"; then if test unsupported = "$allow_undefined_flag"; then if test yes = "$build_old_libs"; then func_warning "undefined symbols not allowed in $host shared libraries; building static only" build_libtool_libs=no else func_fatal_error "can't build $host shared library unless -no-undefined is specified" fi fi else # Don't allow undefined symbols. allow_undefined_flag=$no_undefined_flag fi fi func_generate_dlsyms "$libname" "$libname" : func_append libobjs " $symfileobj" test " " = "$libobjs" && libobjs= if test relink != "$opt_mode"; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) if test -n "$precious_files_regex"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles=$dlfiles dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles=$dlprefiles dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test yes = "$build_libtool_libs"; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-midnightbsd*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test yes = "$build_libtool_need_lc"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release= versuffix= major= newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib=$potent_lib while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | $SED 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib= ;; esac fi if test -n "$a_deplib"; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib=$potent_lib # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs= tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test yes = "$allow_libtool_libs_with_static_runtimes"; then for i in $predeps $postdeps; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test none = "$deplibs_check_method"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test yes = "$droppeddeps"; then if test yes = "$module"; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test no = "$allow_undefined"; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs=$new_libs # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test yes = "$build_libtool_libs"; then # Remove $wl instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test yes = "$hardcode_into_libs"; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath=$finalize_rpath test relink = "$opt_mode" || rpath=$compile_rpath$rpath for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath=$finalize_shlibpath test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname=$1 shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname=$realname fi if test -z "$dlname"; then dlname=$soname fi lib=$output_objdir/$realname linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols=$output_objdir/$libname.uexp func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile func_dll_def_p "$export_symbols" || { # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols=$export_symbols export_symbols= always_export_symbols=yes } fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs=$IFS; IFS='~' for cmd1 in $cmds; do IFS=$save_ifs # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test yes = "$try_normal_branch" \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=$output_objdir/$output_la.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS=$save_ifs if test -n "$export_symbols_regex" && test : != "$skipped_export"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test : != "$skipped_export" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs=$tmp_deplibs if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test yes = "$compiler_needs_object" && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test : != "$skipped_export" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then output=$output_objdir/$output_la.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then output=$output_objdir/$output_la.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test yes = "$compiler_needs_object"; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-$k.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test -z "$objlist" || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test 1 -eq "$k"; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-$k.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-$k.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi ${skipped_export-false} && { func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi } test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs=$IFS; IFS='~' for cmd in $concat_cmds; do IFS=$save_ifs $opt_quiet || { func_quote_arg expand,pretty "$cmd" eval "func_echo $func_quote_arg_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi ${skipped_export-false} && { if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi } libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs=$IFS; IFS='~' for cmd in $cmds; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs $opt_quiet || { func_quote_arg expand,pretty "$cmd" eval "func_echo $func_quote_arg_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs # Restore the uninstalled library and exit if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test yes = "$module" || test yes = "$export_dynamic"; then # On all known operating systems, these are identical. dlname=$soname fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "'-R' is ignored for objects" test -n "$vinfo" && \ func_warning "'-version-info' is ignored for objects" test -n "$release" && \ func_warning "'-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object '$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj=$output ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # if reload_cmds runs $LD directly, get rid of -Wl from # whole_archive_flag_spec and hope we can get by with turning comma # into space. case $reload_cmds in *\$LD[\ \$]*) wl= ;; esac if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags else gentop=$output_objdir/${obj}x func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test yes = "$build_libtool_libs" || libobjs=$non_pic_objects # Create the old-style object. reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs output=$obj func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi test yes = "$build_libtool_libs" || { if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS } if test -n "$pic_flag" || test default != "$pic_mode"; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output=$libobj func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "'-version-info' is ignored for programs" test -n "$release" && \ func_warning "'-release' is ignored for programs" $preload \ && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test CXX = "$tagname"; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " $wl-bind_at_load" func_append finalize_command " $wl-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs=$new_libs func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath=$rpath rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath=$rpath if test -n "$libobjs" && test yes = "$build_old_libs"; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" false # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=: case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=false ;; *cygwin* | *mingw* ) test yes = "$build_libtool_libs" || wrappers_required=false ;; *) if test no = "$need_relink" || test yes != "$build_libtool_libs"; then wrappers_required=false fi ;; esac $wrappers_required || { # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command=$compile_command$compile_rpath # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.$objext"; then func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' fi exit $exit_status } if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test yes = "$no_install"; then # We don't need to create a wrapper script. link_command=$compile_var$compile_command$compile_rpath # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi case $hardcode_action,$fast_install in relink,*) # Fast installation is not supported link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath func_warning "this platform does not like uninstalled shared libraries" func_warning "'$output' will be relinked during installation" ;; *,yes) link_command=$finalize_var$compile_command$finalize_rpath relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` ;; *,no) link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath ;; *,needless) link_command=$finalize_var$compile_command$finalize_rpath relink_command= ;; esac # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_arg pretty "$var_value" relink_command="$var=$func_quote_arg_result; export $var; $relink_command" fi done func_quote eval cd "`pwd`" func_quote_arg pretty,unquoted "($func_quote_result; $relink_command)" relink_command=$func_quote_arg_unquoted_result fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource=$output_path/$objdir/lt-$output_name.c cwrapper=$output_path/$output_name.exe $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host"; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do case $build_libtool_libs in convenience) oldobjs="$libobjs_save $symfileobj" addlibs=$convenience build_libtool_libs=no ;; module) oldobjs=$libobjs_save addlibs=$old_convenience build_libtool_libs=no ;; *) oldobjs="$old_deplibs $non_pic_objects" $preload && test -f "$symfileobj" \ && func_append oldobjs " $symfileobj" addlibs=$old_convenience ;; esac if test -n "$addlibs"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase=$func_basename_result case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj"; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test -z "$oldobjs"; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test yes = "$build_old_libs" && old_library=$libname.$libext func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_arg pretty,unquoted "$var_value" relink_command="$var=$func_quote_arg_unquoted_result; export $var; $relink_command" fi done # Quote the link command for shipping. func_quote eval cd "`pwd`" relink_command="($func_quote_result; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" func_quote_arg pretty,unquoted "$relink_command" relink_command=$func_quote_arg_unquoted_result if test yes = "$hardcode_automatic"; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test yes = "$installed"; then if test -z "$install_libdir"; then break fi output=$output_objdir/${outputname}i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name=$func_basename_result func_resolve_sysroot "$deplib" eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs=$newdependency_libs newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles=$newdlprefiles else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles=$newdlprefiles fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test -n "$bindir"; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result/$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that cannot go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test no,yes = "$installed,$need_relink"; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } if test link = "$opt_mode" || test relink = "$opt_mode"; then func_mode_link ${1+"$@"} fi # func_mode_uninstall arg... func_mode_uninstall () { $debug_cmd RM=$nonopt files= rmforce=false exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic for arg do case $arg in -f) func_append RM " $arg"; rmforce=: ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir=$func_dirname_result if test . = "$dir"; then odir=$objdir else odir=$dir/$objdir fi func_basename "$file" name=$func_basename_result test uninstall = "$opt_mode" && odir=$dir # Remember odir for removal later, being careful to avoid duplicates if test clean = "$opt_mode"; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif $rmforce; then continue fi rmfiles=$file case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case $opt_mode in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test none != "$pic_object"; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test none != "$non_pic_object"; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test clean = "$opt_mode"; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.$objext" if test yes = "$fast_install" && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name"; then func_append rmfiles " $odir/lt-$noexename.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the $objdir's in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then func_mode_uninstall ${1+"$@"} fi test -z "$opt_mode" && { help=$generic_help func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode '$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # where we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: libpqxx-8.0.1/config/m4/000077500000000000000000000000001516427024100147765ustar00rootroot00000000000000libpqxx-8.0.1/config/m4/libtool.m4000066400000000000000000011316521516427024100167150ustar00rootroot00000000000000# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996-2001, 2003-2019, 2021-2022 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ]) # serial 59 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_PREPARE_CC_BASENAME # ----------------------- m4_defun([_LT_PREPARE_CC_BASENAME], [ # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in @S|@*""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } ])# _LT_PREPARE_CC_BASENAME # _LT_CC_BASENAME(CC) # ------------------- # It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, # but that macro is also expanded into generated libtool script, which # arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], [m4_require([_LT_PREPARE_CC_BASENAME])dnl AC_REQUIRE([_LT_DECL_SED])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl func_cc_basename $1 cc_basename=$func_cc_basename_result ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_DECL_FILECMD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC and # ICC, which need '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from 'configure', and 'config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # 'config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain=$ac_aux_dir/ltmain.sh ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the 'libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to 'config.status' so that its # declaration there will have the same value as in 'configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags='_LT_TAGS'dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into 'config.status', and then the shell code to quote escape them in # for loops in 'config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # '#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test 0 = "$lt_write_fail" && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ '$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test 0 != $[#] do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try '$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try '$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test yes = "$silent" && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 _LT_COPYING _LT_LIBTOOL_TAGS # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE _LT_PREPARE_MUNGE_PATH_LIST _LT_PREPARE_CC_BASENAME # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? $SED '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS=$save_LDFLAGS ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR $AR_FLAGS libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR $AR_FLAGS libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) case $MACOSX_DEPLOYMENT_TARGET,$host in 10.[[012]],*|,*powerpc*-darwin[[5-8]]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; *) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test yes = "$lt_cv_ld_force_load"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" _LT_TAGVAR(module_expsym_cmds, $1)="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" m4_if([$1], [CXX], [ if test yes != "$lt_cv_apple_cc_single_mod"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script that will find a shell with a builtin # printf (that we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case $ECHO in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [m4_require([_LT_DECL_SED])dnl AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], [Search for dependent libraries within DIR (or the compiler's sysroot if not specified).])], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([$with_sysroot]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and where our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `$FILECMD conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test yes = "$lt_cv_prog_gnu_ld"; then case `$FILECMD conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `$FILECMD conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then emul=elf case `$FILECMD conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `$FILECMD conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `$FILECMD conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `$FILECMD conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `$FILECMD conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `$FILECMD conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} _LT_DECL([], [AR], [1], [The archiver]) # Use ARFLAGS variable as AR's operation code to sync the variable naming with # Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have # higher priority because thats what people were doing historically (setting # ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS # variable obsoleted/removed. test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr} lt_ar_flags=$AR_FLAGS _LT_DECL([], [lt_ar_flags], [0], [Flags to create an archive (by configure)]) # Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override # by AR_FLAGS because that was never working and AR_FLAGS is about to die. _LT_DECL([], [AR_FLAGS], [\@S|@{ARFLAGS-"\@S|@lt_ar_flags"}], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test yes = "[$]$2"; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS ]) if test yes = "[$]$2"; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n "$lt_cv_sys_max_cmd_len"; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes = "$cross_compiling"; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen=shl_load], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen=dlopen], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) ]) ]) ]) ]) ]) ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links=nottested if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test no = "$hard_links"; then AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", [Define to the sub-directory where libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -z "$STRIP"; then AC_MSG_RESULT([no]) else if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then old_striplib="$STRIP --strip-debug" striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else case $host_os in darwin*) # FIXME - insert some real tests, host_os isn't really good enough striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) ;; freebsd*) if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then old_striplib="$STRIP --strip-debug" striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_PREPARE_MUNGE_PATH_LIST # --------------------------- # Make sure func_munge_path_list() is defined correctly. m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], [[# func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x@S|@2 in x) ;; *:) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" ;; x:*) eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; *::*) eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" ;; *) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; esac } ]])# _LT_PREPARE_PATH_LIST # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown AC_ARG_VAR([LT_SYS_LIBRARY_PATH], [User-defined run-time library search path.]) case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a[(]lib.so.V[)]' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl* | *,icl*) # Native MSVC or ICC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC and ICC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly* | midnightbsd*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], [Detected run-time system search path for libraries]) _LT_DECL([], [configure_time_lt_sys_library_path], [2], [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program that can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$1"; then lt_cv_path_MAGIC_CMD=$ac_dir/"$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac]) MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program that can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], [if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi]) rm -f conftest.i conftest2.i conftest.out]) ])# _LT_PATH_DD # _LT_CMD_TRUNCATE # ---------------- # find command to truncate a binary pipe m4_defun([_LT_CMD_TRUNCATE], [m4_require([_LT_PATH_DD]) AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], [printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) _LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], [Command to truncate a binary pipe]) ])# _LT_CMD_TRUNCATE # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_MAGIC_METHOD], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) AC_CACHE_CHECK([how to recognize dependent libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[[4-9]]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[[45]]*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='$FILECMD -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly* | midnightbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=$FILECMD lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=$FILECMD case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=$FILECMD lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi]) if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # _LT_DLL_DEF_P([FILE]) # --------------------- # True iff FILE is a Windows DLL '.def' file. # Keep in sync with func_dll_def_p in the libtool script AC_DEFUN([_LT_DLL_DEF_P], [dnl test DEF = "`$SED -n dnl -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl -e q dnl Only consider the first "real" line $1`" dnl ])# _LT_DLL_DEF_P # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM=-lm) ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test yes = "$GCC"; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="$SED -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++ or ICC, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([nm_interface], [lt_cv_nm_interface], [1], [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly* | midnightbsd*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test yes = "$GCC"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # flang / f18. f95 an alias for gfortran or flang on Debian flang* | f18* | f95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | $SED 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl* | icl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++ or Intel C++ Compiler. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/([[^)]]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++ or Intel C++ Compiler. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl* | icl*) # Native MSVC or ICC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC and ICC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly* | midnightbsd*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS=$save_LDFLAGS]) if test yes = "$lt_cv_irix_exported_symbol"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi _LT_TAGVAR(link_all_deplibs, $1)=no else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(ld_shlibs, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; esac ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' ;; osf3*) if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test yes = "$GCC"; then wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test yes,yes = "$GCC,$enable_shared"; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting $shlibpath_var if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC=$CC AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report what library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC=$lt_save_CC ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl* | ,icl* | no,icl*) # Native MSVC or ICC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly* | midnightbsd*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(GCC, $1)=$GXX _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case @S|@2 in .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)=$prev$p else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)=$p else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)=$p else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test no = "$F77"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_F77"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$G77 _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_F77" AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test no = "$FC"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_FC"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_FC" AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code=$lt_simple_compile_test_code # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_FILECMD # ---------------- # Check for a file(cmd) program that can be used to detect file type and magic m4_defun([_LT_DECL_FILECMD], [AC_CHECK_TOOL([FILECMD], [file], [:]) _LT_DECL([], [FILECMD], [1], [A file(cmd) program that detects file types]) ])# _LD_DECL_FILECMD # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f "$lt_ac_sed" && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test 10 -lt "$lt_ac_count" && break lt_ac_count=`expr $lt_ac_count + 1` if test "$lt_ac_count" -gt "$lt_ac_max"; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine what file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS libpqxx-8.0.1/config/m4/ltoptions.m4000066400000000000000000000342751516427024100173060ustar00rootroot00000000000000# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004-2005, 2007-2009, 2011-2019, 2021-2022 Free # Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 8 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option '$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the 'shared' and # 'disable-shared' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the 'static' and # 'disable-static' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the 'fast-install' # and 'disable-fast-install' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_AIX_SONAME([DEFAULT]) # ---------------------------------- # implement the --with-aix-soname flag, and support the `aix-soname=aix' # and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT # is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. m4_define([_LT_WITH_AIX_SONAME], [m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[[5-9]]*,yes) AC_MSG_CHECKING([which variant of shared library versioning to provide]) AC_ARG_WITH([aix-soname], [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], [case $withval in aix|svr4|both) ;; *) AC_MSG_ERROR([Unknown argument to --with-aix-soname]) ;; esac lt_cv_with_aix_soname=$with_aix_soname], [AC_CACHE_VAL([lt_cv_with_aix_soname], [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) with_aix_soname=$lt_cv_with_aix_soname]) AC_MSG_RESULT([$with_aix_soname]) if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac _LT_DECL([], [shared_archive_member_spec], [0], [Shared archive member basename, for filename based shared library versioning on AIX])dnl ])# _LT_WITH_AIX_SONAME LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. # MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac], [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) libpqxx-8.0.1/config/m4/ltsugar.m4000066400000000000000000000104531516427024100167240ustar00rootroot00000000000000# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007-2008, 2011-2019, 2021-2022 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) libpqxx-8.0.1/config/m4/ltversion.m4000066400000000000000000000013121516427024100172620ustar00rootroot00000000000000# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004, 2011-2019, 2021-2022 Free Software Foundation, # Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 4245 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.7]) m4_define([LT_PACKAGE_REVISION], [2.4.7]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.7' macro_revision='2.4.7' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) libpqxx-8.0.1/config/m4/lt~obsolete.m4000066400000000000000000000140071516427024100176140ustar00rootroot00000000000000# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007, 2009, 2011-2019, 2021-2022 Free # Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) libpqxx-8.0.1/config/missing000077500000000000000000000153361516427024100160650ustar00rootroot00000000000000#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1996-2021 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=https://www.perl.org/ flex_URL=https://github.com/westes/flex gnu_software_URL=https://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: libpqxx-8.0.1/config/mkinstalldirs000077500000000000000000000066721516427024100172770ustar00rootroot00000000000000#! /bin/sh # mkinstalldirs --- make directory hierarchy scriptversion=2020-07-26.22; # UTC # Original author: Noah Friedman # Created: 1993-05-16 # Public domain. # # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' IFS=" "" $nl" errstatus=0 dirmode= usage="\ Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... Create each directory DIR (with mode MODE, if specified), including all leading file name components. Report bugs to ." # process command line arguments while test $# -gt 0 ; do case $1 in -h | --help | --h*) # -h for help echo "$usage" exit $? ;; -m) # -m PERM arg shift test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } dirmode=$1 shift ;; --version) echo "$0 $scriptversion" exit $? ;; --) # stop option processing shift break ;; -*) # unknown option echo "$usage" 1>&2 exit 1 ;; *) # first non-opt arg break ;; esac done for file do if test -d "$file"; then shift else break fi done case $# in 0) exit 0 ;; esac # Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and # mkdir -p a/c at the same time, both will detect that a is missing, # one will create a, then the other will try to create a and die with # a "File exists" error. This is a problem when calling mkinstalldirs # from a parallel make. We use --version in the probe to restrict # ourselves to GNU mkdir, which is thread-safe. case $dirmode in '') if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then echo "mkdir -p -- $*" exec mkdir -p -- "$@" else # On NextStep and OpenStep, the 'mkdir' command does not # recognize any option. It will interpret all options as # directories to create, and then abort because '.' already # exists. test -d ./-p && rmdir ./-p test -d ./--version && rmdir ./--version fi ;; *) if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && test ! -d ./--version; then echo "umask 22" umask 22 echo "mkdir -m $dirmode -p -- $*" exec mkdir -m "$dirmode" -p -- "$@" else # Clean up after NextStep and OpenStep mkdir. for d in ./-m ./-p ./--version "./$dirmode"; do test -d $d && rmdir $d done fi ;; esac echo "umask 22" umask 22 for file do case $file in /*) pathcomp=/ ;; *) pathcomp= ;; esac oIFS=$IFS IFS=/ set fnord $file shift IFS=$oIFS for d do test "x$d" = x && continue pathcomp=$pathcomp$d case $pathcomp in -*) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr fi fi pathcomp=$pathcomp/ done if test ! -z "$dirmode"; then echo "chmod $dirmode $file" chmod "$dirmode" "$file" || errstatus=$? fi done exit $errstatus # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: libpqxx-8.0.1/config/test-driver000077500000000000000000000114171516427024100166600ustar00rootroot00000000000000#! /bin/sh # test-driver - basic testsuite driver script. scriptversion=2018-03-07.03; # UTC # Copyright (C) 2011-2021 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . # Make unconditional expansion of undefined variables an error. This # helps a lot in preventing typo-related bugs. set -u usage_error () { echo "$0: $*" >&2 print_usage >&2 exit 2 } print_usage () { cat <"$log_file" "$@" >>"$log_file" 2>&1 estatus=$? if test $enable_hard_errors = no && test $estatus -eq 99; then tweaked_estatus=1 else tweaked_estatus=$estatus fi case $tweaked_estatus:$expect_failure in 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 0:*) col=$grn res=PASS recheck=no gcopy=no;; 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; *:*) col=$red res=FAIL recheck=yes gcopy=yes;; esac # Report the test outcome and exit status in the logs, so that one can # know whether the test passed or failed simply by looking at the '.log' # file, without the need of also peaking into the corresponding '.trs' # file (automake bug#11814). echo "$res $test_name (exit status: $estatus)" >>"$log_file" # Report outcome to console. echo "${col}${res}${std}: $test_name" # Register the test result, and other relevant metadata. echo ":test-result: $res" > $trs_file echo ":global-test-result: $res" >> $trs_file echo ":recheck: $recheck" >> $trs_file echo ":copy-in-global-log: $gcopy" >> $trs_file # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: libpqxx-8.0.1/configitems000066400000000000000000000011441516427024100154430ustar00rootroot00000000000000PACKAGE autotools PACKAGE_BUGREPORT autotools PACKAGE_NAME autotools PACKAGE_STRING autotools PACKAGE_TARNAME autotools PACKAGE_VERSION autotools PQXX_HAVE_ASSUME compiler PQXX_HAVE_CHARCONV_FLOAT compiler PQXX_HAVE_CXA_DEMANGLE compiler PQXX_HAVE_GCC_PURE compiler PQXX_HAVE_GCC_VISIBILITY compiler PQXX_HAVE_MULTIDIM compiler PQXX_HAVE_POLL compiler PQXX_HAVE_RANGES compiler PQXX_HAVE_SLEEP_FOR compiler PQXX_HAVE_STACKTRACE compiler PQXX_HAVE_STRERROR_R compiler PQXX_HAVE_STRERROR_S compiler PQXX_HAVE_TYPE_DISPLAY compiler PQXX_HAVE_YEAR_MONTH_DAY compiler PQXX_HAVE_ZARGS compiler VERSION autotools libpqxx-8.0.1/configure000077500000000000000000025046151516427024100151350ustar00rootroot00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.71 for libpqxx 8.0.1. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh as_nop=: if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="as_nop=: if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else \$as_nop case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ) then : else \$as_nop exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 blah=\$(echo \$(echo blah)) test x\"\$blah\" = xblah || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null then : as_have_required=yes else $as_nop as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null then : else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$as_shell as_have_required=yes if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null then : break 2 fi fi done;; esac as_found=false done IFS=$as_save_IFS if $as_found then : else $as_nop if { test -f "$SHELL" || test -f "$SHELL.exe"; } && as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$SHELL as_have_required=yes fi fi if test "x$CONFIG_SHELL" != x then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno then : printf "%s\n" "$0: This script requires a shell more modern than all" printf "%s\n" "$0: the shells that I found on your system." if test ${ZSH_VERSION+y} ; then printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." else printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and Jeroen T. $0: Vermeulen about your system, including any error $0: possibly output before this message. Then install a $0: modern shell, or manually run the script under such a $0: shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_nop # --------- # Do nothing but, unlike ":", preserve the value of $?. as_fn_nop () { return $? } as_nop=as_fn_nop # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else $as_nop as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_nop # --------- # Do nothing but, unlike ":", preserve the value of $?. as_fn_nop () { return $? } as_nop=as_fn_nop # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='libpqxx' PACKAGE_TARNAME='libpqxx' PACKAGE_VERSION='8.0.1' PACKAGE_STRING='libpqxx 8.0.1' PACKAGE_BUGREPORT='Jeroen T. Vermeulen' PACKAGE_URL='' ac_unique_file="src/connection.cxx" ac_default_prefix=/usr/local ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS with_postgres_lib POSTGRES_INCLUDE PG_CONFIG PKG_CONFIG MAINT MAINTAINER_MODE_FALSE MAINTAINER_MODE_TRUE BUILD_DOCS_FALSE BUILD_DOCS_TRUE MKDIR CXXCPP LT_SYS_LIBRARY_PATH OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB ac_ct_AR AR DLLTOOL OBJDUMP FILECMD LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE ac_ct_CC CFLAGS CC host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBTOOL PQXX_ABI PQXXVERSION AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V CSCOPE ETAGS CTAGS am__fastdepCXX_FALSE am__fastdepCXX_TRUE CXXDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__include DEPDIR am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM HAVE_CXX20 OBJEXT EXEEXT ac_ct_CXX CPPFLAGS LDFLAGS CXXFLAGS CXX target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL am__quote' ac_subst_files='' ac_user_opts=' enable_option_checking enable_dependency_tracking enable_silent_rules enable_shared enable_static with_pic enable_fast_install with_aix_soname with_gnu_ld with_sysroot enable_libtool_lock enable_documentation enable_maintainer_mode enable_audit enable_suggest with_postgres_include with_postgres_lib ' ac_precious_vars='build_alias host_alias target_alias CXX CXXFLAGS LDFLAGS LIBS CPPFLAGS CCC CC CFLAGS LT_SYS_LIBRARY_PATH CXXCPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures libpqxx 8.0.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/libpqxx] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of libpqxx 8.0.1:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-shared[=PKGS] build shared libraries [default=no] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-documentation Generate documentation --enable-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-aix-soname=aix|svr4|both shared library versioning (aka "SONAME") variant to provide on AIX, [default=aix]. --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --with-postgres-include=DIR Use PostgreSQL includes from DIR. Defaults to querying pg_config or pkg-config, whichever is available. --with-postgres-lib=DIR Use PostgreSQL libraries from DIR. Defaults to querying pg_config. Some influential environment variables: CXX C++ compiler command CXXFLAGS C++ compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CC C compiler command CFLAGS C compiler flags LT_SYS_LIBRARY_PATH User-defined run-time library search path. CXXCPP C++ preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for configure.gnu first; this name is used for a wrapper for # Metaconfig's "Configure" on case-insensitive file systems. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF libpqxx configure 8.0.1 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. */ #include #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main (void) { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_cxx_try_cpp LINENO # ------------------------ # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_cpp # ac_fn_cxx_try_link LINENO # ------------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_link # ac_fn_cxx_check_header_compile LINENO HEADER VAR INCLUDES # --------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_cxx_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_header_compile ac_configure_args_raw= for ac_arg do case $ac_arg in *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append ac_configure_args_raw " '$ac_arg'" done case $ac_configure_args_raw in *$as_nl*) ac_safe_unquote= ;; *) ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab. ac_unsafe_a="$ac_unsafe_z#~" ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g" ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;; esac cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by libpqxx $as_me 8.0.1, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac printf "%s\n" "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Sanitize IFS. IFS=" "" $as_nl" # Save into config.log some information that might help in debugging. { echo printf "%s\n" "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo printf "%s\n" "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then printf "%s\n" "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then printf "%s\n" "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && printf "%s\n" "$as_me: caught signal $ac_signal" printf "%s\n" "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h printf "%s\n" "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then ac_site_files="$CONFIG_SITE" elif test "x$prefix" != xNONE; then ac_site_files="$prefix/share/config.site $prefix/etc/config.site" else ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi for ac_site_file in $ac_site_files do case $ac_site_file in #( */*) : ;; #( *) : ac_site_file=./$ac_site_file ;; esac if test -f "$ac_site_file" && test -r "$ac_site_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 printf "%s\n" "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 printf "%s\n" "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Test code for whether the C++ compiler supports C++98 (global declarations) ac_cxx_conftest_cxx98_globals=' // Does the compiler advertise C++98 conformance? #if !defined __cplusplus || __cplusplus < 199711L # error "Compiler does not advertise C++98 conformance" #endif // These inclusions are to reject old compilers that // lack the unsuffixed header files. #include #include // and are *not* freestanding headers in C++98. extern void assert (int); namespace std { extern int strcmp (const char *, const char *); } // Namespaces, exceptions, and templates were all added after "C++ 2.0". using std::exception; using std::strcmp; namespace { void test_exception_syntax() { try { throw "test"; } catch (const char *s) { // Extra parentheses suppress a warning when building autoconf itself, // due to lint rules shared with more typical C programs. assert (!(strcmp) (s, "test")); } } template struct test_template { T const val; explicit test_template(T t) : val(t) {} template T add(U u) { return static_cast(u) + val; } }; } // anonymous namespace ' # Test code for whether the C++ compiler supports C++98 (body of main) ac_cxx_conftest_cxx98_main=' assert (argc); assert (! argv[0]); { test_exception_syntax (); test_template tt (2.0); assert (tt.add (4) == 6.0); assert (true && !false); } ' # Test code for whether the C++ compiler supports C++11 (global declarations) ac_cxx_conftest_cxx11_globals=' // Does the compiler advertise C++ 2011 conformance? #if !defined __cplusplus || __cplusplus < 201103L # error "Compiler does not advertise C++11 conformance" #endif namespace cxx11test { constexpr int get_val() { return 20; } struct testinit { int i; double d; }; class delegate { public: delegate(int n) : n(n) {} delegate(): delegate(2354) {} virtual int getval() { return this->n; }; protected: int n; }; class overridden : public delegate { public: overridden(int n): delegate(n) {} virtual int getval() override final { return this->n * 2; } }; class nocopy { public: nocopy(int i): i(i) {} nocopy() = default; nocopy(const nocopy&) = delete; nocopy & operator=(const nocopy&) = delete; private: int i; }; // for testing lambda expressions template Ret eval(Fn f, Ret v) { return f(v); } // for testing variadic templates and trailing return types template auto sum(V first) -> V { return first; } template auto sum(V first, Args... rest) -> V { return first + sum(rest...); } } ' # Test code for whether the C++ compiler supports C++11 (body of main) ac_cxx_conftest_cxx11_main=' { // Test auto and decltype auto a1 = 6538; auto a2 = 48573953.4; auto a3 = "String literal"; int total = 0; for (auto i = a3; *i; ++i) { total += *i; } decltype(a2) a4 = 34895.034; } { // Test constexpr short sa[cxx11test::get_val()] = { 0 }; } { // Test initializer lists cxx11test::testinit il = { 4323, 435234.23544 }; } { // Test range-based for int array[] = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3, 14, 19, 17, 8, 6, 20, 16, 2, 11, 1}; for (auto &x : array) { x += 23; } } { // Test lambda expressions using cxx11test::eval; assert (eval ([](int x) { return x*2; }, 21) == 42); double d = 2.0; assert (eval ([&](double x) { return d += x; }, 3.0) == 5.0); assert (d == 5.0); assert (eval ([=](double x) mutable { return d += x; }, 4.0) == 9.0); assert (d == 5.0); } { // Test use of variadic templates using cxx11test::sum; auto a = sum(1); auto b = sum(1, 2); auto c = sum(1.0, 2.0, 3.0); } { // Test constructor delegation cxx11test::delegate d1; cxx11test::delegate d2(); cxx11test::delegate d3(45); } { // Test override and final cxx11test::overridden o1(55464); } { // Test nullptr char *c = nullptr; } { // Test template brackets test_template<::test_template> v(test_template(12)); } { // Unicode literals char const *utf8 = u8"UTF-8 string \u2500"; char16_t const *utf16 = u"UTF-8 string \u2500"; char32_t const *utf32 = U"UTF-32 string \u2500"; } ' # Test code for whether the C compiler supports C++11 (complete). ac_cxx_conftest_cxx11_program="${ac_cxx_conftest_cxx98_globals} ${ac_cxx_conftest_cxx11_globals} int main (int argc, char **argv) { int ok = 0; ${ac_cxx_conftest_cxx98_main} ${ac_cxx_conftest_cxx11_main} return ok; } " # Test code for whether the C compiler supports C++98 (complete). ac_cxx_conftest_cxx98_program="${ac_cxx_conftest_cxx98_globals} int main (int argc, char **argv) { int ok = 0; ${ac_cxx_conftest_cxx98_main} return ok; } " # Test code for whether the C compiler supports C89 (global declarations) ac_c_conftest_c89_globals=' /* Does the compiler advertise C89 conformance? Do not test the value of __STDC__, because some compilers set it to 0 while being otherwise adequately conformant. */ #if !defined __STDC__ # error "Compiler does not advertise C89 conformance" #endif #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ struct buf { int x; }; struct buf * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not \xHH hex character constants. These do not provoke an error unfortunately, instead are silently treated as an "x". The following induces an error, until -std is added to get proper ANSI mode. Curiously \x00 != x always comes out true, for an array size at least. It is necessary to write \x00 == 0 to get something that is true only with -std. */ int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) '\''x'\'' int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int), int, int);' # Test code for whether the C compiler supports C89 (body of main). ac_c_conftest_c89_main=' ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); ' # Test code for whether the C compiler supports C99 (global declarations) ac_c_conftest_c99_globals=' // Does the compiler advertise C99 conformance? #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L # error "Compiler does not advertise C99 conformance" #endif #include extern int puts (const char *); extern int printf (const char *, ...); extern int dprintf (int, const char *, ...); extern void *malloc (size_t); // Check varargs macros. These examples are taken from C99 6.10.3.5. // dprintf is used instead of fprintf to avoid needing to declare // FILE and stderr. #define debug(...) dprintf (2, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK #error "your preprocessor is broken" #endif #if BIG_OK #else #error "your preprocessor is broken" #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // See if C++-style comments work. // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) continue; return 0; } // Check varargs and va_copy. static bool test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str = ""; int number = 0; float fnumber = 0; while (*format) { switch (*format++) { case '\''s'\'': // string str = va_arg (args_copy, const char *); break; case '\''d'\'': // int number = va_arg (args_copy, int); break; case '\''f'\'': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); return *str && number && fnumber; } ' # Test code for whether the C compiler supports C99 (body of main). ac_c_conftest_c99_main=' // Check bool. _Bool success = false; success |= (argc != 0); // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[0] = argv[0][0]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' || dynamic_array[ni.number - 1] != 543); ' # Test code for whether the C compiler supports C11 (global declarations) ac_c_conftest_c11_globals=' // Does the compiler advertise C11 conformance? #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L # error "Compiler does not advertise C11 conformance" #endif // Check _Alignas. char _Alignas (double) aligned_as_double; char _Alignas (0) no_special_alignment; extern char aligned_as_int; char _Alignas (0) _Alignas (int) aligned_as_int; // Check _Alignof. enum { int_alignment = _Alignof (int), int_array_alignment = _Alignof (int[100]), char_alignment = _Alignof (char) }; _Static_assert (0 < -_Alignof (int), "_Alignof is signed"); // Check _Noreturn. int _Noreturn does_not_return (void) { for (;;) continue; } // Check _Static_assert. struct test_static_assert { int x; _Static_assert (sizeof (int) <= sizeof (long int), "_Static_assert does not work in struct"); long int y; }; // Check UTF-8 literals. #define u8 syntax error! char const utf8_literal[] = u8"happens to be ASCII" "another string"; // Check duplicate typedefs. typedef long *long_ptr; typedef long int *long_ptr; typedef long_ptr long_ptr; // Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. struct anonymous { union { struct { int i; int j; }; struct { int k; long int l; } w; }; int m; } v1; ' # Test code for whether the C compiler supports C11 (body of main). ac_c_conftest_c11_main=' _Static_assert ((offsetof (struct anonymous, i) == offsetof (struct anonymous, w.k)), "Anonymous union alignment botch"); v1.i = 2; v1.w.k = 5; ok |= v1.i != 5; ' # Test code for whether the C compiler supports C11 (complete). ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} ${ac_c_conftest_c11_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} ${ac_c_conftest_c11_main} return ok; } " # Test code for whether the C compiler supports C99 (complete). ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} return ok; } " # Test code for whether the C compiler supports C89 (complete). ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} return ok; } " # Auxiliary files required by this configure script. ac_aux_files="compile config.guess config.sub ltmain.sh missing install-sh" # Locations in which to look for auxiliary files. ac_aux_dir_candidates="${srcdir}/config" # Search for a directory containing all of the required auxiliary files, # $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates. # If we don't find one directory that contains all the files we need, # we report the set of missing files from the *first* directory in # $ac_aux_dir_candidates and give up. ac_missing_aux_files="" ac_first_candidate=: printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in $ac_aux_dir_candidates do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5 ac_aux_dir_found=yes ac_install_sh= for ac_aux in $ac_aux_files do # As a special case, if "install-sh" is required, that requirement # can be satisfied by any of "install-sh", "install.sh", or "shtool", # and $ac_install_sh is set appropriately for whichever one is found. if test x"$ac_aux" = x"install-sh" then if test -f "${as_dir}install-sh"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5 ac_install_sh="${as_dir}install-sh -c" elif test -f "${as_dir}install.sh"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5 ac_install_sh="${as_dir}install.sh -c" elif test -f "${as_dir}shtool"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5 ac_install_sh="${as_dir}shtool install -c" else ac_aux_dir_found=no if $ac_first_candidate; then ac_missing_aux_files="${ac_missing_aux_files} install-sh" else break fi fi else if test -f "${as_dir}${ac_aux}"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5 else ac_aux_dir_found=no if $ac_first_candidate; then ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}" else break fi fi fi done if test "$ac_aux_dir_found" = yes; then ac_aux_dir="$as_dir" break fi ac_first_candidate=false as_found=false done IFS=$as_save_IFS if $as_found then : else $as_nop as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. if test -f "${ac_aux_dir}config.guess"; then ac_config_guess="$SHELL ${ac_aux_dir}config.guess" fi if test -f "${ac_aux_dir}config.sub"; then ac_config_sub="$SHELL ${ac_aux_dir}config.sub" fi if test -f "$ac_aux_dir/configure"; then ac_configure="$SHELL ${ac_aux_dir}configure" fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Suppress checks for standard C headers. One, we're not doing C here; two, # if you don't have these, chances are your system is in no shape to build # libpqxx; and three, we require C++20. It's a bit pointless to guard against # such specific shortcomings of 20th-century compilers. ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CXX+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 printf "%s\n" "$CXX" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CXX+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 printf "%s\n" "$ac_ct_CXX" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5 printf %s "checking whether the C++ compiler works... " >&6; } ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else $as_nop ac_file='' fi if test -z "$ac_file" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C++ compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5 printf %s "checking for C++ compiler default output file name... " >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 printf "%s\n" "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 printf %s "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else $as_nop { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 printf "%s\n" "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 printf %s "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot run C++ compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 printf "%s\n" "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 printf %s "checking for suffix of object files... " >&6; } if test ${ac_cv_objext+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 printf "%s\n" "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C++" >&5 printf %s "checking whether the compiler supports GNU C++... " >&6; } if test ${ac_cv_cxx_compiler_gnu+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_compiler_gnu=yes else $as_nop ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 printf "%s\n" "$ac_cv_cxx_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+y} ac_save_CXXFLAGS=$CXXFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 printf %s "checking whether $CXX accepts -g... " >&6; } if test ${ac_cv_prog_cxx_g+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_g=yes else $as_nop CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : else $as_nop ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 printf "%s\n" "$ac_cv_prog_cxx_g" >&6; } if test $ac_test_CXXFLAGS; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_prog_cxx_stdcxx=no if test x$ac_prog_cxx_stdcxx = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5 printf %s "checking for $CXX option to enable C++11 features... " >&6; } if test ${ac_cv_prog_cxx_cxx11+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cxx_cxx11=no ac_save_CXX=$CXX cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_cxx_conftest_cxx11_program _ACEOF for ac_arg in '' -std=gnu++11 -std=gnu++0x -std=c++11 -std=c++0x -qlanglvl=extended0x -AA do CXX="$ac_save_CXX $ac_arg" if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_cxx11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cxx_cxx11" != "xno" && break done rm -f conftest.$ac_ext CXX=$ac_save_CXX fi if test "x$ac_cv_prog_cxx_cxx11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cxx_cxx11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5 printf "%s\n" "$ac_cv_prog_cxx_cxx11" >&6; } CXX="$CXX $ac_cv_prog_cxx_cxx11" fi ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11 ac_prog_cxx_stdcxx=cxx11 fi fi if test x$ac_prog_cxx_stdcxx = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5 printf %s "checking for $CXX option to enable C++98 features... " >&6; } if test ${ac_cv_prog_cxx_cxx98+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cxx_cxx98=no ac_save_CXX=$CXX cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_cxx_conftest_cxx98_program _ACEOF for ac_arg in '' -std=gnu++98 -std=c++98 -qlanglvl=extended -AA do CXX="$ac_save_CXX $ac_arg" if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_cxx98=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cxx_cxx98" != "xno" && break done rm -f conftest.$ac_ext CXX=$ac_save_CXX fi if test "x$ac_cv_prog_cxx_cxx98" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cxx_cxx98" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5 printf "%s\n" "$ac_cv_prog_cxx_cxx98" >&6; } CXX="$CXX $ac_cv_prog_cxx_cxx98" fi ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98 ac_prog_cxx_stdcxx=cxx98 fi fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ax_cxx_compile_alternatives="20" ax_cxx_compile_cxx20_required=true ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_success=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++20 features by default" >&5 printf %s "checking whether $CXX supports C++20 features by default... " >&6; } if test ${ax_cv_cxx_compile_cxx20+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ // If the compiler admits that it is not ready for C++11, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" // MSVC always sets __cplusplus to 199711L in older versions; newer versions // only set it correctly if /Zc:__cplusplus is specified as well as a // /std:c++NN switch: // https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ #elif __cplusplus < 201103L && !defined _MSC_VER #error "This is not a C++11 compiler" #else namespace cxx11 { namespace test_static_assert { template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; } namespace test_final_override { struct Base { virtual ~Base() {} virtual void f() {} }; struct Derived : public Base { virtual ~Derived() override {} virtual void f() override {} }; } namespace test_double_right_angle_brackets { template < typename T > struct check {}; typedef check single_type; typedef check> double_type; typedef check>> triple_type; typedef check>>> quadruple_type; } namespace test_decltype { int f() { int a = 1; decltype(a) b = 2; return a + b; } } namespace test_type_deduction { template < typename T1, typename T2 > struct is_same { static const bool value = false; }; template < typename T > struct is_same { static const bool value = true; }; template < typename T1, typename T2 > auto add(T1 a1, T2 a2) -> decltype(a1 + a2) { return a1 + a2; } int test(const int c, volatile int v) { static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == false, ""); auto ac = c; auto av = v; auto sumi = ac + av + 'x'; auto sumf = ac + av + 1.0; static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == true, ""); return (sumf > 0.0) ? sumi : add(c, v); } } namespace test_noexcept { int f() { return 0; } int g() noexcept { return 0; } static_assert(noexcept(f()) == false, ""); static_assert(noexcept(g()) == true, ""); } namespace test_constexpr { template < typename CharT > unsigned long constexpr strlen_c_r(const CharT *const s, const unsigned long acc) noexcept { return *s ? strlen_c_r(s + 1, acc + 1) : acc; } template < typename CharT > unsigned long constexpr strlen_c(const CharT *const s) noexcept { return strlen_c_r(s, 0UL); } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("1") == 1UL, ""); static_assert(strlen_c("example") == 7UL, ""); static_assert(strlen_c("another\0example") == 7UL, ""); } namespace test_rvalue_references { template < int N > struct answer { static constexpr int value = N; }; answer<1> f(int&) { return answer<1>(); } answer<2> f(const int&) { return answer<2>(); } answer<3> f(int&&) { return answer<3>(); } void test() { int i = 0; const int c = 0; static_assert(decltype(f(i))::value == 1, ""); static_assert(decltype(f(c))::value == 2, ""); static_assert(decltype(f(0))::value == 3, ""); } } namespace test_uniform_initialization { struct test { static const int zero {}; static const int one {1}; }; static_assert(test::zero == 0, ""); static_assert(test::one == 1, ""); } namespace test_lambdas { void test1() { auto lambda1 = [](){}; auto lambda2 = lambda1; lambda1(); lambda2(); } int test2() { auto a = [](int i, int j){ return i + j; }(1, 2); auto b = []() -> int { return '0'; }(); auto c = [=](){ return a + b; }(); auto d = [&](){ return c; }(); auto e = [a, &b](int x) mutable { const auto identity = [](int y){ return y; }; for (auto i = 0; i < a; ++i) a += b--; return x + identity(a + b); }(0); return a + b + c + d + e; } int test3() { const auto nullary = [](){ return 0; }; const auto unary = [](int x){ return x; }; using nullary_t = decltype(nullary); using unary_t = decltype(unary); const auto higher1st = [](nullary_t f){ return f(); }; const auto higher2nd = [unary](nullary_t f1){ return [unary, f1](unary_t f2){ return f2(unary(f1())); }; }; return higher1st(nullary) + higher2nd(nullary)(unary); } } namespace test_variadic_templates { template struct sum; template struct sum { static constexpr auto value = N0 + sum::value; }; template <> struct sum<> { static constexpr auto value = 0; }; static_assert(sum<>::value == 0, ""); static_assert(sum<1>::value == 1, ""); static_assert(sum<23>::value == 23, ""); static_assert(sum<1, 2>::value == 3, ""); static_assert(sum<5, 5, 11>::value == 21, ""); static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); } // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function // because of this. namespace test_template_alias_sfinae { struct foo {}; template using member = typename T::member_type; template void func(...) {} template void func(member*) {} void test(); void test() { func(0); } } } // namespace cxx11 #endif // __cplusplus >= 201103L // If the compiler admits that it is not ready for C++14, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201402L && !defined _MSC_VER #error "This is not a C++14 compiler" #else namespace cxx14 { namespace test_polymorphic_lambdas { int test() { const auto lambda = [](auto&&... args){ const auto istiny = [](auto x){ return (sizeof(x) == 1UL) ? 1 : 0; }; const int aretiny[] = { istiny(args)... }; return aretiny[0]; }; return lambda(1, 1L, 1.0f, '1'); } } namespace test_binary_literals { constexpr auto ivii = 0b0000000000101010; static_assert(ivii == 42, "wrong value"); } namespace test_generalized_constexpr { template < typename CharT > constexpr unsigned long strlen_c(const CharT *const s) noexcept { auto length = 0UL; for (auto p = s; *p; ++p) ++length; return length; } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("x") == 1UL, ""); static_assert(strlen_c("test") == 4UL, ""); static_assert(strlen_c("another\0test") == 7UL, ""); } namespace test_lambda_init_capture { int test() { auto x = 0; const auto lambda1 = [a = x](int b){ return a + b; }; const auto lambda2 = [a = lambda1(x)](){ return a; }; return lambda2(); } } namespace test_digit_separators { constexpr auto ten_million = 100'000'000; static_assert(ten_million == 100000000, ""); } namespace test_return_type_deduction { auto f(int& x) { return x; } decltype(auto) g(int& x) { return x; } template < typename T1, typename T2 > struct is_same { static constexpr auto value = false; }; template < typename T > struct is_same { static constexpr auto value = true; }; int test() { auto x = 0; static_assert(is_same::value, ""); static_assert(is_same::value, ""); return x; } } } // namespace cxx14 #endif // __cplusplus >= 201402L // If the compiler admits that it is not ready for C++17, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201703L && !defined _MSC_VER #error "This is not a C++17 compiler" #else #include #include #include namespace cxx17 { namespace test_constexpr_lambdas { constexpr int foo = [](){return 42;}(); } namespace test::nested_namespace::definitions { } namespace test_fold_expression { template int multiply(Args... args) { return (args * ... * 1); } template bool all(Args... args) { return (args && ...); } } namespace test_extended_static_assert { static_assert (true); } namespace test_auto_brace_init_list { auto foo = {5}; auto bar {5}; static_assert(std::is_same, decltype(foo)>::value); static_assert(std::is_same::value); } namespace test_typename_in_template_template_parameter { template typename X> struct D; } namespace test_fallthrough_nodiscard_maybe_unused_attributes { int f1() { return 42; } [[nodiscard]] int f2() { [[maybe_unused]] auto unused = f1(); switch (f1()) { case 17: f1(); [[fallthrough]]; case 42: f1(); } return f1(); } } namespace test_extended_aggregate_initialization { struct base1 { int b1, b2 = 42; }; struct base2 { base2() { b3 = 42; } int b3; }; struct derived : base1, base2 { int d; }; derived d1 {{1, 2}, {}, 4}; // full initialization derived d2 {{}, {}, 4}; // value-initialized bases } namespace test_general_range_based_for_loop { struct iter { int i; int& operator* () { return i; } const int& operator* () const { return i; } iter& operator++() { ++i; return *this; } }; struct sentinel { int i; }; bool operator== (const iter& i, const sentinel& s) { return i.i == s.i; } bool operator!= (const iter& i, const sentinel& s) { return !(i == s); } struct range { iter begin() const { return {0}; } sentinel end() const { return {5}; } }; void f() { range r {}; for (auto i : r) { [[maybe_unused]] auto v = i; } } } namespace test_lambda_capture_asterisk_this_by_value { struct t { int i; int foo() { return [*this]() { return i; }(); } }; } namespace test_enum_class_construction { enum class byte : unsigned char {}; byte foo {42}; } namespace test_constexpr_if { template int f () { if constexpr(cond) { return 13; } else { return 42; } } } namespace test_selection_statement_with_initializer { int f() { return 13; } int f2() { if (auto i = f(); i > 0) { return 3; } switch (auto i = f(); i + 4) { case 17: return 2; default: return 1; } } } namespace test_template_argument_deduction_for_class_templates { template struct pair { pair (T1 p1, T2 p2) : m1 {p1}, m2 {p2} {} T1 m1; T2 m2; }; void f() { [[maybe_unused]] auto p = pair{13, 42u}; } } namespace test_non_type_auto_template_parameters { template struct B {}; B<5> b1; B<'a'> b2; } namespace test_structured_bindings { int arr[2] = { 1, 2 }; std::pair pr = { 1, 2 }; auto f1() -> int(&)[2] { return arr; } auto f2() -> std::pair& { return pr; } struct S { int x1 : 2; volatile double y1; }; S f3() { return {}; } auto [ x1, y1 ] = f1(); auto& [ xr1, yr1 ] = f1(); auto [ x2, y2 ] = f2(); auto& [ xr2, yr2 ] = f2(); const auto [ x3, y3 ] = f3(); } namespace test_exception_spec_type_system { struct Good {}; struct Bad {}; void g1() noexcept; void g2(); template Bad f(T*, T*); template Good f(T1*, T2*); static_assert (std::is_same_v); } namespace test_inline_variables { template void f(T) {} template inline T g(T) { return T{}; } template<> inline void f<>(int) {} template<> int g<>(int) { return 5; } } } // namespace cxx17 #endif // __cplusplus < 201703L && !defined _MSC_VER #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 202002L && !defined _MSC_VER #error "This is not a C++20 compiler" #else #include namespace cxx20 { // As C++20 supports feature test macros in the standard, there is no // immediate need to actually test for feature availability on the // Autoconf side. } // namespace cxx20 #endif // __cplusplus < 202002L && !defined _MSC_VER _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ax_cv_cxx_compile_cxx20=yes else $as_nop ax_cv_cxx_compile_cxx20=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx20" >&5 printf "%s\n" "$ax_cv_cxx_compile_cxx20" >&6; } if test x$ax_cv_cxx_compile_cxx20 = xyes; then ac_success=yes fi if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do switch="-std=gnu++${alternative}" cachevar=`printf "%s\n" "ax_cv_cxx_compile_cxx20_$switch" | $as_tr_sh` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++20 features with $switch" >&5 printf %s "checking whether $CXX supports C++20 features with $switch... " >&6; } if eval test \${$cachevar+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_CXX="$CXX" CXX="$CXX $switch" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ // If the compiler admits that it is not ready for C++11, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" // MSVC always sets __cplusplus to 199711L in older versions; newer versions // only set it correctly if /Zc:__cplusplus is specified as well as a // /std:c++NN switch: // https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ #elif __cplusplus < 201103L && !defined _MSC_VER #error "This is not a C++11 compiler" #else namespace cxx11 { namespace test_static_assert { template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; } namespace test_final_override { struct Base { virtual ~Base() {} virtual void f() {} }; struct Derived : public Base { virtual ~Derived() override {} virtual void f() override {} }; } namespace test_double_right_angle_brackets { template < typename T > struct check {}; typedef check single_type; typedef check> double_type; typedef check>> triple_type; typedef check>>> quadruple_type; } namespace test_decltype { int f() { int a = 1; decltype(a) b = 2; return a + b; } } namespace test_type_deduction { template < typename T1, typename T2 > struct is_same { static const bool value = false; }; template < typename T > struct is_same { static const bool value = true; }; template < typename T1, typename T2 > auto add(T1 a1, T2 a2) -> decltype(a1 + a2) { return a1 + a2; } int test(const int c, volatile int v) { static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == false, ""); auto ac = c; auto av = v; auto sumi = ac + av + 'x'; auto sumf = ac + av + 1.0; static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == true, ""); return (sumf > 0.0) ? sumi : add(c, v); } } namespace test_noexcept { int f() { return 0; } int g() noexcept { return 0; } static_assert(noexcept(f()) == false, ""); static_assert(noexcept(g()) == true, ""); } namespace test_constexpr { template < typename CharT > unsigned long constexpr strlen_c_r(const CharT *const s, const unsigned long acc) noexcept { return *s ? strlen_c_r(s + 1, acc + 1) : acc; } template < typename CharT > unsigned long constexpr strlen_c(const CharT *const s) noexcept { return strlen_c_r(s, 0UL); } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("1") == 1UL, ""); static_assert(strlen_c("example") == 7UL, ""); static_assert(strlen_c("another\0example") == 7UL, ""); } namespace test_rvalue_references { template < int N > struct answer { static constexpr int value = N; }; answer<1> f(int&) { return answer<1>(); } answer<2> f(const int&) { return answer<2>(); } answer<3> f(int&&) { return answer<3>(); } void test() { int i = 0; const int c = 0; static_assert(decltype(f(i))::value == 1, ""); static_assert(decltype(f(c))::value == 2, ""); static_assert(decltype(f(0))::value == 3, ""); } } namespace test_uniform_initialization { struct test { static const int zero {}; static const int one {1}; }; static_assert(test::zero == 0, ""); static_assert(test::one == 1, ""); } namespace test_lambdas { void test1() { auto lambda1 = [](){}; auto lambda2 = lambda1; lambda1(); lambda2(); } int test2() { auto a = [](int i, int j){ return i + j; }(1, 2); auto b = []() -> int { return '0'; }(); auto c = [=](){ return a + b; }(); auto d = [&](){ return c; }(); auto e = [a, &b](int x) mutable { const auto identity = [](int y){ return y; }; for (auto i = 0; i < a; ++i) a += b--; return x + identity(a + b); }(0); return a + b + c + d + e; } int test3() { const auto nullary = [](){ return 0; }; const auto unary = [](int x){ return x; }; using nullary_t = decltype(nullary); using unary_t = decltype(unary); const auto higher1st = [](nullary_t f){ return f(); }; const auto higher2nd = [unary](nullary_t f1){ return [unary, f1](unary_t f2){ return f2(unary(f1())); }; }; return higher1st(nullary) + higher2nd(nullary)(unary); } } namespace test_variadic_templates { template struct sum; template struct sum { static constexpr auto value = N0 + sum::value; }; template <> struct sum<> { static constexpr auto value = 0; }; static_assert(sum<>::value == 0, ""); static_assert(sum<1>::value == 1, ""); static_assert(sum<23>::value == 23, ""); static_assert(sum<1, 2>::value == 3, ""); static_assert(sum<5, 5, 11>::value == 21, ""); static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); } // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function // because of this. namespace test_template_alias_sfinae { struct foo {}; template using member = typename T::member_type; template void func(...) {} template void func(member*) {} void test(); void test() { func(0); } } } // namespace cxx11 #endif // __cplusplus >= 201103L // If the compiler admits that it is not ready for C++14, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201402L && !defined _MSC_VER #error "This is not a C++14 compiler" #else namespace cxx14 { namespace test_polymorphic_lambdas { int test() { const auto lambda = [](auto&&... args){ const auto istiny = [](auto x){ return (sizeof(x) == 1UL) ? 1 : 0; }; const int aretiny[] = { istiny(args)... }; return aretiny[0]; }; return lambda(1, 1L, 1.0f, '1'); } } namespace test_binary_literals { constexpr auto ivii = 0b0000000000101010; static_assert(ivii == 42, "wrong value"); } namespace test_generalized_constexpr { template < typename CharT > constexpr unsigned long strlen_c(const CharT *const s) noexcept { auto length = 0UL; for (auto p = s; *p; ++p) ++length; return length; } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("x") == 1UL, ""); static_assert(strlen_c("test") == 4UL, ""); static_assert(strlen_c("another\0test") == 7UL, ""); } namespace test_lambda_init_capture { int test() { auto x = 0; const auto lambda1 = [a = x](int b){ return a + b; }; const auto lambda2 = [a = lambda1(x)](){ return a; }; return lambda2(); } } namespace test_digit_separators { constexpr auto ten_million = 100'000'000; static_assert(ten_million == 100000000, ""); } namespace test_return_type_deduction { auto f(int& x) { return x; } decltype(auto) g(int& x) { return x; } template < typename T1, typename T2 > struct is_same { static constexpr auto value = false; }; template < typename T > struct is_same { static constexpr auto value = true; }; int test() { auto x = 0; static_assert(is_same::value, ""); static_assert(is_same::value, ""); return x; } } } // namespace cxx14 #endif // __cplusplus >= 201402L // If the compiler admits that it is not ready for C++17, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201703L && !defined _MSC_VER #error "This is not a C++17 compiler" #else #include #include #include namespace cxx17 { namespace test_constexpr_lambdas { constexpr int foo = [](){return 42;}(); } namespace test::nested_namespace::definitions { } namespace test_fold_expression { template int multiply(Args... args) { return (args * ... * 1); } template bool all(Args... args) { return (args && ...); } } namespace test_extended_static_assert { static_assert (true); } namespace test_auto_brace_init_list { auto foo = {5}; auto bar {5}; static_assert(std::is_same, decltype(foo)>::value); static_assert(std::is_same::value); } namespace test_typename_in_template_template_parameter { template typename X> struct D; } namespace test_fallthrough_nodiscard_maybe_unused_attributes { int f1() { return 42; } [[nodiscard]] int f2() { [[maybe_unused]] auto unused = f1(); switch (f1()) { case 17: f1(); [[fallthrough]]; case 42: f1(); } return f1(); } } namespace test_extended_aggregate_initialization { struct base1 { int b1, b2 = 42; }; struct base2 { base2() { b3 = 42; } int b3; }; struct derived : base1, base2 { int d; }; derived d1 {{1, 2}, {}, 4}; // full initialization derived d2 {{}, {}, 4}; // value-initialized bases } namespace test_general_range_based_for_loop { struct iter { int i; int& operator* () { return i; } const int& operator* () const { return i; } iter& operator++() { ++i; return *this; } }; struct sentinel { int i; }; bool operator== (const iter& i, const sentinel& s) { return i.i == s.i; } bool operator!= (const iter& i, const sentinel& s) { return !(i == s); } struct range { iter begin() const { return {0}; } sentinel end() const { return {5}; } }; void f() { range r {}; for (auto i : r) { [[maybe_unused]] auto v = i; } } } namespace test_lambda_capture_asterisk_this_by_value { struct t { int i; int foo() { return [*this]() { return i; }(); } }; } namespace test_enum_class_construction { enum class byte : unsigned char {}; byte foo {42}; } namespace test_constexpr_if { template int f () { if constexpr(cond) { return 13; } else { return 42; } } } namespace test_selection_statement_with_initializer { int f() { return 13; } int f2() { if (auto i = f(); i > 0) { return 3; } switch (auto i = f(); i + 4) { case 17: return 2; default: return 1; } } } namespace test_template_argument_deduction_for_class_templates { template struct pair { pair (T1 p1, T2 p2) : m1 {p1}, m2 {p2} {} T1 m1; T2 m2; }; void f() { [[maybe_unused]] auto p = pair{13, 42u}; } } namespace test_non_type_auto_template_parameters { template struct B {}; B<5> b1; B<'a'> b2; } namespace test_structured_bindings { int arr[2] = { 1, 2 }; std::pair pr = { 1, 2 }; auto f1() -> int(&)[2] { return arr; } auto f2() -> std::pair& { return pr; } struct S { int x1 : 2; volatile double y1; }; S f3() { return {}; } auto [ x1, y1 ] = f1(); auto& [ xr1, yr1 ] = f1(); auto [ x2, y2 ] = f2(); auto& [ xr2, yr2 ] = f2(); const auto [ x3, y3 ] = f3(); } namespace test_exception_spec_type_system { struct Good {}; struct Bad {}; void g1() noexcept; void g2(); template Bad f(T*, T*); template Good f(T1*, T2*); static_assert (std::is_same_v); } namespace test_inline_variables { template void f(T) {} template inline T g(T) { return T{}; } template<> inline void f<>(int) {} template<> int g<>(int) { return 5; } } } // namespace cxx17 #endif // __cplusplus < 201703L && !defined _MSC_VER #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 202002L && !defined _MSC_VER #error "This is not a C++20 compiler" #else #include namespace cxx20 { // As C++20 supports feature test macros in the standard, there is no // immediate need to actually test for feature availability on the // Autoconf side. } // namespace cxx20 #endif // __cplusplus < 202002L && !defined _MSC_VER _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : eval $cachevar=yes else $as_nop eval $cachevar=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CXX="$ac_save_CXX" fi eval ac_res=\$$cachevar { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done fi if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do cachevar=`printf "%s\n" "ax_cv_cxx_compile_cxx20_$switch" | $as_tr_sh` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++20 features with $switch" >&5 printf %s "checking whether $CXX supports C++20 features with $switch... " >&6; } if eval test \${$cachevar+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_CXX="$CXX" CXX="$CXX $switch" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ // If the compiler admits that it is not ready for C++11, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" // MSVC always sets __cplusplus to 199711L in older versions; newer versions // only set it correctly if /Zc:__cplusplus is specified as well as a // /std:c++NN switch: // https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ #elif __cplusplus < 201103L && !defined _MSC_VER #error "This is not a C++11 compiler" #else namespace cxx11 { namespace test_static_assert { template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; } namespace test_final_override { struct Base { virtual ~Base() {} virtual void f() {} }; struct Derived : public Base { virtual ~Derived() override {} virtual void f() override {} }; } namespace test_double_right_angle_brackets { template < typename T > struct check {}; typedef check single_type; typedef check> double_type; typedef check>> triple_type; typedef check>>> quadruple_type; } namespace test_decltype { int f() { int a = 1; decltype(a) b = 2; return a + b; } } namespace test_type_deduction { template < typename T1, typename T2 > struct is_same { static const bool value = false; }; template < typename T > struct is_same { static const bool value = true; }; template < typename T1, typename T2 > auto add(T1 a1, T2 a2) -> decltype(a1 + a2) { return a1 + a2; } int test(const int c, volatile int v) { static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == false, ""); auto ac = c; auto av = v; auto sumi = ac + av + 'x'; auto sumf = ac + av + 1.0; static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == true, ""); return (sumf > 0.0) ? sumi : add(c, v); } } namespace test_noexcept { int f() { return 0; } int g() noexcept { return 0; } static_assert(noexcept(f()) == false, ""); static_assert(noexcept(g()) == true, ""); } namespace test_constexpr { template < typename CharT > unsigned long constexpr strlen_c_r(const CharT *const s, const unsigned long acc) noexcept { return *s ? strlen_c_r(s + 1, acc + 1) : acc; } template < typename CharT > unsigned long constexpr strlen_c(const CharT *const s) noexcept { return strlen_c_r(s, 0UL); } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("1") == 1UL, ""); static_assert(strlen_c("example") == 7UL, ""); static_assert(strlen_c("another\0example") == 7UL, ""); } namespace test_rvalue_references { template < int N > struct answer { static constexpr int value = N; }; answer<1> f(int&) { return answer<1>(); } answer<2> f(const int&) { return answer<2>(); } answer<3> f(int&&) { return answer<3>(); } void test() { int i = 0; const int c = 0; static_assert(decltype(f(i))::value == 1, ""); static_assert(decltype(f(c))::value == 2, ""); static_assert(decltype(f(0))::value == 3, ""); } } namespace test_uniform_initialization { struct test { static const int zero {}; static const int one {1}; }; static_assert(test::zero == 0, ""); static_assert(test::one == 1, ""); } namespace test_lambdas { void test1() { auto lambda1 = [](){}; auto lambda2 = lambda1; lambda1(); lambda2(); } int test2() { auto a = [](int i, int j){ return i + j; }(1, 2); auto b = []() -> int { return '0'; }(); auto c = [=](){ return a + b; }(); auto d = [&](){ return c; }(); auto e = [a, &b](int x) mutable { const auto identity = [](int y){ return y; }; for (auto i = 0; i < a; ++i) a += b--; return x + identity(a + b); }(0); return a + b + c + d + e; } int test3() { const auto nullary = [](){ return 0; }; const auto unary = [](int x){ return x; }; using nullary_t = decltype(nullary); using unary_t = decltype(unary); const auto higher1st = [](nullary_t f){ return f(); }; const auto higher2nd = [unary](nullary_t f1){ return [unary, f1](unary_t f2){ return f2(unary(f1())); }; }; return higher1st(nullary) + higher2nd(nullary)(unary); } } namespace test_variadic_templates { template struct sum; template struct sum { static constexpr auto value = N0 + sum::value; }; template <> struct sum<> { static constexpr auto value = 0; }; static_assert(sum<>::value == 0, ""); static_assert(sum<1>::value == 1, ""); static_assert(sum<23>::value == 23, ""); static_assert(sum<1, 2>::value == 3, ""); static_assert(sum<5, 5, 11>::value == 21, ""); static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); } // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function // because of this. namespace test_template_alias_sfinae { struct foo {}; template using member = typename T::member_type; template void func(...) {} template void func(member*) {} void test(); void test() { func(0); } } } // namespace cxx11 #endif // __cplusplus >= 201103L // If the compiler admits that it is not ready for C++14, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201402L && !defined _MSC_VER #error "This is not a C++14 compiler" #else namespace cxx14 { namespace test_polymorphic_lambdas { int test() { const auto lambda = [](auto&&... args){ const auto istiny = [](auto x){ return (sizeof(x) == 1UL) ? 1 : 0; }; const int aretiny[] = { istiny(args)... }; return aretiny[0]; }; return lambda(1, 1L, 1.0f, '1'); } } namespace test_binary_literals { constexpr auto ivii = 0b0000000000101010; static_assert(ivii == 42, "wrong value"); } namespace test_generalized_constexpr { template < typename CharT > constexpr unsigned long strlen_c(const CharT *const s) noexcept { auto length = 0UL; for (auto p = s; *p; ++p) ++length; return length; } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("x") == 1UL, ""); static_assert(strlen_c("test") == 4UL, ""); static_assert(strlen_c("another\0test") == 7UL, ""); } namespace test_lambda_init_capture { int test() { auto x = 0; const auto lambda1 = [a = x](int b){ return a + b; }; const auto lambda2 = [a = lambda1(x)](){ return a; }; return lambda2(); } } namespace test_digit_separators { constexpr auto ten_million = 100'000'000; static_assert(ten_million == 100000000, ""); } namespace test_return_type_deduction { auto f(int& x) { return x; } decltype(auto) g(int& x) { return x; } template < typename T1, typename T2 > struct is_same { static constexpr auto value = false; }; template < typename T > struct is_same { static constexpr auto value = true; }; int test() { auto x = 0; static_assert(is_same::value, ""); static_assert(is_same::value, ""); return x; } } } // namespace cxx14 #endif // __cplusplus >= 201402L // If the compiler admits that it is not ready for C++17, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201703L && !defined _MSC_VER #error "This is not a C++17 compiler" #else #include #include #include namespace cxx17 { namespace test_constexpr_lambdas { constexpr int foo = [](){return 42;}(); } namespace test::nested_namespace::definitions { } namespace test_fold_expression { template int multiply(Args... args) { return (args * ... * 1); } template bool all(Args... args) { return (args && ...); } } namespace test_extended_static_assert { static_assert (true); } namespace test_auto_brace_init_list { auto foo = {5}; auto bar {5}; static_assert(std::is_same, decltype(foo)>::value); static_assert(std::is_same::value); } namespace test_typename_in_template_template_parameter { template typename X> struct D; } namespace test_fallthrough_nodiscard_maybe_unused_attributes { int f1() { return 42; } [[nodiscard]] int f2() { [[maybe_unused]] auto unused = f1(); switch (f1()) { case 17: f1(); [[fallthrough]]; case 42: f1(); } return f1(); } } namespace test_extended_aggregate_initialization { struct base1 { int b1, b2 = 42; }; struct base2 { base2() { b3 = 42; } int b3; }; struct derived : base1, base2 { int d; }; derived d1 {{1, 2}, {}, 4}; // full initialization derived d2 {{}, {}, 4}; // value-initialized bases } namespace test_general_range_based_for_loop { struct iter { int i; int& operator* () { return i; } const int& operator* () const { return i; } iter& operator++() { ++i; return *this; } }; struct sentinel { int i; }; bool operator== (const iter& i, const sentinel& s) { return i.i == s.i; } bool operator!= (const iter& i, const sentinel& s) { return !(i == s); } struct range { iter begin() const { return {0}; } sentinel end() const { return {5}; } }; void f() { range r {}; for (auto i : r) { [[maybe_unused]] auto v = i; } } } namespace test_lambda_capture_asterisk_this_by_value { struct t { int i; int foo() { return [*this]() { return i; }(); } }; } namespace test_enum_class_construction { enum class byte : unsigned char {}; byte foo {42}; } namespace test_constexpr_if { template int f () { if constexpr(cond) { return 13; } else { return 42; } } } namespace test_selection_statement_with_initializer { int f() { return 13; } int f2() { if (auto i = f(); i > 0) { return 3; } switch (auto i = f(); i + 4) { case 17: return 2; default: return 1; } } } namespace test_template_argument_deduction_for_class_templates { template struct pair { pair (T1 p1, T2 p2) : m1 {p1}, m2 {p2} {} T1 m1; T2 m2; }; void f() { [[maybe_unused]] auto p = pair{13, 42u}; } } namespace test_non_type_auto_template_parameters { template struct B {}; B<5> b1; B<'a'> b2; } namespace test_structured_bindings { int arr[2] = { 1, 2 }; std::pair pr = { 1, 2 }; auto f1() -> int(&)[2] { return arr; } auto f2() -> std::pair& { return pr; } struct S { int x1 : 2; volatile double y1; }; S f3() { return {}; } auto [ x1, y1 ] = f1(); auto& [ xr1, yr1 ] = f1(); auto [ x2, y2 ] = f2(); auto& [ xr2, yr2 ] = f2(); const auto [ x3, y3 ] = f3(); } namespace test_exception_spec_type_system { struct Good {}; struct Bad {}; void g1() noexcept; void g2(); template Bad f(T*, T*); template Good f(T1*, T2*); static_assert (std::is_same_v); } namespace test_inline_variables { template void f(T) {} template inline T g(T) { return T{}; } template<> inline void f<>(int) {} template<> int g<>(int) { return 5; } } } // namespace cxx17 #endif // __cplusplus < 201703L && !defined _MSC_VER #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 202002L && !defined _MSC_VER #error "This is not a C++20 compiler" #else #include namespace cxx20 { // As C++20 supports feature test macros in the standard, there is no // immediate need to actually test for feature availability on the // Autoconf side. } // namespace cxx20 #endif // __cplusplus < 202002L && !defined _MSC_VER _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : eval $cachevar=yes else $as_nop eval $cachevar=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CXX="$ac_save_CXX" fi eval ac_res=\$$cachevar { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done if test x$ac_success = xyes; then break fi done fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test x$ax_cxx_compile_cxx20_required = xtrue; then if test x$ac_success = xno; then as_fn_error $? "*** A compiler with support for C++20 language features is required." "$LINENO" 5 fi fi if test x$ac_success = xno; then HAVE_CXX20=0 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: No compiler with C++20 support was found" >&5 printf "%s\n" "$as_me: No compiler with C++20 support was found" >&6;} else HAVE_CXX20=1 printf "%s\n" "#define HAVE_CXX20 1" >>confdefs.h fi am__api_version='1.16' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 printf %s "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if test ${ac_cv_path_install+y} then : printf %s "(cached) " >&6 else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac # Account for fact that we put trailing slashes in our PATH walk. case $as_dir in #(( ./ | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test ${ac_cv_path_install+y}; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 printf "%s\n" "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 printf %s "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`printf "%s\n" "$program_transform_name" | sed "$ac_script"` # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 printf "%s\n" "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_STRIP+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 printf "%s\n" "$STRIP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_STRIP+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 printf "%s\n" "$ac_ct_STRIP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a race-free mkdir -p" >&5 printf %s "checking for a race-free mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if test ${ac_cv_path_mkdir+y} then : printf %s "(cached) " >&6 else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext" || continue case `"$as_dir$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir ('*'coreutils) '* | \ 'BusyBox '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test ${ac_cv_path_mkdir+y}; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 printf "%s\n" "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_AWK+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 printf "%s\n" "$AWK" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$AWK" && break done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval test \${ac_cv_prog_make_${ac_make}_set+y} then : printf %s "(cached) " >&6 else $as_nop cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } SET_MAKE= else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 printf %s "checking whether ${MAKE-make} supports the include directive... " >&6; } cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } case $?:`cat confinc.out 2>/dev/null` in #( '0:this is the am__doit target') : case $s in #( BSD) : am__include='.include' am__quote='"' ;; #( *) : am__include='include' am__quote='' ;; esac ;; #( *) : ;; esac if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 printf "%s\n" "${_am_result}" >&6; } # Check whether --enable-dependency-tracking was given. if test ${enable_dependency_tracking+y} then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi # Check whether --enable-silent-rules was given. if test ${enable_silent_rules+y} then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 printf %s "checking whether $am_make supports nested variables... " >&6; } if test ${am_cv_make_support_nested_variables+y} then : printf %s "(cached) " >&6 else $as_nop if printf "%s\n" 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 printf "%s\n" "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='libpqxx' VERSION='8.0.1' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h printf "%s\n" "#define VERSION \"$VERSION\"" >>confdefs.h # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' depcc="$CXX" am_compiler_list= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 printf %s "checking dependency style of $depcc... " >&6; } if test ${am_cv_CXX_dependencies_compiler_type+y} then : printf %s "(cached) " >&6 else $as_nop if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 printf "%s\n" "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi # Variables for tags utilities; see am/tags.am if test -z "$CTAGS"; then CTAGS=ctags fi if test -z "$ETAGS"; then ETAGS=etags fi if test -z "$CSCOPE"; then CSCOPE=cscope fi # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi PQXX_ABI=8.0 PQXXVERSION=$PACKAGE_VERSION ac_config_headers="$ac_config_headers include/pqxx/config.h" # Default prefix for installs. # Read test programme from config-test. # Checks for programs. ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CXX+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 printf "%s\n" "$CXX" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CXX+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 printf "%s\n" "$ac_ct_CXX" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C++" >&5 printf %s "checking whether the compiler supports GNU C++... " >&6; } if test ${ac_cv_cxx_compiler_gnu+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_compiler_gnu=yes else $as_nop ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 printf "%s\n" "$ac_cv_cxx_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+y} ac_save_CXXFLAGS=$CXXFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 printf %s "checking whether $CXX accepts -g... " >&6; } if test ${ac_cv_prog_cxx_g+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_g=yes else $as_nop CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : else $as_nop ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 printf "%s\n" "$ac_cv_prog_cxx_g" >&6; } if test $ac_test_CXXFLAGS; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_prog_cxx_stdcxx=no if test x$ac_prog_cxx_stdcxx = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5 printf %s "checking for $CXX option to enable C++11 features... " >&6; } if test ${ac_cv_prog_cxx_cxx11+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cxx_cxx11=no ac_save_CXX=$CXX cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_cxx_conftest_cxx11_program _ACEOF for ac_arg in '' -std=gnu++11 -std=gnu++0x -std=c++11 -std=c++0x -qlanglvl=extended0x -AA do CXX="$ac_save_CXX $ac_arg" if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_cxx11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cxx_cxx11" != "xno" && break done rm -f conftest.$ac_ext CXX=$ac_save_CXX fi if test "x$ac_cv_prog_cxx_cxx11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cxx_cxx11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5 printf "%s\n" "$ac_cv_prog_cxx_cxx11" >&6; } CXX="$CXX $ac_cv_prog_cxx_cxx11" fi ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11 ac_prog_cxx_stdcxx=cxx11 fi fi if test x$ac_prog_cxx_stdcxx = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5 printf %s "checking for $CXX option to enable C++98 features... " >&6; } if test ${ac_cv_prog_cxx_cxx98+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cxx_cxx98=no ac_save_CXX=$CXX cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_cxx_conftest_cxx98_program _ACEOF for ac_arg in '' -std=gnu++98 -std=c++98 -qlanglvl=extended -AA do CXX="$ac_save_CXX $ac_arg" if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_cxx98=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cxx_cxx98" != "xno" && break done rm -f conftest.$ac_ext CXX=$ac_save_CXX fi if test "x$ac_cv_prog_cxx_cxx98" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cxx_cxx98" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5 printf "%s\n" "$ac_cv_prog_cxx_cxx98" >&6; } CXX="$CXX $ac_cv_prog_cxx_cxx98" fi ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98 ac_prog_cxx_stdcxx=cxx98 fi fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu # Check whether --enable-shared was given. if test ${enable_shared+y} then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac else $as_nop enable_shared=no fi case `pwd` in *\ * | *\ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 printf "%s\n" "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.7' macro_revision='2.4.7' ltmain=$ac_aux_dir/ltmain.sh # Make sure we can run config.sub. $SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 printf %s "checking build system type... " >&6; } if test ${ac_cv_build+y} then : printf %s "(cached) " >&6 else $as_nop ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 printf "%s\n" "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 printf %s "checking host system type... " >&6; } if test ${ac_cv_host+y} then : printf %s "(cached) " >&6 else $as_nop if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5 fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 printf "%s\n" "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 printf %s "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case $ECHO in printf*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: printf" >&5 printf "%s\n" "printf" >&6; } ;; print*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 printf "%s\n" "print -r" >&6; } ;; *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cat" >&5 printf "%s\n" "cat" >&6; } ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. set dummy ${ac_tool_prefix}clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "clang", so it can be a program name with args. set dummy clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi fi test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 printf %s "checking whether the compiler supports GNU C... " >&6; } if test ${ac_cv_c_compiler_gnu+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_compiler_gnu=yes else $as_nop ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_c_compiler_gnu if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 printf %s "checking whether $CC accepts -g... " >&6; } if test ${ac_cv_prog_cc_g+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes else $as_nop CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 printf "%s\n" "$ac_cv_prog_cc_g" >&6; } if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi ac_prog_cc_stdc=no if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 printf %s "checking for $CC option to enable C11 features... " >&6; } if test ${ac_cv_prog_cc_c11+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c11_program _ACEOF for ac_arg in '' -std=gnu11 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c11" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } CC="$CC $ac_cv_prog_cc_c11" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 ac_prog_cc_stdc=c11 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 printf %s "checking for $CC option to enable C99 features... " >&6; } if test ${ac_cv_prog_cc_c99+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c99_program _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c99" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c99" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } CC="$CC $ac_cv_prog_cc_c99" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 ac_prog_cc_stdc=c99 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 printf %s "checking for $CC option to enable C89 features... " >&6; } if test ${ac_cv_prog_cc_c89+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c89_program _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c89" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c89" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } CC="$CC $ac_cv_prog_cc_c89" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 ac_prog_cc_stdc=c89 fi fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 printf %s "checking whether $CC understands -c and -o together... " >&6; } if test ${am_cv_prog_cc_c_o+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 printf "%s\n" "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu depcc="$CC" am_compiler_list= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 printf %s "checking dependency style of $depcc... " >&6; } if test ${am_cv_CC_dependencies_compiler_type+y} then : printf %s "(cached) " >&6 else $as_nop if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 printf %s "checking for a sed that does not truncate output... " >&6; } if test ${ac_cv_path_SED+y} then : printf %s "(cached) " >&6 else $as_nop ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in sed gsed do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 printf "%s\n" "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 printf %s "checking for grep that handles long lines and -e... " >&6; } if test ${ac_cv_path_GREP+y} then : printf %s "(cached) " >&6 else $as_nop if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in grep ggrep do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 printf "%s\n" "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 printf %s "checking for egrep... " >&6; } if test ${ac_cv_path_EGREP+y} then : printf %s "(cached) " >&6 else $as_nop if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in egrep do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 printf "%s\n" "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 printf %s "checking for fgrep... " >&6; } if test ${ac_cv_path_FGREP+y} then : printf %s "(cached) " >&6 else $as_nop if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in fgrep do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 printf "%s\n" "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test ${with_gnu_ld+y} then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else $as_nop with_gnu_ld=no fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 printf %s "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 printf %s "checking for GNU ld... " >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 printf %s "checking for non-GNU ld... " >&6; } fi if test ${lt_cv_path_LD+y} then : printf %s "(cached) " >&6 else $as_nop if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 printf "%s\n" "$LD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 printf %s "checking if the linker ($LD) is GNU ld... " >&6; } if test ${lt_cv_prog_gnu_ld+y} then : printf %s "(cached) " >&6 else $as_nop # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 printf "%s\n" "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 printf %s "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if test ${lt_cv_path_NM+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 printf "%s\n" "$lt_cv_path_NM" >&6; } if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_DUMPBIN+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 printf "%s\n" "$DUMPBIN" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_DUMPBIN+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 printf "%s\n" "$ac_ct_DUMPBIN" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 printf %s "checking the name lister ($NM) interface... " >&6; } if test ${lt_cv_nm_interface+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 printf "%s\n" "$lt_cv_nm_interface" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 printf %s "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 printf "%s\n" "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 printf %s "checking the maximum length of command line arguments... " >&6; } if test ${lt_cv_sys_max_cmd_len+y} then : printf %s "(cached) " >&6 else $as_nop i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n "$lt_cv_sys_max_cmd_len"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 printf "%s\n" "$lt_cv_sys_max_cmd_len" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5 printf "%s\n" "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 printf %s "checking how to convert $build file names to $host format... " >&6; } if test ${lt_cv_to_host_file_cmd+y} then : printf %s "(cached) " >&6 else $as_nop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 printf "%s\n" "$lt_cv_to_host_file_cmd" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 printf %s "checking how to convert $build file names to toolchain format... " >&6; } if test ${lt_cv_to_tool_file_cmd+y} then : printf %s "(cached) " >&6 else $as_nop #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 printf "%s\n" "$lt_cv_to_tool_file_cmd" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 printf %s "checking for $LD option to reload object files... " >&6; } if test ${lt_cv_ld_reload_flag+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_ld_reload_flag='-r' fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 printf "%s\n" "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test yes != "$GCC"; then reload_cmds=false fi ;; darwin*) if test yes = "$GCC"; then reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}file", so it can be a program name with args. set dummy ${ac_tool_prefix}file; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_FILECMD+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$FILECMD"; then ac_cv_prog_FILECMD="$FILECMD" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_FILECMD="${ac_tool_prefix}file" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi FILECMD=$ac_cv_prog_FILECMD if test -n "$FILECMD"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FILECMD" >&5 printf "%s\n" "$FILECMD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_FILECMD"; then ac_ct_FILECMD=$FILECMD # Extract the first word of "file", so it can be a program name with args. set dummy file; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_FILECMD+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_FILECMD"; then ac_cv_prog_ac_ct_FILECMD="$ac_ct_FILECMD" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_FILECMD="file" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_FILECMD=$ac_cv_prog_ac_ct_FILECMD if test -n "$ac_ct_FILECMD"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_FILECMD" >&5 printf "%s\n" "$ac_ct_FILECMD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_FILECMD" = x; then FILECMD=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac FILECMD=$ac_ct_FILECMD fi else FILECMD="$ac_cv_prog_FILECMD" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_OBJDUMP+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 printf "%s\n" "$OBJDUMP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_OBJDUMP+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 printf "%s\n" "$ac_ct_OBJDUMP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 printf %s "checking how to recognize dependent libraries... " >&6; } if test ${lt_cv_deplibs_check_method+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='$FILECMD -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly* | midnightbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=$FILECMD lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=$FILECMD case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=$FILECMD lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 printf "%s\n" "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_DLLTOOL+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 printf "%s\n" "$DLLTOOL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_DLLTOOL+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 printf "%s\n" "$ac_ct_DLLTOOL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 printf %s "checking how to associate runtime and link libraries... " >&6; } if test ${lt_cv_sharedlib_from_linklib_cmd+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 printf "%s\n" "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_AR+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 printf "%s\n" "$AR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_AR+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 printf "%s\n" "$ac_ct_AR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} # Use ARFLAGS variable as AR's operation code to sync the variable naming with # Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have # higher priority because thats what people were doing historically (setting # ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS # variable obsoleted/removed. test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr} lt_ar_flags=$AR_FLAGS # Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override # by AR_FLAGS because that was never working and AR_FLAGS is about to die. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 printf %s "checking for archiver @FILE support... " >&6; } if test ${lt_cv_ar_at_file+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 printf "%s\n" "$lt_cv_ar_at_file" >&6; } if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_STRIP+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 printf "%s\n" "$STRIP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_STRIP+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 printf "%s\n" "$ac_ct_STRIP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_RANLIB+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 printf "%s\n" "$RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_RANLIB+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 printf "%s\n" "$ac_ct_RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 printf %s "checking command to parse $NM output from $compiler object... " >&6; } if test ${lt_cv_sys_global_symbol_pipe+y} then : printf %s "(cached) " >&6 else $as_nop # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="$SED -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++ or ICC, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&5 if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&5 && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: failed" >&5 printf "%s\n" "failed" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok" >&5 printf "%s\n" "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 printf %s "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test ${with_sysroot+y} then : withval=$with_sysroot; else $as_nop with_sysroot=no fi lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 printf "%s\n" "$with_sysroot" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 printf "%s\n" "${lt_sysroot:-no}" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 printf %s "checking for a working dd... " >&6; } if test ${ac_cv_path_lt_DD+y} then : printf %s "(cached) " >&6 else $as_nop printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} if test -z "$lt_DD"; then ac_path_lt_DD_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in dd do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_lt_DD="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_lt_DD" || continue if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi $ac_path_lt_DD_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_lt_DD"; then : fi else ac_cv_path_lt_DD=$lt_DD fi rm -f conftest.i conftest2.i conftest.out fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 printf "%s\n" "$ac_cv_path_lt_DD" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 printf %s "checking how to truncate binary pipes... " >&6; } if test ${lt_cv_truncate_bin+y} then : printf %s "(cached) " >&6 else $as_nop printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 printf "%s\n" "$lt_cv_truncate_bin" >&6; } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # Check whether --enable-libtool-lock was given. if test ${enable_libtool_lock+y} then : enableval=$enable_libtool_lock; fi test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `$FILECMD conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test yes = "$lt_cv_prog_gnu_ld"; then case `$FILECMD conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `$FILECMD conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then emul=elf case `$FILECMD conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `$FILECMD conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `$FILECMD conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `$FILECMD conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `$FILECMD conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 printf %s "checking whether the C compiler needs -belf... " >&6; } if test ${lt_cv_cc_needs_belf+y} then : printf %s "(cached) " >&6 else $as_nop ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : lt_cv_cc_needs_belf=yes else $as_nop lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 printf "%s\n" "$lt_cv_cc_needs_belf" >&6; } if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `$FILECMD conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_MANIFEST_TOOL+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 printf "%s\n" "$MANIFEST_TOOL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_MANIFEST_TOOL+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 printf "%s\n" "$ac_ct_MANIFEST_TOOL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 printf %s "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if test ${lt_cv_path_mainfest_tool+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 printf "%s\n" "$lt_cv_path_mainfest_tool" >&6; } if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_DSYMUTIL+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 printf "%s\n" "$DSYMUTIL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_DSYMUTIL+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 printf "%s\n" "$ac_ct_DSYMUTIL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_NMEDIT+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 printf "%s\n" "$NMEDIT" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_NMEDIT+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 printf "%s\n" "$ac_ct_NMEDIT" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_LIPO+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 printf "%s\n" "$LIPO" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_LIPO+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 printf "%s\n" "$ac_ct_LIPO" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_OTOOL+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 printf "%s\n" "$OTOOL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_OTOOL+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 printf "%s\n" "$ac_ct_OTOOL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_OTOOL64+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 printf "%s\n" "$OTOOL64" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_OTOOL64+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 printf "%s\n" "$ac_ct_OTOOL64" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 printf %s "checking for -single_module linker flag... " >&6; } if test ${lt_cv_apple_cc_single_mod+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 printf "%s\n" "$lt_cv_apple_cc_single_mod" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 printf %s "checking for -exported_symbols_list linker flag... " >&6; } if test ${lt_cv_ld_exported_symbols_list+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : lt_cv_ld_exported_symbols_list=yes else $as_nop lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 printf "%s\n" "$lt_cv_ld_exported_symbols_list" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 printf %s "checking for -force_load linker flag... " >&6; } if test ${lt_cv_ld_force_load+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR $AR_FLAGS libconftest.a conftest.o" >&5 $AR $AR_FLAGS libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 printf "%s\n" "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) case $MACOSX_DEPLOYMENT_TARGET,$host in 10.[012],*|,*powerpc*-darwin[5-8]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; *) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "" if test "x$ac_cv_header_dlfcn_h" = xyes then : printf "%s\n" "#define HAVE_DLFCN_H 1" >>confdefs.h fi func_stripname_cnf () { case $2 in .*) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%\\\\$2\$%%"`;; *) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%$2\$%%"`;; esac } # func_stripname_cnf # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-static was given. if test ${enable_static+y} then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac else $as_nop enable_static=yes fi # Check whether --with-pic was given. if test ${with_pic+y} then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac else $as_nop pic_mode=default fi # Check whether --enable-fast-install was given. if test ${enable_fast_install+y} then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac else $as_nop enable_fast_install=yes fi shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[5-9]*,yes) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 printf %s "checking which variant of shared library versioning to provide... " >&6; } # Check whether --with-aix-soname was given. if test ${with_aix_soname+y} then : withval=$with_aix_soname; case $withval in aix|svr4|both) ;; *) as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 ;; esac lt_cv_with_aix_soname=$with_aix_soname else $as_nop if test ${lt_cv_with_aix_soname+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_with_aix_soname=aix fi with_aix_soname=$lt_cv_with_aix_soname fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 printf "%s\n" "$with_aix_soname" >&6; } if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 printf %s "checking for objdir... " >&6; } if test ${lt_cv_objdir+y} then : printf %s "(cached) " >&6 else $as_nop rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 printf "%s\n" "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir printf "%s\n" "#define LT_OBJDIR \"$lt_cv_objdir/\"" >>confdefs.h case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC and # ICC, which need '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o func_cc_basename $compiler cc_basename=$func_cc_basename_result # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 printf %s "checking for ${ac_tool_prefix}file... " >&6; } if test ${lt_cv_path_MAGIC_CMD+y} then : printf %s "(cached) " >&6 else $as_nop case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/${ac_tool_prefix}file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 printf "%s\n" "$MAGIC_CMD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for file" >&5 printf %s "checking for file... " >&6; } if test ${lt_cv_path_MAGIC_CMD+y} then : printf %s "(cached) " >&6 else $as_nop case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 printf "%s\n" "$MAGIC_CMD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC=$CC ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test yes = "$GCC"; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 printf %s "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if test ${lt_cv_prog_compiler_rtti_exceptions+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 printf "%s\n" "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test yes = "$GCC"; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi lt_prog_compiler_pic='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # flang / f18. f95 an alias for gfortran or flang on Debian flang* | f18* | f95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | $SED 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 printf %s "checking for $compiler option to produce PIC... " >&6; } if test ${lt_cv_prog_compiler_pic+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 printf "%s\n" "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 printf %s "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if test ${lt_cv_prog_compiler_pic_works+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 printf "%s\n" "$lt_cv_prog_compiler_pic_works" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works"; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 printf %s "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if test ${lt_cv_prog_compiler_static_works+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_static_works=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 printf "%s\n" "$lt_cv_prog_compiler_static_works" >&6; } if test yes = "$lt_cv_prog_compiler_static_works"; then : else lt_prog_compiler_static= fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test ${lt_cv_prog_compiler_c_o+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test ${lt_cv_prog_compiler_c_o+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 printf %s "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 printf "%s\n" "$hard_links" >&6; } if test no = "$hard_links"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 printf "%s\n" "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++ or Intel C++ Compiler. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' export_dynamic_flag_spec='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='$wl--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs=yes ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes file_list_spec='@' ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' export_dynamic_flag_spec='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test no = "$ld_shlibs"; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct=no hardcode_direct_absolute=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if test ${lt_cv_aix_libpath_+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if test ${lt_cv_aix_libpath_+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' $wl-bernotok' allow_undefined_flag=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++ or Intel C++ Compiler. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl* | icl*) # Native MSVC or ICC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC and ICC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly* | midnightbsd*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test yes = "$GCC"; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 printf %s "checking if $CC understands -b... " >&6; } if test ${lt_cv_prog_compiler__b+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler__b=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 printf "%s\n" "$lt_cv_prog_compiler__b" >&6; } if test yes = "$lt_cv_prog_compiler__b"; then archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 printf %s "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if test ${lt_cv_irix_exported_symbol+y} then : printf %s "(cached) " >&6 else $as_nop save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : lt_cv_irix_exported_symbol=yes else $as_nop lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; } if test yes = "$lt_cv_irix_exported_symbol"; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi link_all_deplibs=no else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler ld_shlibs=yes archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' ;; esac ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' else archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='$wl-rpath,$libdir' fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes file_list_spec='@' ;; osf3*) if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test yes = "$GCC"; then wlarc='$wl' archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='$wl-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='$wl-z,text' allow_undefined_flag='$wl-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='$wl-Blargedynsym' ;; esac fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 printf "%s\n" "$ld_shlibs" >&6; } test no = "$ld_shlibs" && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 printf %s "checking whether -lc should be explicitly linked in... " >&6; } if test ${lt_cv_archive_cmds_need_lc+y} then : printf %s "(cached) " >&6 else $as_nop $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 printf "%s\n" "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 printf %s "checking dynamic linker characteristics... " >&6; } if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([A-Za-z]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl* | *,icl*) # Native MSVC or ICC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC and ICC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly* | midnightbsd*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if test ${lt_cv_shlibpath_overrides_runpath+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 printf "%s\n" "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 printf %s "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test yes = "$hardcode_automatic"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && test no != "$hardcode_minus_L"; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 printf "%s\n" "$hardcode_action" >&6; } if test relink = "$hardcode_action" || test yes = "$inherit_rpath"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 printf %s "checking for dlopen in -ldl... " >&6; } if test ${ac_cv_lib_dl_dlopen+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dlopen (); int main (void) { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dl_dlopen=yes else $as_nop ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else $as_nop lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes then : lt_cv_dlopen=shl_load else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 printf %s "checking for shl_load in -ldld... " >&6; } if test ${ac_cv_lib_dld_shl_load+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char shl_load (); int main (void) { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dld_shl_load=yes else $as_nop ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 printf "%s\n" "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes then : lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld else $as_nop ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes then : lt_cv_dlopen=dlopen else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 printf %s "checking for dlopen in -ldl... " >&6; } if test ${ac_cv_lib_dl_dlopen+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dlopen (); int main (void) { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dl_dlopen=yes else $as_nop ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 printf %s "checking for dlopen in -lsvld... " >&6; } if test ${ac_cv_lib_svld_dlopen+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dlopen (); int main (void) { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_svld_dlopen=yes else $as_nop ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 printf "%s\n" "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 printf %s "checking for dld_link in -ldld... " >&6; } if test ${ac_cv_lib_dld_dld_link+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dld_link (); int main (void) { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dld_dld_link=yes else $as_nop ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 printf "%s\n" "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes then : lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld fi fi fi fi fi fi ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 printf %s "checking whether a program can dlopen itself... " >&6; } if test ${lt_cv_dlopen_self+y} then : printf %s "(cached) " >&6 else $as_nop if test yes = "$cross_compiling"; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 printf "%s\n" "$lt_cv_dlopen_self" >&6; } if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 printf %s "checking whether a statically linked program can dlopen itself... " >&6; } if test ${lt_cv_dlopen_self_static+y} then : printf %s "(cached) " >&6 else $as_nop if test yes = "$cross_compiling"; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 printf "%s\n" "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 printf %s "checking whether stripping libraries is possible... " >&6; } if test -z "$STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } else if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then old_striplib="$STRIP --strip-debug" striplib="$STRIP --strip-unneeded" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else case $host_os in darwin*) # FIXME - insert some real tests, host_os isn't really good enough striplib="$STRIP -x" old_striplib="$STRIP -S" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } ;; freebsd*) if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then old_striplib="$STRIP --strip-debug" striplib="$STRIP --strip-unneeded" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi ;; *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } ;; esac fi fi # Report what library types will actually be built { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 printf %s "checking if libtool supports shared libraries... " >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 printf "%s\n" "$can_build_shared" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 printf %s "checking whether to build shared libraries... " >&6; } test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 printf "%s\n" "$enable_shared" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 printf %s "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 printf "%s\n" "$enable_static" >&6; } fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu CC=$lt_save_CC if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 printf %s "checking how to run the C++ preprocessor... " >&6; } if test -z "$CXXCPP"; then if test ${ac_cv_prog_CXXCPP+y} then : printf %s "(cached) " >&6 else $as_nop # Double quotes because $CXX needs to be expanded for CXXCPP in "$CXX -E" cpp /lib/cpp do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO" then : else $as_nop # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else $as_nop # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 printf "%s\n" "$CXXCPP" >&6; } ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO" then : else $as_nop # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else $as_nop # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : else $as_nop { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu else _lt_caught_CXX_error=yes fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu archive_cmds_need_lc_CXX=no allow_undefined_flag_CXX= always_export_symbols_CXX=no archive_expsym_cmds_CXX= compiler_needs_object_CXX=no export_dynamic_flag_spec_CXX= hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no hardcode_libdir_flag_spec_CXX= hardcode_libdir_separator_CXX= hardcode_minus_L_CXX=no hardcode_shlibpath_var_CXX=unsupported hardcode_automatic_CXX=no inherit_rpath_CXX=no module_cmds_CXX= module_expsym_cmds_CXX= link_all_deplibs_CXX=unknown old_archive_cmds_CXX=$old_archive_cmds reload_flag_CXX=$reload_flag reload_cmds_CXX=$reload_cmds no_undefined_flag_CXX= whole_archive_flag_spec_CXX= enable_shared_with_static_runtimes_CXX=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o objext_CXX=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC compiler_CXX=$CC func_cc_basename $compiler cc_basename=$func_cc_basename_result if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' else lt_prog_compiler_no_builtin_flag_CXX= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration # Check whether --with-gnu-ld was given. if test ${with_gnu_ld+y} then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else $as_nop with_gnu_ld=no fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 printf %s "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 printf %s "checking for GNU ld... " >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 printf %s "checking for non-GNU ld... " >&6; } fi if test ${lt_cv_path_LD+y} then : printf %s "(cached) " >&6 else $as_nop if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 printf "%s\n" "$LD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 printf %s "checking if the linker ($LD) is GNU ld... " >&6; } if test ${lt_cv_prog_gnu_ld+y} then : printf %s "(cached) " >&6 else $as_nop # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 printf "%s\n" "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec_CXX= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } ld_shlibs_CXX=yes case $host_os in aix3*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_CXX='' hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes file_list_spec_CXX='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct_CXX=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_CXX=yes hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_libdir_separator_CXX= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec_CXX='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. always_export_symbols_CXX=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. no_undefined_flag_CXX='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if test ${lt_cv_aix_libpath__CXX+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO" then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec_CXX='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag_CXX="-z nodefs" archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if test ${lt_cv_aix_libpath__CXX+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO" then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_CXX=' $wl-bernotok' allow_undefined_flag_CXX=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_CXX='$convenience' fi archive_cmds_need_lc_CXX=yes archive_expsym_cmds_CXX='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_CXX=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs_CXX=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl* | ,icl* | no,icl*) # Native MSVC or ICC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_CXX=' ' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=yes file_list_spec_CXX='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' enable_shared_with_static_runtimes_CXX=yes # Don't use ranlib old_postinstall_cmds_CXX='chmod 644 $oldlib' postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_CXX='-L$libdir' export_dynamic_flag_spec_CXX='$wl--export-all-symbols' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=no enable_shared_with_static_runtimes_CXX=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_CXX=no fi ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc_CXX=no hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec_CXX='' fi link_all_deplibs_CXX=yes allow_undefined_flag_CXX=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds_CXX="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds_CXX="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" if test yes != "$lt_cv_apple_cc_single_mod"; then archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" archive_expsym_cmds_CXX="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi else ld_shlibs_CXX=no fi ;; os2*) hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_minus_L_CXX=yes allow_undefined_flag_CXX=unsupported shrext_cmds=.dll archive_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes_CXX=yes file_list_spec_CXX='@' ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF ld_shlibs_CXX=no ;; freebsd-elf*) archive_cmds_need_lc_CXX=no ;; freebsd* | dragonfly* | midnightbsd*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes ;; haiku*) archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs_CXX=yes ;; hpux9*) hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='$wl-E' hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' hardcode_libdir_separator_CXX=: case $host_cpu in hppa*64*|ia64*) ;; *) export_dynamic_flag_spec_CXX='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no ;; *) hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; interix[3-9]*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_CXX='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi link_all_deplibs_CXX=yes ;; esac hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' hardcode_libdir_separator_CXX=: inherit_rpath_CXX=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac archive_cmds_need_lc_CXX=no hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [1-5].* | *pgcpp\ [1-5].*) prelink_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' old_archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='$wl--rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' whole_archive_flag_spec_CXX='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C++ 5.9 no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' hardcode_libdir_flag_spec_CXX='-R$libdir' whole_archive_flag_spec_CXX='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object_CXX=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; m88k*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) ld_shlibs_CXX=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no hardcode_direct_absolute_CXX=yes archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' export_dynamic_flag_spec_CXX='$wl-E' whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else ld_shlibs_CXX=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx*) case $host in osf3*) allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' ;; *) allow_undefined_flag_CXX=' -expect_unresolved \*' archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' ;; esac hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' case $host in osf3*) archive_cmds_CXX='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ archive_cmds_need_lc_CXX=yes no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_shlibpath_var_CXX=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs_CXX=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then no_undefined_flag_CXX=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. archive_cmds_CXX='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' fi hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir' case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) whole_archive_flag_spec_CXX='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_CXX='$wl-z,text' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag_CXX='$wl-z,text' allow_undefined_flag_CXX='$wl-z,nodefs' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='$wl-R,$libdir' hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes export_dynamic_flag_spec_CXX='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ '"$old_archive_cmds_CXX" reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ '"$reload_cmds_CXX" ;; *) archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 printf "%s\n" "$ld_shlibs_CXX" >&6; } test no = "$ld_shlibs_CXX" && can_build_shared=no GCC_CXX=$GXX LD_CXX=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... # Dependencies to place before and after the object being linked: predep_objects_CXX= postdep_objects_CXX= predeps_CXX= postdeps_CXX= compiler_lib_search_path_CXX= cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$compiler_lib_search_path_CXX"; then compiler_lib_search_path_CXX=$prev$p else compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$postdeps_CXX"; then postdeps_CXX=$prev$p else postdeps_CXX="${postdeps_CXX} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$predep_objects_CXX"; then predep_objects_CXX=$p else predep_objects_CXX="$predep_objects_CXX $p" fi else if test -z "$postdep_objects_CXX"; then postdep_objects_CXX=$p else postdep_objects_CXX="$postdep_objects_CXX $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling CXX test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken case $host_os in interix[3-9]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. predep_objects_CXX= postdep_objects_CXX= postdeps_CXX= ;; esac case " $postdeps_CXX " in *" -lc "*) archive_cmds_need_lc_CXX=no ;; esac compiler_lib_search_dirs_CXX= if test -n "${compiler_lib_search_path_CXX}"; then compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi lt_prog_compiler_wl_CXX= lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX= # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' fi lt_prog_compiler_pic_CXX='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic_CXX='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic_CXX='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static_CXX='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_CXX='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static_CXX= ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_CXX=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac else case $host_os in aix[4-9]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' else lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; dgux*) case $cc_basename in ec++*) lt_prog_compiler_pic_CXX='-KPIC' ;; ghcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; freebsd* | dragonfly* | midnightbsd*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then lt_prog_compiler_pic_CXX='+Z' fi ;; aCC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_CXX='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler lt_prog_compiler_wl_CXX='--backend -Wl,' lt_prog_compiler_pic_CXX='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fPIC' lt_prog_compiler_static_CXX='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fpic' lt_prog_compiler_static_CXX='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) # IBM XL 8.0, 9.0 on PPC and BlueGene lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-qpic' lt_prog_compiler_static_CXX='-qstaticlink' ;; *) case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C++ 5.9 lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) lt_prog_compiler_pic_CXX='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) lt_prog_compiler_wl_CXX='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 lt_prog_compiler_pic_CXX='-pic' ;; cxx*) # Digital/Compaq C++ lt_prog_compiler_wl_CXX='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x lt_prog_compiler_pic_CXX='-pic' lt_prog_compiler_static_CXX='-Bstatic' ;; lcc*) # Lucid lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 lt_prog_compiler_pic_CXX='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) lt_prog_compiler_can_build_shared_CXX=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_CXX= ;; *) lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 printf %s "checking for $compiler option to produce PIC... " >&6; } if test ${lt_cv_prog_compiler_pic_CXX+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 printf "%s\n" "$lt_cv_prog_compiler_pic_CXX" >&6; } lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_CXX"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 printf %s "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } if test ${lt_cv_prog_compiler_pic_works_CXX+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_pic_works_CXX=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works_CXX=yes fi fi $RM conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 printf "%s\n" "$lt_cv_prog_compiler_pic_works_CXX" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works_CXX"; then case $lt_prog_compiler_pic_CXX in "" | " "*) ;; *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; esac else lt_prog_compiler_pic_CXX= lt_prog_compiler_can_build_shared_CXX=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 printf %s "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if test ${lt_cv_prog_compiler_static_works_CXX+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_static_works_CXX=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works_CXX=yes fi else lt_cv_prog_compiler_static_works_CXX=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 printf "%s\n" "$lt_cv_prog_compiler_static_works_CXX" >&6; } if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then : else lt_prog_compiler_static_CXX= fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test ${lt_cv_prog_compiler_c_o_CXX+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 printf "%s\n" "$lt_cv_prog_compiler_c_o_CXX" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test ${lt_cv_prog_compiler_c_o_CXX+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 printf "%s\n" "$lt_cv_prog_compiler_c_o_CXX" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o_CXX" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 printf %s "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 printf "%s\n" "$hard_links" >&6; } if test no = "$hard_links"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 printf "%s\n" "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' case $host_os in aix[4-9]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) export_symbols_cmds_CXX=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl* | icl*) exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' ;; esac ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs_CXX=no ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 printf "%s\n" "$ld_shlibs_CXX" >&6; } test no = "$ld_shlibs_CXX" && can_build_shared=no with_gnu_ld_CXX=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_CXX" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_CXX=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds_CXX in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 printf %s "checking whether -lc should be explicitly linked in... " >&6; } if test ${lt_cv_archive_cmds_need_lc_CXX+y} then : printf %s "(cached) " >&6 else $as_nop $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_CXX pic_flag=$lt_prog_compiler_pic_CXX compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_CXX allow_undefined_flag_CXX= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc_CXX=no else lt_cv_archive_cmds_need_lc_CXX=yes fi allow_undefined_flag_CXX=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 printf "%s\n" "$lt_cv_archive_cmds_need_lc_CXX" >&6; } archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX ;; esac fi ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 printf %s "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl* | *,icl*) # Native MSVC or ICC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC and ICC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly* | midnightbsd*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec_CXX='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if test ${lt_cv_shlibpath_overrides_runpath+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO" then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 printf "%s\n" "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 printf %s "checking how to hardcode library paths into programs... " >&6; } hardcode_action_CXX= if test -n "$hardcode_libdir_flag_spec_CXX" || test -n "$runpath_var_CXX" || test yes = "$hardcode_automatic_CXX"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct_CXX" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" && test no != "$hardcode_minus_L_CXX"; then # Linking always hardcodes the temporary library directory. hardcode_action_CXX=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_CXX=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_CXX=unsupported fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 printf "%s\n" "$hardcode_action_CXX" >&6; } if test relink = "$hardcode_action_CXX" || test yes = "$inherit_rpath_CXX"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_config_commands="$ac_config_commands libtool" # Only expand once: { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval test \${ac_cv_prog_make_${ac_make}_set+y} then : printf %s "(cached) " >&6 else $as_nop cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } SET_MAKE= else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi # Extract the first word of "mkdir", so it can be a program name with args. set dummy mkdir; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_MKDIR+y} then : printf %s "(cached) " >&6 else $as_nop case $MKDIR in [\\/]* | ?:[\\/]*) ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_MKDIR="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi MKDIR=$ac_cv_path_MKDIR if test -n "$MKDIR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR" >&5 printf "%s\n" "$MKDIR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Check whether --enable-documentation was given. if test ${enable_documentation+y} then : enableval=$enable_documentation; enable_documentation="${enableval}" fi if test "$enable_documentation" = "yes"; then BUILD_DOCS_TRUE= BUILD_DOCS_FALSE='#' else BUILD_DOCS_TRUE='#' BUILD_DOCS_FALSE= fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 printf %s "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. if test ${enable_maintainer_mode+y} then : enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval else $as_nop USE_MAINTAINER_MODE=no fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 printf "%s\n" "$USE_MAINTAINER_MODE" >&6; } if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else MAINTAINER_MODE_TRUE='#' MAINTAINER_MODE_FALSE= fi MAINT=$MAINTAINER_MODE_TRUE # See if we want stricter compiler warnings. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking maintainer mode" >&5 printf %s "checking maintainer mode... " >&6; } # Check whether --enable-maintainer-mode was given. if test ${enable_maintainer_mode+y} then : enableval=$enable_maintainer_mode; fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${enable_maintainer_mode}" >&5 printf "%s\n" "${enable_maintainer_mode}" >&6; } # See if we want runtime debug checking. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking audit" >&5 printf %s "checking audit... " >&6; } # Check whether --enable-audit was given. if test ${enable_audit+y} then : enableval=$enable_audit; fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${enable_audit}" >&5 printf "%s\n" "${enable_audit}" >&6; } # See if we want "suggestions," such as "this class could be final." # (The suggestions are often useful, but can also easily be wrong.) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking suggest" >&5 printf %s "checking suggest... " >&6; } # Check whether --enable-suggest was given. if test ${enable_suggest+y} then : enableval=$enable_suggest; fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${enable_suggest:-no}" >&5 printf "%s\n" "${enable_suggest:-no}" >&6; } # Check whether --enable-shared was given. if test ${enable_shared+y} then : enableval=$enable_shared; fi if test "${shared}" = "yes" then : CPPFLAGS="$CPPFLAGS -DPQXX_SHARED" fi # Add options to compiler command line, if compiler accepts them. add_compiler_opts_if_ok() { FLAGS_FILE="$1" CXXFLAGS="$CXXFLAGS $( ${srcdir}/tools/compiler_flags.py \ -c "$CXX $CXXFLAGS" -f "$FLAGS_FILE" -s)" } # Add options to compiler command line, unconditionally. add_compiler_opts() { CXXFLAGS="$CXXFLAGS $*" } # Let's try to get the compiler to be helpful. # # (Omit options -Weffc++ and -Wabi because they currently yield too many # warnings in gcc's standard headers.) if test "$GCC" = "yes" then # In maintainer mode, enable all the warning options we can. if test "$enable_maintainer_mode" = "yes" then # "Eternal" (FLW) g++ options. These have been around for # ages, and both g++ and clang++ support them. Don't bother # checking for support; just add them to the compiler options. # # We'd love to add -D_GLIBCXX_CONCEPT_CHECKS in 8.0 here, but # it complains that the "reference" type in result iterators is # not an actual reference. add_compiler_opts \ -fstrict-enums \ -Werror \ -Wall \ -pedantic \ -Wcast-align \ -Wcast-qual \ -Wconversion \ -Wctor-dtor-privacy \ -Wendif-labels \ -Wextra \ -Wextra-semi \ -Wfloat-equal \ -Wformat=2 \ -Wformat-security \ -Wmissing-include-dirs \ -Wno-div-by-zero \ -Wnon-virtual-dtor \ -Wold-style-cast \ -Woverlength-strings \ -Woverloaded-virtual \ -Wpointer-arith \ -Wredundant-decls \ -Wshadow \ -Wsign-promo \ -Wundef \ -Wunused \ -Wwrite-strings \ -Wzero-as-null-pointer-constant \ # "Iffy" g++ options. Some reasonably current g++-like # compilers may not support these. # # The -fanalyzer one is a macro option for many of the others, # but we can't use it because as of gcc 13.2.0 we still see it # generating errors for the standard library. add_compiler_opts_if_ok \ "${srcdir}/config/flags/maintainer-mode.txt" fi # In "audit," enable all runtime checks we can. if test "$enable_audit" = "yes" then # These macros enable extra runtime checking in various # standard library implementations. add_compiler_opts \ -D_FORTIFY_SOURCE=2 \ -D_GLIBCXX_ASSERTIONS \ -D_GLIBCXX_DEBUG \ -D_GLIBCXX_DEBUG_PEDANTIC \ -D_GLIBCXX_SANITIZE_VECTOR \ -D_LIBCPP_DEBUG=1 \ -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG # Run-time sanitizers and such. These can differ from one # compiler (or version) to the next. add_compiler_opts_if_ok "${srcdir}/config/flags/audit-mode.txt" fi # In "suggest" mode, enable a bunch of code suggestions. if test "$enable_suggest" = "yes" then add_compiler_opts_if_ok \ "${srcdir}/config/flags/suggest-mode.txt" fi fi # End of gcc-specific part. # Do the feature checks now, *after* we add all the extra strictness options, # so that we don't accidentally enable any features that become unacceptable # under our chosen strictness. # Configuration for feature checks. Generated by generate_check_config.py. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PQXX_HAVE_ASSUME" >&5 printf %s "checking PQXX_HAVE_ASSUME... " >&6; } PQXX_HAVE_ASSUME=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if !__has_cpp_attribute(assume) # error "No support for [[assume]] attribute." #endif #include void foo(int i) { [[assume(i > 0)]]; std::cout << i << '\n'; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define PQXX_HAVE_ASSUME 1" >>confdefs.h else $as_nop PQXX_HAVE_ASSUME=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PQXX_HAVE_ASSUME" >&5 printf "%s\n" "$PQXX_HAVE_ASSUME" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PQXX_HAVE_CHARCONV_FLOAT" >&5 printf %s "checking PQXX_HAVE_CHARCONV_FLOAT... " >&6; } PQXX_HAVE_CHARCONV_FLOAT=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ // Test for std::to_string/std::from_string for floating-point types. #include #include int main() { char z[100]; auto rt = std::to_chars(std::begin(z), std::end(z), 3.14159L); if (rt.ec != std::errc{}) return 1; long double n; auto rf = std::from_chars(std::cbegin(z), std::cend(z), n); if (rf.ec != std::errc{}) return 2; return (n > 3 and n < 4) ? 0 : 1; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define PQXX_HAVE_CHARCONV_FLOAT 1" >>confdefs.h else $as_nop PQXX_HAVE_CHARCONV_FLOAT=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PQXX_HAVE_CHARCONV_FLOAT" >&5 printf "%s\n" "$PQXX_HAVE_CHARCONV_FLOAT" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PQXX_HAVE_CXA_DEMANGLE" >&5 printf %s "checking PQXX_HAVE_CXA_DEMANGLE... " >&6; } PQXX_HAVE_CXA_DEMANGLE=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ // Test for cross-vendor C++ ABI's __cxa_demangle function. #include #include #include #include #include int main() { int status = 0; char *name = abi::__cxa_demangle(typeid(10).name(), nullptr, nullptr, &status); if (status != 0) throw std::runtime_error("Demangle failed!"); int result = std::strcmp(name, "int"); std::free(name); return result; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define PQXX_HAVE_CXA_DEMANGLE 1" >>confdefs.h else $as_nop PQXX_HAVE_CXA_DEMANGLE=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PQXX_HAVE_CXA_DEMANGLE" >&5 printf "%s\n" "$PQXX_HAVE_CXA_DEMANGLE" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PQXX_HAVE_GCC_PURE" >&5 printf %s "checking PQXX_HAVE_GCC_PURE... " >&6; } PQXX_HAVE_GCC_PURE=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ // Test for gcc-style "pure" attribute. #if !__has_cpp_attribute(gnu::pure) # error "Compiler does not support gnu::pure attribute." #endif [[gnu::pure]] int f() { return 0; } int main() { return f(); } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define PQXX_HAVE_GCC_PURE 1" >>confdefs.h else $as_nop PQXX_HAVE_GCC_PURE=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PQXX_HAVE_GCC_PURE" >&5 printf "%s\n" "$PQXX_HAVE_GCC_PURE" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PQXX_HAVE_GCC_VISIBILITY" >&5 printf %s "checking PQXX_HAVE_GCC_VISIBILITY... " >&6; } PQXX_HAVE_GCC_VISIBILITY=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ // Test for gcc-style "visibility" attribute. #if !__has_cpp_attribute(gnu::visibility) # error "Compiler does not support gnu::visibility attribute." #endif struct [[gnu::visibility("hidden")]] D { D() {} int f() { return 0; } }; int main() { D d; return d.f(); } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define PQXX_HAVE_GCC_VISIBILITY 1" >>confdefs.h else $as_nop PQXX_HAVE_GCC_VISIBILITY=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PQXX_HAVE_GCC_VISIBILITY" >&5 printf "%s\n" "$PQXX_HAVE_GCC_VISIBILITY" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PQXX_HAVE_MULTIDIM" >&5 printf %s "checking PQXX_HAVE_MULTIDIM... " >&6; } PQXX_HAVE_MULTIDIM=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ // Feature check for 'PQXX_HAVE_MULTIDIM'. // Generated by generate_cxx_checks.py. #include #if !defined(__cpp_multidimensional_subscript) # error "No PQXX_HAVE_MULTIDIM: __cpp_multidimensional_subscript is not set." #endif #if !__cpp_multidimensional_subscript # error "No PQXX_HAVE_MULTIDIM: __cpp_multidimensional_subscript is false." #endif #include struct foo { int operator[](int i) const { return i; } int operator[](int i, std::source_location) const { return i - 1; } }; int main() { return foo{}[1, std::source_location::current()]; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define PQXX_HAVE_MULTIDIM 1" >>confdefs.h else $as_nop PQXX_HAVE_MULTIDIM=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PQXX_HAVE_MULTIDIM" >&5 printf "%s\n" "$PQXX_HAVE_MULTIDIM" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PQXX_HAVE_POLL" >&5 printf %s "checking PQXX_HAVE_POLL... " >&6; } PQXX_HAVE_POLL=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ // Test for poll(). #include int main() { return poll(nullptr, 0, 0); } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define PQXX_HAVE_POLL 1" >>confdefs.h else $as_nop PQXX_HAVE_POLL=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PQXX_HAVE_POLL" >&5 printf "%s\n" "$PQXX_HAVE_POLL" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PQXX_HAVE_RANGES" >&5 printf %s "checking PQXX_HAVE_RANGES... " >&6; } PQXX_HAVE_RANGES=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ // Feature check for 'PQXX_HAVE_RANGES'. // Generated by generate_cxx_checks.py. #include #if !defined(__cpp_lib_ranges) # error "No PQXX_HAVE_RANGES: __cpp_lib_ranges is not set." #endif #if !__cpp_lib_ranges # error "No PQXX_HAVE_RANGES: __cpp_lib_ranges is false." #endif int main() {} _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define PQXX_HAVE_RANGES 1" >>confdefs.h else $as_nop PQXX_HAVE_RANGES=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PQXX_HAVE_RANGES" >&5 printf "%s\n" "$PQXX_HAVE_RANGES" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PQXX_HAVE_SLEEP_FOR" >&5 printf %s "checking PQXX_HAVE_SLEEP_FOR... " >&6; } PQXX_HAVE_SLEEP_FOR=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ // Test for std::this_thread::sleep_for(). /* For some reason MinGW's header seems to be broken. * * But it gets worse. It looks as if we can include without problems * in this configuration test. Why does it break when MinGW users try to build * the library, but succeed when we try it here? * * To try and get close to the situation in the library code itself, we try * including some standard headers and OS headers that we don't strictly need * here. */ #include #include #include #include #include #include #include #if __has_include() # include #endif #if __has_include() # include #endif #if __has_include() # include #endif int main() { std::this_thread::sleep_for(std::chrono::microseconds{10u}); } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define PQXX_HAVE_SLEEP_FOR 1" >>confdefs.h else $as_nop PQXX_HAVE_SLEEP_FOR=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PQXX_HAVE_SLEEP_FOR" >&5 printf "%s\n" "$PQXX_HAVE_SLEEP_FOR" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PQXX_HAVE_STRERROR_R" >&5 printf %s "checking PQXX_HAVE_STRERROR_R... " >&6; } PQXX_HAVE_STRERROR_R=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ // Check for strerror_r. // It can be either the POSIX version (which returns int) or the GNU version // (which returns char *). #include #include int main() { char buffer[200]; auto res{strerror_r(1, buffer, 200)}; // Sidestep type differences. We don't really care what the value is. return not not res; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define PQXX_HAVE_STRERROR_R 1" >>confdefs.h else $as_nop PQXX_HAVE_STRERROR_R=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PQXX_HAVE_STRERROR_R" >&5 printf "%s\n" "$PQXX_HAVE_STRERROR_R" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PQXX_HAVE_STRERROR_S" >&5 printf %s "checking PQXX_HAVE_STRERROR_S... " >&6; } PQXX_HAVE_STRERROR_S=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ // Test for strerror_s, as defined in Windows and C11. // Presumably this'll be part of the C++ standard some day. #include int main() { using namespace std; char buf[200]; return strerror_s(buf, 200, 1); } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define PQXX_HAVE_STRERROR_S 1" >>confdefs.h else $as_nop PQXX_HAVE_STRERROR_S=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PQXX_HAVE_STRERROR_S" >&5 printf "%s\n" "$PQXX_HAVE_STRERROR_S" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PQXX_HAVE_TYPE_DISPLAY" >&5 printf %s "checking PQXX_HAVE_TYPE_DISPLAY... " >&6; } PQXX_HAVE_TYPE_DISPLAY=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include template constexpr std::string_view name_type() { return display_string_of(^^T); } int main() { static_assert(name_type() == "int"); } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define PQXX_HAVE_TYPE_DISPLAY 1" >>confdefs.h else $as_nop PQXX_HAVE_TYPE_DISPLAY=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PQXX_HAVE_TYPE_DISPLAY" >&5 printf "%s\n" "$PQXX_HAVE_TYPE_DISPLAY" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PQXX_HAVE_YEAR_MONTH_DAY" >&5 printf %s "checking PQXX_HAVE_YEAR_MONTH_DAY... " >&6; } PQXX_HAVE_YEAR_MONTH_DAY=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ // Test for std::chrono::year_month_day etc. #include int main() { return int(std::chrono::year{1}); } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define PQXX_HAVE_YEAR_MONTH_DAY 1" >>confdefs.h else $as_nop PQXX_HAVE_YEAR_MONTH_DAY=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PQXX_HAVE_YEAR_MONTH_DAY" >&5 printf "%s\n" "$PQXX_HAVE_YEAR_MONTH_DAY" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PQXX_HAVE_ZARGS" >&5 printf %s "checking PQXX_HAVE_ZARGS... " >&6; } PQXX_HAVE_ZARGS=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #if !__has_cpp_attribute(gnu::null_terminated_string_arg) # error "This compiler does not support gnu::null_terminated_string_arg." #endif [[gnu::null_terminated_string_arg]] void print(char const *msg) { std::cout << msg << '\n'; } int main() { print("zargs works."); } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define PQXX_HAVE_ZARGS 1" >>confdefs.h else $as_nop PQXX_HAVE_ZARGS=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PQXX_HAVE_ZARGS" >&5 printf "%s\n" "$PQXX_HAVE_ZARGS" >&6; } # End of config. # One of the generated checks sets this variable. if test "$PQXX_HAVE_GCC_VISIBILITY" = "yes" then # Make internal definitions accessible only to the library itself. # Only definitions marked PQXX_LIBEXPORT will be accessible. add_compiler_opts -fvisibility=hidden add_compiler_opts -fvisibility-inlines-hidden fi # One of the generated checks sets this variable. if test "$PQXX_HAVE_POLL" != "yes" then # No poll(); we'll fall back to select(). # Some systems keep select() in a separate library which is not linked by # default. See if we need one of those. socklibok=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing select" >&5 printf %s "checking for library containing select... " >&6; } if test ${ac_cv_search_select+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ namespace conftest { extern "C" int select (); } int main (void) { return conftest::select (); ; return 0; } _ACEOF for ac_lib in '' socket nsl ws2_32 wsock32 winsock do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_cxx_try_link "$LINENO" then : ac_cv_search_select=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_select+y} then : break fi done if test ${ac_cv_search_select+y} then : else $as_nop ac_cv_search_select=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_select" >&5 printf "%s\n" "$ac_cv_search_select" >&6; } ac_res=$ac_cv_search_select if test "$ac_res" != no then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" socklibok=yes fi # Microsoft proprietary libraries do not work with code that is generated with # autoconf's SEARCH_LIBS macro, so we need to check manually and just use the # first socket library available. # We only do this if select() is not available by other means, to avoid picking # up an unnecessary Windows compatibility library on a non-Windows system. for l in ws2_32 wsock32 winsock do if test "${socklibok}" != "yes" then as_ac_Lib=`printf "%s\n" "ac_cv_lib_$l""_main" | $as_tr_sh` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -l$l" >&5 printf %s "checking for main in -l$l... " >&6; } if eval test \${$as_ac_Lib+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-l$l $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ namespace conftest { extern "C" int main (); } int main (void) { return conftest::main (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO" then : eval "$as_ac_Lib=yes" else $as_nop eval "$as_ac_Lib=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi eval ac_res=\$$as_ac_Lib { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } if eval test \"x\$"$as_ac_Lib"\" = x"yes" then : LIBS="$LIBS -l$l";socklibok=yes fi fi done if test "${socklibok}" != "yes" then as_fn_error $? " Could not figure out how to link a simple sockets-based program. Please read the config.log file for more clues as to why this failed. " "$LINENO" 5 fi fi # No poll() # Check for std::stacktrace support. # # We need to link this test because some compilers require an extra library to # support std::stacktrace. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for std::stacktrace support" >&5 printf %s "checking for std::stacktrace support... " >&6; } have_stacktrace=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main() { std::cout << std::format("{}", std::stacktrace::current()); } _ACEOF if ac_fn_cxx_try_link "$LINENO" then : printf "%s\n" "#define PQXX_HAVE_STACKTRACE 1" >>confdefs.h else $as_nop have_stacktrace=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_stacktrace" >&5 printf "%s\n" "$have_stacktrace" >&6; } # Find PostgreSQL includes and libraries # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PKG_CONFIG+y} then : printf %s "(cached) " >&6 else $as_nop case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 printf "%s\n" "$PKG_CONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi for ac_prog in pg_config do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PG_CONFIG+y} then : printf %s "(cached) " >&6 else $as_nop case $PG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PG_CONFIG="$PG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PG_CONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PG_CONFIG=$ac_cv_path_PG_CONFIG if test -n "$PG_CONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PG_CONFIG" >&5 printf "%s\n" "$PG_CONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$PG_CONFIG" && break done # Check whether --with-postgres-include was given. if test ${with_postgres_include+y} then : withval=$with_postgres_include; if test "x$with_postgres_include" = "xyes" then : with_postgres_include="" fi fi if test -n "$with_postgres_include" then POSTGRES_INCLUDE="-I$with_postgres_include" else if test -x "$PKG_CONFIG" || test -x "$PG_CONFIG" then # We should prefer pkg-config over pg_config, but there seems to be a # problem in pkg-config 1.6.3. Until that's been resolved (#291), go # with pg_config if we can. if test -x "$PG_CONFIG" then # From pg_config we can either get the C compiler options used to # compile postgres, which isn't quite what we want; or we can get # the headers directory, without the full option. That's something # we can work with. The compiler must support the "-I" option for # that, but both scripts assume that anyway. POSTGRES_INCLUDE="-I$($PG_CONFIG --includedir)" else # From pkg-config we can get the compiler options to extend the # include path. We use that. POSTGRES_INCLUDE=$($PKG_CONFIG libpq --cflags-only-I) fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: finding PostgreSQL headers using $POSTGRES_INCLUDE" >&5 printf "%s\n" "$as_me: finding PostgreSQL headers using $POSTGRES_INCLUDE" >&6;} else POSTGRES_INCLUDE="" fi fi # Add the compiler option so we can compile configure tests which rely on the # libpq headers. CPPFLAGS="$CPPFLAGS $POSTGRES_INCLUDE" # Check whether --with-postgres-lib was given. if test ${with_postgres_lib+y} then : withval=$with_postgres_lib; if test "x$with_postgres_lib" = "xyes" then : with_postgres_lib="" fi fi # If no --with-postgres-lib was given, and we have pkg-config, use that. if test -z "$with_postgres_lib" -a -x "$PKG_CONFIG" then : with_postgres_lib=$($PKG_CONFIG libpq --libs-only-L | sed 's/^-L//') fi # pg_config is deprecated, but for some users it may still provide the only # right answer. For instance, `pkg-config` may not know where `libpq` is # installed. if test -z "$with_postgres_lib" -a -x "$PG_CONFIG" then : with_postgres_lib=$($PG_CONFIG --libdir) fi if test -n "$with_postgres_lib" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: using PostgreSQL libraries at $with_postgres_lib" >&5 printf "%s\n" "$as_me: using PostgreSQL libraries at $with_postgres_lib" >&6;} else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: using PostgreSQL libraries in default location" >&5 printf "%s\n" "$as_me: using PostgreSQL libraries in default location" >&6;} fi ac_fn_cxx_check_header_compile "$LINENO" "libpq-fe.h" "ac_cv_header_libpq_fe_h" "" if test "x$ac_cv_header_libpq_fe_h" = xyes then : else $as_nop as_fn_error $? " Can't find the main PostgreSQL client header, libpq-fe.h. Are you sure the libpq headers are installed correctly, and that we've got the right path? " "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ability to compile source files using libpq" >&5 printf %s "checking for ability to compile source files using libpq... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { PQexec(nullptr,"") ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : else $as_nop as_fn_error $? " Could not compile a call to a basic libpq function. There must be something seriously wrong with the headers that \"pg_config --includedir\" or \"pkg-config libpq --cflags\" pointed to; the contents of config.log may give you a clue about the nature of the failure. Source including the libpq header libpq-fe.h can be compiled, but a call to the most basic libpq function PQexec() failed to compile successfully. This is the litmus test for a working libpq. " "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } if test "x${with_postgres_lib}" = "x"; then with_postgres_libpath="" else with_postgres_libpath="-L${with_postgres_lib}" fi LDFLAGS="$LDFLAGS ${with_postgres_libpath}" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PQexec in -lpq" >&5 printf %s "checking for PQexec in -lpq... " >&6; } if test ${ac_cv_lib_pq_PQexec+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lpq ${with_postgres_libpath} $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ namespace conftest { extern "C" int PQexec (); } int main (void) { return conftest::PQexec (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO" then : ac_cv_lib_pq_PQexec=yes else $as_nop ac_cv_lib_pq_PQexec=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pq_PQexec" >&5 printf "%s\n" "$ac_cv_lib_pq_PQexec" >&6; } if test "x$ac_cv_lib_pq_PQexec" = xyes then : printf "%s\n" "#define HAVE_LIBPQ 1" >>confdefs.h LIBS="-lpq $LIBS" else $as_nop as_fn_error $? " Did not find the PQexec() function in libpq. This is the litmus test for a working libpq installation. A source file using the PQexec() function did compile without problems, and the libpq library is available for linking, but for some reason a call to PQexec() failed to link properly to the libpq library. This may be because the libpq library file is damaged, or in some incorrect format, or if your libpq is much more recent than libpqxx version $PQXX_ABI, perhaps libpq has undergone a radical ABI change. The last parts of config.log may give you a clue as to what really went wrong, but be warned that this is no easy reading. Look for the last error message occurring in the file. " "$LINENO" 5 fi # Remove redundant occurrances of -lpq LIBS=$(echo "$LIBS" | sed -e 's/-lpq * -lpq\>/-lpq/g') { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval test \${ac_cv_prog_make_${ac_make}_set+y} then : printf %s "(cached) " >&6 else $as_nop cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } SET_MAKE= else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi ac_config_files="$ac_config_files Makefile include/Makefile libpqxx.pc" # We've let autoconf generate a config.h. But there's a lot of stuff in there # that we don't need, and that we absolutely do not want. We'd like to avoid # polluting the application's namespace with macros that aren't clearly marked # as libpqxx-related. # # So we take just the ones with the "PQXX" marker and write them into a # header just for compiler-related configuration. ac_config_commands="$ac_config_commands configitems" ac_config_files="$ac_config_files compile_flags" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 printf "%s\n" "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 printf %s "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: done" >&5 printf "%s\n" "done" >&6; } if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_DOCS_TRUE}" && test -z "${BUILD_DOCS_FALSE}"; then as_fn_error $? "conditional \"BUILD_DOCS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh as_nop=: if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else $as_nop as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by libpqxx $as_me 8.0.1, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ libpqxx config.status 8.0.1 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" Copyright (C) 2021 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) printf "%s\n" "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) printf "%s\n" "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) printf "%s\n" "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX printf "%s\n" "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' FILECMD='`$ECHO "$FILECMD" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' lt_ar_flags='`$ECHO "$lt_ar_flags" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ FILECMD \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_import \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ lt_cv_nm_interface \ nm_file_list_spec \ lt_cv_truncate_bin \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib \ compiler_lib_search_dirs \ predep_objects \ postdep_objects \ predeps \ postdeps \ compiler_lib_search_path \ LD_CXX \ reload_flag_CXX \ compiler_CXX \ lt_prog_compiler_no_builtin_flag_CXX \ lt_prog_compiler_pic_CXX \ lt_prog_compiler_wl_CXX \ lt_prog_compiler_static_CXX \ lt_cv_prog_compiler_c_o_CXX \ export_dynamic_flag_spec_CXX \ whole_archive_flag_spec_CXX \ compiler_needs_object_CXX \ with_gnu_ld_CXX \ allow_undefined_flag_CXX \ no_undefined_flag_CXX \ hardcode_libdir_flag_spec_CXX \ hardcode_libdir_separator_CXX \ exclude_expsyms_CXX \ include_expsyms_CXX \ file_list_spec_CXX \ compiler_lib_search_dirs_CXX \ predep_objects_CXX \ postdep_objects_CXX \ predeps_CXX \ postdeps_CXX \ compiler_lib_search_path_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ configure_time_dlsearch_path \ configure_time_lt_sys_library_path \ reload_cmds_CXX \ old_archive_cmds_CXX \ old_archive_from_new_cmds_CXX \ old_archive_from_expsyms_cmds_CXX \ archive_cmds_CXX \ archive_expsym_cmds_CXX \ module_cmds_CXX \ module_expsym_cmds_CXX \ export_symbols_cmds_CXX \ prelink_cmds_CXX \ postlink_cmds_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "include/pqxx/config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/pqxx/config.h" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; "libpqxx.pc") CONFIG_FILES="$CONFIG_FILES libpqxx.pc" ;; "configitems") CONFIG_COMMANDS="$CONFIG_COMMANDS configitems" ;; "compile_flags") CONFIG_FILES="$CONFIG_FILES compile_flags" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 printf "%s\n" "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`printf "%s\n" "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 printf "%s\n" "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 printf "%s\n" "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. case $CONFIG_FILES in #( *\'*) : eval set x "$CONFIG_FILES" ;; #( *) : set x $CONFIG_FILES ;; #( *) : ;; esac shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`printf "%s\n" "$am_mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`$as_dirname -- "$am_mf" || $as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$am_mf" : 'X\(//\)[^/]' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` am_filepart=`$as_basename -- "$am_mf" || $as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$am_mf" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` { echo "$as_me:$LINENO: cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles" >&5 (cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } || am_rc=$? done if test $am_rc -ne 0; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE=\"gmake\" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking). See \`config.log' for more details" "$LINENO" 5; } fi { am_dirpart=; unset am_dirpart;} { am_filepart=; unset am_filepart;} { am_mf=; unset am_mf;} { am_rc=; unset am_rc;} rm -f conftest-deps.mk } ;; "libtool":C) # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # The names of the tagged configurations supported by this script. available_tags='CXX ' # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shared archive member basename,for filename based shared library versioning on AIX. shared_archive_member_spec=$shared_archive_member_spec # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # A file(cmd) program that detects file types. FILECMD=$lt_FILECMD # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # DLL creation program. DLLTOOL=$lt_DLLTOOL # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive (by configure). lt_ar_flags=$lt_ar_flags # Flags to create an archive. AR_FLAGS=\${ARFLAGS-"\$lt_ar_flags"} # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm into a list of symbols to manually relocate. global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # The name lister interface. nm_interface=$lt_lt_cv_nm_interface # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and where our libraries should be installed. lt_sysroot=$lt_sysroot # Command to truncate a binary pipe. lt_truncate_bin=$lt_lt_cv_truncate_bin # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Detected run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path # Explicit LT_SYS_LIBRARY_PATH set during ./configure time. configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects postdep_objects=$lt_postdep_objects predeps=$lt_predeps postdeps=$lt_postdeps # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain=$ac_aux_dir/ltmain.sh # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? $SED '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" cat <<_LT_EOF >> "$ofile" # ### BEGIN LIBTOOL TAG CONFIG: CXX # The linker used to build libraries. LD=$lt_LD_CXX # How to create reloadable object files. reload_flag=$lt_reload_flag_CXX reload_cmds=$lt_reload_cmds_CXX # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds_CXX # A language specific compiler. CC=$lt_compiler_CXX # Is the compiler the GNU compiler? with_gcc=$GCC_CXX # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_CXX # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_CXX # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_CXX # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_CXX # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object_CXX # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds_CXX archive_expsym_cmds=$lt_archive_expsym_cmds_CXX # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds_CXX module_expsym_cmds=$lt_module_expsym_cmds_CXX # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld_CXX # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_CXX # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_CXX # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct_CXX # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute_CXX # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L_CXX # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic_CXX # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath_CXX # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_CXX # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols_CXX # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_CXX # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_CXX # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_CXX # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds_CXX # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds_CXX # Specify filename containing input files. file_list_spec=$lt_file_list_spec_CXX # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_CXX # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects_CXX postdep_objects=$lt_postdep_objects_CXX predeps=$lt_predeps_CXX postdeps=$lt_postdeps_CXX # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_CXX # ### END LIBTOOL TAG CONFIG: CXX _LT_EOF ;; "configitems":C) ${srcdir}/tools/filter_config.py \ include/pqxx/config.h include/pqxx/config-compiler.h ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi libpqxx-8.0.1/configure.ac000066400000000000000000000275101516427024100155040ustar00rootroot00000000000000# Generate configure script for libpqxx. This needs the autoconf archive # package installed. (The configure script itself does not require it though.) AC_PREREQ([2.71]) AC_INIT([libpqxx],[m4_esyscmd_s([./tools/extract_version.py])], [Jeroen T. Vermeulen]) # Suppress checks for standard C headers. One, we're not doing C here; two, # if you don't have these, chances are your system is in no shape to build # libpqxx; and three, we require C++20. It's a bit pointless to guard against # such specific shortcomings of 20th-century compilers. m4_define([AC_INCLUDES_DEFAULT], []) AC_LANG(C++) AX_CXX_COMPILE_STDCXX([20]) AC_CONFIG_SRCDIR([src/connection.cxx]) AC_CONFIG_AUX_DIR(config) AC_CONFIG_MACRO_DIR([config/m4]) AM_INIT_AUTOMAKE([subdir-objects]) PQXX_ABI=m4_esyscmd_s([./tools/extract_version.py --abi]) AC_SUBST(PQXXVERSION, $PACKAGE_VERSION) AC_SUBST(PQXX_ABI) AC_CONFIG_HEADERS([include/pqxx/config.h]) # Default prefix for installs. AC_PREFIX_DEFAULT(/usr/local) # Read test programme from config-test. AC_DEFUN([read_test], [AC_LANG_SOURCE( esyscmd(tools/m4esc.py --input=config-tests/$1))]) # Checks for programs. AC_PROG_CXX AC_PROG_INSTALL AC_DISABLE_SHARED LT_INIT AC_PROG_MAKE_SET AC_PATH_PROG([MKDIR], [mkdir]) AC_ARG_ENABLE( documentation, [AS_HELP_STRING([--enable-documentation], [Generate documentation])], [enable_documentation="${enableval}"]) AM_CONDITIONAL( [BUILD_DOCS], [test "$enable_documentation" = "yes"]) AM_MAINTAINER_MODE # See if we want stricter compiler warnings. AC_MSG_CHECKING([maintainer mode]) AC_ARG_ENABLE(maintainer-mode) AC_MSG_RESULT(${enable_maintainer_mode}) # See if we want runtime debug checking. AC_MSG_CHECKING([audit]) AC_ARG_ENABLE(audit) AC_MSG_RESULT(${enable_audit}) # See if we want "suggestions," such as "this class could be final." # (The suggestions are often useful, but can also easily be wrong.) AC_MSG_CHECKING([suggest]) AC_ARG_ENABLE(suggest) AC_MSG_RESULT(${enable_suggest:-no}) AC_ARG_ENABLE(shared) AS_IF( [test "${shared}" = "yes" ], [CPPFLAGS="$CPPFLAGS -DPQXX_SHARED"]) # Add options to compiler command line, if compiler accepts them. add_compiler_opts_if_ok() { FLAGS_FILE="$1" CXXFLAGS="$CXXFLAGS $( ${srcdir}/tools/compiler_flags.py \ -c "$CXX $CXXFLAGS" -f "$FLAGS_FILE" -s)" } # Add options to compiler command line, unconditionally. add_compiler_opts() { CXXFLAGS="$CXXFLAGS $*" } # Let's try to get the compiler to be helpful. # # (Omit options -Weffc++ and -Wabi because they currently yield too many # warnings in gcc's standard headers.) if test "$GCC" = "yes" then # In maintainer mode, enable all the warning options we can. if test "$enable_maintainer_mode" = "yes" then # "Eternal" (FLW) g++ options. These have been around for # ages, and both g++ and clang++ support them. Don't bother # checking for support; just add them to the compiler options. # # We'd love to add -D_GLIBCXX_CONCEPT_CHECKS in 8.0 here, but # it complains that the "reference" type in result iterators is # not an actual reference. add_compiler_opts \ -fstrict-enums \ -Werror \ -Wall \ -pedantic \ -Wcast-align \ -Wcast-qual \ -Wconversion \ -Wctor-dtor-privacy \ -Wendif-labels \ -Wextra \ -Wextra-semi \ -Wfloat-equal \ -Wformat=2 \ -Wformat-security \ -Wmissing-include-dirs \ -Wno-div-by-zero \ -Wnon-virtual-dtor \ -Wold-style-cast \ -Woverlength-strings \ -Woverloaded-virtual \ -Wpointer-arith \ -Wredundant-decls \ -Wshadow \ -Wsign-promo \ -Wundef \ -Wunused \ -Wwrite-strings \ -Wzero-as-null-pointer-constant \ # "Iffy" g++ options. Some reasonably current g++-like # compilers may not support these. # # The -fanalyzer one is a macro option for many of the others, # but we can't use it because as of gcc 13.2.0 we still see it # generating errors for the standard library. add_compiler_opts_if_ok \ "${srcdir}/config/flags/maintainer-mode.txt" fi # In "audit," enable all runtime checks we can. if test "$enable_audit" = "yes" then # These macros enable extra runtime checking in various # standard library implementations. add_compiler_opts \ -D_FORTIFY_SOURCE=2 \ -D_GLIBCXX_ASSERTIONS \ -D_GLIBCXX_DEBUG \ -D_GLIBCXX_DEBUG_PEDANTIC \ -D_GLIBCXX_SANITIZE_VECTOR \ -D_LIBCPP_DEBUG=1 \ -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG # Run-time sanitizers and such. These can differ from one # compiler (or version) to the next. add_compiler_opts_if_ok "${srcdir}/config/flags/audit-mode.txt" fi # In "suggest" mode, enable a bunch of code suggestions. if test "$enable_suggest" = "yes" then add_compiler_opts_if_ok \ "${srcdir}/config/flags/suggest-mode.txt" fi fi # End of gcc-specific part. # Do the feature checks now, *after* we add all the extra strictness options, # so that we don't accidentally enable any features that become unacceptable # under our chosen strictness. m4_include([pqxx_cxx_feature_checks.ac]) # One of the generated checks sets this variable. if test "$PQXX_HAVE_GCC_VISIBILITY" = "yes" then # Make internal definitions accessible only to the library itself. # Only definitions marked PQXX_LIBEXPORT will be accessible. add_compiler_opts -fvisibility=hidden add_compiler_opts -fvisibility-inlines-hidden fi # One of the generated checks sets this variable. if test "$PQXX_HAVE_POLL" != "yes" then # No poll(); we'll fall back to select(). # Some systems keep select() in a separate library which is not linked by # default. See if we need one of those. socklibok=no AC_SEARCH_LIBS(select, socket nsl ws2_32 wsock32 winsock, [socklibok=yes]) # Microsoft proprietary libraries do not work with code that is generated with # autoconf's SEARCH_LIBS macro, so we need to check manually and just use the # first socket library available. # We only do this if select() is not available by other means, to avoid picking # up an unnecessary Windows compatibility library on a non-Windows system. for l in ws2_32 wsock32 winsock do if test "${socklibok}" != "yes" then AC_CHECK_LIB($l,main,LIBS="$LIBS -l$l";[socklibok=yes]) fi done if test "${socklibok}" != "yes" then AC_MSG_ERROR([ Could not figure out how to link a simple sockets-based program. Please read the config.log file for more clues as to why this failed. ]) fi fi # No poll() # Check for std::stacktrace support. # # We need to link this test because some compilers require an extra library to # support std::stacktrace. AC_MSG_CHECKING([for std::stacktrace support]) have_stacktrace=yes AC_LINK_IFELSE( [read_test(stacktrace_support.cxx)], AC_DEFINE([PQXX_HAVE_STACKTRACE], 1, [Define if std::stacktrace works.]), have_stacktrace=no) AC_MSG_RESULT($have_stacktrace) # Find PostgreSQL includes and libraries AC_PATH_PROG([PKG_CONFIG], [pkg-config]) AC_PATH_PROGS(PG_CONFIG, pg_config) AC_ARG_WITH( [postgres-include], [AS_HELP_STRING( [--with-postgres-include=DIR], [Use PostgreSQL includes from DIR. Defaults to querying pg_config or pkg-config, whichever is available.])], AS_IF( [test "x$with_postgres_include" = "xyes"], [with_postgres_include=""])) if test -n "$with_postgres_include" then POSTGRES_INCLUDE="-I$with_postgres_include" else if test -x "$PKG_CONFIG" || test -x "$PG_CONFIG" then # We should prefer pkg-config over pg_config, but there seems to be a # problem in pkg-config 1.6.3. Until that's been resolved (#291), go # with pg_config if we can. if test -x "$PG_CONFIG" then # From pg_config we can either get the C compiler options used to # compile postgres, which isn't quite what we want; or we can get # the headers directory, without the full option. That's something # we can work with. The compiler must support the "-I" option for # that, but both scripts assume that anyway. POSTGRES_INCLUDE="-I$($PG_CONFIG --includedir)" else # From pkg-config we can get the compiler options to extend the # include path. We use that. POSTGRES_INCLUDE=$($PKG_CONFIG libpq --cflags-only-I) fi AC_MSG_NOTICE([finding PostgreSQL headers using $POSTGRES_INCLUDE]) else POSTGRES_INCLUDE="" fi fi AC_SUBST(POSTGRES_INCLUDE) # Add the compiler option so we can compile configure tests which rely on the # libpq headers. CPPFLAGS="$CPPFLAGS $POSTGRES_INCLUDE" AC_ARG_WITH( [postgres-lib], [AS_HELP_STRING( [--with-postgres-lib=DIR], [Use PostgreSQL libraries from DIR. Defaults to querying pg_config.])], AS_IF( [test "x$with_postgres_lib" = "xyes"], [with_postgres_lib=""])) # If no --with-postgres-lib was given, and we have pkg-config, use that. AS_IF( [test -z "$with_postgres_lib" -a -x "$PKG_CONFIG"], [with_postgres_lib=$($PKG_CONFIG libpq --libs-only-L | sed 's/^-L//')]) # pg_config is deprecated, but for some users it may still provide the only # right answer. For instance, `pkg-config` may not know where `libpq` is # installed. AS_IF( [test -z "$with_postgres_lib" -a -x "$PG_CONFIG"], [with_postgres_lib=$($PG_CONFIG --libdir)]) AS_IF( [test -n "$with_postgres_lib"], [AC_MSG_NOTICE([using PostgreSQL libraries at $with_postgres_lib])], [AC_MSG_NOTICE([using PostgreSQL libraries in default location])]) AC_SUBST(with_postgres_lib) AC_CHECK_HEADER( [libpq-fe.h], [], [AC_MSG_ERROR([ Can't find the main PostgreSQL client header, libpq-fe.h. Are you sure the libpq headers are installed correctly, and that we've got the right path? ])]) AC_MSG_CHECKING([for ability to compile source files using libpq]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [[#include]], [[PQexec(nullptr,"")]] )], [], [AC_MSG_ERROR([ Could not compile a call to a basic libpq function. There must be something seriously wrong with the headers that "pg_config --includedir" or "pkg-config libpq --cflags" pointed to; the contents of config.log may give you a clue about the nature of the failure. Source including the libpq header libpq-fe.h can be compiled, but a call to the most basic libpq function PQexec() failed to compile successfully. This is the litmus test for a working libpq. ])]) AC_MSG_RESULT(yes) if test "x${with_postgres_lib}" = "x"; then with_postgres_libpath="" else with_postgres_libpath="-L${with_postgres_lib}" fi LDFLAGS="$LDFLAGS ${with_postgres_libpath}" AC_CHECK_LIB( [pq], [PQexec], [], [AC_MSG_ERROR([ Did not find the PQexec() function in libpq. This is the litmus test for a working libpq installation. A source file using the PQexec() function did compile without problems, and the libpq library is available for linking, but for some reason a call to PQexec() failed to link properly to the libpq library. This may be because the libpq library file is damaged, or in some incorrect format, or if your libpq is much more recent than libpqxx version $PQXX_ABI, perhaps libpq has undergone a radical ABI change. The last parts of config.log may give you a clue as to what really went wrong, but be warned that this is no easy reading. Look for the last error message occurring in the file. ])], ${with_postgres_libpath}) # Remove redundant occurrances of -lpq LIBS=[$(echo "$LIBS" | sed -e 's/-lpq * -lpq\>/-lpq/g')] AC_PROG_MAKE_SET AC_CONFIG_FILES([Makefile include/Makefile libpqxx.pc]) # We've let autoconf generate a config.h. But there's a lot of stuff in there # that we don't need, and that we absolutely do not want. We'd like to avoid # polluting the application's namespace with macros that aren't clearly marked # as libpqxx-related. # # So we take just the ones with the "PQXX" marker and write them into a # header just for compiler-related configuration. AC_CONFIG_COMMANDS([configitems], [${srcdir}/tools/filter_config.py \ include/pqxx/config.h include/pqxx/config-compiler.h]) AC_CONFIG_FILES([compile_flags]) AC_OUTPUT libpqxx-8.0.1/cxx_features.txt000066400000000000000000000016661516427024100164630ustar00rootroot00000000000000# Feature checks that we can perform simply by testing a C++ feature # test macro, but for which we want a consistent setting between the libpqxx # source files and headers. This can avoid ABI inconsistencies when an # application uses a libpqxx that was compiled with a slightly different # compiler configuration, such as the same compiler but under a different # version ofthe C++ language. # # Each (non-empty, non-comment) line consists of a libpqxx feature macro # and the corresponding C++ feature test macro that we need to check in # order to detect that feature. # # From these, the autogen script generates code snippets that the build # configuration step can try to compile, as well as the bits of config # to do that in the supported build systems. # # Remember to enter each of these in configitems as well, or they won't # end up in the actual configuration headers. # Example: # PQXX_HAVE_MULTIDIM __cpp_multidimensional_subscript libpqxx-8.0.1/doc/000077500000000000000000000000001516427024100137565ustar00rootroot00000000000000libpqxx-8.0.1/doc/CMakeLists.txt000066400000000000000000000012631516427024100165200ustar00rootroot00000000000000find_program(HAVE_DOXYGEN doxygen) set(PQXXVERSION "${CMAKE_PROJECT_VERSION}") # cmake-lint: disable=C0103 set(top_srcdir "${PROJECT_SOURCE_DIR}") set(PQXX_ABI "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}") set(PQXX_MAJOR "${PROJECT_VERSION_MAJOR}") set(PQXX_MINOR "${PROJECT_VERSION_MINOR}") add_custom_target(build-docs ALL COMMAND cp -r ${CMAKE_CURRENT_SOURCE_DIR}/../src/*.[ch]xx ../src/ COMMAND cp -r ${CMAKE_CURRENT_SOURCE_DIR}/../include/pqxx/* ../include/pqxx/ COMMAND doxygen ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile COMMENT "Building documentation" ) install( DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doxygen-html/ DESTINATION ${CMAKE_INSTALL_DOCDIR}/html ) libpqxx-8.0.1/doc/Doxyfile000066400000000000000000000307751516427024100155000ustar00rootroot00000000000000# Doxyfile 1.9.4 # Set up to run Doxygen from the "doc" directory. PROJECT_NAME = "libpqxx" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = "The C++ client library for PostgreSQL" # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. # Path to where to generate Doxygen output. Defaults to working directory # when doxygen was run. Relative paths are relative to there. OUTPUT_DIRECTORY = doc GENERATE_LATEX = NO # The pqxx::transaction template class and the pqxx::work type alias dropped # out of the documentation during the upgrade from Doxygen 1.9.1 to 1.9.8. # This configuration may fix that: EXTRACT_ALL = YES EXTRACT_STATIC = YES HIDE_UNDOC_CLASSES = NO SHOW_NAMESPACES = YES EXTRACT_TEMPLATE_PARAMS = YES # If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096 # sub-directories (in 2 levels) under the output directory of each output format # and will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to # control the number of sub-directories. # The default value is: NO. CREATE_SUBDIRS = NO # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = YES # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = YES # The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use # during processing. When set to 0 doxygen will base this on the number of # cores available in the system. You can set it explicitly to a value larger # than 0 to get more control over the balance between CPU load and processing # speed. At this moment only the input processing can be done using multiple # threads. Since this is still an experimental feature the default is set to 1, # which effectively disables parallel processing. Please report any issues you # encounter. Generating dot graphs in parallel is controlled by the # DOT_NUM_THREADS setting. # Minimum value: 0, maximum value: 32, default value: 1. NUM_PROC_THREADS = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = YES # If the SHOW_HEADERFILE tag is set to YES then the documentation for a class # will show which file needs to be included to use the class. # The default value is: YES. SHOW_HEADERFILE = NO INPUT = src include # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = YES # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = examples test # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = *.cxx # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = include/pqxx/doc/mainpage.md #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all # C-preprocessor directives found in the sources and include files. # The default value is: YES. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names # in the source code. If set to NO, only conditional compilation will be # performed. Macro expansion can be done in a controlled way by setting # EXPAND_ONLY_PREDEF to YES. # The default value is: NO. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. MACRO_EXPANSION = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by the # preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of # RECURSIVE has no effect here. # This tag requires that the tag SEARCH_INCLUDES is set to YES. INCLUDE_PATH = include /usr/include/postgresql # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will be # used. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. INCLUDE_FILE_PATTERNS = * # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will # remove all references to function-like macros that are alone on a line, have # an all uppercase name, and do not end with a semicolon. Such function macros # are typically used for boiler-plate code, and will confuse the parser if not # removed. # The default value is: YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. SKIP_FUNCTION_MACROS = NO #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the # clang parser (see: # http://clang.llvm.org/) for more accurate parsing at the cost of reduced # performance. This can be particularly helpful with template rich C++ code for # which doxygen's built-in parser lacks the necessary type information. # Note: The availability of this option depends on whether or not doxygen was # generated with the -Duse_libclang=ON option for CMake. # The default value is: NO. # TODO: Re-enable this once clang parser gets better. CLANG_ASSISTED_PARSING = NO # If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS # tag is set to YES then doxygen will add the directory of each input to the # include path. # The default value is: YES. # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. CLANG_ADD_INC_PATHS = NO # If clang assisted parsing is enabled you can provide the compiler with command # line options that you would normally use when invoking the compiler. Note that # the include paths will already be set by doxygen for the files and directories # specified with INPUT and INCLUDE_PATH. # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. CLANG_OPTIONS = -O0 -std=c++23 #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = doxygen-html # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a color-wheel, see # https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 200 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use gray-scales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 80 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = YES # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine tune the look of the index (see "Fine-tuning the output"). As an # example, the default style sheet generated by doxygen has an example that # shows how to put an image at the root of the tree instead of the PROJECT_NAME. # Since the tree basically has the same information as the tab index, you could # consider setting DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = YES #--------------------------------------------------------------------------- # Configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that # captures the structure of the code including all documentation. # The default value is: NO. # TODO: Not really doing Sphinx/Breathe for now. Should we? # GENERATE_XML = YES # The XML_OUTPUT tag is used to specify where the XML pages will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: xml. # This tag requires that the tag GENERATE_XML is set to YES. XML_OUTPUT = doxygen-xml libpqxx-8.0.1/doc/requirements.txt000066400000000000000000000001401516427024100172350ustar00rootroot00000000000000# TODO: Pin versions. # TODO: Do we even still need this file? dia sphinx-rtd-theme myst-parser libpqxx-8.0.1/doc/source/000077500000000000000000000000001516427024100152565ustar00rootroot00000000000000libpqxx-8.0.1/doc/source/conf.py000066400000000000000000000017311516427024100165570ustar00rootroot00000000000000# Configuration file for the Sphinx documentation builder. from pathlib import Path project = "libpqxx" copyright = "2000-2026, Jeroen T. Vermeulen" author = "Jeroen T. Vermeulen" version = (Path(__file__).parents[2] / "VERSION").read_text().strip() release = ".".join(version.split(".")[:2]) extensions = [ # TODO: Not actually using Sphinx for now. Should we? # From readthedocs template: # 'sphinx.ext.duration', # 'sphinx.ext.doctest', # 'sphinx.ext.autodoc', # 'sphinx.ext.autosummary', # 'sphinx.ext.intersphinx', # Additional: # TODO: Not using Breathe for now. Should we? # 'breathe', "myst_parser", ] # TODO: What do these actually mean? # intersphinx_mapping = { # 'python': ('https://docs.python.org/3/', None), # 'sphinx': ('https://www.sphinx-doc.org/en/master/', None), # } # intersphinx_disabled_domains = ['std'] templates_path = ["_templates"] # -- Options for HTML output html_theme = "sphinx_rtd_theme" libpqxx-8.0.1/doc/source/index.rst000066400000000000000000000004341516427024100171200ustar00rootroot00000000000000libpqxx documentation ===================== This documentation is for libpqxx_, the C++ client library for PostgreSQL. This is the library you call in order to work with a postgres database from your C++ code. .. _libpqxx: https://pqxx.org/libpqxx/ Contents -------- .. toctree:: libpqxx-8.0.1/examples/000077500000000000000000000000001516427024100150275ustar00rootroot00000000000000libpqxx-8.0.1/examples/CMakeLists.txt000066400000000000000000000004221516427024100175650ustar00rootroot00000000000000file(GLOB SOURCE_FILES "*.cxx") foreach(source_file ${SOURCE_FILES}) get_filename_component(name ${source_file} NAME_WLE) add_executable(${name} ${source_file}) target_link_libraries(${name} PRIVATE pqxx) add_test(NAME ${name} COMMAND ${name}) endforeach() libpqxx-8.0.1/examples/README.md000066400000000000000000000004751516427024100163140ustar00rootroot00000000000000Examples ======== Here are some simple, readable, maintained examples of how to use libpqxx. As the API evolves, these will evolve with it. You can always look at the tests for more detail, but the examples are more natural and easier to read, because they don't have to go through every crazy possible edge case. libpqxx-8.0.1/examples/complete_example.cxx000066400000000000000000000063271516427024100211060ustar00rootroot00000000000000#include #include /* Example for using libpqxx. * * This shows a bit of how a real C++ application might access a PostgreSQL * database using libpqxx. * * It sets up a minimal database schema, and then executes some queries on it; * and handles any errors that might crop up in the process. */ namespace { void set_up(pqxx::connection &cx) { pqxx::work tx{cx}; tx.exec("CREATE TEMP TABLE Employee(name varchar, salary integer)"); tx.exec("INSERT INTO Employee(name, salary) VALUES ('Someone', 4632)"); tx.commit(); } } // namespace /// Query employees from database. Return result. pqxx::result query() { pqxx::connection cx; set_up(cx); pqxx::work tx{cx}; // Silly example: Add up all salaries. Normally you'd let the database do // this for you. long total = 0; for (auto [salary] : tx.query("SELECT salary FROM Employee")) total += salary; std::cout << "Total salary: " << total << '\n'; // Execute and process some data. pqxx::result r{tx.exec("SELECT name, salary FROM Employee")}; for (auto row : r) std::cout // Address column by name. Use c_str() to get C-style string. << row["name"].c_str() << " makes " // Address column by zero-based index. Use as() to parse as int. << row[1].as() << "." << std::endl; // Not really needed, since we made no changes, but good habit to be // explicit about when the transaction is done. tx.commit(); // Connection object goes out of scope here. It closes automatically. // But the result object remains valid. return r; } /// Query employees from database, print results. int main() { try { pqxx::result const r{query()}; // Results can be accessed and iterated again. Even after the connection // has been closed. for (auto row : r) { std::cout << "Row: "; // Iterate over fields in a row. for (auto field : row) std::cout << field.c_str() << " "; std::cout << std::endl; } } // Catch libpqxx exceptions. There are different subclasses for various // types of errors, but we really don't need to care about those differences // unless we're trying to catch one very specific error. // // This central base libpqxx exception class, pqxx::failure, is derived from // std::exception. So if we're going to catch both, we'll have to catch // pqxx::failure first. // // All the API for libpqxx exceptions is present right from this base class // on down. Some of the more specific exception types will have additional // data, such as which SQL query triggered the error. But the function to // read that query is present even in the base class. When not applicable, // it will simply return an empty string. catch (pqxx::failure const &e) { std::cerr << e.name() << ": " << e.what() << '\n'; std::cerr << "Happened in " << pqxx::source_loc(e.location()) << ".\n"; if (not std::empty(e.query())) std::cerr << "Query was:\n" << e.query() << '\n'; if (not std::empty(e.sqlstate())) std::cerr << "SQLSTATE " << e.sqlstate() << '\n'; return 2; } // Catch other exceptions. catch (std::exception const &e) { std::cerr << "Error: " << e.what() << std::endl; return 1; } } libpqxx-8.0.1/examples/faster_data.cxx000066400000000000000000000112771516427024100200400ustar00rootroot00000000000000#include #include /** An example showing how to optimise data processing for your needs in * libpqxx. */ namespace { /// Some processing function that we want to execute on a bunch of records. /** Each of the records will consist of a string and an integer. */ int process_row(std::string_view name, int number) { return number - static_cast(std::ssize(name)); } /// Generate a query that produces `num_rows` rows of data. /** Each row will consist of a string and an integer. */ std::string make_query(int num_rows) { return std::format( "SELECT ('name' || n), n FROM generate_series(1, {}) n", num_rows); } } // namespace int main() { try { pqxx::connection cx; pqxx::transaction tx{cx}; // Here's the basic way to query the database. It loads all the result // data into our memory, and returns a pqxx::result. pqxx::result const r1 = tx.exec(make_query(100)); // We can ask the result to check that it has exactly 100 rows. If it does // not, this will throw an exception. r1.expect_rows(100); // Here's a very basic way to run `process_row` on each of the rows, and // add up all the numbers. It converts each row's two fields to a // `std::string` and an `int`, respectively. int sum1a = 0; for (auto const row : r1) sum1a += process_row(row.at(0).as(), row.at(1).as()); // But, that loop does unnecessary work. It reads each string into a full // std::string object, which can involve memory allocations and // deallocations internally. // // To get rid of that waste, you can instead read each string into a // std::string_view. This is a lighter-weight object that's merely a // reference to data elsewhere. But be careful: that's only valid for as // long as r1 (or a copy of it) remains in memory. Otherwise, the // underlying result data will be deallocated and your reference will refer // to invalid memory. // // As a shortcut, instead of `.as()`, you can also use // the simpler `.view()` member function. int sum1b = 0; for (auto const row : r1) sum1b += process_row(row.at(0).as(), row.at(1).as()); // This produces the exact same results. assert(sum1b == sum1a); // If you prefer a declarative style with callbacks, you can also use the // result's `for_each()` function. // // What's really neat about this is that you don't need to specify how you // want to read the fields. The `for_each()` function inspects your // callback to figure out what parameter types it takes, and converts each // row's fields to those respective types. // // It figures this out at compile time, so there's no run-time cost. int sum1c = 0; r1.for_each([&sum1c](std::string_view name, int number) { sum1c += process_row(name, number); }); // This again produces the same results. assert(sum1c == sum1a); // But all these are just the first way of querying data. It reads all the // result data from the database server and returns an object representing // all that data. // // There is another way: _streaming._ This does not work for all queries; // it does not accept parameters, for instance. Due to some constant // overhead it's also likely to be a bit _slower_ for small result sets. // But it gets much faster for larger result sets. The actual numbers // depend on your individual use-case, so when performance is crucial, // measure what works best for you. // // Why does streaming tend to be faster? There are several reasons: // 1. You can start processing the first rows before the query even // finishes. // 2. It bypasses calls to the underlying C library, libpq. // 3. Fewer memory allocations and deallocations are needed. // 4. Encoding support in libpqxx has very little overhead. // // When streaming a query, you specify as what types you want to read the // respective columns, as template arguments. int sum2a = 0; // This executes the query with a large number of result rows, and iterates // over each row as it streams in. for (auto const [name, number] : tx.stream(make_query(10'000))) sum2a += process_row(name, number); // Streaming, too, has a variant where you pass a callback. int sum2b = 0; tx.for_stream( make_query(10'000), [&sum2b](std::string_view name, int number) { sum2b += process_row(name, number); }); assert(sum2b == sum2a); } catch (std::exception const &e) { std::cerr << "Error: " << e.what() << '\n'; return 1; } return 0; } libpqxx-8.0.1/examples/from_readme.cxx000066400000000000000000000067671516427024100200530ustar00rootroot00000000000000#include #include namespace { void set_up(pqxx::connection &cx) { pqxx::work tx{cx}; tx.exec("CREATE TEMP TABLE employee(name varchar, salary money)"); tx.exec("INSERT INTO employee(name, salary) VALUES ('Me', 5432)"); tx.commit(); } } // namespace int main() { try { // Connect to the database. You can have multiple connections open // at the same time, even to the same database. pqxx::connection cx; std::cout << "Connected to " << cx.dbname() << '\n'; set_up(cx); // Start a transaction. A connection can only have one transaction // open at the same time, but after you finish a transaction, you // can start a new one on the same connection. pqxx::work tx{cx}; // Query data of two columns, converting them to std::string and // int respectively. Iterate the rows. for (auto const &[name, salary] : tx.query( "SELECT name, floor(salary::numeric) FROM employee ORDER BY name")) { std::cout << name << " earns " << salary << ".\n"; } // For large amounts of data, "streaming" the results is more // efficient. It does not work for all types of queries though. // // You can read fields as std::string_view here, which is not // something you can do in most places. A string_view becomes // meaningless when the underlying string ceases to exist. In this // particular situation, you can convert a field to string_view and // it will be valid for just that one iteration of the loop. The // next iteration may overwrite or deallocate its buffer space. for (auto [name, salary] : tx.stream( "SELECT name, floor(salary::numeric) FROM employee")) { std::cout << name << " earns " << salary << ".\n"; } // Execute a statement, and check that it returns 0 rows of data. // This will throw pqxx::unexpected_rows if the query returns rows. std::cout << "Doubling all employees' salaries...\n"; tx.exec("UPDATE employee SET salary = salary*2").no_rows(); // Shorthand: conveniently query a single value from the database, // and convert it to an `int`. int const my_salary = tx.query_value( "SELECT floor(salary::numeric) FROM employee WHERE name = 'Me'"); std::cout << "I now earn " << my_salary << ".\n"; // Or, query one whole row. This function will throw an exception // unless the result contains exactly 1 row. auto [top_name, top_salary] = tx.query1( R"( SELECT name, floor(salary::numeric) FROM employee WHERE salary = (SELECT max(salary) FROM employee) LIMIT 1 )"); std::cout << "Top earner is " << top_name << " with a salary of " << top_salary << ".\n"; // If you need to access the result metadata, not just the actual // field values, use `exec()`. It returns a pqxx::result object. pqxx::result const res = tx.exec("SELECT * FROM employee"); std::cout << "Columns:\n"; for (pqxx::row_size_type col = 0; col < res.columns(); ++col) std::cout << res.column_name(col) << '\n'; // Commit the transaction. If you don't do this, the database will // undo any changes you made in the transaction. std::cout << "Making changes definite: "; tx.commit(); std::cout << "OK.\n"; } catch (std::exception const &e) { std::cerr << "ERROR: " << e.what() << '\n'; return 1; } return 0; } libpqxx-8.0.1/examples/getting_started_1.cxx000066400000000000000000000027411516427024100211660ustar00rootroot00000000000000#include #include int main() { try { // Connect to the database. In practice we may have to pass some // arguments to say where the database server is, and so on. // The constructor parses options exactly like libpq's // PQconnectdb/PQconnect, see: // https://www.postgresql.org/docs/10/static/libpq-connect.html pqxx::connection cx; // Start a transaction. In libpqxx, you always work in one. pqxx::work tx(cx); // We'll just ask the database to return the number 1 to us. // The one_row() call checks that the result contains exactly one row // of data, and throws an exception if it does not. It returns the // row. pqxx::row const r = tx.exec("SELECT 1").one_row(); // Commit your transaction. If an exception occurred before this // point, execution will have left the block, and the transaction will // have been destroyed along the way. In that case, the failed // transaction would implicitly abort instead of getting to this point. tx.commit(); // Look at the first and only field in the row, parse it as an integer, // and print it. // // "r[0]" returns the first field, which has an "as<...>()" member // function template to convert its contents from their string format // to a type of your choice. std::cout << r[0].as() << std::endl; } catch (std::exception const &e) { std::cerr << e.what() << std::endl; return 1; } return 0; } libpqxx-8.0.1/examples/getting_started_2.cxx000066400000000000000000000013761516427024100211720ustar00rootroot00000000000000#include #include #include int main(int, char *argv[]) { try { char const *const text = ((argv[1] == nullptr) ? "Default text" : argv[1]); pqxx::connection cx; pqxx::work tx(cx); // work::exec() returns a full result set, which can consist of any // number of rows. pqxx::result const r = tx.exec("SELECT $1", pqxx::params{text}); // End our transaction here. We can still use the result afterwards. tx.commit(); // Print the first field of the first row. Read it as a C string, // just like std::string::c_str() does. std::cout << r[0][0].c_str() << std::endl; } catch (std::exception const &e) { std::cerr << e.what() << std::endl; return 1; } return 0; } libpqxx-8.0.1/examples/quick_example.cxx000066400000000000000000000027121516427024100204040ustar00rootroot00000000000000#include #include namespace { void set_up(pqxx::connection &cx) { pqxx::transaction tx{cx}; tx.exec( "CREATE TEMP TABLE Employee (id integer, name varchar, salary integer)"); tx.exec( "INSERT INTO Employee(id, name, salary) VALUES (1, 'Ichiban', 65432)"); tx.commit(); } } // namespace int main(int, char *argv[]) { // (Normally you'd check for valid command-line arguments.) char const *const name = ((argv[1] == nullptr) ? "Ichiban" : argv[1]); // (Normally you'd pass connection settings to the connection constructor.) pqxx::connection cx; set_up(cx); pqxx::work tx{cx}; // For querying just one single value, the transaction has a shorthand method // query_value(). // // The employee ID shows up in the query as "$1"; that means we'll pass it as // a parameter. Pass all parameters together in a single "params" object. int const employee_id = tx.query_value( "SELECT id " "FROM Employee " "WHERE name = $1", pqxx::params{name}); std::cout << "Updating employee #" << employee_id << '\n'; // Update the employee's salary. Use exec() to perform the command, and // no_rows() to check that it produces no result rows. If the result does // contain data, this will throw an exception. tx.exec( "UPDATE Employee " "SET salary = salary + 1 " "WHERE id = $1", pqxx::params{employee_id}) .no_rows(); // Make our change definite. tx.commit(); } libpqxx-8.0.1/examples/simple_queries.cxx000066400000000000000000000301111516427024100205750ustar00rootroot00000000000000#include #include /** Here's an example of how to use PostgreSQL in a C++ application, using * libpqxx. * * In this example we'll populate a small company database, and query it. */ namespace { /// Create an SQL schema. /** The tables are all temporary to simplify cleanup. In a real application * of course they wouldn't be `TEMP`. */ void create_schema(pqxx::connection &cx) { // We have a connection. We want to execute some SQL statements. // // In libpqxx you don't do that directly on the connection. You create a // _transaction,_ and use that to execute statements. // // Once you're done with your statements, you _commit_ the transaction. If // there's an error, you'll typically get an exception, and destroy the // transaction without committing it. When that happens, the transaction // _aborts,_ and its changes are undone. // // There can be only one regular transaction on a connection at the same // time. You'll have to commit, abort, or destroy it before you can start // another. // // In SQL, "work" is an alias for "transaction." In libpqxx, `transaction` // is a template, letting you choose a transaction isolation level. To keep // it simple, `work` is an alias for the default kind. pqxx::work tx{cx}; // Execute a simple SQL statement: create a table. tx.exec( "CREATE TEMP TABLE department (" "id integer PRIMARY KEY, " "name varchar UNIQUE NOT NULL)"); // When executing a statement that should not return any rows of data, you // can indicate this by calling no_rows() on the result. This checks that // there really are no data rows, and throws an exception if there are. tx.exec( "CREATE TEMP TABLE employee (" "id integer PRIMARY KEY, " "name varchar NOT NULL, " "date_hired timestamp without time zone, " "dept_id integer REFERENCES department(id))") .no_rows(); // More generally, you can specify that there should be `n` rows by calling // `expect_rows(n)` on the result. tx.exec( "CREATE TEMP TABLE customer (" "id integer PRIMARY KEY, " "name varchar NOT NULL)") .expect_rows(0); // If we got this far without exceptions, that means we're successful. // Commit the transaction so that the changes become persistent. tx.commit(); } /// Write sample data to our schema. void populate_schema(pqxx::connection &cx) { // Again we need to create a transaction. There are also a few SQL // statements that can't be run inside a transaction; for those you'll use a // `pqxx::nontransaction`. That way you get the same, single API for // executing SQL regardless of whether you're in a transaction. pqxx::work tx{cx}; // We'll _stream_ our data into the tables. Each stream is an object, and // only one can be active on a transaction at any given time. // // Here, we set up a stream to write IDs and names to the "department" table. // // We specify the transaction; a "path" for the table (which in the simplest // case consists of just its name); and the column names we're writing. In // any columns we don't write we will get the default values, usually NULL. auto depts = pqxx::stream_to::table(tx, {"department"}, {"id", "name"}); // Now we can feed our data into the table. This is much faster than // executing individual "INSERT" statements. // // We can feed many kinds of data into the fields. In this case, we use an // integer for the ID and a string for the name. But we could also use two // strings, if we wanted to, so long as the ID string contains only digits. // // There is one caveat: if there is a clash (e.g. because there already is // a department with the same name), this will simply fail with an exception. // If you want to resolve conflicts by keeping the row you had, or by // overwriting it with the new one, you'll have to write into a temporary // table and write your own SQL to move the data over into the destination. depts.write_values(1, "accounting"); depts.write_values(2, "marketing"); depts.write_values(3, "widgets"); // Just like we had to commit a transaction to make our work persistent, we // need to tell the stream that we're done writing data. Until we do this, // it may still be buffering some data on the client side. depts.complete(); // Now that there are departments, we can populate them with employees. auto emps = pqxx::stream_to::table( tx, {"employee"}, {"id", "name", "date_hired", "dept_id"}); // There are many ways to pass a null. We can use a nullptr, or an empty // std::optional, an empty std::unique_ptr or std::shared_ptr, and so on. emps.write_values(1, "Piet Hein", nullptr, 1); emps.write_values(2, "Hugo de Groot", std::optional{}, 3); emps.write_values("3", "Johan de Witt", std::unique_ptr{}, 2); emps.write_values("4", "Willem van Oranje", std::shared_ptr{}, 3); // Again we must tell the stream when we're done feeding data into it. emps.complete(); auto cust = pqxx::stream_to::table(tx, {"customer"}, {"id", "name"}); cust.write_values(1, "Acme"); cust.write_values(2, "The Government"); cust.write_values(3, "Sirius Cybernetics Corp."); cust.write_values(4, "A chap I met at the club called Bernard"); cust.complete(); // Don't forget to commit the transaction! Otherwise it was all for nought. tx.commit(); } /// Query and print out departments. void query_depts(pqxx::connection &cx) { // Again we need a transaction. In this case we don't really care what // kind. We'll use a `nontransaction`, which just immediately commits every // statement you execute. Its `commit()` and `abort()` functions are no-ops. pqxx::nontransaction tx{cx}; // We execute an SQL command, and get a `pqxx::result` back. This contains // all of the data and metadata resulting from the query, in their SQL // textual representation. // // There are other ways of querying (see below for more), but this one is // perfect when we want the metadata, and the amount of data is small enough // to retrieve in one go. We only get the result once the query has // executed to completion and we have received all the data. pqxx::result const res = tx.exec("SELECT name FROM department ORDER BY name"); // The result has metadata, such as its number of rows. std::cout << "Number of departments: " << std::size(res) << '\n'; // And of course it contains the rows of data. You can iterate these just // like a standard C++ container. for (pqxx::row_ref const row : res) { // Each row contains a series of fields, corresponding to the columns of // the result. You can iterate these as well, or you can address them by // index, just like a standard C++ container: `operator[]` if you are sure // the field exists, or `at()` if you want error checking. // // The simplest way to read a field's contents is to call its `view()`. // It gives you a `std::string_view` on its value. std::cout << '\t' << row.at(0).view() << '\n'; } std::cout << '\n'; } /// Query and print out employees. void query_emps(pqxx::connection &cx) { pqxx::work tx{cx}; // Query employees. Specify how many columns we expect in the result; if // the number is wrong, we'll get an exception. pqxx::result const res = tx.exec( "SELECT employee.id, employee.name, department.name " "FROM employee " "JOIN department ON department.id = employee.dept_id " "ORDER BY employee.name, department.name") .expect_columns(3); // Print out the results. This time we convert the fields' contents to // various C++ types. It doesn't matter what type they were in the database; // you can convert them to anything so long as the data fits the type. You // can read an integer as a string, or as a floating-point number, and so on. std::cout << "Employees:\n"; for (auto row : res) { std::cout << '\t' << row[0].as() << '\t' << row[1].as() << '\t' << row[2].as() << '\n'; } // There is also a completely different way of iterating over a result: you // pass a lambda or function to its `for_each()`. That function will figure // out what parameter types your callable expects, and convert the respective // columns to those and pass them as arguments. // // Of course your callable must take exactly the same number of arguments as // the result contains. // // Here, we use that to determine the highest employee ID. int top_id{0}; res.for_each([&top_id](int id, std::string_view, std::string_view) { // (Don't worry about the extra parentheses. Those are just there because // std::min() and std::max() confuse Visual Studio.) top_id = (std::max)(top_id, id); }); if (top_id > 0) std::cout << "The highest employee ID is " << top_id << ".\n\n"; } /// Query and print customers. This could be a lot of data. void query_customers(pqxx::connection &cx) { pqxx::work tx{cx}; std::cout << "Customers:\n"; // Query the number of customers. There's a convenience shortcut for // "execute this query, check that it produces a result consisting of a // single field (so one row of one column), and convert that one field value // to the type I specify": auto const num_customers = tx.query_value("SELECT count(*) FROM customer"); std::cout << "Total customers: " << num_customers << '\n'; // There's also a convenience shortcut for "execute this query, and iterate // over the result rows, converting each to a tuple of the given types." // You use this with a "for" loop and structured binding: for (auto [id, name] : tx.query( "SELECT id, name FROM customer ORDER BY id")) { std::cout << '\t' << id << '\t' << name << '\n'; } std::cout << "\n\n"; // Or, if you prefer a callback-based style, for_query() takes a query and a // callback. It executes the query, iterates over the result rows, calling // your callback with the row's respective field values as argments. It // detects the parameter types your callback expects, and converts the fields // to those respective types. std::cout << "That same data again:\n"; tx.for_query( "SELECT id, name FROM customer ORDER BY id", [](int id, std::string_view name) { std::cout << '\t' << id << '\t' << name << '\n'; }); } } // namespace int main(int, char *argv[]) { // We may need a connection string setting a database address (either host // and port, or path to a Unix domain socket), a database name, username, // password, and so on. Any values not set in the connection string will // use either values set in environment variables, or built-in defaults. // // For connection strings, see: // https://postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING // // For the environment variables, see: // https://postgresql.org/docs/current/libpq-envars.html // // Here we'll just assume you pass a connection string on the command line. std::string const connect_string{(argv[1] == nullptr) ? "" : argv[1]}; try { // Connect to the database. In libpqxx this is the same thing as "creating // a connection." // // You don't need to check whether this succeeds. If there's a problem, // this will throw an exception. pqxx::connection cx{connect_string}; // We're connected to a database. Let's set up our schema and populate it. create_schema(cx); populate_schema(cx); // Query the database, and print out various information. query_depts(cx); query_emps(cx); query_customers(cx); } catch (pqxx::failure const &e) { // In the case of a libpqxx exception, there's some extra useful // information that we can print. std::cerr << "*** " << e.name() << " ***: " << e.what() << '\n'; std::cerr << "Happened in " << pqxx::source_loc(e.location()) << ".\n"; if (not std::empty(e.query())) std::cerr << "\nQuery was:\n" << e.query() << '\n'; return 1; } catch (std::exception const &e) { // We only get here if there was an error. std::cerr << "Error: " << e.what() << '\n'; return 1; } return 0; } libpqxx-8.0.1/include/000077500000000000000000000000001516427024100146345ustar00rootroot00000000000000libpqxx-8.0.1/include/CMakeLists.txt000066400000000000000000000035201516427024100173740ustar00rootroot00000000000000# ############################################################################## # AUTOMATICALLY GENERATED FILE -- DO NOT EDIT. # # This file is generated automatically by libpqxx's template2mak.py script, and # will be rewritten from time to time. # # If you modify this file, chances are your modifications will be lost. # # The template2mak.py script should be available in the tools directory of the # libpqxx source archive. # # Generated from template './include/CMakeLists.txt.template'. # ############################################################################## install( DIRECTORY pqxx "${PROJECT_BINARY_DIR}/include/pqxx" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FILES_MATCHING # For each X.hxx, install both X.hxx itself and plain X. PATTERN *.hxx # TODO: Is there any way to do this with CMake's globbing? PATTERN array PATTERN blob PATTERN composite PATTERN connection PATTERN cursor PATTERN dbtransaction PATTERN encoding_group PATTERN errorhandler PATTERN except PATTERN field PATTERN isolation PATTERN largeobject PATTERN nontransaction PATTERN notification PATTERN params PATTERN pipeline PATTERN prepared_statement PATTERN range PATTERN result PATTERN robusttransaction PATTERN row PATTERN separated_list PATTERN strconv PATTERN stream_from PATTERN stream_to PATTERN subtransaction PATTERN time PATTERN transaction PATTERN transaction_base PATTERN transaction_focus PATTERN transactor PATTERN types PATTERN util PATTERN version PATTERN zview PATTERN internal/*.hxx PATTERN internal/gates/*.hxx PATTERN config-compiler.h PATTERN pqxx PATTERN doc EXCLUDE ) install( DIRECTORY pqxx/doc/ DESTINATION ${CMAKE_INSTALL_DOCDIR} FILES_MATCHING PATTERN *.md ) libpqxx-8.0.1/include/CMakeLists.txt.template000066400000000000000000000011411516427024100212030ustar00rootroot00000000000000install( DIRECTORY pqxx "${PROJECT_BINARY_DIR}/include/pqxx" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FILES_MATCHING # For each X.hxx, install both X.hxx itself and plain X. PATTERN *.hxx # TODO: Is there any way to do this with CMake's globbing? ###MAKTEMPLATE:FOREACH include/pqxx/*.hxx PATTERN ###BASENAME### ###MAKTEMPLATE:ENDFOREACH PATTERN internal/*.hxx PATTERN internal/gates/*.hxx PATTERN config-compiler.h PATTERN pqxx PATTERN doc EXCLUDE ) install( DIRECTORY pqxx/doc/ DESTINATION ${CMAKE_INSTALL_DOCDIR} FILES_MATCHING PATTERN *.md ) libpqxx-8.0.1/include/Makefile.am000066400000000000000000000061321516427024100166720ustar00rootroot00000000000000nobase_include_HEADERS= pqxx/pqxx \ pqxx/array pqxx/array.hxx \ pqxx/blob pqxx/blob.hxx \ pqxx/composite pqxx/composite.hxx \ pqxx/connection pqxx/connection.hxx \ pqxx/cursor pqxx/cursor.hxx \ pqxx/dbtransaction pqxx/dbtransaction.hxx \ pqxx/encoding_group pqxx/encoding_group.hxx \ pqxx/errorhandler pqxx/errorhandler.hxx \ pqxx/except pqxx/except.hxx \ pqxx/field pqxx/field.hxx \ pqxx/isolation pqxx/isolation.hxx \ pqxx/largeobject pqxx/largeobject.hxx \ pqxx/nontransaction pqxx/nontransaction.hxx \ pqxx/notification pqxx/notification.hxx \ pqxx/params pqxx/params.hxx \ pqxx/pipeline pqxx/pipeline.hxx \ pqxx/prepared_statement pqxx/prepared_statement.hxx \ pqxx/range pqxx/range.hxx \ pqxx/result pqxx/result.hxx \ pqxx/robusttransaction pqxx/robusttransaction.hxx \ pqxx/separated_list pqxx/separated_list.hxx \ pqxx/strconv pqxx/strconv.hxx \ pqxx/stream_from pqxx/stream_from.hxx \ pqxx/stream_to pqxx/stream_to.hxx \ pqxx/subtransaction pqxx/subtransaction.hxx \ pqxx/time pqxx/time.hxx \ pqxx/transaction pqxx/transaction.hxx \ pqxx/transaction_base pqxx/transaction_base.hxx \ pqxx/transaction_focus pqxx/transaction_focus.hxx \ pqxx/transactor pqxx/transactor.hxx \ pqxx/row pqxx/row.hxx \ pqxx/util pqxx/util.hxx \ pqxx/types pqxx/types.hxx \ pqxx/zview pqxx/zview.hxx \ pqxx/version pqxx/version.hxx \ pqxx/internal/array-composite.hxx \ pqxx/internal/callgate.hxx \ pqxx/internal/connection-string.hxx \ pqxx/internal/conversions.hxx \ pqxx/internal/encodings.hxx \ pqxx/internal/header-pre.hxx \ pqxx/internal/header-post.hxx \ pqxx/internal/ignore-deprecated-post.hxx \ pqxx/internal/ignore-deprecated-pre.hxx \ pqxx/internal/result_iter.hxx \ pqxx/internal/result_iterator.hxx \ pqxx/internal/sql_cursor.hxx \ pqxx/internal/statement_parameters.hxx \ pqxx/internal/stream_iterator.hxx \ pqxx/internal/stream_query.hxx \ pqxx/internal/stream_query_impl.hxx \ pqxx/internal/wait.hxx \ pqxx/internal/gates/connection-errorhandler.hxx \ pqxx/internal/gates/connection-largeobject.hxx \ pqxx/internal/gates/connection-notification_receiver.hxx \ pqxx/internal/gates/connection-pipeline.hxx \ pqxx/internal/gates/connection-sql_cursor.hxx \ pqxx/internal/gates/connection-stream_from.hxx \ pqxx/internal/gates/connection-stream_to.hxx \ pqxx/internal/gates/connection-transaction.hxx \ pqxx/internal/gates/errorhandler-connection.hxx \ pqxx/internal/gates/field_ref-const_row_iterator.hxx \ pqxx/internal/gates/icursor_iterator-icursorstream.hxx \ pqxx/internal/gates/icursorstream-icursor_iterator.hxx \ pqxx/internal/gates/result-connection.hxx \ pqxx/internal/gates/result-creation.hxx \ pqxx/internal/gates/result-field_ref.hxx \ pqxx/internal/gates/result-pipeline.hxx \ pqxx/internal/gates/result-sql_cursor.hxx \ pqxx/internal/gates/row_ref-const_result_iterator.hxx \ pqxx/internal/gates/row_ref-result.hxx \ pqxx/internal/gates/row_ref-row.hxx \ pqxx/internal/gates/transaction-transaction_focus.hxx nobase_nodist_include_HEADERS = pqxx/config.h pqxx/config-compiler.h EXTRA_DIST = \ pqxx/doc/*.md \ pqxx/doc/mainpage.md.template \ pqxx/version.hxx.template libpqxx-8.0.1/include/Makefile.in000066400000000000000000000524451516427024100167130ustar00rootroot00000000000000# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = include ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \ $(top_srcdir)/config/m4/ltoptions.m4 \ $(top_srcdir)/config/m4/ltsugar.m4 \ $(top_srcdir)/config/m4/ltversion.m4 \ $(top_srcdir)/config/m4/lt~obsolete.m4 \ $(top_srcdir)/pqxx_cxx_feature_checks.ac \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(nobase_include_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/pqxx/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)" HEADERS = $(nobase_include_HEADERS) $(nobase_nodist_include_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/config/mkinstalldirs DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FILECMD = @FILECMD@ GREP = @GREP@ HAVE_CXX20 = @HAVE_CXX20@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR = @MKDIR@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PG_CONFIG = @PG_CONFIG@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_INCLUDE = @POSTGRES_INCLUDE@ PQXXVERSION = @PQXXVERSION@ PQXX_ABI = @PQXX_ABI@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_postgres_lib = @with_postgres_lib@ nobase_include_HEADERS = pqxx/pqxx \ pqxx/array pqxx/array.hxx \ pqxx/blob pqxx/blob.hxx \ pqxx/composite pqxx/composite.hxx \ pqxx/connection pqxx/connection.hxx \ pqxx/cursor pqxx/cursor.hxx \ pqxx/dbtransaction pqxx/dbtransaction.hxx \ pqxx/encoding_group pqxx/encoding_group.hxx \ pqxx/errorhandler pqxx/errorhandler.hxx \ pqxx/except pqxx/except.hxx \ pqxx/field pqxx/field.hxx \ pqxx/isolation pqxx/isolation.hxx \ pqxx/largeobject pqxx/largeobject.hxx \ pqxx/nontransaction pqxx/nontransaction.hxx \ pqxx/notification pqxx/notification.hxx \ pqxx/params pqxx/params.hxx \ pqxx/pipeline pqxx/pipeline.hxx \ pqxx/prepared_statement pqxx/prepared_statement.hxx \ pqxx/range pqxx/range.hxx \ pqxx/result pqxx/result.hxx \ pqxx/robusttransaction pqxx/robusttransaction.hxx \ pqxx/separated_list pqxx/separated_list.hxx \ pqxx/strconv pqxx/strconv.hxx \ pqxx/stream_from pqxx/stream_from.hxx \ pqxx/stream_to pqxx/stream_to.hxx \ pqxx/subtransaction pqxx/subtransaction.hxx \ pqxx/time pqxx/time.hxx \ pqxx/transaction pqxx/transaction.hxx \ pqxx/transaction_base pqxx/transaction_base.hxx \ pqxx/transaction_focus pqxx/transaction_focus.hxx \ pqxx/transactor pqxx/transactor.hxx \ pqxx/row pqxx/row.hxx \ pqxx/util pqxx/util.hxx \ pqxx/types pqxx/types.hxx \ pqxx/zview pqxx/zview.hxx \ pqxx/version pqxx/version.hxx \ pqxx/internal/array-composite.hxx \ pqxx/internal/callgate.hxx \ pqxx/internal/connection-string.hxx \ pqxx/internal/conversions.hxx \ pqxx/internal/encodings.hxx \ pqxx/internal/header-pre.hxx \ pqxx/internal/header-post.hxx \ pqxx/internal/ignore-deprecated-post.hxx \ pqxx/internal/ignore-deprecated-pre.hxx \ pqxx/internal/result_iter.hxx \ pqxx/internal/result_iterator.hxx \ pqxx/internal/sql_cursor.hxx \ pqxx/internal/statement_parameters.hxx \ pqxx/internal/stream_iterator.hxx \ pqxx/internal/stream_query.hxx \ pqxx/internal/stream_query_impl.hxx \ pqxx/internal/wait.hxx \ pqxx/internal/gates/connection-errorhandler.hxx \ pqxx/internal/gates/connection-largeobject.hxx \ pqxx/internal/gates/connection-notification_receiver.hxx \ pqxx/internal/gates/connection-pipeline.hxx \ pqxx/internal/gates/connection-sql_cursor.hxx \ pqxx/internal/gates/connection-stream_from.hxx \ pqxx/internal/gates/connection-stream_to.hxx \ pqxx/internal/gates/connection-transaction.hxx \ pqxx/internal/gates/errorhandler-connection.hxx \ pqxx/internal/gates/field_ref-const_row_iterator.hxx \ pqxx/internal/gates/icursor_iterator-icursorstream.hxx \ pqxx/internal/gates/icursorstream-icursor_iterator.hxx \ pqxx/internal/gates/result-connection.hxx \ pqxx/internal/gates/result-creation.hxx \ pqxx/internal/gates/result-field_ref.hxx \ pqxx/internal/gates/result-pipeline.hxx \ pqxx/internal/gates/result-sql_cursor.hxx \ pqxx/internal/gates/row_ref-const_result_iterator.hxx \ pqxx/internal/gates/row_ref-result.hxx \ pqxx/internal/gates/row_ref-row.hxx \ pqxx/internal/gates/transaction-transaction_focus.hxx nobase_nodist_include_HEADERS = pqxx/config.h pqxx/config-compiler.h EXTRA_DIST = \ pqxx/doc/*.md \ pqxx/doc/mainpage.md.template \ pqxx/version.hxx.template all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu include/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_includeHEADERS: $(nobase_include_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(includedir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(includedir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(includedir)/$$dir" || exit $$?; }; \ done uninstall-nobase_includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) install-nobase_nodist_includeHEADERS: $(nobase_nodist_include_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(includedir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(includedir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(includedir)/$$dir" || exit $$?; }; \ done uninstall-nobase_nodist_includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(HEADERS) installdirs: for dir in "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-nobase_includeHEADERS \ install-nobase_nodist_includeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-nobase_includeHEADERS \ uninstall-nobase_nodist_includeHEADERS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool cscopelist-am ctags ctags-am distclean \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man \ install-nobase_includeHEADERS \ install-nobase_nodist_includeHEADERS install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-nobase_includeHEADERS \ uninstall-nobase_nodist_includeHEADERS .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: libpqxx-8.0.1/include/pqxx/000077500000000000000000000000001516427024100156345ustar00rootroot00000000000000libpqxx-8.0.1/include/pqxx/array000066400000000000000000000003271516427024100166770ustar00rootroot00000000000000/** Handling of SQL arrays. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/array.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/array.hxx000066400000000000000000000714571516427024100175210ustar00rootroot00000000000000/* Handling of SQL arrays. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_ARRAY_HXX #define PQXX_ARRAY_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include #include #include #include #include #include #include #include "pqxx/connection.hxx" #include "pqxx/encoding_group.hxx" #include "pqxx/internal/array-composite.hxx" namespace pqxx { // TODO: Specialise for string_view/zview, allocate all strings in one buffer. /// An SQL array received from the database. /** Parses an SQL array from its text format, making it available as a * container of C++-side values. * * The array can have one or more dimensions. You must specify the number of * dimensions at compile time. In each dimension, the array has a size which * the `array` constructor determines at run time based on the SQL array's * textual representation. The sizes of a given SQL array are consistent: if * your array has two dimensions, for example, then it will have one * "horizontal" size which determines the number of elements in each row; and * it will have one "vertical" size which determines the number of rows. * * Physical memory storage is "row-major." This means that the last of the * dimensions represents a row. So in memory, element `a[m][n]` comes right * before `a[m][n+1]`. */ template< not_borrowed ELEMENT, std::size_t DIMENSIONS = 1u, char SEPARATOR = array_separator> class array final { public: /// Parse an SQL array, read as text from a pqxx::result or stream. /** Uses `cx` only during construction, to find out the text encoding in * which it should interpret `data`. * * Once the `array` constructor completes, destroying or moving the * `connection` will not affect the `array` object in any way. * * @throws pqxx::unexpected_null if the array contains a null value, and the * `ELEMENT` type does not support null values. */ array(std::string_view data, connection const &cx, sl loc = sl::current()) : array{data, cx.get_encoding_group(loc), loc} {} array(std::string_view data, encoding_group enc, sl loc = sl::current()) : m_ctx{enc, loc} { using group = encoding_group; switch (enc) { case group::unknown: throw usage_error{ "Tried to parse array without knowing its encoding.", loc}; case group::ascii_safe: parse(data, loc); break; case group::two_tier: parse(data, loc); break; case group::gb18030: parse(data, loc); break; case group::sjis: parse(data, loc); break; // clang-tidy rule bug: // NOLINTNEXTLINE(bugprone-suspicious-semicolon) default: PQXX_UNREACHABLE; break; } } /// The element type of values in this array using value_type = ELEMENT; /// How many dimensions does this array have? /** This value is known at compile time. */ PQXX_PURE static constexpr std::size_t dimensions() noexcept { return DIMENSIONS; } /// What is the separator used for parsing this array's values? /** This value is known at compile time. */ PQXX_PURE [[nodiscard]] static constexpr char separator() noexcept { return SEPARATOR; } /// Return the sizes of this array in each of its dimensions. /** The last of the sizes is the number of elements in a single row. The * size before that is the number of rows of elements, and so on. The first * is the "outer" size. */ PQXX_PURE [[nodiscard]] std::array const & sizes() const noexcept { return m_extents; } template [[nodiscard]] ELEMENT const &at(INDEX... index) const { static_assert(sizeof...(index) == DIMENSIONS); check_bounds(index...); return m_elts.at(locate(index...)); } /// Access element (without bounds check). /** Return element at given index. Blindly assumes that the index lies * within the bounds of the array. This is likely to be slightly faster than * `at()`. * * Multi-dimensional indexing using `operator[]` only works in C++23 or * better. In older versions of C++ it will work only with * single-dimensional arrays. * * @warning This function is marked as "pure." This means that if it fails, * depending on your compiler, the exception may occur in a different place * than you expected. The compiler may even find scenarios where it can * avoid calling this operator, meaning that the exception does not happen at * all. If you need more deterministic exception behaviour, use @ref at(). */ template PQXX_PURE ELEMENT const &operator[](INDEX... index) const { static_assert(sizeof...(index) == DIMENSIONS); // TODO: Use operator[]. But Facebook's "infer" sees a buffer overflow. return m_elts.at(locate(index...)); } /** * @name Array iteration * * There is no "nice" way to iterate over a multi-dimensional array as yet. * Instead, you can iterate over all the elements as if it were a simple, * flat, one-dimensional array. * * If this is a multi-dimensional array, iteration proceeds in row-major * order. So for example, a two-dimensional array `a` would start at * `a[0, 0]`, then `a[0, 1]`, and so on. Once it reaches the end of that * first row, it moves on to element `a[1, 0]`, and continues from there. */ //@{ /// Begin iteration of individual elements. PQXX_PURE [[nodiscard]] constexpr auto cbegin() const noexcept { return m_elts.cbegin(); } /// Return end point of iteration. PQXX_PURE [[nodiscard]] constexpr auto cend() const noexcept { return m_elts.cend(); } /// Begin iteration of individual elements. PQXX_PURE [[nodiscard]] constexpr auto begin() const noexcept { return cbegin(); } /// Return endpoint of iteration. PQXX_PURE [[nodiscard]] constexpr auto end() const noexcept { return cend(); } /// Begin reverse iteration. PQXX_PURE [[nodiscard]] constexpr auto crbegin() const noexcept { return m_elts.crbegin(); } /// Return end point of reverse iteration. PQXX_PURE [[nodiscard]] constexpr auto crend() const noexcept { return m_elts.crend(); } PQXX_PURE [[nodiscard]] constexpr auto rbegin() const noexcept { return crbegin(); } /// Return end point of reverse iteration. PQXX_PURE [[nodiscard]] constexpr auto rend() const noexcept { return crend(); } //@} /// Number of elements in the array. /** This includes all elements, in all dimensions. Therefore it is the * product of all values in `sizes()`. */ [[nodiscard]] constexpr std::size_t size() const noexcept { return m_elts.size(); } /// Number of elements in the array (as a signed number). /** This includes all elements, in all dimensions. Therefore it is the * product of all values in `sizes()`. * * In principle, the size could get so large that it had no signed * equivalent. If that can ever happen, this is your own problem and * behaviour is undefined. * * In practice however, I don't think `ssize()` could ever overflow. You'd * need an array where each element takes up just one byte, such as Booleans, * filling up more than half your address space. But the input string for * that array would need at least two bytes per value: one for the value, one * for the separating comma between elements. So even then you wouldn't have * enough address space to create the array, even if your system allowed you * to use your full address space. */ [[nodiscard]] constexpr auto ssize() const noexcept { return static_cast(size()); } /// Refer to the first element, if any. /** If the array is empty, dereferencing this results in undefined behaviour. */ [[nodiscard]] constexpr auto const &front() const noexcept { return m_elts.front(); } /// Refer to the last element, if any. /** If the array is empty, dereferencing this results in undefined behaviour. */ [[nodiscard]] constexpr auto const &back() const noexcept { return m_elts.back(); } private: /// Throw an error if `data` is not a `DIMENSIONS`-dimensional SQL array. /** Sanity-checks two aspects of the array syntax: the opening braces at the * beginning, and the closing braces at the end. * * One syntax error this does not detect, for efficiency reasons, is for too * many closing braces at the end. That's a tough one to detect without * walking through the entire array sequentially, and identifying all the * character boundaries. The main parsing routine detects that one. */ void check_dims(std::string_view data, sl loc) { auto sz{std::size(data)}; if (sz < DIMENSIONS * 2) throw conversion_error{ std::format( "Trying to parse a {}-dimensional array out of '{}'.", DIMENSIONS, data), loc}; // Making some assumptions here: // * The array holds no extraneous whitespace. // * None of the sub-arrays can be null. // * Only ASCII characters start off with a byte in the 0-127 range. // // Given those, the input must start with a sequence of DIMENSIONS bytes // with the ASCII value for '{'; and likewise it must end with a sequence // of DIMENSIONS bytes with the ASCII value for '}'. if (data.at(0) != '{') throw conversion_error{"Malformed array: does not start with '{'.", loc}; for (std::size_t i{0}; i < DIMENSIONS; ++i) if (data.at(i) != '{') throw conversion_error{ std::format( "Expecting {}-dimensional array, but found {}.", DIMENSIONS, i), loc}; if (data.at(DIMENSIONS) == '{') throw conversion_error{ std::format( "Tried to parse {}-dimensional array from array data that has more " "dimensions.", DIMENSIONS), loc}; for (std::size_t i{0}; i < DIMENSIONS; ++i) if (data.at(sz - 1 - i) != '}') throw conversion_error{ "Malformed array: does not end in the right number of '}'.", loc}; } /// Handle the end of a field. /** Check for a trailing separator, detect any syntax errors at this somewhat * complicated point, and return the offset where parsing should continue. */ [[nodiscard]] std::size_t parse_field_end(std::string_view data, std::size_t here, sl loc) const { auto const sz{std::size(data)}; if (here < sz) switch (data.at(here)) { case SEPARATOR: ++here; if (here >= sz) throw conversion_error{"Array looks truncated.", loc}; switch (data.at(here)) { case SEPARATOR: throw conversion_error{"Array contains double separator.", loc}; case '}': throw conversion_error{"Array contains trailing separator.", loc}; default: break; } break; case '}': break; default: throw conversion_error{ std::format( "Unexpected character in array: {} where separator or closing " "brace expected.", static_cast(static_cast(data.at(here)))), loc}; } return here; } /// Estimate the number of elements in this array. /** We use this to pre-allocate internal storage, so that we don't need to * keep extending it on the fly. It doesn't need to be too precise, so long * as it's fast; doesn't usually underestimate; and never overestimates by * orders of magnitude. */ [[nodiscard]] constexpr std::size_t estimate_elements(std::string_view data) const noexcept { // Dirty trick: just count the number of bytes that look as if they may be // separators. auto const separators{ std::count(std::begin(data), std::end(data), SEPARATOR)}; // The number of dimensions makes no difference here. It's still one // separator between consecutive elements, just possibly with some extra // braces as well. return static_cast(separators + 1); } template void parse(std::string_view data, sl loc) { static_assert(DIMENSIONS > 0u, "Can't create a zero-dimensional array."); conversion_context const c{m_ctx.enc, loc}; auto const sz{std::size(data)}; check_dims(data, loc); m_elts.reserve(estimate_elements(data)); // We discover the array's extents along each of the dimensions, starting // with the final dimension and working our way towards the first. At any // given point during parsing, we know the extents starting at this // dimension. std::size_t know_extents_from{DIMENSIONS}; // Currently parsing this dimension. We start off at -1, relying on C++'s // well-defined rollover for unsigned numbers. // The actual outermost dimension of the array is 0, and the innermost is // at the end. But, the array as a whole is enclosed in braces just like // each row. So we act like there's an anomalous "outer" dimension holding // the entire array. constexpr std::size_t outer{std::size_t{0u} - std::size_t{1u}}; // We start parsing at the fictional outer dimension. The input begins // with opening braces, one for each dimension, so we'll start off by // bumping all the way to the innermost dimension. std::size_t dim{outer}; // Extent counters, one per "real" dimension. // Note initialiser syntax; this zero-initialises all elements. std::array extents{}; // Current parsing position. std::size_t here{0}; PQXX_ASSUME(here <= sz); while (here < sz) { if (data.at(here) == '{') { if (dim == outer) { // This must be the initial opening brace. if (know_extents_from != DIMENSIONS) throw conversion_error{ "Array text representation closed and reopened its outside " "brace pair.", loc}; assert(here == 0); PQXX_ASSUME(here == 0); } else { if (dim >= (DIMENSIONS - 1)) throw conversion_error{ "Array seems to have inconsistent number of dimensions.", loc}; ++extents.at(dim); } // (Rolls over to zero if we're coming from the outer dimension.) ++dim; extents.at(dim) = 0u; ++here; } else if (data.at(here) == '}') { if (dim == outer) throw conversion_error{"Array has spurious '}'.", loc}; if (dim < know_extents_from) { // We just finished parsing our first row in this dimension. // Now we know the array dimension's extent. m_extents.at(dim) = extents.at(dim); know_extents_from = dim; } else { if (extents.at(dim) != m_extents.at(dim)) throw conversion_error{ "Rows in array have inconsistent sizes.", loc}; } // Bump back down to the next-lower dimension. Which may be the outer // dimension, through underflow. --dim; ++here; here = parse_field_end(data, here, loc); } else { // Found an array element. The actual elements always live in the // "inner" dimension. if (dim != DIMENSIONS - 1) throw conversion_error{ "Malformed array: found element where sub-array was expected.", loc}; assert(dim != outer); ++extents.at(dim); std::size_t end{}; switch (data.at(here)) { case '\0': throw conversion_error{"Unexpected zero byte in array.", loc}; case ',': throw conversion_error{"Array contains empty field.", loc}; case '"': { // Double-quoted string. We parse it into a buffer before parsing // the resulting string as an element. This seems wasteful: the // string might not contain any special characters. So it's // tempting to check, and try to use a string_view and avoid a // useless copy step. But. Even besides the branch prediction // risk, the very fact that the back-end chose to quote the string // indicates that there is some kind of special character in there. // So in practice, this optimisation would only apply if the only // special characters in the string were commas. end = pqxx::internal::scan_double_quoted_string(data, here, loc); // TODO: scan_double_quoted_string() with reusable buffer. std::string const buf{ pqxx::internal::parse_double_quoted_string( data.substr(0, end), here, loc)}; m_elts.emplace_back(from_string(buf, c)); } break; default: { // Unquoted string. An unquoted string is always literal, no // escaping or encoding, so we don't need to parse it into a // buffer. We can just read it as a string_view. end = pqxx::internal::scan_unquoted_string( data, here, loc); std::string_view const field{ std::string_view{std::data(data) + here, end - here}}; if (field == "NULL") { if constexpr (has_null()) m_elts.emplace_back(make_null()); else throw unexpected_null{ std::format( "Array contains a null {}. Consider making it an array of " "std::optional<{}> instead.", name_type(), name_type()), loc}; } else m_elts.emplace_back(from_string(field, c)); } } here = end; PQXX_ASSUME(here <= sz); here = parse_field_end(data, here, loc); } } if (dim != outer) throw conversion_error{"Malformed array; may be truncated.", loc}; assert(know_extents_from == 0); PQXX_ASSUME(know_extents_from == 0); init_factors(); } /// Pre-compute indexing factors. void init_factors() noexcept { std::size_t factor{1}; for (std::size_t dim{DIMENSIONS - 1}; dim > 0; --dim) { factor *= m_extents.at(dim); m_factors.at(dim - 1) = factor; } } /// Map a multidimensional index to an entry in our linear storage. template [[nodiscard]] std::size_t locate(INDEX... index) const noexcept { static_assert( sizeof...(index) == DIMENSIONS, "Indexing array with wrong number of dimensions."); return add_index(index...); } template [[nodiscard]] constexpr std::size_t add_index(OUTER outer, INDEX... indexes) const noexcept { std::size_t const first{ check_cast(outer, "array index"sv, m_ctx.loc)}; if constexpr (sizeof...(indexes) == 0) { return first; } else { static_assert(sizeof...(indexes) < DIMENSIONS); // (Offset by 1 here because the outer dimension is not in there.) constexpr auto dimension{DIMENSIONS - (sizeof...(indexes) + 1)}; static_assert(dimension < DIMENSIONS); return first * m_factors.at(dimension) + add_index(indexes...); } } /// Check that indexes are within bounds. /** @throw pqxx::range_error if not. */ template constexpr void check_bounds(OUTER outer, INDEX... indexes) const { std::size_t const first{ check_cast(outer, "array index"sv, m_ctx.loc)}; static_assert(sizeof...(indexes) < DIMENSIONS); // (Offset by 1 here because the outer dimension is not in there.) constexpr auto dimension{DIMENSIONS - (sizeof...(indexes) + 1)}; static_assert(dimension < DIMENSIONS); if (std::cmp_greater_equal(first, m_extents.at(dimension))) throw range_error{ std::format( "Array index for dimension {} is out of bounds: {} >= {}.", dimension, first, m_extents.at(dimension)), m_ctx.loc}; // Now check the rest of the indexes, if any. if constexpr (sizeof...(indexes) > 0) check_bounds(indexes...); } /// Linear storage for the array's elements. std::vector m_elts; /// Size along each dimension. std::array m_extents; /// Multiplication factors for indexing in each dimension. /** This wouldn't make any sense if `locate()` could recurse from the "inner" * dimension towards the "outer" one. Unfortunately we've got to recurse in * the opposite direction, so it helps to pre-compute the factors. * * We don't need to cache a factor for the outer dimension, since we never * multiply by that number. */ std::array m_factors; /// Conversion context representing the construction point. /** It's not always possible to pass a context, e.g. in overloaded operators * or functions that take parameter packs (at least not nicely). In those * situations, we use the construction point. */ conversion_context m_ctx; }; /// String traits for SQL arrays represented as @ref pqxx::array. /** This supports two-way conversion. There is also a more generic conversion * which only knows how to convert _to_ a string. */ template struct string_traits< array>> final { private: using elt_type = std::remove_cvref_t; using elt_traits = string_traits; static constexpr zview s_null{"NULL"}; public: using array_type = array>; static std::string_view to_buf(std::span buf, array_type const &value, ctx c = {}) { auto const len{pqxx::internal::array_into_buf(buf, value, c)}; assert(len > 0); assert(buf[len - 1] == '\0'); return {std::data(buf), len - 1}; } static std::size_t size_buffer(array_type const &value) noexcept { if constexpr (is_unquoted_safe) return 3 + std::accumulate( std::begin(value), std::end(value), std::size_t{}, [](std::size_t acc, elt_type const &elt) { // Budget for each element includes a terminating zero. // We won't actually be wanting those, but don't subtract // that one byte: we want room for a separator instead. // However, std::size(s_null) doesn't account for the // terminating zero, so add one to make s_null pay for its // own separator. return acc + (pqxx::is_null(elt) ? (std::size(s_null) + 1) : elt_traits::size_buffer(elt)); }); else return 3 + std::accumulate( std::begin(value), std::end(value), std::size_t{}, [](std::size_t acc, elt_type const &elt) { // Opening and closing quotes, plus worst-case escaping, // and the one byte for the trailing zero becomes room // for a separator. However, std::size(s_null) doesn't // account for the terminating zero, so add one to make // s_null pay for its own separator. std::size_t const elt_size{ pqxx::is_null(elt) ? (std::size(s_null) + 1) : elt_traits::size_buffer(elt)}; return acc + 2 * elt_size + 2; }); } static array_type from_string(std::string_view text, ctx c = {}) { return array>{ text, c.enc, c.loc}; } }; /// No-null trait for SQL arrays represented as @ref pqxx::array. template struct nullness>> final : no_null>> {}; } // namespace pqxx namespace pqxx::internal { template concept containerlike = requires(CONT con) { CONT{con.begin(), con.end()}; }; template concept nonbinary_container = nonbinary_range and containerlike; } // namespace pqxx::internal namespace pqxx { /// A container of nonbinary data. It has no inherent null value. template struct nullness final : no_null {}; // TODO: Can we support multiple dimensions? /// A container of nonbinary data can represent a 1-dimensional SQL array. /** This does not define a conversion _to_ an SQL string; we leave that to the * `specialisation for nonbinary ranges. */ template struct string_traits final : pqxx::internal::nonbinary_range_traits { [[nodiscard]] static CONT from_string(std::string_view text, ctx c = {}) { using value_type = typename CONT::value_type; using array_type = array; auto const arr = pqxx::from_string(text, c); return CONT{arr.cbegin(), arr.cend()}; } }; /// Low-level parser for C++ arrays. @deprecated Use @ref pqxx::array instead. /** Clunky old API for parsing SQL arrays. * * @warning This parser will only work reliably if your client encoding is * UTF-8, ASCII, or a "safe ASCII superset" (such as the EUC encodings) where * a byte value in the ASCII range can only occur as an actual ASCII character, * never as one byte in a multi-byte character. * * @warning The parser only supports array element types which use a comma * (`','`) as the separator between array elements. All built-in SQL types use * comma, except for `box` which uses semicolon. However some custom types may * not work. * * The input is a C-style string containing the textual representation of an * array, as returned by the database. The parser reads this representation * on the fly. The string must remain in memory until parsing is done. * * Parse the array by making calls to @ref get_next until it returns a * @ref juncture of `done`. The @ref juncture tells you what the parser found * in that step: did the array "nest" to a deeper level, or "un-nest" back up? */ class PQXX_LIBEXPORT array_parser final { public: /// What's the latest thing found in the array? enum class juncture { /// Starting a new row. row_start, /// Ending the current row. row_end, /// Found a NULL value. null_value, /// Found a string value. string_value, /// Parsing has completed. done, }; /// Constructor. You don't need this; use @ref field::as_array instead. /** The parser only remains valid while the data underlying the @ref result * remains valid. Once all `result` objects referring to that data have been * destroyed, the parser will no longer refer to valid memory. */ [[deprecated("Use pqxx::array instead.")]] explicit array_parser( std::string_view input, encoding_group = encoding_group::ascii_safe); /// Parse the next step in the array. /** Returns what it found. If the juncture is @ref juncture::string_value, * the string will contain the value. Otherwise, it will be empty. * * Call this until the @ref array_parser::juncture it returns is * @ref juncture::done. */ std::pair get_next(sl loc = sl::current()) { return (this->*m_impl)(loc); } private: std::string_view m_input; /// Current parsing position in the input. std::size_t m_pos = 0u; /// A function implementing the guts of `get_next`. /** Internally this class uses a template to specialise the implementation of * `get_next` for each of the various encoding groups. This allows the * compiler to inline the parsing of each text encoding, which happens in * very hot loops. */ using implementation = std::pair (array_parser::*)(sl); /// Pick the `implementation` for `enc`. static implementation specialize_for_encoding(encoding_group enc, sl loc); /// Our implementation of `parse_array_step`, specialised for our encoding. implementation m_impl; /// Perform one step of array parsing. template std::pair parse_array_step(sl loc); template [[nodiscard]] std::size_t scan_double_quoted_string(sl loc) const; template [[nodiscard]] std::string parse_double_quoted_string(std::size_t end, sl loc) const; template [[nodiscard]] std::size_t scan_unquoted_string(sl loc) const; template [[nodiscard]] std::string_view parse_unquoted_string(std::size_t end, sl loc) const; }; } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/blob000066400000000000000000000003361516427024100164770ustar00rootroot00000000000000/** Binary Large Objects interface. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/blob.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/blob.hxx000066400000000000000000000247231516427024100173130ustar00rootroot00000000000000/* Binary Large Objects interface. * * Read or write large objects, stored in their own storage on the server. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_BLOB_HXX #define PQXX_BLOB_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include #include #include "pqxx/dbtransaction.hxx" namespace pqxx { /** Binary large object. * * This is how you store data that may be too large for the `BYTEA` type. * Access operations are similar to those for a file: you can read, write, * query or set the current reading/writing position, and so on. * * These large objects live in their own storage on the server, indexed by an * integer object identifier ("oid"). * * Two `blob` objects may refer to the same actual large object in the * database at the same time. Each will have its own reading/writing position, * but writes to the one will of course affect what the other sees. */ class PQXX_LIBEXPORT blob final { public: /// Create a new, empty large object. /** You may optionally specify an oid for the new blob. If you do, then * the new object will have that oid -- or creation will fail if there * already is an object with that oid. */ [[nodiscard]] static oid create(dbtransaction &, oid = 0, sl = sl::current()); /// Delete a large object, or fail if it does not exist. static void remove(dbtransaction &, oid, sl = sl::current()); /// Open blob for reading. Any attempt to write to it will fail. [[nodiscard]] static blob open_r(dbtransaction &, oid, sl = sl::current()); // Open blob for writing. Any attempt to read from it will fail. [[nodiscard]] static blob open_w(dbtransaction &, oid, sl = sl::current()); // Open blob for reading and/or writing. [[nodiscard]] static blob open_rw(dbtransaction &, oid, sl = sl::current()); /// You can default-construct a blob, but it won't do anything useful. /** Most operations on a default-constructed blob will throw @ref * usage_error. */ blob() = default; /// You can move a blob, but not copy it. The original becomes unusable. blob(blob &&); /// You can move a blob, but not copy it. The original becomes unusable. blob &operator=(blob &&); blob(blob const &) = delete; blob &operator=(blob const &) = delete; ~blob(); /// Maximum number of bytes that can be read or written at a time. /** The underlying protocol only supports reads and writes up to 2 GB * exclusive. * * If you need to read or write more data to or from a binary large object, * you'll have to break it up into chunks. */ static constexpr std::size_t chunk_limit = 0x7fffffff; /// Read up to `size` bytes of the object into `buf`. /** Uses a buffer that you provide, resizing it as needed. If it suits you, * this lets you allocate the buffer once and then re-use it multiple times. * * Resizes `buf` as needed. * * @warning The underlying protocol only supports reads up to 2GB at a time. * If you need to read more, try making repeated calls to @ref append_to_buf. */ std::size_t read(bytes &buf, std::size_t size, sl = sl::current()); /// Read up to `std::size(buf)` bytes from the object. /** Retrieves bytes from the blob, at the current position, until `buf` is * full or there are no more bytes to read, whichever comes first. * * Returns the filled portion of `buf`. This may be empty. */ template writable_bytes_view read(std::span buf, sl loc = sl::current()) { return buf.first(raw_read(std::data(buf), std::size(buf), loc)); } /// Read up to `std::size(buf)` bytes from the object. /** Retrieves bytes from the blob, at the current position, until `buf` is * full or there are no more bytes to read, whichever comes first. * * Returns the filled portion of `buf`. This may be empty. */ template writable_bytes_view read(DATA &buf, sl loc = sl::current()) { return {std::data(buf), raw_read(std::data(buf), std::size(buf), loc)}; } /// Write `data` to large object, at the current position. /** If the writing position is at the end of the object, this will append * `data` to the object's contents and move the writing position so that * it's still at the end. * * If the writing position was not at the end, writing will overwrite the * prior data, but it will not remove data that follows the part where you * wrote your new data. * * @warning This is a big difference from writing to a file. You can * overwrite some data in a large object, but this does not truncate the * data that was already there. For example, if the object contained binary * data "abc", and you write "12" at the starting position, the object will * contain "12c". * * @warning The underlying protocol only supports writes up to 2 GB at a * time. If you need to write more, try making repeated calls to * @ref append_from_buf. */ template void write(DATA const &data, sl loc = sl::current()) { return raw_write(binary_cast(data), loc); } /// Resize large object to `size` bytes. /** If the blob is more than `size` bytes long, this removes the end so as * to make the blob the desired length. * * If the blob is less than `size` bytes long, it adds enough zero bytes to * make it the desired length. */ void resize(std::int64_t size, sl = sl::current()); /// Return the current reading/writing position in the large object. [[nodiscard]] std::int64_t tell(sl = sl::current()) const; /// Set the current reading/writing position to an absolute offset. /** Returns the new file offset. */ std::int64_t seek_abs(std::int64_t offset = 0, sl = sl::current()); /// Move the current reading/writing position forwards by an offset. /** To move backwards, pass a negative offset. * * Returns the new file offset. */ std::int64_t seek_rel(std::int64_t offset = 0, sl = sl::current()); /// Set the current position to an offset relative to the end of the blob. /** You'll probably want an offset of zero or less. * * Returns the new file offset. */ std::int64_t seek_end(std::int64_t offset = 0, sl = sl::current()); /// Create a binary large object containing given `data`. /** You may optionally specify an oid for the new object. If you do, and an * object with that oid already exists, creation will fail. */ static oid from_buf(dbtransaction &tx, bytes_view data, oid id = 0, sl = sl::current()); /// Create a binary large object containing given `data`. /** You may optionally specify an oid for the new object. If you do, and an * object with that oid already exists, creation will fail. */ template static oid from_buf( dbtransaction &tx, DATA const &data, oid id = 0, sl loc = sl::current()) { return from_buf(tx, binary_cast(data), id, loc); } /// Append `data` to binary large object. /** The underlying protocol only supports appending blocks up to 2 GB. */ static void append_from_buf( dbtransaction &tx, bytes_view data, oid id, sl = sl::current()); /// Append `data` to binary large object. /** The underlying protocol only supports appending blocks up to 2 GB. */ template static void append_from_buf( dbtransaction &tx, DATA const &data, oid id, sl loc = sl::current()) { append_from_buf(tx, binary_cast(data), id, loc); } /// Read client-side file and store it server-side as a binary large object. [[nodiscard]] static oid from_file(dbtransaction &, zview path, sl = sl::current()); /// Read client-side file and store it server-side as a binary large object. /** In this version, you specify the binary large object's oid. If that oid * is already in use, the operation will fail. */ static oid from_file(dbtransaction &, zview path, oid, sl = sl::current()); /// Convenience function: Read up to `max_size` bytes from blob with `id`. /** You could easily do this yourself using the @ref open_r and @ref read * functions, but it can save you a bit of code to do it this way. */ static void to_buf( dbtransaction &, oid, bytes &, std::size_t max_size, sl = sl::current()); /// Read part of the binary large object with `id`, and append it to `buf`. /** Use this to break up a large read from one binary large object into one * massive buffer. Just keep calling this function until it returns zero. * * The `offset` is how far into the large object your desired chunk is, and * `append_max` says how much to try and read in one go. */ static std::size_t append_to_buf( dbtransaction &tx, oid id, std::int64_t offset, bytes &buf, std::size_t append_max, sl = sl::current()); /// Write a binary large object's contents to a client-side file. static void to_file(dbtransaction &, oid, zview path, sl = sl::current()); /// Close this blob. /** This does not delete the blob from the database; it only terminates your * local object for accessing the blob. * * Resets the blob to a useless state similar to one that was * default-constructed. * * The destructor will do this for you automatically. Still, there is a * reason to `close()` objects explicitly where possible: if an error should * occur while closing, `close()` can throw an exception. A destructor * cannot. */ void close(); private: PQXX_PRIVATE blob(connection &cx, int fd) noexcept : m_conn{&cx}, m_fd{fd} {} static blob open_internal(dbtransaction &, oid, int, sl); PQXX_PRIVATE PQXX_PURE static pqxx::internal::pq::PGconn * raw_conn(pqxx::connection *) noexcept; PQXX_PRIVATE PQXX_PURE static pqxx::internal::pq::PGconn * raw_conn(pqxx::dbtransaction const &) noexcept; PQXX_PRIVATE static std::string errmsg(connection const *); PQXX_PRIVATE static std::string errmsg(dbtransaction const &tx) { return errmsg(&tx.conn()); } PQXX_PRIVATE [[nodiscard]] std::string errmsg() const { return errmsg(m_conn); } PQXX_PRIVATE std::int64_t seek(std::int64_t offset, int whence, sl); std::size_t raw_read(std::byte buf[], std::size_t size, sl); void raw_write(bytes_view, sl); connection *m_conn = nullptr; int m_fd = -1; }; } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/composite000066400000000000000000000003501516427024100175570ustar00rootroot00000000000000/** Handling of SQL "composite types." */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/composite.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/composite.hxx000066400000000000000000000117141516427024100203730ustar00rootroot00000000000000#ifndef PQXX_COMPOSITE_HXX #define PQXX_COMPOSITE_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include "pqxx/internal/array-composite.hxx" #include "pqxx/util.hxx" namespace pqxx { /// Parse a string representation of a value of a composite type. /** @warning This code is still experimental. Use with care. * * You may use this as a helper while implementing your own @ref string_traits * for a composite type. * * This function interprets `text` as the string representation of a value of * some composite type, and sets each of `fields` to the respective values of * its fields. The field types must be copy-assignable. * * The number of fields must match the number of fields in the composite type, * and there must not be any other text in the input. The function is meant to * handle any value string that the backend can produce, but not necessarily * every valid alternative spelling. * * Fields in composite types can be null. When this happens, the C++ type of * the corresponding field reference must be of a type that can handle nulls. * If you are working with a type that does not have an inherent null value, * such as e.g. `int`, consider using `std::optional`. */ template inline void parse_composite(ctx c, std::string_view text, T &...fields) { static constexpr auto num_fields{sizeof...(T)}; static_assert(num_fields > 0); auto const data{std::data(text)}; auto const size{std::size(text)}; if (size == 0) throw conversion_error{ "Cannot parse composite value from empty string.", c.loc}; if (data[0] != '(') throw conversion_error{ std::format("Invalid composite value string: '{}'.", text), c.loc}; // clang-tidy rule bug: // NOLINTBEGIN(misc-const-correctness) std::size_t here{1}; std::size_t index{0}; // NOLINTEND(misc-const-correctness) (pqxx::internal::specialize_parse_composite_field(c)( index, text, here, fields, num_fields - 1, c.loc), ...); if (here != std::size(text)) throw conversion_error{ std::format( "Composite value did not end at the closing parenthesis: '{}'.", text), c.loc}; if (text[here - 1] != ')') throw conversion_error{ std::format("Composite value did not end in parenthesis: '{}'.", text), c.loc}; } } // namespace pqxx namespace pqxx::internal { constexpr char empty_composite_str[]{"()"}; } // namespace pqxx::internal namespace pqxx { /// Estimate the buffer size needed to represent a value of a composite type. /** Returns a conservative estimate. */ template [[nodiscard]] inline std::size_t composite_size_buffer(T const &...fields) noexcept { constexpr auto num{sizeof...(fields)}; // Size for a multi-field composite includes room for... // + opening parenthesis // + field budgets // + separating comma per field // - comma after final field // + closing parenthesis // + terminating zero if constexpr (num == 0) return std::size(pqxx::internal::empty_composite_str); else return 1 + (pqxx::internal::size_composite_field_buffer(fields) + ...) + num + 1; } /// Render a series of values as a single composite SQL value. /** You may use this as a helper while implementing your own `string_traits` * for a composite type. * * @param loc An `std::source_location`, so that any error messages can report * this as the place where the error occurred. This is probably more useful to * you than a location inside this function itself. * * After writing the composite's text representation to `buf`, this will append * a terminating zero. This facilitates usage where the resulting SQL string * gets passed in as a query parameter. */ template inline zview composite_into_buf(ctx c, std::span buf, T const &...fields) { if (std::size(buf) < composite_size_buffer(fields...)) throw conversion_error{ "Buffer space may not be enough to represent composite value.", c.loc}; constexpr auto num_fields{sizeof...(fields)}; if constexpr (num_fields == 0) { constexpr std::string_view empty{"()"}; return zview{ std::data(buf), pqxx::internal::copy_chars(empty, buf, 0, c.loc) - 1}; } std::size_t pos{0}; // C++26: Use buf.at(). buf[pos++] = '('; (pqxx::internal::write_composite_field(buf, pos, fields, c), ...); // If we've got multiple fields, "backspace" that last comma. if constexpr (num_fields > 1) --pos; // C++26: Use buf.at(). buf[pos++] = ')'; buf[pos] = '\0'; return zview{std::data(buf), pos}; } /// Render a series of values as a single composite SQL value. template [[deprecated( "Pass conversion_context and std::span, not two pointers.")]] inline char *composite_into_buf(char *begin, char *end, T const &...fields) { auto const text{composite_into_buf( {sl::current()}, std::span{begin, end}, fields...)}; return begin + std::size(text); } } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/config.h.in000066400000000000000000000037561516427024100176720ustar00rootroot00000000000000/* include/pqxx/config.h.in. Generated from configure.ac by autoheader. */ /* define if the compiler supports basic C++20 syntax */ #undef HAVE_CXX20 /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the `pq' library (-lpq). */ #undef HAVE_LIBPQ /* Define to the sub-directory where libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define if this feature is available. */ #undef PQXX_HAVE_ASSUME /* Define if this feature is available. */ #undef PQXX_HAVE_CHARCONV_FLOAT /* Define if this feature is available. */ #undef PQXX_HAVE_CXA_DEMANGLE /* Define if this feature is available. */ #undef PQXX_HAVE_GCC_PURE /* Define if this feature is available. */ #undef PQXX_HAVE_GCC_VISIBILITY /* Define if this feature is available. */ #undef PQXX_HAVE_MULTIDIM /* Define if this feature is available. */ #undef PQXX_HAVE_POLL /* Define if this feature is available. */ #undef PQXX_HAVE_RANGES /* Define if this feature is available. */ #undef PQXX_HAVE_SLEEP_FOR /* Define if std::stacktrace works. */ #undef PQXX_HAVE_STACKTRACE /* Define if this feature is available. */ #undef PQXX_HAVE_STRERROR_R /* Define if this feature is available. */ #undef PQXX_HAVE_STRERROR_S /* Define if this feature is available. */ #undef PQXX_HAVE_TYPE_DISPLAY /* Define if this feature is available. */ #undef PQXX_HAVE_YEAR_MONTH_DAY /* Define if this feature is available. */ #undef PQXX_HAVE_ZARGS /* Version number of package */ #undef VERSION libpqxx-8.0.1/include/pqxx/connection000066400000000000000000000004341516427024100177170ustar00rootroot00000000000000/** pqxx::connection class. * * pqxx::connection encapsulates a connection to a database. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/connection.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/connection.hxx000066400000000000000000002027621516427024100205350ustar00rootroot00000000000000/* Definition of the connection class. * * pqxx::connection encapsulates a connection to a database. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/connection instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_CONNECTION_HXX #define PQXX_CONNECTION_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "pqxx/errorhandler.hxx" #include "pqxx/except.hxx" #include "pqxx/internal/connection-string.hxx" #include "pqxx/params.hxx" #include "pqxx/result.hxx" #include "pqxx/separated_list.hxx" #include "pqxx/strconv.hxx" #include "pqxx/types.hxx" #include "pqxx/util.hxx" #include "pqxx/zview.hxx" /** * @addtogroup connections * * Use of the libpqxx library starts here. * * Everything that can be done with a database through libpqxx must go through * a @ref pqxx::connection object. It connects to a database when you create * it, and it terminates that communication during destruction. * * Many things come together in this class. For example, if you want custom * handling of error andwarning messages, you control that in the context of a * connection. You also define prepared statements here. For actually * executing SQL, however, you'll also need a transaction object which operates * "on top of" the connection. (See @ref transactions for more about these.) * * When you connect to a database, you pass a connection string containing any * parameters and options, such as the server address and the database name. * * These are identical to the ones in libpq, the C language binding upon which * libpqxx itself is built: * * https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING * * There are also environment variables you can set to provide defaults, again * as defined by libpq: * * https://www.postgresql.org/docs/current/libpq-envars.html * * You can also create a database connection _asynchronously_ using an * intermediate @ref pqxx::connecting object. */ namespace pqxx::internal { class sql_cursor; /// Control OpenSSL/crypto library initialisation. /** This is an internal helper. Unless you're working on libpqxx itself, use * @ref pqxx::skip_init_ssl instead. * * @param flags a bitmask of `1 << flag` for each of the `skip_init` flags. * * Ignores the `skip_init::nothing` flag. */ PQXX_COLD PQXX_LIBEXPORT void skip_init_ssl(int skips) noexcept; } // namespace pqxx::internal namespace pqxx::internal::gate { class connection_dbtransaction; class connection_errorhandler; class connection_largeobject; class connection_notification_receiver; class connection_pipeline; class connection_sql_cursor; class connection_stream_from; class connection_stream_to; class connection_transaction; class const_connection_largeobject; } // namespace pqxx::internal::gate namespace pqxx { /// Concept: T is a range of pairs of zero-terminated strings. /** For example, this could be a `std::map`, or a * `std::vector`, or a * `std::array, 10>`, etc. * * The pairs have to be recognisable as pairs _at compile time._ It's not * enough to pass a container of `std::vector` and ensure at run time that they * each contain 2 elements. */ template concept ZKey_ZValues = std::ranges::input_range and requires(T t) { { std::get<0>(*std::cbegin(t)) } -> ZString; { std::get<1>(*std::cbegin(t)) } -> ZString; requires( std::tuple_size_v> == 2u); }; /// An incoming notification. /** PostgreSQL extends SQL with a "message bus" using the `LISTEN` and `NOTIFY` * commands. In libpqxx you use @ref connection::listen() and (optionally) * @ref transaction_base::notify(). * * When you receive a notification for which you have been listening, your * handler receives it in the form of a `notification` object. * * @warning These structs are meant for extremely short lifespans: the fields * reference memory that may become invalid as soon as your handler has been * called. */ struct notification final { // NOLINTBEGIN(cppcoreguidelines-avoid-const-or-ref-data-members) /// The connection which received the notification. /** There will be no _backend_ transaction active on the connection when your * handler gets called, but there may be a @ref nontransaction. (This is a * special transaction type in libpqxx which does not start a transaction on * the backend.) */ connection &conn; // NOLINTEND(cppcoreguidelines-avoid-const-or-ref-data-members) /// Channel name. /** The notification logic will only pass the notification to a handler which * was registered to listen on this exact name. */ zview channel; /// Optional payload text. /** If the notification did not carry a payload, the string will be empty. */ zview payload; /// Process ID of the backend that sent the notification. /** This can be useful in situations where a multiple clients are listening * on the same channel, and also send notifications on it. * * In those situations, it often makes sense for a client to ignore its own * incoming notifications, but handle all others on the same channel in some * way. * * To check for that, compare this process ID to the return value of the * connection's `backendpid()`. */ int backend_pid = 0; }; /// Flags for skipping initialisation of SSL-related libraries. /** When a running process makes its first SSL connection to a database through * libpqxx, libpq automatically initialises the OpenSSL and libcrypto * libraries. But there are scenarios in which you may want to suppress that. * * This enum is a way to express this. Pass values of this enum to * @ref pqxx::skip_init_ssl as template arguments. */ enum skip_init : int { /// A do-nothing flag that does not affect anything. nothing, /// Skip initialisation of OpenSSL library. openssl, /// Skip initialisation of libcrypto. crypto, }; /// Control initialisation of OpenSSL and libcrypto libraries. /** By default, libpq initialises the openssl and libcrypto libraries when your * process first opens an SSL connection to a database. But this may not be * what you want: perhaps your application (or some other library it uses) * already initialises one or both of these libraries. * * Call this function to stop libpq from initialising one or the other of * these. Pass as arguments each of the `skip_init` flags for which of the * libraries whose initialisation you want to prevent. * * @warning Each call to this function _overwrites_ the effects of any previous * call. So if you make one call to skip OpenSSL initialisation, and then * another to skip libcrypto initialisation, the first call will do nothing. * * Examples: * * To let libpq initialise libcrypto but not OpenSSL: * `skip_init_ssl();` * * To let libpq know that it should not initialise either: * ```cxx * skip_init_ssl(); * ``` * * To say explicitly that you want libpq to initialise both: * `skip_init_ssl();` */ template inline void skip_init_ssl() noexcept { // (Normalise skip flags to one per.) pqxx::internal::skip_init_ssl(((1 << SKIP) | ...)); } /// Representation of a PostgreSQL table path. /** A "table path" consists of a table name, optionally prefixed by a schema * name, which in turn is optionally prefixed by a database name. * * A minimal example of a table path would be `{mytable}`. But a table path * may also take the forms `{myschema,mytable}` or * `{mydb,myschema,mytable}`. */ using table_path = std::initializer_list; /// Error verbosity levels. enum class error_verbosity : int { // These values must match those in libpq's PGVerbosity enum. terse = 0, normal = 1, verbose = 2 }; /// Connection to a database. /** This is the first class to look at when you wish to work with a database * through libpqxx. As per RAII principles, the connection opens during * construction, and closes upon destruction. * * To query or manipulate the database once connected, use one of the * _transaction_ classes. Their API is defined in @ref pqxx::transaction_base. * * When a connection breaks, or fails to establish itself in the first place, * you will typically get a @ref broken_connection exception. In some cases * when a physical network connection disappears, it can take minutes before * this happens, as various layers of software try to reconnect. * * @warning On Unix-like systems, including GNU and BSD systems, your program * may receive the SIGPIPE signal when the connection to the backend breaks. * By default this signal will abort your program. Use * `signal(SIGPIPE, SIG_IGN)` if you want your program to continue running * after a connection fails. */ class PQXX_LIBEXPORT connection final { public: /** * @name Connecting to a database * * You connect to a database by creating a `connection` object. (Except * advanced users can also connect asynchronously using the @ref connecting * class; in that case creating the `connection` is only the beginning. In * the normal case, however, creating a `connection` and connecting to a * database are the same thing.) * * If the attempt to connect fails, you will not get a @ref connection * object; the constructor will fail with a @ref pqxx::broken_connection * exception. * * You can control each of the details of how to connect (hostname, username, * database name, etc.) in up to 4 ways. All are optional, and you can * combine some or all of them: * * 1. You can pass _connection parameters_ to the constructor. * 2. You can pass a _connection string_ to the constructor. * 3. There are environment variables you can set: `PGHOST`, `PGUSER`, etc. * 4. Each has a built-in _default value._ * * For each individual item, the connection will take the value from the * first item in this list that defines it. * * @note All of the strings that you pass into the constructor must be * _zero-terminated,_ i.e. they must end in a byte with value zero, like * classic C-style strings. That's because libpqxx passes them on to the * underlying C library, libpq. A C++ `std::string` is guaranteed to have a * terminating zero, so that's fine. However a `std::string_view` does not, * and that's why libpqxx has @ref pqxx::zview. A `zview` is like a * `std::string_view` except you promise that there's a terminating zero. * * _Connection parameters_ are individual key/value pairs of strings. You * can pass these as a `std::map`, or as a `std::vector` of `std::pair`, or * in pretty much any other form that boils down to "a series of pairs of * zero-terminated strings." If you pass the same parameter multiple times * with different values in the same series of parameters, the latest value * applies. * * The connection parameters are documented here: * * https://postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS * * _Connection strings_ can be in one of two formats: a custom key-value * format, or a RFC 3986 Uniform Resource Identifier (URI). They are * documented here: * * https://postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING * * _Environment variables_ for controlling how you connect are documented * here: * * https://postgresql.org/docs/current/libpq-envars.html */ //@{ explicit connection(sl loc = sl::current()) : connection("", empty_params_t(), loc) {} /// Connect to a database with both connection string and parameter pairs. /** If a parameter is defined both in `connection_string` and in `params`, * the value in `params` takes hold. * * If a parameter is defined more than once in `params`, the last definition * takes hold. */ template explicit inline connection( STRING const &connection_string, MAPPING &¶ms = empty_params_t(), sl = sl::current()); /// Connect to a database, passing a connection string. /** If a parameter is defined both in `connection_string` and in `params`, * the value in `params` takes hold. * * If a parameter is defined more than once in `params`, the last definition * takes hold. */ template explicit connection( STRING const &connection_string, sl loc = sl::current()) : connection{connection_string, empty_params_t(), loc} {} /// Connect to a database, passing connection parameters. template explicit connection(MAPPING &¶ms, sl loc = sl::current()) : connection{"", params, loc} {} //@} /// Move constructor. /** Moving a connection is not allowed if it has an open transaction, or has * error handlers or is listening for notifications. In those situations, * other objects may hold references to the old object which would become * invalid and might produce hard-to-diagnose bugs. */ connection(connection &&rhs, sl = sl::current()); ~connection() { try { close(m_created_loc); } catch (std::exception const &) { // TODO: Try to report the error. } } // TODO: Once we drop notification_receiver/errorhandler, move is easier. /// Move assignment. /** Neither connection can have an open transaction, `errorhandler`, or * `notification_receiver`. * * If libpqxx needs to throw an exception during this operation, its error * message will state the `std::source_location` not for where you call it, * since there is no way to pass a `std::source_location` parameter in the * assignment operator. Instead, it will report the location where the * current connection was _created._ */ connection &operator=(connection &&rhs); connection(connection const &) = delete; connection &operator=(connection const &) = delete; /// Is this connection open at the moment? /** @warning Most code does **not** need this function. Resist the * temptation to check your connection after opening it: if the connection * attempt failed, the constructor will never even return, throwing a * @ref broken_connection exception instead. */ [[nodiscard]] bool is_open() const noexcept; /// Invoke notice processor function. The message should end in newline. PQXX_ZARGS void process_notice(char const[]) noexcept; /// Invoke notice processor function. Newline at end is recommended. /** The zview variant, with a message ending in newline, is the most * efficient way to call process_notice. */ void process_notice(zview) noexcept; /// Enable tracing to a given output stream, or nullptr to disable. void trace(std::FILE *) noexcept; /** * @name Connection properties * * These are probably not of great interest, since most are derived from * information supplied by the client program itself, but they are included * for completeness. * * The connection needs to be currently active for these to work. */ //@{ /// Name of the database to which we're connected, if any. /** Returns nullptr when not connected. */ [[nodiscard]] char const *dbname() const noexcept; /// Database user ID under which we are connected, if any. /** Returns nullptr when not connected. */ [[nodiscard]] char const *username() const noexcept; /// Database server address, if given. /** This may be an IP address, or a hostname, or (for a Unix domain socket) * a socket path. Returns nullptr when not connected. */ [[nodiscard]] PQXX_PURE char const *hostname() const noexcept; /// Server port number on which we are connected to the database. [[nodiscard, deprecated("Use port_number().")]] PQXX_PURE char const * port() const noexcept; /// Server port number on which we are connected to the database, if any. [[nodiscard]] PQXX_PURE std::optional port_number(sl loc = sl::current()) const; /// Process ID for backend process, or 0 if inactive. [[nodiscard]] PQXX_PURE int backendpid() const & noexcept; /// Socket currently used for connection, or -1 for none. /** Query the current socket number. This is intended for event loops based * on functions such as select() or poll(), where you're waiting for any of * multiple file descriptors to become ready for communication. * * Please try to stay away from this function. It is really only meant for * event loops that need to wait on more than one file descriptor. If all * you need is to block until a notification arrives, for instance, use * await_notification(). If you want to issue queries and retrieve results * in nonblocking fashion, check out the pipeline class. */ [[nodiscard]] PQXX_PURE int sock() const & noexcept; /// What version of the PostgreSQL protocol is this connection using? /** The answer can be 0 (when there is no connection); 3 for protocol 3.0; or * possibly higher values as newer protocol versions come into use. */ [[nodiscard]] PQXX_PURE int protocol_version() const noexcept; /// What version of the PostgreSQL server are we connected to? /** The result is a bit complicated: each of the major, medium, and minor * release numbers is written as a two-digit decimal number, and the three * are then concatenated. Thus server version 9.4.2 will be returned as the * decimal number 90402. If there is no connection to the server, this * returns zero. * * @warning When writing version numbers in your code, don't add zero at the * beginning! Numbers beginning with zero are interpreted as octal (base-8) * in C++. Thus, 070402 is not the same as 70402, and 080000 is not a number * at all because there is no digit "8" in octal notation. Use strictly * decimal notation when it comes to these version numbers. */ [[nodiscard]] PQXX_PURE int server_version() const noexcept; //@} /// @name Text encoding /** * Each connection is governed by a "client encoding," which dictates how * strings and other text is represented in bytes. The database server will * send text data to you in this encoding, and you should use it for the * queries and data which you send to the server. * * Search the PostgreSQL documentation for "character set encodings" to find * out more about the available encodings, how to extend them, and how to use * them. Not all server-side encodings are compatible with all client-side * encodings or vice versa. * * Encoding names are case-insensitive, so e.g. "UTF8" is equivalent to * "utf8". * * You can change the client encoding, but this may not work when the * connection is in a special state, such as when streaming a table. It's * not clear what happens if you change the encoding during a transaction, * and then abort the transaction. */ //@{ /// Get client-side character encoding, by name. [[nodiscard]] std::string get_client_encoding(sl loc = sl::current()) const; /// Set client-side character encoding, by name. /** * @param encoding Name of the character set encoding to use. */ void set_client_encoding(zview encoding, sl loc = sl::current()) & { set_client_encoding(encoding.c_str(), loc); } /// Set client-side character encoding, by name. /** * @param encoding Name of the character set encoding to use. */ PQXX_ZARGS void set_client_encoding(char const encoding[], sl = sl::current()) &; /// Get the connection's encoding, as a PostgreSQL-defined code. [[nodiscard]] int encoding_id(sl = sl::current()) const; /// Read the curent client encoding's @ref pqxx::encoding_group. [[nodiscard]] encoding_group get_encoding_group(sl loc = sl::current()) const { return pqxx::internal::enc_group(this->encoding_id(loc), loc); } //@} /// Set one of the session variables to a new value. /** This executes SQL, so do not do it while a pipeline or stream is active * on the connection. * * The value you set here will last for the rest of the connection's * duration, or until you set a new value. * * If you set the value while in a @ref dbtransaction (i.e. any transaction * that is not a @ref nontransaction), then rolling back the transaction will * undo the change. * * All applies to setting _session_ variables. You can also set the same * variables as _local_ variables, in which case they will always revert to * their previous value when the transaction ends (or when you overwrite them * of course). To set a local variable, simply execute an SQL statement * along the lines of "`SET LOCAL var = 'value'`" inside your transaction. * * @param var The variable to set. * @param value The new value for the variable. * @throw @ref variable_set_to_null if the value is null; this is not * allowed. */ template void set_session_var( std::string_view var, TYPE const &value, sl loc = sl::current()) & { if constexpr (has_null()) { if (is_null(value)) throw variable_set_to_null{ std::format("Attempted to set variable {} to null.", var), loc}; } exec(std::format("SET {}={}", quote_name(var), quote(value, loc)), loc); } /// Read currently applicable value of a configuration variable. /** This function executes an SQL statement, so it won't work while a * @ref pipeline, query stream, or other object derived from * @ref transaction_focus is active on the connection. * * @return The variable's current string value (which may be empty). */ std::string get_var(std::string_view var, sl loc = sl::current()); /// Read currently applicable value of a configuration variable. /** This function executes an SQL statement, so it won't work while a * @ref pipeline, query stream, or other object derived from * @ref transaction_focus is active on the connection. * * @warning The connection does not store the underlying string anywhere. * So if you try to read the variable as a `std::string_view`, a `std::span`, * a @ref pqxx::zview, or anything like that... the string value will no * longer be valid by the time you receive it! If you want to read the * variable as a string value, use `std::string`. */ template TYPE get_var_as(std::string_view var, sl loc = sl::current()) { conversion_context const c{get_encoding_group(), loc}; return from_string(get_var(var, loc), c); } /** * @name Notifications and Receivers * * This is PostgreSQL-specific extension that goes beyond standard SQL. It's * a communications mechanism between clients on a database, akin to a * transactional message bus. * * A notification happens on a _channel,_ identified by a name. You can set * a connection to _listen_ for notifications on the channel, using the * connection's @ref listen() function. (Internally this will issue a * `LISTEN` SQL command). Any client on the database can send a * notification on that channel by executing a `NOTIFY` SQL command. The * transaction classes implement a convenience function for this, called * @ref transaction_base::notify(). * * Notifications can carry an optional _payload_ string. This is free-form * text which carries additional information to the receiver. * * @warning There are a few pitfalls with the channel names: case sensitivity * and encodings. They are not too hard to avoid, but the safest thing to do * is use only lower-case ASCII names. * * * ### Case sensitivity * * Channel names are _case-sensitive._ By default, however, PostgreSQL does * convert the channel name in a `NOTIFY` or `LISTEN` command to lower-case, * to give the impression that it is _not_ case-sensitive while keeping the * performance cost low. * * Thus, a `LISTEN Hello` will pick up a notification from `NOTIFY Hello` but * also one from `NOTIFY hello`, because the database converts `Hello` into * `hello` going in either direction. * * You can prevent this conversion by putting the name in double quotes, as * @ref quote_name() does. This is what libpqxx's notification functions do. * If you use libpqxx to lisen on `Hello` but raw SQL to notify `Hello`, the * notification will not arrive because the notification actually uses the * string `hello` instead. * * Confused? Safest thing to do is to use only lower-case letters in the * channel names! * * * ### Transactions * * Both listening and notifying are _transactional_ in the backend: they * only take effect once the back-end transaction in which you do them is * committed. * * For an outgoing notification, this means that the transaction holds on to * the outgoing message until you commit. (A @ref nontransaction does not * start a backend transaction, so if that's the transaction type you're * using, the message does go out immediately.) * * For listening to incoming notifications, it gets a bit more complicated. * To avoid complicating its internal bookkeeping, libpqxx only lets you * start listening while no transaction is open. * * No notifications will come in while you're in a transaction... again * unless it's a @ref nontransaction of course, because that does not open a * transaction on the backend. * * * ### Exceptions * * If your handler throws an exception, that will simply propagate up the * call chain to wherever you were when you received it. * * This is differnt from the old `notification_receiver` mechanism which * logged exceptions but did not propagate them. * * * ### Encoding * * When a client sends a notification, it does so in its client encoding. If * necessary, the back-end converts them to its internal encoding. And then * when a client receives the notification, the database converts it to the * receiver's client encoding. * * Simple enough, right? * * However if you should _change_ your connection's client encoding after you * start listening on a channel, then any notifications you receive may have * different channel names than the ones for which you are listening. * * If this could be a problem in your scenario, stick to names in pure * ASCII. Those will look the same in all the encodings postgres supports. */ //@{ /// Check for pending notifications and take appropriate action. /** This does not block. To wait for incoming notifications, either call * @ref await_notification() (it calls this function); or wait for incoming * data on the connection's socket (i.e. wait to read), and then call this * function repeatedly until it returns zero. After that, there are no more * pending notifications so you may want to wait again, or move on and do * other work. * * If any notifications are pending when you call this function, it * processes them by checking for a matching notification handler, and if it * finds one, invoking it. If there is no matching handler, nothing happens. * * If your notifcation handler throws an exception, `get_notifs()` will just * propagate it back to you. (This is different from the old * `notification_receiver` mechanism, which would merely log them.) * * @return Number of notifications processed. */ int get_notifs(sl = sl::current()); // TODO: Unify with the other overload. /// Wait briefly for a notification to come in. /** There are other events that will also cancel the wait, such as the * backend failing, or some kinds of signal coming in. After a while the * function just returns anyway. * * This means that the function can return early, before any notification * comes in _or_ the timeout expires. Your code MUST be ready to handle * such early returns. * * If a notification does come in, this function will immediately process it, * along with any other notifications that may have been pending, calling any * handlers you may have set for them. It will then return. * * To wait for notifications from your own event loop instead, wait until * there is incoming data on the connection's socket to be read, then call * @ref get_notifs repeatedly until it returns zero. This allows you to * handle other events besides notifications with a single wait point. * * If your notifcation handler throws an exception, this function will just * propagate it on up to you. (This is different from the old * `notification_receiver` mechanism, which would merely log them.) * * @return Number of notifications processed. */ int await_notification(sl = sl::current()); /// Wait for a notification to come in, or for given timeout to pass. /** There are other events that will also cancel the wait, such as the * backend failing, or some kinds of signal coming in. * * This means that the function can return early, before any notification * comes in _or_ the timeout expires. Your code MUST be ready to handle * such early returns. * * If a notification does come in, this function will immediately process it, * along with any other notifications that may have been pending, calling any * handlers you may have set for them. It will then return. * * To wait for notifications from your own event loop instead, wait until * there is incoming data on the connection's socket to be read, then call * @ref get_notifs repeatedly until it returns zero. This allows you to * handle other events besides notifications with a single wait point. * * If your notifcation handler throws an exception, this function will just * propagate it on up to you. (This is different from the old * `notification_receiver` mechanism, which would merely log them.) * * @return Number of notifications processed. */ int await_notification( std::time_t seconds = 10, long microseconds = 0, sl = sl::current()); /// A handler callback for incoming notifications on a given channel. /** Your callback must accept a @ref notification object. This object can * and will exist only for the duration of the handling of that one incoming * notification. * * The handler can be "empty," i.e. contain no code. Setting an empty * handler on a channel disables listening on that channel. */ using notification_handler = std::function; /// Attach a handler to a notification channel. /** Issues a `LISTEN` SQL command for channel `channel`, and stores `handler` * as the callback for when a notification comes in on that channel. * * The connection can call this handler when you call @ref get_notifs() or * @ref await_notification() on the connection. Some internal functions may * also call these functions. The client-side handling is fully synchronous * and notifications only come in while the connection is _not_ in a back-end * transaction. * * The handler is a `std::function` (see @ref notification_handler), but you * can simply pass in a lambda with the right parameters, or a function, or * an object of a type you define that happens to implemnt the right function * call operator. * * Your handler probably needs to interact with your application's data; the * simple way to get that working is to pass a lambda with a closure * referencing the data items you need. * * If the handler is empty (the default), then that stops the connection * listening on the channel. It cancels your subscription, so to speak. * You can do that as many times as you like, even when you never started * listening to that channel in the first place. * * A connection can only have one handler per channel, so if you register two * different handlers on the same channel, then the second overwrites the * first. */ void listen( std::string_view channel, notification_handler handler = {}, sl = sl::current()); //@} /** * @name Password encryption * * Use this when setting a new password for the user if password encryption * is enabled. Inputs are the SQL name for the user for whom you with to * encrypt a password; the plaintext password; and the hash algorithm. * * The algorithm must be one of "md5", "scram-sha-256" (introduced in * PostgreSQL 10), or `nullptr`. If the pointer is null, this will query * the `password_encryption setting` from the server, and use the default * algorithm as defined there. * * @return encrypted version of the password, suitable for encrypted * PostgreSQL authentication. * * Thus you can change a user's password with: * ```cxx * void setpw(transaction_base &t, string const &user, string const &pw) * { * t.exec0("ALTER USER " + user + " " * "PASSWORD '" + t.conn().encrypt_password(user,pw) + "'"); * } * ``` * * When building this against a libpq older than version 10, this will use * an older function which only supports md5. In that case, requesting a * different algorithm than md5 will result in a @ref feature_not_supported * exception. */ //@{ /// Encrypt a password for a given user. [[nodiscard]] std::string encrypt_password(zview user, zview password, zview algorithm) { return encrypt_password(user.c_str(), password.c_str(), algorithm.c_str()); } /// Encrypt a password for a given user. [[nodiscard]] PQXX_ZARGS std::string encrypt_password( char const user[], char const password[], char const *algorithm = nullptr); //@} /** * @name Prepared statements * * PostgreSQL supports prepared SQL statements, i.e. statements that you can * register under a name you choose, optimized once by the backend, and * executed any number of times under the given name. * * Prepared statement definitions are not sensitive to transaction * boundaries. A statement defined inside a transaction will remain defined * outside that transaction, even if the transaction itself is subsequently * aborted. Once a statement has been prepared, it will only go away if you * close the connection or explicitly "unprepare" the statement. * * Use the `pqxx::transaction_base::exec_prepared` functions to execute a * prepared statement. See @ref prepared for a full discussion. * * @warning Using prepared statements can save time, but if your statement * takes parameters, it may also make your application significantly slower! * The reason is that the server works out a plan for executing the query * when you prepare it. At that time, of course it does not know the values * for the parameters that you will pass. If you execute a query without * preparing it, then the server works out the plan on the spot, with full * knowledge of the parameter values. * * A statement's definition can refer to its parameters as `$1`, `$2`, etc. * The first parameter you pass to the call provides a value for `$1`, and * so on. * * Here's an example of how to use prepared statements. * * ```cxx * using namespace pqxx; * void foo(connection &c) * { * c.prepare("findtable", "select * from pg_tables where name=$1"); * work tx{c}; * result r = tx.exec_prepared("findtable", "mytable"); * if (std::empty(r)) throw runtime_error{"mytable not found!"}; * } * ``` */ //@{ /// Define a prepared statement. /** * @param name unique name for the new prepared statement. * @param definition SQL statement to prepare. */ void prepare(zview name, zview definition, sl loc = sl::current()) & { prepare(name.c_str(), definition.c_str(), loc); } /// Define a prepared statement. /** Extra overload for disambiguation. It may also help avoid the slightly * less efficient `string_view`-based overload. * * @param name unique name for the new prepared statement. * @param definition SQL statement to prepare. */ void prepare( std::string const &name, std::string const &definition, sl loc = sl::current()) & { prepare(name.c_str(), definition.c_str(), loc); } /// Define a prepared statement. /** * @param name unique name for the new prepared statement. * @param definition SQL statement to prepare. */ PQXX_ZARGS void prepare( char const name[], char const definition[], sl loc = sl::current()) &; /// Define a prepared statement. /** This is a convenience overload, slightly less efficient than the versions * that take `std::string`, `pqxx::zview` or raw C strings. The reason is * that these functions internally call a C-level function that expects * zero-terminated strings. * * If you cannot guarantee that these strings are zero-terminated, the * function will have to create temporary internal copies of these strings in * order to ensure the terminating zero. * * @param name unique name for the new prepared statement. * @param definition SQL statement to prepare. */ void prepare( std::string_view name, std::string_view definition, sl loc = sl::current()) & { std::string const n{name}, d{definition}; prepare(n.c_str(), d.c_str(), loc); } /// Define a nameless prepared statement. [[deprecated("Either name your statement, or just parameterise it.")]] PQXX_ZARGS void prepare(char const definition[], sl loc = sl::current()) &; [[deprecated("Either name your statement, or just parameterise it.")]] void prepare(zview definition, sl loc = sl::current()) & { #include "pqxx/internal/ignore-deprecated-pre.hxx" prepare(definition.c_str(), loc); #include "pqxx/internal/ignore-deprecated-post.hxx" } /// Drop prepared statement. void unprepare(std::string_view name, sl loc = sl::current()); //@} /// Suffix unique number to name to make it unique within session context. /** Used internally to generate identifiers for SQL objects (such as cursors * and nested transactions) based on a given human-readable base name. */ [[nodiscard]] std::string adorn_name(std::string_view); /** * @defgroup escaping-functions String-escaping functions */ //@{ /// Escape string for use as SQL string literal on this connection. [[nodiscard]] PQXX_ZARGS std::string esc(char const text[], sl loc = sl::current()) const { return esc(std::string_view{text}, loc); } /// Escape string for use as SQL string literal, into `buffer`. /** Use this variant when you want to re-use the same buffer across multiple * calls. If that's not the case, or convenience and simplicity are more * important, use the single-argument variant. * * For every byte in `text`, there must be at least 2 bytes of space in * `buffer`; plus there must be one byte of space for a trailing zero. * Throws @ref range_error if this space is not available. * * Returns a reference to the escaped string, which is actually stored in * `buffer`. */ [[nodiscard]] std::string_view esc(std::string_view text, std::span buffer, sl loc = sl::current()) { auto const size{std::size(text)}, space{std::size(buffer)}; auto const needed{2 * size + 1}; if (space < needed) throw range_error{ std::format( "Not enough room to escape string of {} byte(s): need {} bytes of " "buffer space, but buffer size is {}.", size, needed, size), loc}; return {std::data(buffer), esc_to_buf(text, buffer, loc)}; } /// Escape string for use as SQL string literal on this connection. /** @warning This is meant for text strings only. It cannot contain bytes * whose value is zero ("nul bytes"). */ [[nodiscard]] std::string esc(std::string_view text, sl loc = sl::current()) const; /// Escape binary string for use as SQL string literal on this connection. /** This is identical to `esc_raw(data)`. */ template [[nodiscard]] std::string esc(DATA const &data) const { return esc_raw(data); } /// Escape binary string for use as SQL string literal, into `buffer`. /** Use this variant when you want to re-use the same buffer across multiple * calls. If that's not the case, or convenience and simplicity are more * important, use the single-argument variant. * * For every byte in `data`, there must be at least two bytes of space in * `buffer`; plus there must be two bytes of space for a header and one for * a trailing zero. Throws @ref range_error if this space is not available. * * Returns a reference to the escaped string, which is actually stored in * `buffer`. */ template [[nodiscard]] zview esc(DATA const &data, std::span buffer, sl loc = sl::current()) const { auto const size{std::size(data)}, space{std::size(buffer)}; auto const needed{internal::size_esc_bin(std::size(data))}; if (space < needed) throw range_error{ std::format( "Not enough room to escape binary string of {} byte(s): need {} ", " bytes of buffer space, but buffer size is {}.", size, needed, space), loc}; bytes_view const view{std::data(data), std::size(data)}; // Actually, in the modern format, we know beforehand exactly how many // bytes we're going to fill. Just leave out the trailing zero. internal::esc_bin(view, buffer); return zview{std::data(buffer), needed - 1}; } /// Escape binary string for use as SQL string literal on this connection. /** You can also just use @ref esc with a binary string. */ [[nodiscard]] std::string esc_raw(bytes_view) const; /// Escape binary string for use as SQL string literal on this connection. /** You can also just use @ref esc with a binary string. */ template [[nodiscard]] std::string esc_raw(DATA const &data) const { return esc_raw(bytes_view{std::data(data), std::size(data)}); } /// Escape binary string for use as SQL string literal, into `buffer`. template [[nodiscard]] zview esc_raw(DATA const &data, std::span buffer) const { return this->esc(binary_cast(data), buffer); } // TODO: Make "into buffer" variant to eliminate a string allocation. /// Unescape binary data, e.g. from a `bytea` field. /** Takes a binary string as escaped by PostgreSQL, and returns a restored * copy of the original binary data. * * (The data must be encoded in PostgreSQL's "hex" format. The legacy * "bytea" escape format, used prior to PostgreSQL 9.0, is no longer * supported.) */ [[nodiscard]] bytes unesc_bin(std::string_view text, sl loc = sl::current()) const { bytes buf{pqxx::internal::size_unesc_bin(std::size(text))}; pqxx::internal::unesc_bin(text, buf, loc); return buf; } /// Escape and quote a string of binary data. /** You can also just use @ref quote with binary data. */ [[nodiscard]] std::string quote_raw(bytes_view) const; /// Escape and quote a string of binary data. /** You can also just use @ref quote with binary data. */ template [[nodiscard]] std::string quote_raw(DATA const &data) const { return quote_raw(bytes_view{std::data(data), std::size(data)}); } // TODO: Make "into buffer" variant to eliminate a string allocation. /// Escape and quote an SQL identifier for use in a query. [[nodiscard]] std::string quote_name(std::string_view identifier) const; // TODO: Make "into buffer" variant to eliminate a string allocation. /// Escape and quote a table name. /** When passing just a table name, this is just another name for * @ref quote_name. */ [[nodiscard]] std::string quote_table(std::string_view name) const; // TODO: Make "into buffer" variant to eliminate a string allocation. /// Escape and quote a table path. /** A table path consists of a table name, optionally prefixed by a schema * name; and if both are given, they are in turn optionally prefixed by a * database name. * * Each portion of the path (database name, schema name, table name) will be * quoted separately, and they will be joined together by dots. So for * example, `myschema.mytable` will become `"myschema"."mytable"`. */ [[nodiscard]] std::string quote_table(table_path) const; // TODO: Make "into buffer" variant to eliminate a string allocation. /// Quote and comma-separate a series of column names. /** Use this to save a bit of work in cases where you repeatedly need to pass * the same list of column names, e.g. with @ref stream_to and @ref * stream_from. Some functions that need to quote the columns list * internally, will have a "raw" alternative which let you do the quoting * yourself. It's a bit of extra work, but it can in rare cases let you * eliminate some duplicate work in quoting them repeatedly. */ template inline std::string quote_columns(STRINGS const &columns, sl = sl::current()) const; // TODO: Make "into buffer" variant to eliminate a string allocation. /// Represent object as SQL string, including quoting & escaping. /** * Recognises nulls and represents them as SQL nulls. They get no quotes. */ template [[nodiscard]] inline std::string quote(T const &t, sl = sl::current()) const; // TODO: Make "into buffer" variant to eliminate a string allocation. /// Escape string for literal LIKE match. /** Use this when part of an SQL "LIKE" pattern should match only as a * literal string, not as a pattern, even if it contains "%" or "_" * characters that would normally act as wildcards. * * The string does not get string-escaped or quoted. You do that later. * * For instance, let's say you have a string `name` entered by the user, * and you're searching a `file` column for items that match `name` * followed by a dot and three letters. Even if `name` contains wildcard * characters "%" or "_", you only want those to match literally, so "_" * only matches "_" and "%" only matches a single "%". * * You do that by "like-escaping" `name`, appending the wildcard pattern * `".___"`, and finally, escaping and quoting the result for inclusion in * your query: * * ```cxx * tx.exec( * "SELECT file FROM item WHERE file LIKE " + * tx.quote(tx.esc_like(name) + ".___")); * ``` * * The SQL "LIKE" operator also lets you choose your own escape character. * This is supported, but must be a single-byte character. */ [[nodiscard]] std::string esc_like( std::string_view text, char escape_char = '\\', sl loc = sl::current()) const; //@} /// Attempt to cancel the ongoing query, if any. /** You can use this from another thread, and/or while a query is executing * in a pipeline, but it's up to you to ensure that you're not canceling the * wrong query. This may involve locking. */ void cancel_query(sl = sl::current()); #if defined(_WIN32) || __has_include() /// Set socket to blocking (true) or nonblocking (false). /** @warning Do not use this unless you _really_ know what you're doing. * @warning This function is available on most systems, but not necessarily * all. */ void set_blocking(bool block, sl = sl::current()) &; #endif // defined(_WIN32) || __has_include() /// Set session verbosity. /** Set the verbosity of error messages to "terse", "normal" (the default), * or "verbose." * * This affects the notices that the `connection` and its `result` objects * will pass to your notice handler. * * If "terse", returned messages include severity, primary text, and * position only; this will normally fit on a single line. "normal" produces * messages that include the above plus any detail, hint, or context fields * (these might span multiple lines). "verbose" includes all available * fields. */ void set_verbosity(error_verbosity verbosity) & noexcept; /// Set a notice handler to the connection. /** When a notice comes in (a warning or error message), the connection or * result object on which it happens will call the notice handler, passing * the message as its argument. * * The handler must not throw any exceptions. If it does, the program will * terminate. * * @warning It's not just the `connection` that can call a notice handler, * but any of the `result` objects that it produces as well. So, be prepared * for the possibility that the handler may still receive a call after the * connection has been closed. */ void set_notice_handler(std::function handler) { m_notice_waiters->notice_handler = std::move(handler); } /// @deprecated Return pointers to the active errorhandlers. /** The entries are ordered from oldest to newest handler. * * The pointers point to the real errorhandlers. The container it returns * however is a copy of the one internal to the connection, not a reference. */ [[nodiscard, deprecated("Use a notice handler instead.")]] std::vector get_errorhandlers() const; /// Return a connection string encapsulating this connection's options. /** The connection must be currently open for this to work. * * Returns a reconstruction of this connection's connection string. It may * not exactly match the connection string you passed in when creating this * connection. */ [[nodiscard]] std::string connection_string() const; /// Explicitly close the connection. /** The destructor will do this for you automatically. Still, there is a * reason to `close()` objects explicitly where possible: if an error should * occur while closing, `close()` can throw an exception. A destructor * cannot. * * Closing a connection is idempotent. Closing a connection that's already * closed does nothing. */ void close(sl = sl::current()); /// Seize control of a raw libpq connection. /** @warning Do not do this. Please. It's for very rare, very specific * use-cases. The mechanism may change (or break) in unexpected ways in * future versions. * * @param raw_conn a raw libpq `::PQconn` pointer, cast to a * @ref pqxx::internal::pq::PGconn pointer. */ static connection seize_raw_connection(internal::pq::PGconn *raw_conn, sl loc = sl::current()) { return connection{raw_conn, loc}; } /// Release the raw connection without closing it. /** @warning Do not do this. It's for very rare, very specific use-cases. * The mechanism may change (or break) in unexpected ways in future versions. * * The `connection` object becomes unusable after this. * * In order to _use_ the resulting pointer, for most purposes you'll have to * cast it to its original C type: `::PGconn *` as defined by libpq. */ internal::pq::PGconn *release_raw_connection() && { return std::exchange(m_conn, nullptr); } /// Set session variable, using SQL's `SET` command. /** @deprecated To set a session variable, use @ref set_session_var. To set * a transaction-local variable, execute an SQL `SET` command. * * @warning When setting a string value, you must escape and quote it first. * Use the @ref quote() function to do that. * * @warning This executes an SQL query, so do not get or set variables while * a table stream or pipeline is active on the same connection. * * @param var Variable to set. * @param value New value for Var. This can be any SQL expression. If it's * a string, be sure that it's properly escaped and quoted. */ [[deprecated("To set session variables, use set_session_var.")]] void set_variable( std::string_view var, std::string_view value, sl loc = sl::current()) &; /// Read session variable, using SQL's `SHOW` command. /** @warning This executes an SQL query, so do not get or set variables while * a table stream or pipeline is active on the same connection. */ [[deprecated("Use get_var instead.")]] std::string get_variable(std::string_view, sl loc = sl::current()); private: /// Type for empty connection parameters sequence. using empty_params_t = std::initializer_list>; friend class connecting; enum connect_mode { connect_nonblocking }; /// Start connecting asynchronously. For use by @ref connecting. connection(connect_mode, zview connection_string, sl); /// For use by @ref seize_raw_connection. explicit connection(internal::pq::PGconn *raw_conn, sl); /// Poll for ongoing connection, try to progress towards completion. /** Returns a pair of "now please wait to read data from socket" and "now * please wait to write data to socket." Both will be false when done. * * Throws an exception if polling indicates that the connection has failed. */ std::pair poll_connect(sl); // Initialise based on connection string and key/value parameter pairs. void init( std::vector const &override_keys, std::vector const &override_values, sl); void set_up_notice_handlers(); /// Complete setup after libpq has completed creating its connection. void complete_connection(sl); result make_result( internal::pq::PGresult *pgr, std::shared_ptr const &query, std::string_view desc, sl = sl::current()); result make_result( internal::pq::PGresult *pgr, std::shared_ptr const &query, sl loc = sl::current()) { return make_result(pgr, query, "", loc); } PQXX_PRIVATE [[nodiscard]] int status() const noexcept; /// Escape a string, into a buffer allocated by the caller. /** The buffer must have room for at least `2*std::size(text) + 1` bytes. * * Returns the number of bytes written, including the trailing zero. */ [[nodiscard]] std::size_t esc_to_buf(std::string_view text, std::span buf, sl loc) const; friend class internal::gate::const_connection_largeobject; [[nodiscard]] char const *err_msg() const noexcept; result exec_prepared( std::string_view statement, internal::c_params const &, sl loc = sl::current()); /// Throw @ref usage_error if this connection is not in a movable state. void check_movable(sl) const; /// Throw @ref usage_error if not in a state where it can be move-assigned. void check_overwritable(sl) const; friend class internal::gate::connection_errorhandler; PQXX_PRIVATE void register_errorhandler(errorhandler *); PQXX_PRIVATE void unregister_errorhandler(errorhandler *) noexcept; friend class internal::gate::connection_transaction; result exec(std::string_view query, sl loc) { return exec(query, "", loc); } result exec(std::string_view, std::string_view, sl); PQXX_PRIVATE result exec(std::shared_ptr const &, std::string_view, sl); PQXX_PRIVATE result exec(std::shared_ptr const &query, sl loc) { return exec(query, "", loc); } PQXX_PRIVATE void register_transaction(transaction_base *); PQXX_PRIVATE void unregister_transaction(transaction_base *) noexcept; friend class internal::gate::connection_stream_from; /// Read a line of COPY output. /** If the output indicates that the COPY has ended, the buffer pointer * will be null and the size will be zero. Otherwise, the pointer will hold * a buffer containing the line, and size will be its length not including * the newline at the end. */ std::pair, std::size_t> read_copy_line(sl); friend class internal::gate::connection_stream_to; PQXX_PRIVATE void write_copy_line(std::string_view, sl); PQXX_PRIVATE void end_copy_write(sl); friend class internal::gate::connection_largeobject; [[nodiscard]] constexpr internal::pq::PGconn *raw_connection() const noexcept { return m_conn; } friend class internal::gate::connection_notification_receiver; void add_receiver(notification_receiver *, sl); void remove_receiver(notification_receiver *, sl) noexcept; friend class internal::gate::connection_pipeline; PQXX_PRIVATE PQXX_ZARGS void start_exec(char const query[]); PQXX_PRIVATE bool consume_input() noexcept; PQXX_PRIVATE [[nodiscard]] bool is_busy() const noexcept; internal::pq::PGresult *get_result(); friend class internal::gate::connection_dbtransaction; friend class internal::gate::connection_sql_cursor; result exec_params(std::string_view query, internal::c_params const &args, sl); /// Connection handle. internal::pq::PGconn *m_conn = nullptr; /// Active transaction on connection, if any. /** We don't use this for anything, except to check for open transactions * when we close the connection or start a new transaction. * * We also don't allow move construction or move assignment while there's a * transaction, since moving the connection in that case would leave one or * more pointers back from the transaction to the connection dangling. */ transaction_base const *m_trans = nullptr; /// 9.0: Replace with just notice handler. std::shared_ptr m_notice_waiters; // TODO: Remove these when we retire notification_receiver. // TODO: Can we make these movable? using receiver_list = std::multimap; /// Notification receivers. receiver_list m_receivers; /// Notification handlers. /** These are the functions we call when notifications come in. Each * corresponds to a `LISTEN` we have executed. * * The map does not contain any `std::function` which are empty. If the * caller registers an empty function, that simply cancels any subscription * to that channel. */ std::map m_notification_handlers; /// A `std::source_location` for where this object was created. sl m_created_loc; /// Unique number to use as suffix for identifiers (see adorn_name()). int m_unique_id = 0; }; /// An ongoing, non-blocking stepping stone to a connection. /** Use this when you want to create a connection to the database, but without * blocking your whole thread. It is only available on systems that have * the `` header, and Windows. * * Connecting in this way is probably not "faster" (it's more complicated and * has some extra overhead), but in some situations you can use it to make your * application as a whole faster. It all depends on having other useful work * to do in the same thread, and being able to wait on a socket. If you have * other I/O going on at the same time, your event loop can wait for both the * libpqxx socket and your own sockets, and wake up whenever any of them is * ready to do work. * * Connecting in this way is not properly "asynchronous;" it's merely * "nonblocking." This means it's not a super-high-performance mechanism like * you might get with e.g. `io_uring`. In particular, if we need to look up * the database hostname in DNS, that will happen synchronously. * * To use this, create the `connecting` object, passing a connection string. * Then loop: If @ref wait_to_read returns true, wait for the socket to have * incoming data on it. If @ref wait_to_write returns true, wait for the * socket to be ready for writing. Then call @ref process to process any * incoming or outgoing data. Do all of this until @ref done returns true (or * there is an exception). Finally, call @ref produce to get the completed * connection. * * For example: * * ```cxx * pqxx::connecting cg{}; * * // Loop until we're done connecting. * while (!cg.done()) * { * wait_for_fd(cg.sock(), cg.wait_to_read(), cg.wait_to_write()); * cg.process(); * } * * pqxx::connection cx = std::move(cg).produce(); * * // At this point, cx is a working connection. You can no longer use * // cg at all. * ``` */ class PQXX_LIBEXPORT connecting final { public: /// Start connecting. explicit connecting(zview connection_string = ""_zv, sl = sl::current()); connecting(connecting const &) = delete; connecting(connecting &&) = default; ~connecting() = default; connecting &operator=(connecting const &) = delete; connecting &operator=(connecting &&) = default; /// Get the socket. The socket may change during the connection process. [[nodiscard]] int sock() const & noexcept { return m_conn.sock(); } /// Should we currently wait to be able to _read_ from the socket? [[nodiscard]] constexpr bool wait_to_read() const & noexcept { return m_reading; } /// Should we currently wait to be able to _write_ to the socket? [[nodiscard]] constexpr bool wait_to_write() const & noexcept { return m_writing; } /// Progress towards completion (but don't block). void process(sl loc = sl::current()) &; /// Is our connection finished? [[nodiscard]] constexpr bool done() const & noexcept { return not m_reading and not m_writing; } /// Produce the completed connection object. /** Use this only once, after @ref done returned `true`. Once you have * called this, the `connecting` instance has no more use or meaning. You * can't call any of its member functions afterwards. * * This member function is rvalue-qualified, meaning that you can only call * it on an rvalue instance of the class. If what you have is not an rvalue, * turn it into one by wrapping it in `std::move()`. */ [[nodiscard]] connection produce(sl = sl::current()) &&; private: connection m_conn; bool m_reading{false}; bool m_writing{true}; }; template inline std::string connection::quote(T const &t, sl loc) const { if (is_null(t)) { // It's easy to forget, but we can't support nulls in string conversion // itself, because the "NULL" may end up inside quotes or something. // We can only handle nulls at this slightly higher level in the call tree, // where there is awareness of the quoting. return "NULL"; } else if constexpr (binary) { return quote_raw(t); } else { // TODO: Can we leave the quotes out if unquoted_safe? auto const text{to_string(t)}; // Okay, there's an easy way to do this and there's a hard way. The easy // way was "quote, esc(to_string(t)), quote". I'm going with the hard way // because it's going to save some string manipulation that will probably // incur some unnecessary memory allocations and deallocations. std::string buf{'\''}; buf.resize(2 + 2 * std::size(text) + 1); auto const content_bytes{ esc_to_buf(text, {std::begin(buf) + 1, std::end(buf)}, loc)}; auto const closing_quote{1 + content_bytes}; buf[closing_quote] = '\''; auto const end{closing_quote + 1}; buf.resize(end); return buf; } } template inline std::string connection::quote_columns(STRINGS const &columns, sl loc) const { conversion_context const c{get_encoding_group(), loc}; return separated_list( ","sv, std::cbegin(columns), std::cend(columns), [this](auto col) { return this->quote_name(*col); }, c); } template inline connection::connection( STRING const &connection_string, MAPPING &¶ms, sl loc) : m_created_loc{loc} { // Check that the libpqxx binary library version is compatible with the // version against which the application was compiled. We're in an inline // function, so this _call_ ends up in the application binary. On the other // hand, `check_libpqxx_version()` is compiled into the libpqx binary. // That's how the function is in a position to compare the two versions. // // There is no particular reason to do this here in @ref connection, except // to ensure that every meaningful libpqxx client will execute it, while // minimising overhead. The ideal would be to pay a small price exactly once // per application run. // // A local static variable is initialised only on the definition's first // execution. Compilers will be well optimised for this, so there's a // minimal one-time cost. [[maybe_unused]] static auto const version_check{ pqxx::internal::check_libpqxx_version( version_major, version_minor, version_patch, version)}; // clang-tidy rule bug: // NOLINTBEGIN( // cppcoreguidelines-pro-bounds-array-to-pointer-decay, // hicpp-no-array-decay // ) pqxx::internal::connection_string_parser const parsed_string{ pqxx::internal::as_c_string(connection_string), loc}; // NOLINTEND( // cppcoreguidelines-pro-bounds-array-to-pointer-decay, // hicpp-no-array-decay // ) auto [keys, values]{parsed_string.parse()}; // Merge key/value pairs into the pairs we got from the connection string. for (auto const &[org_key, org_value] : params) { auto const key{pqxx::internal::as_c_string(org_key)}, value{pqxx::internal::as_c_string(org_value)}; // Did we have a value for key already? This is a horrible O(n^2) search, // in principle, but there's only so many possible options. Trying to // optimise this might make it worse in common practical cases. // // (Landau's "large O" notation really only applies to inputs growing // towards infinity. If there's a known constant bound b such that n < b, // then O(n^2) is at worst O(b^2). Since b is a constant, O(b^2) boils // down to O(1).) auto const it{std::ranges::find_if(keys, [key](char const *existing) { return std::strcmp(existing, key) == 0; })}; if (it == keys.end()) { // New key. Append. keys.push_back(key); values.push_back(value); } else { // A key we've already seen. Override. auto const idx{ static_cast(std::distance(keys.begin(), it))}; values[idx] = value; } } // Null-terminate both arrays. keys.push_back(nullptr); values.push_back(nullptr); init(keys, values, loc); } } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/cursor000066400000000000000000000004441516427024100170760ustar00rootroot00000000000000/** Definition of the iterator/container-style cursor classes. * * C++-style wrappers for SQL cursors */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/cursor.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/cursor.hxx000066400000000000000000000501511516427024100177040ustar00rootroot00000000000000/* Definition of the iterator/container-style cursor classes. * * C++-style wrappers for SQL cursors. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/cursor instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_CURSOR_HXX #define PQXX_CURSOR_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include #include "pqxx/result.hxx" #include "pqxx/transaction_base.hxx" namespace pqxx { /// Common definitions for cursor types /** In C++ terms, fetches are always done in pre-increment or pre-decrement * fashion--i.e. the result does not include the row the cursor is on at the * beginning of the fetch, and the cursor ends up being positioned on the last * row in the result. * * There are singular positions akin to `end()` at both the beginning and the * end of the cursor's range of movement, although these fit in so naturally * with the semantics that one rarely notices them. The cursor begins at the * first of these, but any fetch in the forward direction will move the cursor * off this position and onto the first row before returning anything. */ class PQXX_LIBEXPORT cursor_base { public: using size_type = result_size_type; using difference_type = result_difference_type; /// Cursor access-pattern policy /** Allowing a cursor to move forward only can result in better performance, * so use this access policy whenever possible. */ enum access_policy { /// Cursor can move forward only forward_only, /// Cursor can move back and forth random_access }; /// Cursor update policy /** * @warning Not all PostgreSQL versions support updatable cursors. */ enum update_policy { /// Cursor can be used to read data but not to write read_only, /// Cursor can be used to update data as well as read it update }; /// Cursor destruction policy /** The normal thing to do is to make a cursor object the owner of the SQL * cursor it represents. There may be cases, however, where a cursor needs * to persist beyond the end of the current transaction (and thus also beyond * the lifetime of the cursor object that created it!), where it can be * "adopted" into a new cursor object. See the basic_cursor documentation * for an explanation of cursor adoption. * * If a cursor is created with "loose" ownership policy, the object * representing the underlying SQL cursor will not take the latter with it * when its own lifetime ends, nor will its originating transaction. * * @warning Use this feature with care and moderation. Only one cursor * object should be responsible for any one underlying SQL cursor at any * given time. */ enum ownership_policy { /// Destroy SQL cursor when cursor object is closed at end of transaction owned, /// Leave SQL cursor in existence after close of object and transaction loose }; cursor_base() = delete; cursor_base(cursor_base const &) = delete; cursor_base(cursor_base &&) = delete; // Really weird: gcc complains that this accesses deprecated m_name. #include "pqxx/internal/ignore-deprecated-pre.hxx" ~cursor_base() = default; #include "pqxx/internal/ignore-deprecated-post.hxx" cursor_base &operator=(cursor_base const &) = delete; cursor_base &operator=(cursor_base &&) = delete; /** * @name Special movement distances. */ //@{ /// Special value: read until end. /** @return Maximum value for result::difference_type, so the cursor will * attempt to read the largest possible result set. */ [[nodiscard]] static constexpr difference_type all() noexcept { return (std::numeric_limits::max)() - 1; } /// Special value: read one row only. /** @return Unsurprisingly, 1. */ [[nodiscard]] static constexpr difference_type next() noexcept { return 1; } /// Special value: read backwards, one row only. /** @return Unsurprisingly, -1. */ [[nodiscard]] static constexpr difference_type prior() noexcept { return -1; } /// Special value: read backwards from current position back to origin. /** @return Minimum value for result::difference_type. */ [[nodiscard]] static constexpr difference_type backward_all() noexcept { return (std::numeric_limits::min)() + 1; } //@} /// Name of underlying SQL cursor /** * @returns Name of SQL cursor, which may differ from original given name. * @warning Don't use this to access the SQL cursor directly without going * through the provided wrapper classes! */ [[nodiscard]] constexpr std::string const &name() const noexcept { #include "pqxx/internal/ignore-deprecated-pre.hxx" return m_name; #include "pqxx/internal/ignore-deprecated-post.hxx" } protected: cursor_base( connection &, std::string_view Name, bool embellish_name = true, sl loc = sl::current()); /// The `std::source_location` for where this cursor was created. [[nodiscard]] sl created_loc() const { #include "pqxx/internal/ignore-deprecated-pre.hxx" return m_created_loc; #include "pqxx/internal/ignore-deprecated-post.hxx" } // NOLINTBEGIN( // cppcoreguidelines-non-private-member-variables-in-classes, // misc-non-private-member-variables-in-classes // ) [[deprecated( "This will become private. Use name() instead.")]] std::string const m_name; /// The `std::source_location` for where this cursor was created. [[deprecated("This will become private. Use created_loc() instead.")]] sl m_created_loc; // NOLINTEND( // cppcoreguidelines-non-private-member-variables-in-classes, // misc-non-private-member-variables-in-classes // ) }; } // namespace pqxx #include namespace pqxx { /// "Stateless cursor" class: easy API for retrieving parts of result sets /** This is a front-end for SQL cursors, but with a more C++-like API. * * Actually, stateless_cursor feels entirely different from SQL cursors. You * don't keep track of positions, fetches, and moves; you just say which rows * you want. See the retrieve() member function. */ template class stateless_cursor final { public: using size_type = result_size_type; using difference_type = result_difference_type; /// Create cursor. /** * @param tx The transaction within which you want to create the cursor. * @param query The SQL query whose results the cursor should traverse. * @param cname A hint for the cursor's name. The actual SQL cursor's name * will be based on this (though not necessarily identical). * @param hold Create a `WITH HOLD` cursor? Such cursors stay alive after * the transaction has ended, so you can continue to use it. */ stateless_cursor( transaction_base &tx, std::string_view query, std::string_view cname, bool hold, sl loc = sl::current()) : m_cur{tx, query, cname, cursor_base::random_access, up, op, hold, loc} {} /// Adopt an existing scrolling SQL cursor. /** This lets you define a cursor yourself, and then wrap it in a * libpqxx-managed `stateless_cursor` object. * * @param tx The transaction within which you want to manage the cursor. * @param adopted_cursor Your cursor's SQL name. */ stateless_cursor( transaction_base &tx, std::string_view adopted_cursor, sl loc = sl::current()) : m_cur{tx, adopted_cursor, op} { // Put cursor in known position m_cur.move(cursor_base::backward_all(), loc); } stateless_cursor(stateless_cursor &&) = default; stateless_cursor(stateless_cursor const &) = delete; ~stateless_cursor() = default; stateless_cursor &operator=(stateless_cursor &&) = default; stateless_cursor &operator=(stateless_cursor const &) = delete; /// Close this cursor. /** The destructor will do this for you automatically. * * Closing a cursor is idempotent. Closing a cursor that's already closed * does nothing. */ void close(sl loc = sl::current()) { m_cur.close(loc); } /// Number of rows in cursor's result set /** @note This function is not const; it may need to scroll to find the size * of the result set. */ [[nodiscard]] size_type size(sl loc = sl::current()) { return internal::obtain_stateless_cursor_size(m_cur, loc); } /// Retrieve rows from begin_pos (inclusive) to end_pos (exclusive) /** Rows are numbered starting from 0 to size()-1. * * @param begin_pos First row to retrieve. May be one row beyond the end of * the result set, to avoid errors for empty result sets. Otherwise, must be * a valid row number in the result set. * @param end_pos Row up to which to fetch. Rows are returned ordered from * begin_pos to end_pos, i.e. in ascending order if begin_pos < end_pos but * in descending order if begin_pos > end_pos. The end_pos may be * arbitrarily inside or outside the result set; only existing rows are * included in the result. */ result retrieve( difference_type begin_pos, difference_type end_pos, sl loc = sl::current()) { return internal::stateless_cursor_retrieve( m_cur, result::difference_type(size()), begin_pos, end_pos, loc); } /// Return this cursor's name. [[nodiscard]] constexpr std::string const &name() const noexcept { return m_cur.name(); } private: internal::sql_cursor m_cur; }; class icursor_iterator; } // namespace pqxx namespace pqxx::internal::gate { class icursor_iterator_icursorstream; class icursorstream_icursor_iterator; } // namespace pqxx::internal::gate namespace pqxx { /// Simple read-only cursor represented as a stream of results /** SQL cursors can be tricky, especially in C++ since the two languages seem * to have been designed on different planets. An SQL cursor has two singular * positions akin to `end()` on either side of the underlying result set. * * These cultural differences are hidden from view somewhat by libpqxx, which * tries to make SQL cursors behave more like familiar C++ entities such as * iterators, sequences, streams, and containers. * * Data is fetched from the cursor as a sequence of result objects. Each of * these will contain the number of rows defined as the stream's stride, except * of course the last block of data which may contain fewer rows. * * This class can create or adopt cursors that live outside any backend * transaction, which your backend version may not support. */ class PQXX_LIBEXPORT icursorstream final { public: using size_type = cursor_base::size_type; using difference_type = cursor_base::difference_type; /// Set up a read-only, forward-only cursor. /** Roughly equivalent to a C++ Standard Library istream, this cursor type * supports only two operations: reading a block of rows while moving * forward, and moving forward without reading any data. * * @param context Transaction context in which this cursor will be active. * @param query SQL query whose results this cursor shall iterate. * @param basename Suggested name for the SQL cursor; the library will append * a unique code to ensure its uniqueness. * @param sstride Number of rows to fetch per read operation; must be a * positive number. */ icursorstream( transaction_base &context, std::string_view query, std::string_view basename, difference_type sstride = 1, sl = sl::current()); /// Adopt existing SQL cursor. Use with care. /** Forms a cursor stream around an existing SQL cursor, as returned by e.g. * a server-side function. The SQL cursor will be cleaned up by the stream's * destructor as if it had been created by the stream; cleaning it up by hand * or adopting the same cursor twice is an error. * * Passing the name of the cursor as a string is not allowed, both to avoid * confusion with the other constructor and to discourage unnecessary use of * adopted cursors. * * @warning It is technically possible to adopt a "WITH HOLD" cursor, i.e. a * cursor that stays alive outside its creating transaction. However, any * cursor stream (including the underlying SQL cursor, naturally) must be * destroyed before its transaction context object is destroyed. Therefore * the only way to use SQL's WITH HOLD feature is to adopt the cursor, but * defer doing so until after entering the transaction context that will * eventually destroy it. * * @param context Transaction context in which this cursor will be active. * @param cname Result field containing the name of the SQL cursor to adopt. * @param sstride Number of rows to fetch per read operation; must be a * positive number. * @param op Ownership policy. Determines whether the cursor underlying this * stream will be destroyed when the stream is closed. */ icursorstream( transaction_base &context, field const &cname, difference_type sstride = 1, cursor_base::ownership_policy op = cursor_base::owned, sl = sl::current()); // NOLINTBEGIN(google-explicit-constructor,hicpp-explicit-conversions) /// Return `true` if this stream may still return more data. constexpr operator bool() const & noexcept { return not m_done; } // NOLINTEND(google-explicit-constructor,hicpp-explicit-conversions) /// Read new value into given result object; same as operator `>>`. /** The result set may continue any number of rows from zero to the chosen * stride, inclusive. An empty result will only be returned if there are no * more rows to retrieve. * * @param res Write the retrieved data into this result object. * @return Reference to this very stream, to facilitate "chained" invocations * ("C.get(r1).get(r2);") */ icursorstream &get(result &res, sl loc = sl::current()) { res = fetchblock(loc); return *this; } /// Read new value into given result object; same as `get(result&)`. /** The result set may continue any number of rows from zero to the chosen * stride, inclusive. An empty result will only be returned if there are no * more rows to retrieve. * * @param res Write the retrieved data into this result object. * @return Reference to this very stream, to facilitate "chained" invocations * ("C >> r1 >> r2;") */ icursorstream &operator>>(result &res) { return get(res); } /// Move given number of rows forward without reading data. /** Ignores any stride that you may have set. It moves by a given number of * rows, not a number of strides. * * @return Reference to this stream itself, to facilitate "chained" * invocations. */ icursorstream &ignore(std::streamsize n = 1, sl = sl::current()) &; /// Change stride, i.e. the number of rows to fetch per read operation. /** * @param stride Must be a positive number. */ void set_stride(difference_type stride, sl = sl::current()) &; [[nodiscard]] constexpr difference_type stride() const noexcept { return m_stride; } /// The ``std::source_location` for where this stream was created. [[nodiscard]] PQXX_PURE sl created_loc() const noexcept { return m_cur.created_loc(); } private: result fetchblock(sl); friend class internal::gate::icursorstream_icursor_iterator; size_type forward(size_type n = 1); void insert_iterator(icursor_iterator *) noexcept; void remove_iterator(icursor_iterator *) const noexcept; void service_iterators(difference_type, sl); internal::sql_cursor m_cur; mutable icursor_iterator *m_iterators = nullptr; difference_type m_stride; difference_type m_realpos, m_reqpos; bool m_done = false; }; /// Approximate istream_iterator for icursorstream. /** Intended as an implementation of an input_iterator (as defined by the C++ * Standard Library), this class supports only two basic operations: reading * the current element, and moving forward. In addition to the minimal * guarantees for istream_iterators, this class supports multiple successive * reads of the same position (the current result set is cached in the * iterator) even after copying and even after new data have been read from the * stream. This appears to be a requirement for input_iterators. Comparisons * are also supported in the general case. * * The iterator does not care about its own position, however. Moving an * iterator forward moves the underlying stream forward and reads the data from * the new stream position, regardless of the iterator's old position in the * stream. * * The stream's stride defines the granularity for all iterator movement or * access operations, i.e. "ici += 1" advances the stream by one stride's worth * of rows, and "*ici++" reads one stride's worth of rows from the stream. * * @warning Do not read from the underlying stream or its cursor, move its read * position, or change its stride, between the time the first icursor_iterator * on it is created and the time its last icursor_iterator is destroyed. * * @warning Manipulating these iterators within the context of a single cursor * stream is not thread-safe. Creating a new iterator, copying one, * or destroying one affects the stream as a whole. */ class PQXX_LIBEXPORT icursor_iterator final { public: using iterator_category = std::input_iterator_tag; using value_type = result; using pointer = result const *; using reference = result const &; using istream_type = icursorstream; using size_type = istream_type::size_type; using difference_type = istream_type::difference_type; icursor_iterator() noexcept; explicit icursor_iterator(istream_type &) noexcept; icursor_iterator(icursor_iterator const &) noexcept; icursor_iterator(icursor_iterator &&) = delete; ~icursor_iterator() noexcept; icursor_iterator &operator=(icursor_iterator &&) = delete; result const &operator*() const noexcept { refresh(created_loc()); return m_here; } PQXX_RETURNS_NONNULL result const *operator->() const noexcept { refresh(created_loc()); return &m_here; } icursor_iterator &operator++(); icursor_iterator operator++(int) &; icursor_iterator &operator+=(difference_type); icursor_iterator &operator=(icursor_iterator const &) noexcept; [[nodiscard]] bool operator==(icursor_iterator const &rhs) const; [[nodiscard]] bool operator!=(icursor_iterator const &rhs) const noexcept { return not operator==(rhs); } [[nodiscard]] bool operator<(icursor_iterator const &rhs) const; [[nodiscard]] bool operator>(icursor_iterator const &rhs) const { return rhs < *this; } [[nodiscard]] bool operator<=(icursor_iterator const &rhs) const { return not(*this > rhs); } [[nodiscard]] bool operator>=(icursor_iterator const &rhs) const { return not(*this < rhs); } private: void refresh(sl) const; friend class internal::gate::icursor_iterator_icursorstream; [[nodiscard]] difference_type pos() const noexcept { return m_pos; } void fill(result const &); /// The `std::source_location` for where this iterator's stream was created. /** We don't keep the information for the iterator itself, since iterators * are meant to be lightweight. They are often passed as arguments, where * space is especially limited. * * If there is no stream, returns the immediate call site. */ [[nodiscard]] PQXX_PURE sl created_loc(sl loc = sl::current()) const noexcept { return (m_stream == nullptr) ? loc : m_stream->created_loc(); } /** This is for use in assignment and comparison operators, where we have * two `icursor_iterator` objects but the caller can't pass a * `std::source_location` that might be useful to the application maintainer. * * Returns the first one available of: the creation location for this * iterator's stream, the creeation location of the `other` iterator's * stream, or the immediate call site. */ [[nodiscard]] sl best_location(icursor_iterator const &other, sl loc = sl::current()) const { if (m_stream != nullptr) return created_loc(); else return other.created_loc(loc); } icursorstream *m_stream{nullptr}; result m_here; difference_type m_pos; icursor_iterator *m_prev{nullptr}, *m_next{nullptr}; }; } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/dbtransaction000066400000000000000000000004651516427024100204170ustar00rootroot00000000000000/** pqxx::dbtransaction abstract base class. * * pqxx::dbransaction defines a real transaction on the database. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/dbtransaction.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/dbtransaction.hxx000066400000000000000000000054701516427024100212260ustar00rootroot00000000000000/* Definition of the pqxx::dbtransaction abstract base class. * * pqxx::dbransaction defines a real transaction on the database. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/dbtransaction instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_DBTRANSACTION_HXX #define PQXX_DBTRANSACTION_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include "pqxx/transaction_base.hxx" namespace pqxx { /// Abstract transaction base class: bracket transactions on the database. /** * @ingroup transactions * * Use a dbtransaction-derived object such as "work" (transaction<>) to enclose * operations on a database in a single "unit of work." This ensures that the * whole series of operations either succeeds as a whole or fails completely. * In no case will it leave half-finished work behind in the database. * * Once processing on a transaction has succeeded and any changes should be * allowed to become permanent in the database, call commit(). If something * has gone wrong and the changes should be forgotten, call abort() instead. * If you do neither, an implicit abort() is executed at destruction time. * * It is an error to abort a transaction that has already been committed, or to * commit a transaction that has already been aborted. Aborting an already * aborted transaction or committing an already committed one is allowed, to * make error handling easier. Repeated aborts or commits have no effect after * the first one. * * Database transactions are not suitable for guarding long-running processes. * If your transaction code becomes too long or too complex, consider ways to * break it up into smaller ones. Unfortunately there is no universal recipe * for this. * * The actual operations for committing/aborting the backend transaction are * implemented by a derived class. The implementing concrete class must also * call @ref close from its destructor. */ class PQXX_LIBEXPORT PQXX_NOVTABLE dbtransaction : public transaction_base { public: dbtransaction() = delete; protected: /// Begin transaction. explicit dbtransaction(connection &cx, sl loc = sl::current()) : transaction_base{cx, loc} {} /// Begin transaction. dbtransaction( connection &cx, std::string_view tname, sl loc = sl::current()) : transaction_base{cx, tname, loc} {} /// Begin transaction. dbtransaction( connection &cx, std::string_view tname, std::shared_ptr rollback_cmd, sl loc = sl::current()) : transaction_base{cx, tname, std::move(rollback_cmd), loc} {} }; } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/doc/000077500000000000000000000000001516427024100164015ustar00rootroot00000000000000libpqxx-8.0.1/include/pqxx/doc/accessing-results.md000066400000000000000000000240561516427024100223700ustar00rootroot00000000000000Accessing results and result rows {#accessing-results} ================================= A query produces a result set consisting of rows, and each row consists of fields. There are several ways to receive this data. The fields are _untyped._ That is to say, libpqxx has no opinion on what their respective types are. The database sends the data in a very flexible textual format. When you read a field, you specify what type you want it to be, and libpqxx converts the text format to that type for you. If a value does not conform to the format for the type you specify, the conversion fails. For example, if you have strings that all happen to contain numbers, you can read them as `int`. But if any of the values is empty, or it's null (for a type that doesn't support null), or it's some string that does not look like an integer, or it's too large, you can't convert it to `int`. So usually, reading result data from the database means not just retrieving the data; it also means converting it to some target type. Querying rows of data --------------------- The simplest way to query rows of data is to call one of a transaction's "query" functions, passing as template arguments the types of columns you want to get back (e.g. `int`, `std::string`, `double`, and so on) and as a regular argument the query itself. You can then iterate over the result to go over the rows of data: ```cxx for (auto [id, value] : tx.query("SELECT id, name FROM item")) { std::cout << id << '\t' << value << '\n'; } ``` The "query" functions execute your query, load the complete result data from the database, and iterate them. Along the way they convert each row to a tuple of C++ types that you indicated. There are different query functions for querying any number of rows (`query()`); querying just one row of data as a `std::tuple` and throwing an error if it doesn't produce exactly one row (`query1()`); or querying either zero or one rows and getting a `std::optional` tuple of the values converted to the respective types you requested. Streaming rows -------------- There's another way to go through the rows coming out of a query. It's usually easier and faster if there are a lot of rows, but there are drawbacks. **One,** you start getting rows before all the data has come in from the database. That speeds things up, but what happens if you lose your network connection while transferring the data? Your application may already have processed some of the data before finding out that the rest isn't coming. If that is a problem for your application, streaming may not be the right choice. **Two,** streaming only works for some types of query. The `stream()` function wraps your query in a PostgreSQL `COPY` command, and `COPY` only supports a few commands: `SELECT`, `VALUES`, or an `INSERT`, `UPDATE`, or `DELETE` with a `RETURNING` clause. See the `COPY` documentation here: [ https://www.postgresql.org/docs/current/sql-copy.html ](https://www.postgresql.org/docs/current/sql-copy.html). **Three,** when you convert a field to a "view" type (such as `std::string_view` or `pqxx::bytes_view`), the view points to underlying data which only stays valid until you iterate to the next row or exit the loop. So if you want to use that data for longer than a single iteration of the streaming loop, you'll have to store it somewhere yourself. Now for the good news. Streaming does make it very easy to query data and loop over it, and often faster than with the "query" or "exec" functions: ```cxx for (auto [id, name, x, y] : tx.stream( "SELECT id, name, x, y FROM point")) process(id + 1, "point-" + name, x * 10.0, y * 10.0); ``` The conversion to C++ types (here `int`, `std::string_view`, and two `float`s) is built into the function. You never even see `row` objects, `field` objects, iterators, or conversion methods. You just put in your query and you receive your data. The 'result' class ------------------ Sometimes you want more from a query result than just rows of data. You may need to know how many rows your `UPDATE` statement has affected, or the names of the columns, and so on. For that, use the transaction's `exec()` function. It returns a `pqxx::result` object. A `result` is really a smart pointer to a data structure managed by the C library, libpq. But seen from the outside, it _acts_ like a random-access container of rows of data, which you can iterate like any other container, or index them like you would index an array. Each row in turn is a container of field values. And finally, each field holds a value. Since `result` is at its core just a smart pointer, it is fairly cheap to copy: it doesn't copy the data, it just creates an extra reference to the same underlying data structure. When you destroy the last copy of the original `result` object you got back from the database, that will destroy the underlying data structure as a side effect. ### Rows and fields A field does not know what type of data it contains. It holds the data in string form. So, _you_ specify the type when you read the value (using functions like `as()`), and the field will convert its string representation to that type. By the way, there are no separate objects holding the rows or the fields. That data is all held inside the data structure managed by libpq. There are however two classes representing a row of data, and two classes representing a field: 1. _`row_ref`_: effectively a pointer to the `result`, plus a row number. 2. _`row`_: effectively a _copy_ of the `result`, plus a row number. 3. _`field_ref`_: effectively a pointer to the `result`, with row & column numbers. 4. _`field`_: effectively a copy of the result, with row & column numbers. When you index a `result` or dereference a `result` iterator, you get a `row_ref`. When you index a `row_ref` or `row` or dereference an iterator of either, you get a `field_ref`. Usually you'll deal with `row_ref` and `field_ref`. These are effficient, cheap to copy, and straightforward. All you really need to do is ensure that the `result` object does not move in memory, or get destroyed. In rare cases you may need to reference a row or field but without keeping the `result`, you can use a `row` or `field` object. These are less efficient, but they keep a `result` object so that the underlying data structure does not get destroyed so long as you stlil have a `row` or `field` referencing it. ### Iterating rows and fields For example, your code might just read it as raw text using `c_str()`: ```cxx pqxx::result r = tx.exec("SELECT * FROM mytable"); for (auto const &row_ref: r) { for (auto const &field_ref: row) std::cout << field.c_str() << '\t'; std::cout << '\n'; } ``` ### Data types Or you can ask for the field to convert itself to some other C++ type, using `as()`: ```cxx pqxx::result r = tx.exec("SELECT number, number * 2 FROM data"); for (auto const &row: r) { for (auto const &field: row) { int n = field.as(); double f = field.as(); std::cout << n << '\t << f << '\n'; } } ``` ### Indexing But results and rows also support other kinds of access. Array-style indexing, for instance, such as `r[rownum]`: ```cxx std::size_t const num_rows = std::size(r); for (std::size_t rownum=0u; rownum < num_rows; ++rownum) { pqxx::row_ref const row = r[rownum]; std::size_t const num_cols = std::size(row); for (std::size_t colnum=0u; colnum < num_cols; ++colnum) { pqxx::field_ref const field = row[colnum]; std::cout << field.c_str() << '\t'; } std::cout << '\n'; } ``` Every row in the result has the same number of columns, so you don't need to look up the number of fields again for each one: ```cxx std::size_t const num_rows = std::size(r); std::size_t const num_cols = r.columns(); for (std::size_t rownum=0u; rownum < num_rows; ++rownum) { pqxx::row_ref const row = r[rownum]; for (std::size_t colnum=0u; colnum < num_cols; ++colnum) { pqxx::field_ref const field = row[colnum]; std::cout << field.c_str() << '\t'; } std::cout << '\n'; } ``` You can even address a field by indexing the `row` using the field's _name:_ ```cxx std::cout << row["salary"] << '\n'; ``` But try not to do that if speed matters, because looking up the column by name takes time. At least you'd want to look up the column index before your loop and then use numerical indexes inside the loop. For C++23 or better, there's also a two-dimensional array access operator, which is actually a little faster than the classic indexing: ```cxx for (std::size_t rownum=0u; rownum < num_rows; ++rownum) { for (std::size_t colnum=0u; colnum < num_cols; ++colnum) std::cout result[rownum, colnum].c_str() << '\t'; std::cout << '\n'; } ``` ### Going old-school And of course you can use classic "begin/end" loops: ```cxx for (auto row = std::begin(r); row != std::end(r); row++) { for (auto field = std::begin(row); field != std::end(row); field++) std::cout << field->c_str() << '\t'; std::cout << '\n'; } ``` Fine print ---------- Result sets are immutable, so all iterators on results and rows are actually `const_iterator`s. There are also `const_reverse_iterator` types, which iterate backwards from `rbegin()` to `rend()` exclusive. All these iterator types provide one extra bit of convenience that you won't normally find in C++ iterators: referential transparency. You don't need to dereference them to get to the row or field they refer to. That is, instead of `row->end()` you can also choose to say `row.end()`. Similarly, you may prefer `field.c_str()` over `field->c_str()`. This becomes really helpful with the array-indexing operator. With regular C++ iterators you would need ugly expressions like `(*row)[0]` or `row->operator[](0)`. With the iterator types defined by the result and row classes you can simply say `row[0]`. libpqxx-8.0.1/include/pqxx/doc/binary-data.md000066400000000000000000000033111516427024100211140ustar00rootroot00000000000000Binary data {#binary} =========== The database has two ways of storing binary data: `BYTEA` is like a string, but containing bytes rather than text characters. And _large objects_ are more like a separate table containing binary objects. Generally you'll want to use `BYTEA` for reasonably-sized values, and large objects for very large values. That's the database side. On the C++ side, in libpqxx, all binary data must be some block of contiguous `std::byte` values in memory. That could be a `std::vector`, or `std::span`, and so on. However the _preferred_ types for binary data in libpqxx are... * `pqxx::bytes` for storing the data, similar to `std::string` for text. * `pqxx::bytes_view` for reading data stored elsewhere, similar to how you'd use `std::string_view` for text. * `pqxx::writable_bytes_view` for writing to data stored elsewhere. So for example, if you want to write a large object, you'd create a `pqxx::blob` object. You might use that to write data which you pass in the form of a `pqxx::bytes_view`. You might then read that data back by letting `pqxx::blob` write the data into a `pqxx::bytes &` or a `pqxx::writable_bytes_view` that you give it. So long as it's _basically_ still a block of bytes though, you can use `pqxx::binary_cast` to construct a `pqxx::bytes_view` from it: ```cxx std::string hi{"Hello binary world"}; my_blob.write(pqxx::binary_cast(hi); ``` For convenience there's also a form of `binary_cast` that takes a pointer and a length. ```cxx char const greeting[] = "Hello binary world"; char const *hi = greeting; my_blob.write(pqxx::binary_cast(hi, sizeof(greeting))); ``` libpqxx-8.0.1/include/pqxx/doc/datatypes.md000066400000000000000000000516551516427024100207350ustar00rootroot00000000000000Supporting additional data types {#datatypes} ================================ Communication with the database mostly happens in a text format. When you include an integer value in a query, either you use `to_string` to convert it to that text format, or you pass it as a paraemeter and libpqxx does it for you under the bonnet. When you get a query result field "as a float," libpqxx converts from the text format to a floating-point type. These conversions are everywhere in libpqxx. The conversion system supports many built-in types, but it is also extensible. You can "teach" libpqxx (in the scope of your own application) to convert additional types of values to and from PostgreSQL's string format. This is massively useful, but it's not for the faint of heart. You'll need to specialise several templates. And, **the API for doing this can change with any major libpqxx release.** If that happens, your code may fail to compile with the newer libpqxx version, and you'll have to go through the `NEWS` file to find the API changes. Usually it'll be a small change, like an additional function you need to implement, or a constant you need to define. Converting types ---------------- In your application, a conversion is driven entirely by a C++ type you specify. The value's SQL type on the database side has nothing to do with it. Nor is there anything in the string that would identify its type. Your code says "convert to this type" and libpqxx does it. So, if you've SELECTed a 64-bit integer from the database, and you try to convert it to a C++ `short,` one of two things will happen: either the number is small enough to fit in your `short` and it just works, or else it throws a conversion exception. Similarly, if you try to read a 32-bit SQL `int` as a C++ 32-bit `unsigned int`, that'll work fine, unless the value happens to be negative. In such cases the conversion will throw a `conversion_error`. Or, your database table might have a text column, but a given field may contain a string that _looks_ just like a number. You can convert that value to an integer type just fine. Or to a floating-point type. All that matters to the conversion is the actual value, and the type that your code specifies. Conversions to strings can tell the type from the arguments you pass them: ```cxx auto x = to_string(99); ``` For conversions in the other direction you need to instantiate the function template explicitly: ```cxx auto y = from_string("99"); ``` Supporting a new type --------------------- Let's say you have some other SQL type which you want to be able to store in, or retrieve from, the database. What would it take to support that? Sometimes you do not need _complete_ support. You might need a conversion _to_ a string but not _from_ a string, or vice versa. You write out the conversion at compile time, so don't be too afraid to be incomplete. If you leave out one of these steps, it's not going to crash at run time or mess up your data. The worst that can happen is that your code won't build. So what do you need for a complete conversion? First off, of course, you need a C++ type. It may be your own, but it doesn't have to be. It could be a type from a third-party library, or even one from the standard library that libpqxx does not yet support. First thing to do is specialise the `pqxx::name_type()` function to give the type a human-readable name. That allows libpqxx error messages and such to talk about the type in a clear way. If you don't define it, libpqxx will try to figure one out with some help from the compiler, but it may not always be easy to read. In C++26 we expect to get a standard way to query the name, but until then it's a bit messy. Then, does your type have a built-in null value? For example, a `char *` can be null on the C++ side. Or some types are _always_ null, such as `nullptr`. You specialise the `pqxx::nullness` template to specify the details. Finally, you specialise the `pqxx::string_traits` template. This is where you define the actual conversions. Let's go through these steps one by one. Your type --------- You'll need a type for which the conversions are not yet defined, because the C++ type is what determines the right conversion. One type gets one pair of conversions (to/from SQL strings). The type doesn't have to be one that you create. The conversion logic was designed such that you can build it around any type. So you can just as easily build a conversion for a type that's defined somewhere else. There's no need to include any special methods or other members inside the type itself. This is also why libpqxx can convert built-in types like `int`. The library also provides conversions for `std::optional`, `std::shared_ptr`, and `std::unique_ptr` (for any given `T`). If you have conversions for `T`, you'll also automatically have conversions for those. Specialise 'name\_type()' ------------------------- (This is a feature that should disappear once we have introspection in the C++ language. The current expectation is that C++26 will have a standard, reliable way for the code to obtain a type's name.) When errors happen during conversion, libpqxx will compose an error message that the application can show to the user, or write to a log. Sometimes this message will need to mention the name of the type that's being converted. By default, this will probably work fine on some compilers, or the name may come out a little strange on other compilers, but some make the names harder to recognise. So it can help to define a name yourself. To tell libpqxx the human-readable name of a type `T`, there's a function template called `pqxx::name_type()`. This function should exist for any given type `T`: ```cxx // T is your type. namespace pqxx { template<> inline constexpr std::string_view name_type() noexcept { return "My T type's name"; }; } ``` (Yes, this means that you need to define something inside the pqxx namespace.) Define this early on in your translation unit, before any code that might cause libpqxx to need the name. That way, the libpqxx code which needs to know the type's name can see your definition. In cases where the name is not a simple compile-time constant but needs code to compute, you may need to make its type `std::string`. A `string_view` does not maintain storage space for the text it contains. However, some code analysis tools may report false posiives when initialising such strings at initialisation time. Specialise 'nullness' --------------------- A struct template `pqxx::nullness` defines whether your type has a natural "null value" built in. For example, a `std::optional` instantiation has a value that neatly maps to an SQL null: the un-initialised state. If your type has a value like that, its `pqxx::nullness` specialisation also provides member functions for producing and recognising null values. The simplest scenario is also the most common: most types don't have a null value built in. There is no "null `int`" in C++. In that kind of case, just derive your nullness traits from `pqxx::no_null` as a shorthand: This tells libpqxx that your type has no null value of its own. ```cxx // T is your type. namespace pqxx { template<> struct nullness : pqxx::no_null {}; } ``` (Here again you're defining this in the pqxx namespace.) Nullness is not part of the `string_traits` because as far as the string conversion system is concerned, a null is not a value! You can't convert it to or from a string. Consider what would happen if you tried to convert a null value to an SQL string: you'd get a string containing the value `NULL`, not the null value. Handling of nulls happens at a higher level, when passing parameters to SQL statements, or quoting-and-escaping values for inclusion in SQL statements as literal values. If your type has a natural null value, the definition for `nullness` gets a little more complex than the one above: ```cxx namespace pqxx { // T is your type. template<> struct nullness { // Does T have a value that should translate to an SQL null? static constexpr bool has_null{true}; // Does this C++ type _always_ denote an SQL null, like with nullptr_t? static constexpr bool always_null{false}; // Is `value` a null? static bool is_null(T const &value) { return ...; } // Return a null. [[nodiscard]] static T null() { return ...; } }; } ``` (In writing an application, if you have a type like `int` that doesn't have a null value but you need to pass or parse an SQL value that may be null, you can use `std::optional` instead. An `optional` without a value is a null.) You may be wondering why there's a function to produce a null value, but also a function to check whether a value is null. Why not just compare the value to the result of `null()`? Because two null values may not be equal. It could be like in SQL, where `NULL` is not equal to anything including `NULL`. Or there may be several different null values. Or `T` may override the comparison operator to behave in some unusual way. As a third case, your type may be one that _always_ represents a null value. This is the case for `std::nullptr_t` and `std::nullopt_t`. In a case like that, you set `nullness::always_null` to `true` (as well as `has_null` of course), and you won't need to define any actual conversions. Specialise 'string\_traits' -------------------------- This part is the most work. You can skip it for types that are always null, but of course those are extremely rare. The APIs for doing this are designed to avoid, where opssible, the need to allocate memory on the free store (a.k.a. "the heap"). In other words, the API minimises use of `new`/`delete`, even ones hidden inside `std::string`, `std::vector`, etc. The conversion API allows you to use `std::string` for convenience, or fixed memory buffers for maximum speed. Start by specialising the `pqxx::string_traits` template. It has conversion functions going in both directions: from a C++ value to an SQL string, and from an SQL string to a C++ value. You don't absolutely have to implement both. Generally, if the code you need compiles, you're OK for the time being. Just bear in mind that future libpqxx versions may change the API — or how it uses the API internally. In fact libpqxx 8.0 made a lot of changes compared to 7.x. As of 8.0, this is what a full specialisation of `string_traits` looks like: ```cxx namespace pqxx { // T is your type. template<> struct string_traits { // If you support conversion _to_ an SQL string: // Represent `value` as a string, using `buf` for storage if needed. // (But the result may live somewhere outside the buffer, or lie inside // it but not start exactly at the beginning of the buffer. It may even // be a reference back to `value` itself.) // // We'll explain the context `c` further down. static [[nodiscard]] std::string_view to_buf( std::span buf, T const &value, ctx c = {}); // Converting value to string may require at most this much buffer space. static [[nodiscard]] std::size_t size_buffer(T const &value) noexcept; // If you support conversion _from_ an SQL string: // Parse `text` as a T value. static [[nodiscard]] T from_string(std::string_view text, ctx c = {}); }; } ``` In your own code, you typically wouldn't call these functions yourself by the way. Instead you'd call global wrappers: `pqxx::to_string()`, `pqxx::to_buf()`, `pqxx::into_buf()` (it's subtly different), and `pqxx::size_buffer()`. ### `ctx` Notice those `ctx` parameters, with a default value of `{}`? These hold some additional "context" information for the conversion. It has no clearly defined role, except to hold extra information that your conversion may or may not need. Passing it in this way makes it easier for libpqxx to extend the conversion API further in the future without breaking compatibility. The name `ctx` is shorthand for `pqxx::conversion_context const t&`. There are reasonable defaults for every item in there, so it's acceptable for a caller to leave it out. As of libpqxx 8.0, `conversion_context` contains: * `pqxx::encoding_group enc`. This tells the conversion just enough about the text's encoding do to its job. It doesn't say exactly whether the text is in UTF-8, or Latin-15, or EUC-KR, and so on. But it's enough that the code can figure out where each character begins and ends, which is all the understanding that it really needs. which is all that most conversions need. * `std::source_location loc`. We abbreviate that type as `pqxx::sl` because it shows up in so many places. In case the conversion throws an exception, the exception can include this source location in its message as a debugging hint. There may be more fields in the future. The encoding group defaults to a special group, `unknown`. This is good enough for dealing with plain ASCII text, which is all that most conversions need. If your conversion does need to know the text's encoding, it is up to the code calling the conversion to pass that information along. The source location defaults to the location of the immediate calling code. But if that caller is also within libpqxx, this isn't usually very helpful to application authors trying to debug errors. Therefore we try to pass the location where control last transferred from the application into libpqxx. ### `from_string` Now we start implementing the functions. We start off simple: `from_string` parses a string as an SQL value and translates it into a C++ value of type `T` (your type). The string is a `std::string_view`, which means it doesn't necessarily end in a terminating zero. In many situations there will still be a zero just after the string, so be sure to have your tests cover cases where there's a non-zero byte behind the string! It's always possible that the string doesn't actually represent a `T` value. Mistakes happen. There can be corner cases. Maybe a value is outside the range you can reasonably support, such as when you're trying to read an SQL `integer` into an `unsigned int` and it happens to be negative. When you run into that kind of thing, throw a `pqxx::conversion_error`. (Of course it's also possible that you run into some other error, so it's fine to throw different exceptions as well. But when it's definitely "this is not the right format for a `T`," throw `conversion_error`.) ### `to_buf` In this function, you convert a value of `T` into a string that the postgres server will understand. The caller will provide you with a buffer where you can write the string, if you need it. But for this function it doesn't really matter where you store the string: somewhere inside the buffer, or as a string constant, or even by referring to the input value. The buffer is just there in case that you need it. Usually you do. What you can _not_ do is allocate some memory to store your SQL text. If `buf` is not large enough to store your output, throw a `pqxx::conversion_overrun`. This doesn't have to be exact: you can be a little pessimistic and demand a bit more space than you actually need. We'll get to the negotiation for how much buffer space you need later. Just be sure to throw the exception if there's any risk of overrunning the buffer. Beware of locales when converting. If you use standard library features like `sprintf`, they may obey whatever locale is currently set on the system where the code runs. That means that a simple integer like 1000000 may come out as "1000000" on your system, but as "1,000,000" on mine, or as "1.000.000" for somebody else, and on an Indian system it may be "1,00,000". Don't let that happen, or it will confuse things. Use only non-locale-sensitive library functions. Values coming from or going to the database should be in fixed, non-localised formats. If your type contains fields of types that libpqxx already supports, you can use the existing conversion functions for those: `pqxx::from_string`, `pqxx::to_string`, `pqxx::to_buf`, etc. They in turn will call the `string_traits` specialisations for those types. For example, if you wanted to convert a date, you might use the `int` conversions for each of the year, month, and date numbers. ### `size_buffer` Here you estimate how much buffer space you may need for converting a `T` to an SQL string. Be precise if you can, but pessimistic if you must. It's usually better to waste a few bytes of space than to spend a lot of time computing the exact buffer space you need. And failing the conversion because you under-budgeted the buffer is worst of all. Make `size_buffer` a `constexpr` function if you can. It may sometiems allow the caller to allocate the buffer on the stack, with a size known at compile time. Optional: Specialise 'is\_unquoted\_safe' ----------------------------------------- When converting arrays or composite values to strings, libpqxx may need to quote values and escape any special characters. This takes time. Some types though, such as integral or floating-point types, can never have any special characters such as quotes, commas, or backslashes in their string representations. In such cases, there's no need to quote or escape such values in SQL arrays or composite types. If your type is like that, you can tell libpqxx about this by defining: ```cxx namespace pqxx { // T is your type. template<> inline constexpr bool is_unquoted_safe{true}; } ``` The code that converts this type of field to strings in an array or a composite type can then use a simpler, more efficient variant of the code. It's always safe to leave this out; it's _just_ an optimisation for when you're completely sure that it's safe. Make sure this definition is visible wherever you call libpqxx code that may call your conversoin. Do not do this if a string representation of your type may contain a comma; semicolon; parenthesis; brace; quote; backslash; newline; or any other character that might need escaping. Optional: Specialise 'param\_format' ------------------------------------ This one you don't generally need to worry about. Read on if you're writing a type which represents raw binary data, or if you're writing a template where _some specialisations_ may contain raw binary data. When you call parameterised statements, or prepared statements with parameters, libpqxx needs to pass your parameters on to libpq, the underlying C-level PostgreSQL client library. There are two formats for doing that: _text_ and _binary._ In the first, we represent all values as strings in the PostgreSQL text format, and the server then converts them into its own internal binary representation. That's what those string conversions above are all about, and it's what we do for almost all types of parameters. But we do it differently when the parameter is a contiguous series of raw bytes and the corresponding SQL type is `BYTEA`. There is a text format for those, but we bypass it for efficiency. In this situation the server can use the binary data in the exact same form in which you provide it, without any conversion or extra processing. The binary data for BYTEA is also twice as compact during transport. (People sometimes ask why we can't just treat all types as binary. However the general case isn't so clear-cut. The binary formats are not documented, there are no guarantees that they will be platform-independent or that they will remain stable across postgres releases, and there's no really solid way to detect when we might get the format wrong. On top of all that, the conversions aren't necessarily as straightforward and efficient as they sound. So, for the general case, libpqxx sticks with the text formats. Raw binary data alone stands out as a clear win.) Long story short, the machinery for passing parameters needs to know: is this parameter a binary string, or not? In the normal case it can assume "no," and that's what it does. The text format is always a safe choice; we just try to use the binary format where it's faster, and safe. The `param_format` function template is what drives the decision. We specialise it for types which may be binary strings, and use the default for all other types. "Types which _may_ be binary"? You might think we know whether a type is a binary type or not. But there are some complications with generic types. Templates like `std::shared_ptr`, `std::optional`, and so on act like "wrappers" for another type. A `std::optional` is binary if `T` is binary. Otherwise, it's not. And `std::variant` may contain wildly different types, so the decision can even be based on the individual object rather than just the type. If you're building support for a template of this nature, you'll probably want to implement `param_format` for it. Containers are another hard case. Should we pass `std::vector` in binary? Even when `T` is a binary type, we don't currently have any way to pass an array in binary format, so we always pass it as text. libpqxx-8.0.1/include/pqxx/doc/escaping.md000066400000000000000000000101221516427024100205100ustar00rootroot00000000000000String escaping {#escaping} =============== Writing queries as strings is easy. But sometimes you need a variable in there: `"SELECT id FROM user WHERE name = '" + name + "'"`. This is dangerous. See the bug? If `name` can contain quotes, you may have an SQL injection vulnerability there, where users can enter nasty stuff like "`.'; DROP TABLE user`". Or if you're lucky, it's just a nasty bug that you discover when `name` happens to be "d'Arcy". Or... Well, I was born in a place called _'s-Gravenhage..._ There are two ways of dealing with this. One is statement @ref parameters — many SQL execution functions in libpqxx let you write _placeholders_ for variable values in your SQL, like `$1`, `$2`, etc. When you then pass your variables as the parameter values, they get substituted into the query, but in a safe form. The other is to _escape_ the values yourself, before inserting them into your SQL. This isn't as safe as using parameters, since you need to be really conscientious about it. Use @ref parameters if you can... and libpqxx will do the escaping for you. In escaping, quotes and other problematic characters are marked as "this is just a character inside the string, not the end of the string." There are [several functions](@ref escaping-functions) in libpqxx to do this for you. SQL injection ------------- To understand what SQL injection vulnerabilities are and why they should be prevented, imagine you use the following SQL statement somewhere in your program: ```cxx tx.exec( "SELECT number, amount " "FROM account " "WHERE allowed_to_see('" + userid + "','" + password + "')"); ``` This shows a logged-in user important information on all accounts he is authorized to view. The userid and password strings are variables entered by the user himself. Now, if the user is actually an attacker who knows (or can guess) the general shape of this SQL statement, imagine getting the following password: ```text x') OR ('x' = 'x ``` Does that make sense to you? Probably not. But if this is inserted into the SQL string by the C++ code above, the query becomes: ```sql SELECT number, amount FROM account WHERE allowed_to_see('user','x') OR ('x' = 'x') ``` Is this what you wanted to happen? Probably not! The neat `allowed_to_see()` clause is completely circumvented by the "`OR ('x' = 'x')`" clause, which is always `true`. Therefore, the attacker will get to see all accounts in the database! Using the esc functions ----------------------- Here's how you can fix the problem in the example above: ```cxx tx.exec( "SELECT number, amount " "FROM account " "WHERE allowed_to_see('" + tx.esc(userid) + "', " "'" + tx.esc(password) + "')"); ``` Now, the quotes embedded in the attacker's string will be neatly escaped so they can't "break out" of the quoted SQL string they were meant to go into: ```sql SELECT number, amount FROM account WHERE allowed_to_see('user', 'x'') OR (''x'' = ''x') ``` If you look carefully, you'll see that thanks to the added escape characters (a single-quote is escaped in SQL by doubling it) all we get is a very strange-looking password string — but not a change in the SQL statement. In practice, of course, it would be better to use parameters: ```cxx tx.exec( " SELECT number, amount " "FROM account " "WHERE allowed_to_see($1, $2)", pqxx::params{tx, userid, password}); ``` You may be wondering why this passes `tx` into `params{...}`. That's not actually a parameter; it's just a way to inform the `params` constructor about the prevailing client encoding. It doesn't _usually_ need to know that, but it can come as a nasty surprise when suddenly it does, in the case of arrays or composite objects. So it's a good habit always to pass the transaction, or the connection, or a `pqxx::conversion_context`, or the `encoding_group` as the first parameter to let the `params` know what encoding to use. Especially so when you're using it in template code where the types of the parameters aren't necessarily known _a priori._ libpqxx-8.0.1/include/pqxx/doc/getting-started.md000066400000000000000000000131431516427024100220320ustar00rootroot00000000000000Getting started {#getting-started} =============== The most basic three types in libpqxx are the _connection_, the _transaction_, and the _result_. They fit together as follows: * You connect to the database by creating a `pqxx::connection` object (see @ref connections). * You create a transaction object (see @ref transactions) operating on that connection. You'll usually want the `pqxx::work` variety. Once you're done you call the transaction's `commit` function to make its work final. If you don't call this, the work will be rolled back when the transaction object is destroyed. * Until then, use the transaction's `exec`, `query_value`, and `stream` functions (and variants) to execute SQL statements. You pass the statements themselves in as simple strings. (See @ref streams for more about data streaming). * Most of the `exec` functions return a `pqxx::result` object, which acts as a standard container of rows: `pqxx::row`. Each row in a result, in turn, acts as a container of fields: `pqxx::field`. See @ref accessing-results for more about results, rows, and fields. * Each field's data is stored internally as a text string, in a format defined by PostgreSQL. You can convert field or row values using their `as()` and `to()` member functions. * After you've closed the transaction, the connection is free to run a next transaction. Here's a very basic example. It connects to the default database (you'll need to have one set up), queries it for a very simple result, converts it to an `int`, and prints it out. It also contains some basic error handling. ```cxx #include #include int main() { try { // Connect to the database. In practice we may have to pass some // arguments to say where the database server is, and so on. // The constructor parses options exactly like libpq's // PQconnectdb/PQconnect, see: // https://www.postgresql.org/docs/10/static/libpq-connect.html pqxx::connection cx; // Start a transaction. In libpqxx, you always work in one. pqxx::work tx(cx); // We'll just ask the database to return the number 1 to us. // The one_row() call checks that the result contains exactly one row // of data, and throws an exception if it does not. It returns the // row. pqxx::row r = tx.exec("SELECT 1").one_row(); // Commit your transaction. If an exception occurred before this // point, execution will have left the block, and the transaction will // have been destroyed along the way. In that case, the failed // transaction would implicitly abort instead of getting to this point. tx.commit(); // Look at the first and only field in the row, parse it as an integer, // and print it. // // "r[0]" returns the first field, which has an "as<...>()" member // function template to convert its contents from their string format // to a type of your choice. std::cout << r[0].as() << std::endl; } catch (std::exception const &e) { std::cerr << e.what() << std::endl; return 1; } } ``` This prints the number 1. Notice that you can keep the result object around after you've closed the transaction or even the connection. There are situations where you can't do it, but generally it's fine. If you're interested: you can install your own callbacks for receiving error messages from the database, and in that case you'll have to keep the connection object alive. But otherwise, it's nice to be able to "fire and forget" your connection and deal with the data. You can also convert an entire row to a series of C++-side types in one go, using the @c as member function on the row: ```cxx pqxx::connection cx; pqxx::work tx(cx); pqxx::row r = tx.exec("SELECT 1, 2, 'Hello'").one_row(); auto [one, two, hello] = r.as(); std::cout << (one + two) << ' ' << std::size(hello) << std::endl; ``` Here's a slightly more complicated example. It takes an argument from the command line and retrieves a string with that value. The interesting part is that it uses the escaping-and-quoting function `quote` to embed this string value in SQL safely. It also reads the result field's value as a plain C-style string using its `c_str` function. ```cxx #include #include #include int main(int, char *argv[]) { try { if (!argv[1]) throw std::runtime_error("Give me a string!"); pqxx::connection cx; pqxx::work tx(cx); // work::exec() returns a full result set, which can consist of any // number of rows. pqxx::result r = tx.exec("SELECT $1", pqxx::params{argv[1]}); // End our transaction here. We can still use the result afterwards. tx.commit(); // Print the first field of the first row. Read it as a C string, // just like std::string::c_str() does. std::cout << r[0][0].c_str() << std::endl; } catch (std::exception const &e) { std::cerr << e.what() << std::endl; return 1; } } ``` You can find more about converting field values to native types, or converting values to strings for use with libpqxx, under @ref stringconversion. More about getting to the rows and fields of a result is under @ref accessing-results. If you want to handle exceptions thrown by libpqxx in more detail, for example to print the SQL contents of a query that failed, see @ref exception. libpqxx-8.0.1/include/pqxx/doc/mainpage.md000066400000000000000000000015501516427024100205050ustar00rootroot00000000000000libpqxx {#mainpage} ======= @version 8.0.1 @author Jeroen T. Vermeulen @see https://pqxx.org/libpqxx/ @see https://github.com/jtv/libpqxx Welcome to libpqxx, the C++ API to the PostgreSQL database management system. Compiling this package requires PostgreSQL to be installed -- including the C headers for client development. The library builds on top of PostgreSQL's standard C API, libpq. The libpq headers are not needed to compile client programs, however. For a quick introduction to installing and using libpqxx, see the README.md file. The latest information can be found at [http://pqxx.org/](http://pqxx.org/). Some links that should help you find your bearings: * @ref getting-started * @ref thread-safety * @ref connections * @ref transactions * @ref escaping * @ref performance * @ref transactor * @ref datatypes libpqxx-8.0.1/include/pqxx/doc/mainpage.md.template000066400000000000000000000015601516427024100223200ustar00rootroot00000000000000libpqxx {#mainpage} ======= @version @PQXXVERSION@ @author Jeroen T. Vermeulen @see https://pqxx.org/libpqxx/ @see https://github.com/jtv/libpqxx Welcome to libpqxx, the C++ API to the PostgreSQL database management system. Compiling this package requires PostgreSQL to be installed -- including the C headers for client development. The library builds on top of PostgreSQL's standard C API, libpq. The libpq headers are not needed to compile client programs, however. For a quick introduction to installing and using libpqxx, see the README.md file. The latest information can be found at [http://pqxx.org/](http://pqxx.org/). Some links that should help you find your bearings: * @ref getting-started * @ref thread-safety * @ref connections * @ref transactions * @ref escaping * @ref performance * @ref transactor * @ref datatypes libpqxx-8.0.1/include/pqxx/doc/parameters.md000066400000000000000000000116061516427024100210720ustar00rootroot00000000000000Statement parameters {#parameters} ==================== In an SQL statement (including a prepared statemen), you may write special _placeholders_ in the query text. They look like `$1`, `$2`, and so on. When executing the query later, you pass parameter values. The call will respectively substitute the first parameter value where it finds `$1` in the query, the second where it finds `$2`, _et cetera._ For example, let's say you have a transaction called `tx`. Here's how you execute a plain statement: ```cxx pqxx::result r = tx.exec("SELECT name FROM employee where id=101"); ``` Inserting the `101` in there is awkward and even dangerous. We'll get to that in a moment. Here's how you do it better, using parameters: ```cxx pqxx::result r = tx.exec("SELECT name FROM employee WHERE id=$1", {101}); ``` That second argument to `exec()`, the `{101}`, constructs a `pqxx::params` object. The `exec()` call will fill this value in where the query says `$1`. Doing this saves you work. If you don't use statement parameters, you'll need to quote and escape your values (see `connection::quote()` and friends) as you insert them into your query as literal values. Or if you forget to do that, you leave yourself open to horrible [SQL injection attacks](https://xkcd.com/327/). Trust me, I was born in a town whose name started with an apostrophe! With parameters you can pass your values as they are, and they will go across the wire to the database in a safe format. In some cases it may even be faster! When a parameter represents binary data (as in the SQL `BYTEA` type), libpqxx will send it directly as binary, which is a bit more efficient than the standard textual format in which the data normally gets sent to the database. If you insert the binary data directly in your query text, your CPU will have some extra work to do, converting the data into a text format, escaping it, and adding quotes; and the data will take up more bytes, which take time to transmit. Multiple parameters ------------------- The `pqxx::params` class is quite flexible. It can contain any number of parameter values, of many different types. You can pass them in while constructing the `params` object: ```cxx pqxx::params{23, "acceptance", 3.14159} ``` Or you can add them one by one: ```cxx pqxx::params p; p.append(23); p.append("acceptance"); p.append(3.14159); ``` You can also combine the two, passing some values int the constructor and adding the rest later. You can even insert a `params` into a `params`: ```cxx pqxx::params p{23}; p.append(params{"acceptance", 3.14159}); ``` Each of these examples will produce the same list of parameters. Encodings and complex parameters -------------------------------- For some parameter types, the `params` code will need to know about the text encoding. This happens especially with composite types. You may see errors about the encoding not being known. To prevent that, pass as your first parameter the `pqxx::encoding_group` for the connection's current client encoding. You can get this by calling the connection's `get_encoding_group()` member function, but as a shortcut, you may just pass in a reference to your connection or your transaction instead. Or if you already had a `pqxx::conversion_context`, you can pass that instead. In those cases, that special first argument will _not_ become a parameter to the SQL statement. It will only be used to obtain the necessary text encoding information. Generating placeholders ----------------------- If your code gets particularly complex, it may sometimes happen that it becomes hard to track which parameter value belongs with which placeholder. Did you intend to pass this numeric value as `$7`, or as `$8`? The answer may depend on an `if` that happened earlier in a different function. (Generally if things get that complex, it's a good idea to look for simpler solutions. But especially when performance matters, sometimes you can't avoid complexity like that.) There's a little helper class called `placeholders`. You can use it as a counter which produces those placeholder strings, `$1`, `$2`, `$3`, et cetera. When you start generating a complex statement, you can create both a `params` and a `placeholders`: ```cxx pqxx::params values; pqxx::placeholders name; ``` Let's say you've got some complex code to generate the conditions for an SQL "WHERE" clause. You'll generally want to do these things close together in your, so that you don't accidentally update one part and forget another: ```cxx if (extra_clause) { // Extend the query text, using the current placeholder. query += " AND x = " + name.get(); // Add the parameter value. values.append(my_x); // Move on to the next placeholder value. name.next(); } ``` Depending on the starting value of `name`, this might add to `query` a fragment like " `AND x = $3` " or " `AND x = $5` ". libpqxx-8.0.1/include/pqxx/doc/performance.md000066400000000000000000000023541516427024100212300ustar00rootroot00000000000000Performance features {#performance} ==================== If your program's database interaction is not as efficient as it needs to be, the first place to look is usually the SQL you're executing. But libpqxx has a few specialized features to help you squeeze more performance out of how you issue commands and retrieve data: * @ref streams. Use these as a faster way to transfer data between your code and the database. * `std::string_view` and `pqxx::zview`. In places where traditional C++ worked with `std::string`, see whether `std::string_view` or `pqxx::zview` will do. Of course that means that you'll have to look at the data's lifetime more carefully, but it'll save the computer a lot of copying. * @ref prepared. These can be executed many times without the server parsing and planning them anew each time. They also save you having to escape string parameters. * `pqxx::pipeline` lets you send queries to the database in batches, and continue other processing while they are executing. * `pqxx::connecting` lets you start setting up a database connection, but without blocking the thread. As always of course, don't risk the quality of your code for optimizations that you don't need! libpqxx-8.0.1/include/pqxx/doc/prepared-statement.md000066400000000000000000000126221516427024100225320ustar00rootroot00000000000000Prepared statements {#prepared} =================== Prepared statements are SQL queries that you define once and then invoke as many times as you like, typically with varying parameters. It's a lot like a function that you can define ad hoc, within the scope of one connection. If you have an SQL statement that you're going to execute many times in quick succession, it _may_ (but see below!) be more efficient to prepare it once and reuse it. This saves the database backend the effort of parsing the SQL and figuring out an efficient execution plan. Preparing a statement --------------------- You create a prepared statement by preparing it on the connection (using the `pqxx::connection::prepare` functions), passing an identifying name for the statement, and its SQL text. The statement's name should consist of ASCII letters, digits, and underscores only, and start with an ASCII letter. The name is case-sensitive. ```cxx void prepare_my_statement(pqxx::connection &cx) { cx.prepare( "my_statement", "SELECT * FROM Employee WHERE name = 'Xavier'"); } ``` Once you've done this, you'll be able to call `my_statement` from any transaction you execute on the same connection. For this, call `pqxx::transaction_base::exec()` and pass a `pqxx::prepped` object instead of an SQL statement string. The `pqxx::prepped` type is just a wrapper that tells the library "this is not SQL text, it's the name of a prepared statement." ```cxx pqxx::result execute_my_statement(pqxx::transaction_base &t) { return t.exec(pqxx::prepped{"my_statement"}); } ``` Parameters ---------- You can pass parameters to a prepared statement, just like you can with a regular statement. The query text can contain `$1`, `$2` etc. as placeholders for parameter values that you will provide when you invoke the prepared statement. See @ref parameters for more about this. And here's a simple example of preparing a statement and invoking it with parameters: ```cxx void prepare_find(pqxx::connection &cx) { // Prepare a statement called "find" that looks for employees with a // given name (parameter 1) whose salary exceeds a given number // (parameter 2). cx.prepare( "find", "SELECT * FROM Employee WHERE name = $1 AND salary > $2"); } ``` This example looks up the prepared statement "find," passes `name` and `min_salary` as parameters, and invokes the statement with those values: ```cxx pqxx::result execute_find( pqxx::transaction_base &tx, std::string name, int min_salary) { return tx.exec(pqxx::prepped{"find"}, pqxx::params{name, min_salary}); } ``` A special prepared statement ---------------------------- You may sometimes see an error message about a prepared statement whose name is just an empty string. That is a special name that libpq uses internally when you execute an SQL statement with parameters, but don't actually prepare it with a name. Performance note ---------------- Don't _assume_ that using prepared statements will speed up your application. There are cases where prepared statements are actually slower than plain SQL. The reason is that the backend can often produce a better execution plan when it knows the statement's actual parameter values. For example, say you've got a web application and you're querying for users with status "inactive" who have email addresses in a given domain name X. If X is a very popular provider, the best way for the database engine to plan the query may be to list the inactive users first and then filter for the email addresses you're looking for. But in other cases, it may be much faster to find matching email addresses first and then see which of their owners are "inactive." A prepared statement must be planned to fit either case, but a direct query will be optimised based on table statistics, partial indexes, etc. So, as with any optimisation... measure where your real performance problems are before you start making changes, and then afterwards, measure whether your changes actually helped. Don't complicate your code unless it solves a real problem. Knuth's Law applies. Zero bytes ---------- @warning Beware of zero ("nul") bytes! Since libpqxx is a wrapper around libpq, the C-level client library, most strings you pass to the library should be compatible with C-style strings. So they must end with a single byte with value 0, and the text within them cannot contain any such zero bytes. (The `pqxx::zview` type exists specifically to tell libpqxx: "this is a C-compatible string, containing no zero bytes but ending in a zero byte.") One example is prepared statement names. But the same also goes for the parameters values. Any string you pass as a parameter will end at the _first char with value zero._ If you pass a string that contains a zero byte, the last byte in the value will be the one just before the zero. So, if you need a zero byte in a string, consider that it's really a _binary string,_ which is not the same thing as a text string. SQL represents binary data as the `BYTEA` type, or in binary large objects ("blobs"). In libpqxx, you represent binary data as a range of `std::byte`. They must be contiguous in memory, so that libpqxx can pass pointers to the underlying C library. So you might use `pqxx::bytes`, or `pqxx::bytes_view`, or `std::vector`, or `std::array`, or `std::span`, etc. libpqxx-8.0.1/include/pqxx/doc/streams.md000066400000000000000000000203071516427024100204030ustar00rootroot00000000000000Streams {#streams} ======= Most of the time it's fine to retrieve data from the database using `SELECT` queries, and store data using `INSERT`. But for those cases where efficiency matters, there are two _data streaming_ mechanisms to help you do this more efficiently: "streaming queries," for reading query results from the database; and the @ref pqxx::stream_to class, for writing data from the client into a table. These are less flexible than SQL queries. _You can't pass parameters into streaming queries._ There are also some complex constructs that won't work due to limitations in underlying protocol layers. But, you get some scalability and memory efficiencies in return. Just like regular querying, these streaming mechanisms do data conversion for you. You deal with the C++ data types, and the database deals with the SQL data types. Interlude: null values ---------------------- So how do you deal with nulls? It depends on the C++ type you're using. Some types may have a built-in null value. For instance, if you have a `char const *` value and you convert it to an SQL string, then converting a `nullptr` will produce a NULL SQL value. But what do you do about C++ types which don't have a built-in null value, such as `int`? The trick is to wrap it in `std::optional`. The difference between `int` and `std::optional` is that the former always has an `int` value, and the latter doesn't have to. Actually it's not just `std::optional`. You can do the same thing with `std::unique_ptr` or `std::shared_ptr`. A smart pointer is less efficient than `std::optional` in most situations because they allocate their value on the heap, but sometimes that's what you want in order to save moving or copying large values around. This part is not generic though. It won't work with just any smart-pointer type, just the ones which are explicitly supported: `shared_ptr` and `unique_ptr`. If you really need to, you can build support for additional wrappers and smart pointers by copying the implementation patterns from the existing smart-pointer support. Streaming data from a query --------------------------- Use @ref transaction_base::stream to read large amounts of data directly from the database. In terms of API it works just like @ref transaction_base::query, but it's faster than the `exec` and `query` functions For larger data sets. Also, you won't need to keep your full result set in memory. That can really matter with larger data sets. Another performance advantage is that with a streaming query, you can start processing your data right after the first row of data comes in from the server. With `exec()` or `query()` you need to wait to receive all data, and only then can you begin processing. With streaming queries you can be processing data on the client side while the server is still sending you the rest. Not all kinds of queries will work in a stream. Internally the streams make use of PostgreSQL's `COPY` command, so see the PostgreSQL documentation for `COPY` for the exact limitations. Basic `SELECT` and `UPDATE ... RETURNING` queries will just work, but fancier constructs may not. As you read a row, the stream converts its fields to a tuple type containing the value types you ask for: ```cxx for (auto [name, score] : tx.stream("SELECT name, points FROM score") ) process(name, score); ``` On each iteration, the stream gives you a `std::tuple` of the column types you specify. It converts the row's fields (which internally arrive at the client in text format) to your chosen types. The `auto [name, score]` in the example is a _structured binding_ which unpacks the tuple's fields into separate variables. If you prefer, you can choose to receive the tuple instead: `for (std::tuple :`. ### Is streaming right for my query? Here are the things you need to be aware of when deciding whether to stream a query, or just execute it normally. First, when you stream a query, there is no metadata describing how many rows it returned, what the columns are called, and so on. With a regular query you get a @ref result object which contains this metadata as well as the data itself. If you absolutely need this metadata for a particular query, then that means you can't stream the query. Second, under the bonnet, streaming from a query uses a PostgreSQL-specific SQL command `COPY (...) TO STDOUT`. There are some limitations on what kinds of queries this command can handle. These limitations may change over time, so I won't describe them here. Instead, see PostgreSQL's [COPY documentation](https://www.postgresql.org/docs/current/sql-copy.html) for the details. (Look for the `TO` variant, with a query as the data source.) Third: when you stream a query, you start receiving and processing data before you even know whether you will receive all of the data. If you lose your connection to the database halfway through, you will have processed half your data, unaware that the query may never execute to completion. If this is a problem for your application, don't stream that query! The fourth and final factor is performance. If you're interested in streaming, obviously you care about this one. I can't tell you _a priori_ whether streaming will make your query faster. It depends on how many rows you're retrieving, how much data there is in those rows, the speed of your network connection to the database, your client encoding, how much processing you do per row, and the details of the client-side system: hardware speed, CPU load, and available memory. Ultimately, no amount of theory beats real-world measurement for your specific situation so... if it really matters, measure. (And as per Knuth's Law: if it doesn't really matter, don't optimise.) That said, here are a few data points from some toy benchmarks: If your query returns e.g. a hundred small rows, it's not likely to make up a significant portion of your application's run time. Streaming is likely to be _slower_ than regular querying, but most likely the difference just won't amtter. If your query returns _a thousand_ small rows, streaming is probably still going to be a bit slower than regular querying, though "your mileage may vary." If you're querying _ten thousand_ small rows, however, it becomes more likely that streaming will speed it up. The advantage increases as the number of rows increases. That's for small rows, based on a test where each row consisted of just one integer number. If your query returns larger rows, with more columns, I find that streaming seems to become more attractive. In a simple test with 4 columns (two integers and two strings), streaming even just a thousand rows was considerably faster than a regular query. If your network connection to the database is slow, however, that may make streaming a bit _less_ effcient. There is a bit more communication back and forth between the client and the database to set up a stream. This overhead takes a more or less constant amount of time, so for larger data sets it will tend to become insignificant compared to the other performance costs. Streaming data into a table --------------------------- Use `stream_to` to write data directly to a database table. This saves you having to perform an `INSERT` for every row, and so it can be significantly faster if you want to insert more than just one or two rows at a time. As with `stream()` on a transaction, you can specify the table and the columns, and not much else. You insert tuple-like objects of your choice: ```cxx pqxx::stream_to stream{ tx, "score", std::vector{"name", "points"}}; for (auto const &entry: scores) stream << entry; stream.complete(); ``` Each row is processed as you provide it, and not retained in memory after that. The call to `complete()` is more important here than it is for `stream()`. It's a lot like a "commit" or "abort" at the end of a transaction. If you omit it, it will still be done automatically during the stream's destructor. But, since destructors can't throw exceptions, any failures at that stage won't be visible to your code. So, always call `complete()` at the end of a `stream_to`, to close it off properly. libpqxx-8.0.1/include/pqxx/doc/thread-safety.md000066400000000000000000000025531516427024100214700ustar00rootroot00000000000000Thread safety {#thread-safety} ============= This library does not contain any locking code to protect objects against simultaneous modification in multi-threaded programs. Therefore it is up to you, the user of the library, to ensure that your threaded client programs perform no conflicting operations concurrently. Most of the time this isn't hard. Result sets are immutable, so you can share them between threads without problem. The main rule is: @li Treat a connection, together with any and all objects related to it, as a "world" of its own. You should generally make sure that the same "world" is never accessed by another thread while you're doing anything non-const in there. That means: don't issue a query on a transaction while you're also opening a subtransaction, don't access a cursor while you may also be committing, and so on. In particular, cursors are tricky. It's easy to perform a non-const operation without noticing. So, if you're going to share cursors or cursor-related objects between threads, lock very conservatively! Use `pqxx::describe_thread_safety` to find out at runtime what level of thread safety is implemented in your build and version of libpqxx. It returns a `pqxx::thread_safety_model` describing what you can and cannot rely on. A command-line utility `tools/pqxxthreadsafety` prints out the same information. libpqxx-8.0.1/include/pqxx/encoding_group000066400000000000000000000006031516427024100205600ustar00rootroot00000000000000/** Client text encoding information. * * There is only minimal encoding awareness in libpqxx. The only thing the * library really needs to know is where in memory a given character ends. */ // Actual definitions in .hxx file so editors and such recognize file type #include "pqxx/internal/header-pre.hxx" #include "pqxx/encoding_group.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/encoding_group.hxx000066400000000000000000000107151516427024100213730ustar00rootroot00000000000000/** Enum type for supporting encodings in libpqxx * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_ENCODING_GROUP_HXX #define PQXX_ENCODING_GROUP_HXX #include #include "pqxx/types.hxx" namespace pqxx { /** The supported types of text encoding supported. * * See: * https://www.postgresql.org/docs/current/static/multibyte.html#CHARSET-TABLE * * This enum does not name the individual supported encodings, only the various * schemes for determining where in memory a character ends and a potential new * one may begin. This is crucial for determining such things as where a * string ends: a byte in the text may look like an ASCII quote character, but * is it really the closing quote, or is it merely a byte inside a multibyte * character which just happens to have the same value as the ASCII value for * a quote? This is not an issue in most encodings, but it can happen in * others, and can pose a real security risk. * * Some functions in libpqxx need to know the type of encoding used in a given * text in order to find closing quotes or field boundaries. * * All supported encodings are supersets of ASCII: any byte with a value * between 0 and 127 inclusive at the beginning of a character is always a * simple, single-byte ASCII character. */ enum class encoding_group { /// Default: indeterminate encoding. All we know is it supports ASCII. /** This is the minimum assumption, and therefore the default. * * We can parse simple SQL values such as integers without knowing more about * their encoding, since all supported encodings are supersets of ASCII. An * integer string consists of only digits and an optional sign, so we can * parse that without knowing the encoding. * * But, for example, a quoted string is harder because we can't know _a * priori_ whether a byte that looks like the closing quote is indeed an * ASCII quote character, or just a trail byte in a multibyte character which * just happens to have the same numeric value. * * Conversions that _may_ run into this problem will throw an exception if * the uncoding is `unknown`, even if the actual uncertainty about the * meaning of a byte never occurs. That may seem a little pedantic, but it's * better to go through the pain in testing than to risk missing the problem * until your code goes into production. */ unknown, /// "ASCII-safe" encodings. /** * This includes all single-byte encodings (such as ASCII or ISO 8859-15) * but also all other encodings where there is no risk of ever confusing a * byte inside a multibyte character for an ASCII character. UTF-8 is an * example of an ASCII-safe encoding, as are the EUC encodings. * * This property makes encodings very efficient to parse: to find the next * character (if any), just move to the next byte. */ ascii_safe, /// Low byte is ASCII, high byte starts a 2-byte character. /** Both BIG5 and UHC work like this. The details vary, but we don't need to * validate the input in detail; we just need to be sure that we don't * mistake a byte in a multibyte character for a separate special ASCII * character (or vice versa if the input ends in mid-character). * * UHC is, for our purposes, ASCII-safe so long as none of the characters * you're looking for are ASCII letters. So in that common case, feel free * to use the `ascii_safe` glyph scanner instead. */ two_tier, /// Non-ASCII-safe: GB18030 for Chinese (Traditional & Simplified). /** This also covers older subsets such as GBK. */ gb18030, /// Non-ASCII-safe: Japanese JIS and Shift JIS. sjis, }; } // namespace pqxx namespace pqxx::internal { /// Function type: "find first occurrence of any of these ASCII characters." /** This type of function takes a text buffer, and a location in that buffer; * it returns the location of the first occurrence within that string, from * the `start` position onwards, of any of a specific set of ASCII characters. * * The `start` offset marks the beginning of the current glyph. So, if this * glyph matches, the function will return `start` * * If there is no match, returns the end of `haystack`. */ using char_finder_func = std::size_t(std::string_view haystack, std::size_t start, sl); } // namespace pqxx::internal #endif libpqxx-8.0.1/include/pqxx/errorhandler000066400000000000000000000004241516427024100202460ustar00rootroot00000000000000/** pqxx::errorhandler class. * * Callbacks for handling errors and warnings. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/errorhandler.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/errorhandler.hxx000066400000000000000000000050431516427024100210560ustar00rootroot00000000000000/* Definition of the pqxx::errorhandler class. * * pqxx::errorhandler handlers errors and warnings in a database session. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/errorhandler instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_ERRORHANDLER_HXX #define PQXX_ERRORHANDLER_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include "pqxx/types.hxx" namespace pqxx::internal::gate { class errorhandler_connection; } // namespace pqxx::internal::gate namespace pqxx { /** * @addtogroup errorhandler */ //@{ /// @deprecated Base class for obsolete error-handler callbacks. /** This method of handling errors is obsolete. Use a "notice handler" * instead. * * @warning Strange things happen when a result object outlives its parent * connection. If you register an error handler on a connection, then you must * not access the result after destroying the connection. This applies even if * you destroy the error handler first! */ class PQXX_LIBEXPORT errorhandler { public: [[deprecated("Use a notice handler instead.")]] explicit errorhandler(connection &); virtual ~errorhandler(); /// Define in subclass: receive an error or warning message from the /// database. /** * @return Whether the same error message should also be passed to the * remaining, older errorhandlers. */ PQXX_ZARGS virtual bool operator()(char const msg[]) noexcept = 0; errorhandler() = delete; errorhandler(errorhandler const &) = delete; errorhandler(errorhandler &&) = delete; errorhandler &operator=(errorhandler const &) = delete; errorhandler &operator=(errorhandler &&) = delete; private: connection *m_home; friend class internal::gate::errorhandler_connection; void unregister() noexcept; }; /// @deprecated Use a notice handler instead. class quiet_errorhandler : public errorhandler { public: #include "pqxx/internal/ignore-deprecated-pre.hxx" /// Suppress error notices. [[deprecated("Use notice handlers instead.")]] explicit quiet_errorhandler(connection &cx) : errorhandler{cx} {} #include "pqxx/internal/ignore-deprecated-post.hxx" /// Revert to previous handling of error notices. PQXX_ZARGS bool operator()(char const[]) noexcept override { return false; } quiet_errorhandler() = delete; }; //@} } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/except000066400000000000000000000004451516427024100170520ustar00rootroot00000000000000/** libpqxx exception classes. * * pqxx::sql_error, pqxx::broken_connection, pqxx::in_doubt_error, ... */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/except.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/except.hxx000066400000000000000000001017211516427024100176570ustar00rootroot00000000000000/* Definition of libpqxx exception classes. * * pqxx::sql_error, pqxx::broken_connection, pqxx::in_doubt_error, ... * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/except instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_EXCEPT_HXX #define PQXX_EXCEPT_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include #include #include "pqxx/types.hxx" namespace pqxx { /** * @addtogroup exception Exception classes * * All exception types thrown by libpqxx are derived from @ref pqxx::failure, * so that should be your starting point in exploring them. When you write a * `catch` clause in your code, it's probably worth either having a separate * clause for `failure` and its subclasses, or checking at run time whether an * error is of this type using `dynamic_cast(...)`. if * the exception is a libpqxx exception, you can get a lot of extra information * that's not normally available in exceptions. * * There is no multiple inheritance in this class hierarchy. That means that * the different kinds of libpqxx exception are not reflected in inheritance * from `std::logic_error,` `std::runtime_error`, and so on. They are _all_ * derived from @ref pqxx::failure (whether directly or indirectly), which in * turn inherits directly from `std::exception`. * * You may wonder whether this was the best design decision. Before libpqxx 8, * various libpqxx exceptions derived from different types in the standard C++ * exception hierarchy (`std::out_of_range`, `std::argument_error`, and so on). * But in practice we saw that: * 1. The standard exception type distinctions are not very _actionable._ * 2. Applications would generally just catch `std::exception` anyway. * 3. Important properties never quite follow a neat hierarchy. * 4. Making effective use of the hierarchy was hard, finicky work. * 5. A `try` could end up with a lot of highly similar `catch` clauses. * 6. Shaping the hierarchy around one exception property would confuse * another. * * So as of libpqxx 8, if you want more detail in how you handle different * types of exceptions, you use member functions, mostly at run time. All of * the properties are available right from the top down, in the @ref failure * base class. Some of the strings will not apply to all types of exception, * but in those cases, they will simply be empty strings. * * In libpqxx, the exception hierarchy exists not for taxonomy's sake but to * enable your application to function well without requiring too much code or * effort from you. In most cases, when an exception occurs, both the safest * and the easiest thing to do is drop the objects involved in the error, * report what happened, and move on from a reliable state. That is what these * classes are here to support. * * @{ */ /// Base class for all exceptions specific to libpqxx. struct PQXX_LIBEXPORT failure : std::exception { failure(failure const &) = default; failure(failure &&) = default; explicit failure(sl loc = sl::current(), st tr = st::current()) : m_block{std::make_shared(loc, std::move(tr))} {} explicit failure( std::string whatarg, sl loc = sl::current(), st tr = st::current()) : m_block{ std::make_shared(std::move(whatarg), loc, std::move(tr))} {} ~failure() noexcept override; failure &operator=(failure const &) = default; failure &operator=(failure &&) = default; /// Error message. [[nodiscard]] PQXX_PURE char const *what() const noexcept override { return m_block->message.c_str(); } /// Best known `std::source_location` for where the error occurred. /** Generally there's no one single source location, but the exception only * stores one. This is generally either one that the caller passed to a * libpqxx call, or the place where the caller called libpqxx. */ [[nodiscard]] PQXX_PURE sl const &location() const noexcept { return m_block->location; } /// If available in this compiler, a `std::stacktrace` of this exception. /** The stacktrace does not include the creation of the exception object * itself. By default it goes right up to that point. You can pass a * stacktrace of your own choosing to the exception constructors, if you * really want, but it generally makes more sense to use the default. * * If `std::stacktrace` was not available when the libpqxx build was * configured, this returns an empty ("null") pointer to * `pqxx::stacktrace_placeholder`. * * This is meant to keep the ABI for `pqxx::failure` stable across builds * with and without `std::stacktrace`, and make it easy to upgrade the * compiler and get the feature. */ [[nodiscard]] PQXX_PURE std::shared_ptr trace() const noexcept { return m_block->trace; } /// SQLSTATE error code, or empty string if unavailable. /** The PostgreSQL error codes are documented here: * * https://www.postgresql.org/docs/current/errcodes-appendix.html */ [[nodiscard]] PQXX_PURE std::string_view sqlstate() const noexcept { return m_block->sqlstate; } /// SQL statement that encountered the error, if applicable; or empty string. /** In some cases there will be a placeholder string, to give a rough * indication of an SQL operation that's being performed in your name, such * as beginning or committing a transaction. Those will be in square * brackets: `[COMMIT]` etc. */ [[nodiscard]] PQXX_PURE std::string_view query() const noexcept { return m_block->statement; } /// Does this type of error make the current @ref connection unusable? /** If the answer is `true`, assume that there is nothing more you can get * done using your existing connection object. It _may_ still be possible, * but it may fail, or things could conceivably be in a confused state where * it's just not a good idea to try. * * If your connection is poisoned, then it follows that any ongoing * transaction will no longer be usable either. * * @note This is a general indication based on the _type_ of exception. It * can be wrong for some specific situations. */ [[nodiscard]] virtual bool poisons_connection() const noexcept { return false; } /// Does this type of error make an ongoing @ref dbtransaction unusable? /** When this is the case, before you try to do anything else, you'll want to * close any transaction you may have open. If necessary, a call to * @ref poisons_connection() will tell you whether it is still possible (and * advisable) to open a new one on the same connection. * * If you are using a @ref nontransaction, bear in mind that it is not * derived from @ref dbtransaction. So if you see an exception which reports * that it poisons transactions but not the connection, then a * @ref nontransaction should still be usable. * * @note This is a general indication based on the _type_ of exception. It * can be wrong for some specific situations. */ [[nodiscard]] virtual bool poisons_transaction() const noexcept { return false; } // C++26: Implement using reflection. /// The name of this exception type: "failure", "sql_error", etc. /** Do not count on this being exact, or eternal as libpqxx evolves. There * can be mistakes, names may change, new exception subclasses show up during * libpqxx development. * * @note If you need to check whether an exception you've caught is of a * specific type, e.g. `pqxx::deadlock_detected`, _do not_ use `name()` for * this, since its answer may change as libpqxx evolves. Instead, use * something like: * * ```cxx * try * { * // ... * } * catch (pqxx::failure const &e) * { * auto const deadlock = dynamic_cast(&e); * if (deadlock == nullptr) * { * // `e` is some other type of exception, not a deadlock. * } * else * { * // `e` is a `deadlock_detected` error, and `deadlock` points to it * // by its more specific static type. * } * } * ``` */ [[nodiscard]] virtual std::string_view name() const noexcept; protected: /// For constructing derived exception types with the additional /// fields. failure( std::string whatarg, std::string stat, std::string sqls, sl loc = sl::current(), st tr = st::current()) : m_block{std::make_shared( std::move(whatarg), std::move(stat), std::move(sqls), loc, std::move(tr))} {} private: /// All the data this exception or its descendants might need. struct block final { // NOLINTBEGIN(misc-non-private-member-variables-in-classes) /// Message string. std::string message; /// SQL statement, if applicable (empty string otherwise). std::string statement; /// SQLSTATE variable, if applicable (empty string otherwise). std::string sqlstate; /// Source location. sl location; /// Stack trace, or if not supported, an empty placeholder. std::shared_ptr trace; // NOLINTEND(misc-non-private-member-variables-in-classes) block(sl loc, st &&tr) : location{loc}, trace{make_trace_ptr(std::move(tr))} {} block(std::string &&msg, sl loc, st &&tr) : message{std::move(msg)}, location{loc}, trace{make_trace_ptr(std::move(tr))} {} block( std::string &&msg, std::string &&stat, std::string &&sqls, sl loc, st &&tr) : message{std::move(msg)}, statement{std::move(stat)}, sqlstate{std::move(sqls)}, location{loc}, trace{make_trace_ptr(std::move(tr))} {} /// Move `tr` into a `shared_ptr`. /** If no `std::stacktrace` support is available, return an empty pointer. * This makes it easier for users of `pqxx::failure` to detect the case * where `std::stacktrace` is not supported. */ [[nodiscard]] static std::shared_ptr make_trace_ptr([[maybe_unused]] st &&tr) { #if defined(PQXX_HAVE_STACKTRACE) // We have std::stacktrace support. Move tr from the stack to the heap. return std::make_shared(std::move(tr)); #else // We don't have std::stacktrace. Keep the pointer empty. return {}; #endif } }; /// The data for this exception, as a shared pointer for easy copying. /** The "block" never, ever moves, changes, or disappears during the * exception object's lifetime. That's why various functions can return * views or references pointing to the data in there. */ std::shared_ptr m_block; }; /// Exception class for lost or failed backend connection. /** * @warning When this happens on Unix-like systems, you may also get a SIGPIPE * signal. That signal aborts the program by default, so if you wish to be * able to continue after a connection breaks, be sure to disarm this signal. * * If you're working on a Unix-like system, see the manual page for * `signal` (2) on how to deal with SIGPIPE. The easiest way to make this * signal harmless is to make your program ignore it: * * ```cxx * #include * * int main() * { * std::signal(SIGPIPE, SIG_IGN); * // ... * } * ``` */ struct PQXX_LIBEXPORT broken_connection : failure { explicit broken_connection(sl loc = sl::current(), st &&tr = st::current()) : failure{"Connection to database failed.", loc, std::move(tr)} {} explicit broken_connection( std::string const &whatarg, sl loc = sl::current(), st &&tr = st::current()) : failure{whatarg, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; /// By its nature, this type of error makes the connection unusable. [[nodiscard]] bool poisons_connection() const noexcept override { return true; } /// When the connection breaks, so will an ongoing transaction. [[nodiscard]] bool poisons_transaction() const noexcept override { return true; } }; /// Could not establish connection due to version mismatch. struct PQXX_LIBEXPORT version_mismatch : broken_connection { explicit version_mismatch( std::string const &whatarg, sl loc = sl::current(), st &&tr = st::current()) : broken_connection{whatarg, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; /// The caller attempted to set a variable to null, which is not allowed. struct PQXX_LIBEXPORT variable_set_to_null : failure { explicit variable_set_to_null( std::string const &whatarg, sl loc = sl::current(), st &&tr = st::current()) : failure{whatarg, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; /// Exception class for failed queries. /** Carries, in addition to a regular error message, a copy of the failed query * and (if available) the SQLSTATE value accompanying the error. * * These exception classes follow, roughly, the two-level hierarchy defined by * the PostgreSQL SQLSTATE error codes (see Appendix A of the PostgreSQL * documentation corresponding to your server version). This is not a complete * mapping though. There are other differences as well, e.g. the error code * for `statement_completion_unknown` has a separate status in libpqxx as * @ref in_doubt_error, and `too_many_connections` is classified as a * `broken_connection` rather than a subtype of `insufficient_resources`. */ struct PQXX_LIBEXPORT sql_error : public failure { PQXX_ZARGS explicit sql_error( std::string const &whatarg = {}, std::string const &stmt = {}, std::string const &sqls = {}, sl loc = sl::current(), st &&tr = st::current()) : failure{whatarg, stmt, sqls, loc, std::move(tr)} {} sql_error(sql_error const &other) = default; sql_error(sql_error &&other) = default; ~sql_error() override = default; sql_error &operator=(sql_error const &other) = default; sql_error &operator=(sql_error &&other) = default; [[nodiscard]] std::string_view name() const noexcept override; /// If a transaction was ongoing, an SQL error will break it. [[nodiscard]] bool poisons_transaction() const noexcept override { return true; } }; /// Exception class for mis-communication with the server. /** This happens when the conversation between libpq and the server gets messed * up. There aren't many situations where this happens, but one known instance * is when you call a parameterised or prepared statement with the wrong number * of parameters. * * When this happens, your connection will most likely be in a broken state and * you're probably best off discarding it and starting a new one. In that * sense it is like @ref broken_connection. * * Retrying your statement is not likely to make this problem go away. */ struct PQXX_LIBEXPORT protocol_violation : sql_error { explicit protocol_violation( std::string const &whatarg, std::string const &stmt = {}, std::string const &sqls = {}, sl loc = sl::current(), st &&tr = st::current()) : sql_error{whatarg, stmt, sqls, loc, std::move(tr)} {} /// When this happens, the connection is in a confused state. [[nodiscard]] bool poisons_connection() const noexcept override { return true; } /// Since the connection is broken, so is a transaction. [[nodiscard]] bool poisons_transaction() const noexcept override { return true; } [[nodiscard]] std::string_view name() const noexcept override; }; /// "Help, I don't know whether transaction was committed successfully!" /** Exception that might be thrown in rare cases where the connection to the * database is lost while finishing a database transaction, and there's no way * of telling whether it was actually executed by the backend. In this case * the database is left in an indeterminate (but consistent) state, and only * manual inspection will tell which is the case. */ struct PQXX_LIBEXPORT in_doubt_error : failure { explicit in_doubt_error( std::string const &whatarg, sl loc = sl::current(), st &&tr = st::current()) : failure{whatarg, loc, std::move(tr)} {} /// This kind of error can only happen when the connection breaks. [[nodiscard]] bool poisons_connection() const noexcept override { return true; } /// The transaction is already closed, and the connection is broken. [[nodiscard]] bool poisons_transaction() const noexcept override { return true; } [[nodiscard]] std::string_view name() const noexcept override; }; /// The backend saw itself forced to roll back the ongoing transaction. struct PQXX_LIBEXPORT transaction_rollback : sql_error { PQXX_ZARGS explicit transaction_rollback( std::string const &whatarg, std::string const &q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : sql_error{whatarg, q, sqlstate, loc, std::move(tr)} {} /// Some earlier failure broke the transaction. [[nodiscard]] bool poisons_transaction() const noexcept override { return true; } [[nodiscard]] std::string_view name() const noexcept override; }; /// Transaction failed to serialize. Please retry the whole thing. /** Can only happen at transaction isolation levels REPEATABLE READ and * SERIALIZABLE. * * The current transaction cannot be committed without violating the guarantees * made by its isolation level. This is the effect of a conflict with another * ongoing transaction. The transaction may still succeed if you try to * perform it again. */ struct PQXX_LIBEXPORT serialization_failure : transaction_rollback { PQXX_ZARGS explicit serialization_failure( std::string const &whatarg, std::string const &q, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : transaction_rollback{whatarg, q, sqlstate, loc, std::move(tr)} {} /// To retry the transaction, you'll need to start a fresh one. [[nodiscard]] bool poisons_transaction() const noexcept override { return true; } [[nodiscard]] std::string_view name() const noexcept override; }; /// We can't tell whether our last statement succeeded. struct PQXX_LIBEXPORT statement_completion_unknown : transaction_rollback { PQXX_ZARGS explicit statement_completion_unknown( std::string const &whatarg, std::string const &q, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : transaction_rollback{whatarg, q, sqlstate, loc, std::move(tr)} {} /// It's not advisable to continue using the connection after this. [[nodiscard]] bool poisons_connection() const noexcept override { return true; } [[nodiscard]] std::string_view name() const noexcept override; }; /// The ongoing transaction has deadlocked. Retrying it may help. struct PQXX_LIBEXPORT deadlock_detected : transaction_rollback { PQXX_ZARGS explicit deadlock_detected( std::string const &whatarg, std::string const &q, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : transaction_rollback{whatarg, q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; /// Internal error in libpqxx library struct PQXX_LIBEXPORT internal_error : failure { explicit internal_error( std::string const &, sl = sl::current(), st &&tr = st::current()); /// When this happens, all bets are off. It _may_ work, but don't risk it. [[nodiscard]] bool poisons_connection() const noexcept override { return true; } /// When this happens, all bets are off. It _may_ work, but don't risk it. [[nodiscard]] bool poisons_transaction() const noexcept override { return true; } [[nodiscard]] std::string_view name() const noexcept override; }; /// Error in usage of libpqxx library, similar to std::logic_error struct PQXX_LIBEXPORT usage_error : failure { explicit usage_error( std::string const &whatarg, sl loc = sl::current(), st &&tr = st::current()) : failure{whatarg, loc, std::move(tr)} {} /// Your transaction will probably still work, but something is badly wrong. [[nodiscard]] bool poisons_transaction() const noexcept override { return true; } [[nodiscard]] std::string_view name() const noexcept override; }; /// Invalid argument passed to libpqxx, similar to std::invalid_argument struct PQXX_LIBEXPORT argument_error : failure { explicit argument_error( std::string const &whatarg, sl loc = sl::current(), st &&tr = st::current()) : failure{whatarg, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; /// Value conversion failed, e.g. when converting "Hello" to int. struct PQXX_LIBEXPORT conversion_error : failure { explicit conversion_error( std::string const &whatarg, sl loc = sl::current(), st &&tr = st::current()) : failure{whatarg, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; /// Could not convert null value: target type does not support null. struct PQXX_LIBEXPORT unexpected_null : conversion_error { explicit unexpected_null( std::string const &whatarg, sl loc = sl::current(), st &&tr = st::current()) : conversion_error{whatarg, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; /// Could not convert value to string: not enough buffer space. struct PQXX_LIBEXPORT conversion_overrun : conversion_error { explicit conversion_overrun( std::string const &whatarg, sl loc = sl::current(), st &&tr = st::current()) : conversion_error{whatarg, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; /// Something is out of range, similar to std::out_of_range struct PQXX_LIBEXPORT range_error : failure { explicit range_error( std::string const &whatarg, sl loc = sl::current(), st &&tr = st::current()) : failure{whatarg, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; /// Query returned an unexpected number of rows. struct PQXX_LIBEXPORT unexpected_rows : range_error { explicit unexpected_rows( std::string const &msg, sl loc = sl::current(), st &&tr = st::current()) : range_error{msg, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; /// Database feature not supported in current setup. struct PQXX_LIBEXPORT feature_not_supported : sql_error { PQXX_ZARGS explicit feature_not_supported( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : sql_error{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; /// It all depends on the details, but this _can_ break your connection. [[nodiscard]] bool poisons_connection() const noexcept override { return true; } /// If this poisons your connection, it also poisons your transaction. [[nodiscard]] bool poisons_transaction() const noexcept override { return true; } }; /// Error in data provided to SQL statement. struct PQXX_LIBEXPORT data_exception : sql_error { PQXX_ZARGS explicit data_exception( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : sql_error{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; struct PQXX_LIBEXPORT integrity_constraint_violation : sql_error { PQXX_ZARGS explicit integrity_constraint_violation( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : sql_error{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; struct PQXX_LIBEXPORT restrict_violation : integrity_constraint_violation { PQXX_ZARGS explicit restrict_violation( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : integrity_constraint_violation{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; struct PQXX_LIBEXPORT not_null_violation : integrity_constraint_violation { PQXX_ZARGS explicit not_null_violation( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : integrity_constraint_violation{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; struct PQXX_LIBEXPORT foreign_key_violation : integrity_constraint_violation { PQXX_ZARGS explicit foreign_key_violation( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : integrity_constraint_violation{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; struct PQXX_LIBEXPORT unique_violation : integrity_constraint_violation { PQXX_ZARGS explicit unique_violation( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : integrity_constraint_violation{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; struct PQXX_LIBEXPORT check_violation : integrity_constraint_violation { PQXX_ZARGS explicit check_violation( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : integrity_constraint_violation{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; struct PQXX_LIBEXPORT invalid_cursor_state : sql_error { PQXX_ZARGS explicit invalid_cursor_state( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : sql_error{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; struct PQXX_LIBEXPORT invalid_sql_statement_name : sql_error { PQXX_ZARGS explicit invalid_sql_statement_name( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : sql_error{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; struct PQXX_LIBEXPORT invalid_cursor_name : sql_error { PQXX_ZARGS explicit invalid_cursor_name( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : sql_error{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; struct PQXX_LIBEXPORT syntax_error : sql_error { // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) [[deprecated("Call error_pos() instead.")]] int error_position; #include "pqxx/internal/ignore-deprecated-pre.hxx" PQXX_ZARGS explicit syntax_error( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, int pos = -1, sl loc = sl::current(), st &&tr = st::current()) : sql_error{err, Q, sqlstate, loc, std::move(tr)}, error_position{pos} {} #include "pqxx/internal/ignore-deprecated-post.hxx" [[nodiscard]] std::string_view name() const noexcept override; /// Approximate position in statement where the error occurred, or -1. /** The special value `-1` is for cases where the error has no useful * location in the SQL statement to indicate. */ [[nodiscard]] constexpr int error_pos() const noexcept { #include "pqxx/internal/ignore-deprecated-pre.hxx" return error_position; #include "pqxx/internal/ignore-deprecated-post.hxx" } }; struct PQXX_LIBEXPORT undefined_column : syntax_error { PQXX_ZARGS explicit undefined_column( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : // TODO: Can we get the column? syntax_error{err, Q, sqlstate, -1, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; struct PQXX_LIBEXPORT undefined_function : syntax_error { PQXX_ZARGS explicit undefined_function( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : // TODO: Can we get the column? syntax_error{err, Q, sqlstate, -1, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; struct PQXX_LIBEXPORT undefined_table : syntax_error { PQXX_ZARGS explicit undefined_table( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : // TODO: Can we get the column? syntax_error{err, Q, sqlstate, -1, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; struct PQXX_LIBEXPORT insufficient_privilege : sql_error { PQXX_ZARGS explicit insufficient_privilege( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : sql_error{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; /// Resource shortage on the server. struct PQXX_LIBEXPORT insufficient_resources : sql_error { PQXX_ZARGS explicit insufficient_resources( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : sql_error{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; struct PQXX_LIBEXPORT disk_full : insufficient_resources { PQXX_ZARGS explicit disk_full( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : insufficient_resources{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; struct PQXX_LIBEXPORT server_out_of_memory : insufficient_resources { PQXX_ZARGS explicit server_out_of_memory( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : insufficient_resources{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; struct PQXX_LIBEXPORT too_many_connections : broken_connection { explicit too_many_connections( std::string const &err, sl loc = sl::current(), st &&tr = st::current()) : broken_connection{err, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; /// PL/pgSQL error. /** Exceptions derived from this class are errors from PL/pgSQL procedures. */ struct PQXX_LIBEXPORT plpgsql_error : sql_error { PQXX_ZARGS explicit plpgsql_error( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : sql_error{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; /// Exception raised in PL/pgSQL procedure struct PQXX_LIBEXPORT plpgsql_raise : plpgsql_error { PQXX_ZARGS explicit plpgsql_raise( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : plpgsql_error{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; struct PQXX_LIBEXPORT plpgsql_no_data_found : plpgsql_error { PQXX_ZARGS explicit plpgsql_no_data_found( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : plpgsql_error{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; struct PQXX_LIBEXPORT plpgsql_too_many_rows : plpgsql_error { PQXX_ZARGS explicit plpgsql_too_many_rows( std::string const &err, std::string const &Q = {}, std::string const &sqlstate = {}, sl loc = sl::current(), st &&tr = st::current()) : plpgsql_error{err, Q, sqlstate, loc, std::move(tr)} {} [[nodiscard]] std::string_view name() const noexcept override; }; /** * @} */ } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/field000066400000000000000000000004111516427024100166360ustar00rootroot00000000000000/** pqxx::field class. * * pqxx::field refers to a field in a query result. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/field.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/field.hxx000066400000000000000000000672551516427024100174670ustar00rootroot00000000000000/* Definitions for the pqxx::field class. * * pqxx::field refers to a field in a query result. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_FIELD_HXX #define PQXX_FIELD_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include "pqxx/array.hxx" #include "pqxx/composite.hxx" #include "pqxx/internal/gates/result-field_ref.hxx" #include "pqxx/result.hxx" #include "pqxx/strconv.hxx" #include "pqxx/types.hxx" namespace pqxx::internal::gate { class field_ref_const_row_iterator; } // namespace pqxx::internal::gate namespace pqxx { /// Lightweight reference to a field in a result set. /** Like @ref field, represents one field in a query result set. Unlike with * @ref field, however, for as long as you're using a `field_ref`, the * @ref result object must... * * 1. remain valid, i.e. you can't destroyit; * 2. and in the same place in memory, i.e. you can't move it; * 3. and keep the same value, i.e you can't assign to it. * * When you use `field_ref`, it is your responsibility to ensure all that. * * You can query whether a `field_ref` is null, and if not, you can convert its * value from its textual "SQL representation" to a more suitable C++ type. */ class PQXX_LIBEXPORT field_ref final { public: /// A type for holding the number of bytes in a field. using size_type = field_size_type; field_ref() noexcept = default; field_ref(field_ref const &) noexcept = default; field_ref(field_ref &&) noexcept = default; field_ref( result const &res, result_size_type row_num, row_size_type col_num) noexcept : m_result(&res), m_row{row_num}, m_column{col_num} {} ~field_ref() = default; field_ref &operator=(field_ref const &) noexcept = default; field_ref &operator=(field_ref &&) noexcept = default; [[nodiscard]] PQXX_PURE result const &home() const noexcept { return *m_result; } [[nodiscard]] PQXX_PURE result_size_type row_number() const noexcept { return m_row; } /** * @name Comparison * * Equality between two `field_ref` objects means that they both refer to * the same row and column in _the exact same @ref result object._ * * So, if you copy a @ref result, even though the two copies refer to the * exact same underlying data structure, a `field_ref` in the one will never * be equal to a `field_ref` in the other. */ //@{ [[nodiscard]] PQXX_PURE bool operator==(field_ref const &rhs) const noexcept { return (home() == rhs.home()) and (row_number() == rhs.row_number()) and (column_number() == rhs.column_number()); } [[nodiscard]] PQXX_PURE bool operator!=(field_ref const &rhs) const noexcept { return not operator==(rhs); } //@} /** * @name Column information */ //@{ /// Column name. [[nodiscard]] PQXX_PURE char const *name(sl loc = sl::current()) const & { return home().column_name(column_number(), loc); } /// Column type. [[nodiscard]] PQXX_PURE oid type(sl loc = sl::current()) const; /// What table did this column come from? [[nodiscard]] PQXX_PURE oid table(sl = sl::current()) const; /// Return column number. The first column is 0, the second is 1, etc. [[nodiscard]] PQXX_PURE constexpr row_size_type column_number() const noexcept { return m_column; } /// What column number in its originating table did this column come from? [[nodiscard]] PQXX_PURE row_size_type table_column(sl loc = sl::current()) const { return home().table_column(column_number(), loc); } //@} /** * @name Content access * * You can read a `field_ref` as any C++ type for which a conversion from * PostgreSQL's text format is defined. See @ref datatypes for how this * works. This mechanism is _weakly typed:_ the conversions do not care * what SQL type a field had in the database, only that its actual contents * convert to the target type without problems. So for instance, you can * read a `text` field as an `int`, so long as the string in the field spells * out a valid `int` number. * * Many built-in types come with conversions predefined. To find out how to * add your own, see @ref datatypes. */ //@{ /// Read as @ref zview, or an empty one if null. /** A @ref zview is also a `std::string_view`. It just adds the promise that * there is a terminating zero right behind the string. */ [[nodiscard]] PQXX_PURE std::string_view view() const & noexcept { return zview{c_str(), size()}; } /// Read as plain C string. /** Since the field's data is stored internally in the form of a * zero-terminated C string, this is the fastest way to read it. Use the * @ref is_null() and @ref as() functions to convert the string to other * types such as `int`, or to C++ strings. * * @warning Binary data may contain null bytes, so do not use `c_str()` for * those. Instead, convert the value to a binary type using @ref as(), e.g. * `f.as()`. */ [[nodiscard]] PQXX_PURE char const *c_str() const & noexcept; /// Is this field's value null? [[nodiscard]] PQXX_PURE bool is_null() const noexcept; /// Return number of bytes taken up by the field's value. [[nodiscard]] PQXX_PURE size_type size() const noexcept; /// Return value as object of given type, or `default value` if null. /** Note that unless the function is instantiated with an explicit template * argument, the Default value's type also determines the result type. */ template [[nodiscard]] T as(T const &default_value, sl loc = sl::current()) const { if (is_null()) return default_value; else return from_string(this->view(), make_context(loc)); } /// Return value as object of given type, or throw exception if null. /** Use as `as>()` or `as()` as * an alternative to `get()`; this is disabled for use with raw pointers * (other than C-strings) because storage for the value can't safely be * allocated here */ template [[nodiscard]] T as(sl loc = sl::current()) const { if (is_null()) { if constexpr (not has_null()) internal::throw_null_conversion(name_type(), loc); else return make_null(); } else { return from_string(this->view(), make_context(loc)); } } /// Read value into `obj`; or if null, leave `obj` untouched. /** This can be handy to read a field's value but also check for nullness * along the way. * * @return Whether the field contained an actual value. So: `true` for a * non-null field, or `false` for a null field. */ template bool to(T &obj, sl loc = sl::current()) const { if (is_null()) { return false; } else { from_string(view(), obj, make_context(loc)); return true; } } /// Read value into `obj`; or if null, set default value and return `false`. template bool to(T &obj, T const &default_value, sl loc = sl::current()) const { bool const null{is_null()}; if (null) obj = default_value; else obj = from_string(this->view(), make_context(loc)); return not null; } /// Return value wrapped in some optional type (empty for nulls). /** Use as `get()` as before to obtain previous behavior, or specify * container type with `get()` */ template typename O = std::optional> constexpr O get() const { return as>(); } /// Read SQL array contents as a @ref pqxx::array. template [[deprecated("Use as>().")]] [[nodiscard]] array< ELEMENT, ARGS...> as_sql_array(sl loc = sl::current()) const { using array_type = array; // There's no such thing as a null SQL array. if (is_null()) internal::throw_null_conversion(name_type(), loc); else return array_type{ this->view(), pqxx::internal::gate::result_field_ref{home()}.encoding(), loc}; } //@} private: friend class pqxx::internal::gate::field_ref_const_row_iterator; /// Jump n columns ahead (negative to jump back). void offset(row_difference_type n) { m_column += n; } /// Build a @ref conversion_context, using the result's encoding group. [[nodiscard]] conversion_context make_context(sl loc) const { return conversion_context{home().get_encoding_group(), loc}; } /// The result in which we're iterating. Must remain valid. result const *m_result = nullptr; /// Row's number inside the result. result_size_type m_row = -1; /// Field's column number inside the result. /** * You'd expect this to be unsigned, but due to the way reverse iterators * are related to regular iterators, it must be allowed to underflow to -1. */ row_size_type m_column = -1; }; } // namespace pqxx #include "pqxx/internal/gates/field_ref-const_row_iterator.hxx" namespace pqxx { /// Reference to a field in a result set. /** This is like @ref field_ref, except it's safe to destroy the @ref result * object or move it to a different place in memory. * * A field represents one entry in a row. It represents an actual value * in the result set, and can be converted to various types. */ class PQXX_LIBEXPORT field final { public: using size_type = field_size_type; explicit field(field_ref const &f) : m_home{f.home()}, m_row{f.row_number()}, m_col{f.column_number()} {} /** * @name Comparison */ //@{ /// Byte-by-byte comparison of two fields (all nulls are considered equal) /** @warning This differs from what comparisons do in @ref result, @ref row, * @ref row_ref, @ref field, @ref field_ref, and the iterator classes. It * will change in the future to compare only the fields' identities, not the * actual data. * * Handling of null values differs from that in SQL where a comparison * involving a null value yields null, so nulls are never considered equal * to one another or even to themselves. * * Null handling also probably differs from the closest equivalent in C++, * which is the NaN (Not-a-Number) value, a singularity comparable to * SQL's null. This is because the builtin == operator demands that a == a. * * The usefulness of this operator is questionable. No interpretation * whatsoever is imposed on the data; 0 and 0.0 are considered different, * as are null vs. the empty string, or even different (but possibly * equivalent and equally valid) encodings of the same Unicode character * etc. */ [[deprecated( "To compare fields by content, compare their view()s.")]] PQXX_PURE bool operator==(field const &) const noexcept; /// Byte-by-byte comparison (all nulls are considered equal) /** @warning See operator==() for important information about this operator */ [[deprecated( "To compare fields by content, compare their view()s.")]] PQXX_PURE bool operator!=(field const &rhs) const noexcept { #include "pqxx/internal/ignore-deprecated-pre.hxx" return not operator==(rhs); #include "pqxx/internal/ignore-deprecated-post.hxx" } //@} /** * @name Column information */ //@{ /// Column name. [[nodiscard]] PQXX_PURE char const *name(sl = sl::current()) const &; /// Column type. [[nodiscard]] PQXX_PURE oid type(sl loc = sl::current()) const { return as_field_ref().type(loc); } /// What table did this column come from? [[nodiscard]] PQXX_PURE oid table(sl loc = sl::current()) const { return as_field_ref().table(loc); } /// Return column number. The first column is 0, the second is 1, etc. [[deprecated("Use column_number().")]] [[nodiscard]] row_size_type num() const noexcept { return column_number(); } /// What column number in its originating table did this column come from? [[nodiscard]] row_size_type table_column(sl = sl::current()) const; //@} /** * @name Content access * * You can read a field as any C++ type for which a conversion from * PostgreSQL's text format is defined. See @ref datatypes for how this * works. This mechanism is _weakly typed:_ the conversions do not care * what SQL type a field had in the database, only that its actual contents * convert to the target type without problems. So for instance, you can * read a `text` field as an `int`, so long as the string in the field spells * out a valid `int` number. * * Many built-in types come with conversions predefined. To find out how to * add your own, see @ref datatypes. */ //@{ /// Read as @ref zview (which is also a `string_view`). /** Returns an empty view if the field is null. * * The result only remains usable while the data for the underlying * @ref result exists. Once all `result` objects referring to that data have * been destroyed, the view will no longer point to valid memory. */ [[nodiscard]] PQXX_PURE std::string_view view() const & noexcept { return {c_str(), size()}; } /// Read as plain C string. /** Since the field's data is stored internally in the form of a * zero-terminated C string, this is the fastest way to read it. Use the * `to()` or `as()` functions to convert the string to other types such as * `int`, or to C++ strings. * * Do not use `c_str()` for BYTEA values, or other binary values. To read * those, convert the value to some binary type using `to()` or `as()`. For * example: `f.as()`. * * If the field is null, returns an empty string. */ [[nodiscard]] PQXX_PURE PQXX_RETURNS_NONNULL char const * c_str() const & noexcept { return as_field_ref().c_str(); } /// Is this field's value null? [[nodiscard]] PQXX_PURE bool is_null() const noexcept { return as_field_ref().is_null(); } /// Return number of bytes taken up by the field's value. [[nodiscard]] PQXX_PURE size_type size() const noexcept { return as_field_ref().size(); } /// Read value into `obj`; or if null, leave `obj` untouched. /** This can be handy to read a field's value but also check for nullness * along the way. * * @return Whether the field contained an actual value. So: `true` for a * non-null field, or `false` for a null field. */ template bool to(T &obj, sl loc = sl::current()) const { if (is_null()) { return false; } else { obj = from_string(view(), make_context(loc)); return true; } } /// Read field as a composite value, write its components into `fields`. /** Returns whether the field was null. If it was, it will not touch the * values in `fields`. */ template bool composite_to(sl loc, T &...fields) const { if (is_null()) { return false; } else { parse_composite(make_context(loc), view(), fields...); return true; } } /// Read field as a composite value, write its components into `fields`. /** @warning This version does not accept a `std::source_location` (what in * libpqxx we call @ref pqxx::sl for short). That means that should * conversion fail with an exception, the exception will refer to this * function. It's generally more helpful to pass a location that's more * meaningful in the context of your codebase, using the version of this * function that takes it as a first argumet. * * Returns whether the field was null. If it was, it will not touch the * values in `fields`. */ template bool composite_to(T &...fields) const { return composite_to(sl::current(), fields...); } /// Read value into obj; or leave obj untouched and return `false` if null. template [[deprecated("Use to() or as().")]] bool operator>>(T &obj) const { return to(obj); } /// Read value into obj; or if null, use default value and return `false`. /** This can be used with `std::optional`, as well as with standard smart * pointer types, but not with raw pointers. */ template bool to(T &obj, T const &default_value, sl loc = sl::current()) const { return as_field_ref().to(obj, default_value, make_context(loc)); } /// Return value as object of given type, or default value if null. /** Note that unless the function is instantiated with an explicit template * argument, the Default value's type also determines the result type. */ template [[nodiscard]] T as(T const &default_value, sl loc = sl::current()) const { return as_field_ref().as(default_value, loc); } /// Return value as object of given type, or throw exception if null. /** Use as `as>()` or `as()` as * an alternative to `get()`; this is disabled for use with raw pointers * (other than C-strings) because storage for the value can't safely be * allocated here */ template [[nodiscard]] T as(sl loc = sl::current()) const { return as_field_ref().as(loc); } /// Return value wrapped in some optional type (empty for nulls). /** Use as `get()` as before to obtain previous behavior, or specify * container type with `get()` */ template typename O = std::optional> constexpr O get() const { return as>(); } /// Read SQL array contents as a @ref pqxx::array. template array as_sql_array(sl loc = sl::current()) const { return as_field_ref().as_sql_array(loc); } /// Parse the field as an SQL array. /** Call the parser to retrieve values (and structure) from the array. * * Make sure the @ref result object stays alive until parsing is finished. If * you keep the @ref row of `field` object alive, it will keep the @ref * result object alive as well. */ [[deprecated( "Avoid pqxx::array_parser. " "Instead, use as_sql_array() to convert to " "pqxx::array.")]] [[nodiscard]] array_parser as_array() const & noexcept { #include "pqxx/internal/ignore-deprecated-pre.hxx" return array_parser{c_str(), m_home.get_encoding_group()}; #include "pqxx/internal/ignore-deprecated-post.hxx" } //@} /// This field's row number within the result. [[nodiscard]] PQXX_PURE result_size_type row_number() const noexcept { return m_row; } /// This field's column number within the result. [[nodiscard]] PQXX_PURE row_size_type column_number() const noexcept { return m_col; } private: /** Create field as reference to a field in a result set. * @param r Row that this field is part of. * @param c Column number of this field. */ field(row const &r, row_size_type c) noexcept; /// Constructor. field() noexcept = default; /// Retun @ref field_ref for this field. /** @warning The @ref field_ref holds a reference to the @ref result * object _inside this `field` object._ So if you change that, the * @ref field_ref becomes invalid. */ [[nodiscard]] field_ref as_field_ref() const noexcept { return field_ref{home(), row_number(), column_number()}; } [[nodiscard]] constexpr result const &home() const noexcept { return m_home; } field(result r, result_size_type row_num, row_size_type col_num) noexcept : m_home{std::move(r)}, m_row{row_num}, m_col{col_num} {} /// Build a @ref conversion_context, using the result's encoding group. [[nodiscard]] conversion_context make_context(sl loc) const { return conversion_context{home().get_encoding_group(), loc}; } result m_home; result::size_type m_row = 0; /** * You'd expect this to be unsigned, but due to the way reverse iterators * are related to regular iterators, it must be allowed to underflow to -1. */ row_size_type m_col = 0; }; inline char const *field_ref::c_str() const & noexcept { return pqxx::internal::gate::result_field_ref{home()}.get_value( row_number(), column_number()); } inline bool field_ref::is_null() const noexcept { return pqxx::internal::gate::result_field_ref{home()}.get_is_null( row_number(), column_number()); } inline field_size_type field_ref::size() const noexcept { return pqxx::internal::gate::result_field_ref{home()}.get_length( row_number(), column_number()); } inline oid field_ref::type(sl loc) const { return pqxx::internal::gate::result_field_ref{home()}.column_type( column_number(), loc); } inline oid field_ref::table(sl loc) const { return pqxx::internal::gate::result_field_ref{home()}.column_table( column_number(), loc); } /// Specialization: `to(zview &)`. /** This conversion is not generally available, since the general conversion * would not know whether there was indeed a terminating zero at the end of * the string. (It could check, but it would have no way of knowing that a * zero occurring after the string in memory was actually part of the same * allocation.) */ template<> inline bool field::to(zview &obj, sl) const { bool const null{is_null()}; if (not null) obj = zview{c_str(), size()}; return not null; } template<> inline bool field::to(zview &obj, zview const &default_value, sl) const { bool const null{is_null()}; if (null) obj = default_value; else obj = zview{c_str(), size()}; return not null; } /// Efficient specialisation: you can convert a field to a `zview`. /** String conversions generally accept `std::string_view`. You can't just * "convert" any old `std::string_view` to a `pqxx::zview` because `zview` is * a promise that the string is zero-terminated. One can't generally make that * promise based on a `string_view`. * */ template<> inline zview field_ref::as(sl loc) const { if (is_null()) internal::throw_null_conversion(name_type(), loc); return zview{c_str(), size()}; } template<> inline zview field::as(zview const &default_value, sl) const { return is_null() ? default_value : zview{c_str(), size()}; } template> class field_streambuf final : public std::basic_streambuf { public: using char_type = CHAR; using traits_type = TRAITS; using int_type = typename traits_type::int_type; using pos_type = typename traits_type::pos_type; using off_type = typename traits_type::off_type; using openmode = std::ios::openmode; using seekdir = std::ios::seekdir; explicit field_streambuf(field const &f) : m_field{f} { initialize(); } protected: int sync() override { return traits_type::eof(); } pos_type seekoff(off_type, seekdir, openmode) override { return traits_type::eof(); } pos_type seekpos(pos_type, openmode) override { return traits_type::eof(); } int_type overflow(int_type) override { return traits_type::eof(); } int_type underflow() override { return traits_type::eof(); } private: // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) field const &m_field; int_type initialize() { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast) auto g{static_cast(const_cast(m_field.c_str()))}; this->setg(g, g, g + std::size(m_field)); return int_type(std::size(m_field)); } }; // NOLINTBEGIN(fuchsia-multiple-inheritance) /// Input stream that gets its data from a result field /** @deprecated To convert a field's value string to some other type, e.g. to * an `int`, use the field's `as<...>()` member function. To read a field * efficiently just as a string, use its `c_str()` or its * `as()`. * * Works like any other istream to read data from a field. It supports all * formatting and streaming operations of `std::istream`. For convenience * there is a fieldstream alias, which defines a @ref basic_fieldstream for * `char`. This is similar to how e.g. `std::ifstream` relates to * `std::basic_ifstream`. * * This class has only been tested for the char type (and its default traits). */ template> class basic_fieldstream final : public std::basic_istream { using super = std::basic_istream; public: using char_type = CHAR; using traits_type = TRAITS; using int_type = typename traits_type::int_type; using pos_type = typename traits_type::pos_type; using off_type = typename traits_type::off_type; [[deprecated("Use field::as<...>() or field::c_str().")]] explicit basic_fieldstream(field const &f) : super{nullptr}, m_buf{f} { super::init(&m_buf); } private: field_streambuf m_buf; }; // NOLINTEND(fuchsia-multiple-inheritance) /// @deprecated Read a field using `field::as<...>()` or `field::c_str()`. using fieldstream = basic_fieldstream; /// Write a result field to any type of stream. /** @deprecated The C++ streams library is not great to work with. In * particular, error handling is easy to get wrong. So you're probably better * off doing this by hand. * * This can be convenient when writing a field to an output stream. More * importantly, it lets you write a field to e.g. a `stringstream` which you * can then use to read, format and convert the field in ways that to() does * not support. * * Example: parse a field into a variable of the nonstandard `long long` type. * * ```cxx * extern result R; * long long L; * stringstream S; * * // Write field's string into S * S << R[0][0]; * * // Parse contents of S into L * S >> L; * ``` */ template [[deprecated("To write a pqxx::field, use its view() method.")]] inline std:: basic_ostream & operator<<(std::basic_ostream &s, field const &value) { s.write(value.c_str(), std::streamsize(std::size(value))); return s; } /// Convert a field's value to type `T`. /** Unlike the "regular" `from_string`, this knows how to deal with null * values. */ template inline T from_string(field const &value, ctx c = {}) { if (value.is_null()) { if constexpr (has_null()) return make_null(); else internal::throw_null_conversion(name_type(), c.loc); } else { return from_string(value.view(), c); } } /// Convert a field's value to type `T`. /** Unlike the "regular" `from_string`, this knows how to deal with null * values. */ template inline T from_string(field_ref const &value, ctx c = {}) { if (value.is_null()) { if constexpr (has_null()) return make_null(); else internal::throw_null_conversion(name_type(), c.loc); } else { return from_string(value.view(), c); } } // TODO: Can we make this generic across all "always-null" types? // TODO: Do the same for streams. /// Convert a field's value to `nullptr_t`. /** Yes, you read that right. This conversion does nothing useful. It always * returns `nullptr`. * * Except... what if the field is not null? In that case, this throws * @ref conversion_error. */ template<> inline std::nullptr_t from_string(field const &value, ctx c) { if (not value.is_null()) throw conversion_error{ "Extracting non-null field into nullptr_t variable.", c.loc}; return nullptr; } // clang-tidy rule bug: // NOLINTBEGIN(misc-unused-parameters) /// Convert a field_ref to a string. template<> PQXX_LIBEXPORT inline std::string to_string(field_ref const &value, ctx) { return std::string{value.view()}; } // NOLINTEND(misc-unused-parameters) /// Convert a field to a string. template<> PQXX_LIBEXPORT inline std::string to_string(field const &value, ctx) { return std::string{value.view()}; } } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/internal/000077500000000000000000000000001516427024100174505ustar00rootroot00000000000000libpqxx-8.0.1/include/pqxx/internal/array-composite.hxx000066400000000000000000000374541516427024100233340ustar00rootroot00000000000000#if !defined(PQXX_ARRAY_COMPOSITE_HXX) # define PQXX_ARRAY_COMPOSITE_HXX # include # include "pqxx/util.hxx" # include "pqxx/internal/encodings.hxx" # include "pqxx/strconv.hxx" namespace pqxx::internal { // The width in bytes of a single ASCII character. In other words, one. constexpr std::size_t one_ascii_char{1u}; // Find the end of a double-quoted string. /** `input[pos]` must be the opening double quote. * * The backend double-quotes strings in composites or arrays, when needed. * Special characters are escaped using backslashes. * * Returns the offset of the first position after the closing quote. */ template PQXX_INLINE_COV inline constexpr std::size_t scan_double_quoted_string(std::string_view input, std::size_t pos, sl loc) { assert(input[pos] == '"'); auto const sz{std::size(input)}; // Skip over the opening double-quote, and after that, any leading // "un-interesting" characters. pos = find_ascii_char(input, pos + one_ascii_char, loc); while (pos < sz) { // No need to check for a multibyte character here: if it's multibyte, its // first byte won't match either of these ASCII characters. switch (input[pos]) { case '"': // Is this the closing quote we're looking for? Scan ahead to find out. pos += one_ascii_char; if (pos >= sz) { // Clear-cut case. This is the closing quote and it's right at the end // of the input. return pos; } else if (input[pos] == '"') { // What we found is a doubled-up double-quote. That's the other way of // escaping them. Why can't this ever be simple? pos += one_ascii_char; if (pos >= sz) throw argument_error{ "Unexpected end of string: double double-quote."}; } else { // This was the closing quote (though not at the end of the input). // We are now at the one-past-end position. return pos; } break; case '\\': // Backslash escape. Move on to the next character, so that at the end // of the iteration we'll skip right over it. pos += one_ascii_char; if (pos >= sz) throw argument_error{"Unexpected end of string: backslash.", loc}; if ((input[pos] == '\\') or (input[pos] == '"')) { // As you'd expect: the backslash escapes a double-quote, or another // backslash. Move past it, or the find_ascii_char<>() at the end of // the iteration will just stop here again. pos += one_ascii_char; if (pos >= sz) throw argument_error{ "Unexpected end of string: escape sequence.", loc}; } break; } // We've reached the end of one iteration without reaching the end of the // string. pos = find_ascii_char(input, pos, loc); } // If we got here, we never found the closing double-quote. throw argument_error{ "Missing closing double-quote: " + std::string{input}, loc}; } // TODO: Needs version with caller-supplied buffer. /// Un-quote and un-escape a double-quoted SQL string. /** @param input Text. The double-quoted string must start at offset `pos`, * and must end at the end of `input`. So, truncate `input` before calling if * necessary. */ template PQXX_INLINE_COV inline constexpr std::string parse_double_quoted_string(std::string_view input, std::size_t pos, sl loc) { std::string output; auto const end{std::size(input)}; assert((end - pos) > 1); assert(input[end - 1] == '"'); // Maximum output size is same as the input size, minus the opening and // closing quotes. Or in the extreme opposite case, the real number could be // half that. Usually it'll be a pretty close estimate. output.reserve(std::size_t(end - pos - 2)); auto const closing_quote{end - 1}; // We're at the starting quote. Skip it. assert(pos < closing_quote); assert(input[pos] == '"'); pos += one_ascii_char; assert(pos <= closing_quote); // In theory, the closing quote should mean that there's no need for the // find_ascii_char() call to check for end-of-string inside its loop. Not // sure whether the compiler will be smart enough to see that though. assert(input[closing_quote] == '"'); while (pos < closing_quote) { auto const next{find_ascii_char(input, pos, loc)}; output.append(input.substr(pos, next - pos)); pos = next; assert(pos <= closing_quote); assert((input[pos] == '"') or (input[pos] == '\\')); if (pos >= closing_quote) return output; // We're at either a backslash or a double-quote... and we're not at the // closing quote. Therefore, we're at an escape character. Skip it. pos += one_ascii_char; // We are now at the escaped character. // If the input has been scanned correctly, the string can't end here. assert(pos < closing_quote); if ((input[pos] == '"') or (input[pos] == '\\')) { // We know this is a single-byte character. Append that (skipping the // escaping character) and move on to the next character. output.push_back(input[pos]); pos += one_ascii_char; } else { // This could be a multibyte character. But no matter: we can let the // next iteration handle it like any run-of-the-mill character. } } assert(pos == closing_quote); return output; } /// Find the end of an unquoted string in an array or composite-type value. /** Stops when it gets to the end of the input; or when it sees any of the * characters in STOP which has not been escaped. * * For array values, STOP is an array element separator (typically comma, or * semicolon), or a closing brace. For a value of a composite type, STOP is a * comma or a closing parenthesis. */ template PQXX_INLINE_COV inline constexpr std::size_t scan_unquoted_string(std::string_view input, std::size_t pos, sl loc) { return find_ascii_char(input, pos, loc); } /// Parse an unquoted array entry or cfield of a composite-type field. /** @param input A view on the text, truncated at the end of the string. So, * the end of `input` must coincide with the end of the string. Truncate * before calling if necessary. * @param pos The string's starting offset within `input`. */ template PQXX_INLINE_ONLY inline constexpr std::string_view parse_unquoted_string(std::string_view input, std::size_t pos, sl) { return input.substr(pos); } /// Parse a field of a composite-type value. /** `T` is the C++ type of the field we're parsing, and `index` is its * zero-based number. * * Strip off the leading parenthesis or bracket yourself before parsing. * However, this function will parse the lcosing parenthesis or bracket. * * After a successful parse, `pos` will point at `std::end(text)`. * * For the purposes of parsing, ranges and arrays count as compositve values, * so this function supports parsing those. If you specifically need a closing * parenthesis, check afterwards that `text` did not end in a bracket instead. * * @param index Index of the current field, zero-based. It will increment for * the next field. * @param input Full input text for the entire composite-type value. * @param pos Starting position (in `input`) of the field that we're parsing. * After parsing, this will point at the beginning of the next field if * there is one, or one position past the last character otherwise. * @param field Destination for the parsed value. * @param scan Glyph scanning function for the relevant encoding type. * @param last_field Number of the last field in the value (zero-based). When * parsing the last field, this will equal `index`. */ template PQXX_INLINE_COV inline void parse_composite_field( std::size_t &index, std::string_view input, std::size_t &pos, T &field, std::size_t last_field, sl loc) { assert(index <= last_field); assert(pos < std::size(input)); conversion_context const c{ENC, loc}; // Expect a field. switch (input[pos]) { case ',': case ')': case ']': // The field is empty, i.e, null. if constexpr (has_null()) field = make_null(); else throw conversion_error{ std::format( "Can't read composite field {}: C++ type {} does not support nulls.", to_string(index), name_type()), loc}; break; case '"': { auto const stop{scan_double_quoted_string(input, pos, loc)}; PQXX_ASSUME(stop > pos); auto const text{ parse_double_quoted_string(input.substr(0, stop), pos, loc)}; field = from_string(text, c); pos = stop; } break; default: { // Parse an unquoted string field. It ends when we see a comma (meaning // there's a next field after it), or a closing parenthesis or bracket // (meaning we're at the last field). auto const stop{scan_unquoted_string(input, pos, loc)}; PQXX_ASSUME(stop >= pos); field = from_string(input.substr(pos, stop - pos), c); pos = stop; } break; } // End of field. Expect a comma or a closing parenthesis. if (index < last_field) { // There's another field coming after this one. if (input[pos] != ',') throw conversion_error{ std::format( "Found '{}' in composite value where comma was expected: '{}.", input[pos], input), loc}; pos += one_ascii_char; } else { // We're parsing the last field. if (input[pos] == ',') throw conversion_error{ std::format( "Composite value contained more fields than the expected {}: '{}'.", to_string(last_field, c), std::data(input)), loc}; if (input[pos] != ')' and input[pos] != ']') throw conversion_error{ std::format( "Composite value has unexpected characters where closing " "parenthesis " "was expected: '{}'.", std::string{input}), loc}; pos += one_ascii_char; if (pos != std::size(input)) throw conversion_error{ std::format( "Composite value has unexpected text after closing parenthesis: " "'{}'.", std::string{input}), loc}; } ++index; } /// Pointer to an encoding-specific specialisation of parse_composite_field. template using composite_field_parser = void (*)( std::size_t &index, std::string_view input, std::size_t &pos, T &field, std::size_t last_field, sl loc); /// Look up implementation of parse_composite_field for ENC. template PQXX_INLINE_COV inline constexpr composite_field_parser specialize_parse_composite_field(conversion_context const &c) { switch (c.enc) { case encoding_group::unknown: throw usage_error{ "Tried to parse array/composite without knowing its text encoding.", c.loc}; case encoding_group::ascii_safe: return parse_composite_field; case encoding_group::two_tier: return parse_composite_field; case encoding_group::gb18030: return parse_composite_field; case encoding_group::sjis: return parse_composite_field; } throw internal_error{ std::format("Unexpected encoding group code: {}.", to_string(c.enc)), c.loc}; } /// Conservatively estimate buffer size needed for a composite field. template PQXX_INLINE_COV inline std::size_t size_composite_field_buffer(T const &field) { if constexpr (is_unquoted_safe) { // Safe to copy, without quotes or escaping. Drop the terminating zero. return size_buffer(field) - 1; } else { // + Opening quote. // + Field budget. // - Terminating zero. // + Escaping for each byte in the field's string representation. // - Escaping for terminating zero. // + Closing quote. return 1 + 2 * (size_buffer(field) - 1) + 1; } } template PQXX_INLINE_ONLY inline void write_composite_field( std::span buf, std::size_t &pos, T const &field, ctx c) { if constexpr (is_unquoted_safe) { // No need for quoting or escaping. Convert it straight into its final // place in the buffer. pos += into_buf(buf.subspan(pos), field, c); } else { // The field may need escaping, which means we need an intermediate buffer. // To avoid allocating that at run time, we use the end of the buffer that // we have. auto const budget{size_buffer(field)}; assert(budget < std::size(buf)); // C++26: Use buf.at(). buf[pos++] = '"'; // Now escape buf into its final position. for (char const x : to_buf(buf.last(budget), field, c)) { if ((x == '"') or (x == '\\')) // C++26: Use buf.at(). buf[pos++] = '\\'; // C++26: Use buf.at(). buf[pos++] = x; } // C++26: Use buf.at(). buf[pos++] = '"'; } // C++26: Use buf.at(). buf[pos++] = ','; } /// Write an SQL array representation into `buf`. /** @return The number of bytes used, from the beginning of `buf`. There is no * terminating zero. */ template [[nodiscard]] PQXX_INLINE_COV inline std::size_t array_into_buf( std::span buf, TYPE const &value, std::size_t budget, ctx c) { using elt_type = std::remove_cvref_t>; if (std::cmp_less(std::size(buf), budget)) throw conversion_overrun{ "Not enough buffer space to convert array to string.", c.loc}; std::size_t here{0u}; // C++26: Use buf.at(). buf[here++] = '{'; bool nonempty{false}; for (auto const &elt : value) { static constexpr zview s_null{"NULL"}; if (is_null(elt)) { here = copy_chars(s_null, buf, here, c.loc); } else if constexpr (is_sql_array) { // Render nested array in-place. here += pqxx::into_buf(buf.subspan(here), elt, c); } else if constexpr (is_unquoted_safe) { // No need to quote or escape. Just convert the value straight into // its place in the array. here += pqxx::into_buf(buf.subspan(here), elt, c); } else { // Quote & escape. // C++26: Use buf.at(). buf[here++] = '"'; auto const sz{std::size(buf)}, elt_budget{pqxx::size_buffer(elt)}; // Use the tail end of the destination buffer as an intermediate // buffer. assert(std::cmp_less(elt_budget, sz - here)); auto const from{pqxx::to_buf(buf.last(elt_budget), elt, c)}; auto const end{std::size(from)}; auto const find{get_char_finder<'\\', '"'>(c.enc, c.loc)}; // Copy the intermediate buffer into the final buffer, but escape // using backslashes. The tricky part here is to handle encodings right. std::size_t i{0}; while (i < end) { auto next{find(from, i, c.loc)}; here = copy_chars({std::data(from) + i, next - i}, buf, here, c.loc); if (next < end) { // We hit either a quote or a backslash. Insert an escape // character (which is always a simple single ASCII byte). // C++26: Use buf.at(). buf[here++] = '\\'; // C++26: Use buf.at(). // Copy the escaped character itself. This is another simple single // ASCII byte. // TODO: Can we restructure this to leave that to the next iteration? buf[here++] = from[next++]; } i = next; } // Copy any final text. here = copy_chars({std::data(from) + i, end - i}, buf, here, c.loc); // C++26:Use buf.at(). buf[here++] = '"'; } // C++26:Use buf.at(). buf[here++] = array_separator; nonempty = true; } // Erase that last comma, if present. if (nonempty) here--; // C++26:Use buf.at(). buf[here++] = '}'; return here; } } // namespace pqxx::internal #endif libpqxx-8.0.1/include/pqxx/internal/callgate.hxx000066400000000000000000000045301516427024100217570ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_CALLGATE_HXX #define PQXX_INTERNAL_CALLGATE_HXX /* Here's what a typical gate class definition looks like: ```cxx #include namespace pqxx::internal::gate { class PQXX_PRIVATE @gateclass@ final : callgate<@host@> { friend class @client@; explicit constexpr @gateclass@(reference x) noexcept : super(x) {} // Methods here. Use home() to access the host-class object. }; } // namespace pqxx::internal::gate ``` */ namespace pqxx::internal { /// Base class for call gates. /** * A call gate defines a limited, private interface on the host class that * specified client classes can access. * * The metaphor works as follows: the gate stands in front of a "home," which * is really a class, and only lets specific friends in. * * To implement a call gate that gives client C access to host H, * * derive a gate class from callgate; * * make the gate class a friend of H; * * make C a friend of the gate class; and * * implement "stuff C can do with H" as private members in the gate class. * * This special kind of "gated" friendship gives C private access to H, but * only through an expressly limited interface. The gate class can access its * host object as home(). * * Keep gate classes entirely stateless. They should be ultra-lightweight * wrappers for their host classes, and be optimized away as much as possible * by the compiler. Once you start adding state, you're on a slippery slope * away from the pure, clean, limited interface pattern that gate classes are * meant to implement. * * Ideally, all member functions of the gate class should be one-liners passing * calls straight on to the host class. It can be useful however to break this * rule temporarily during inter-class refactoring. */ template class PQXX_PRIVATE callgate { protected: /// This class, to keep constructors easy. using super = callgate; /// A reference to the host class. Helps keep constructors easy. using reference = HOME &; explicit constexpr callgate(reference x) noexcept : m_home(x) {} /// The home object. The gate class has full "private" access. [[nodiscard]] constexpr reference home() const noexcept { return m_home; } private: // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) reference m_home; }; } // namespace pqxx::internal #endif libpqxx-8.0.1/include/pqxx/internal/connection-string.hxx000066400000000000000000000035471516427024100236550ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_CONNECTION_STRING_HXX #define PQXX_INTERNAL_CONNECTION_STRING_HXX namespace pqxx::internal { /// Parse a connection string into option keys and their values. /** This is a class and not a function for just one reason: the outputs contain * pointers to storage that needs to be held in memory. */ class PQXX_LIBEXPORT connection_string_parser final { public: explicit connection_string_parser( char const connection_string[], sl = sl::current()); connection_string_parser() = delete; connection_string_parser(connection_string_parser const &) = delete; connection_string_parser(connection_string_parser &&) = default; connection_string_parser & operator=(connection_string_parser const &) = delete; connection_string_parser &operator=(connection_string_parser &&) = default; ~connection_string_parser() noexcept; /// Parse the string, return matching vectors of option names & values. /** The two vectors are of equal length. The first holds the option names * and the second their respective values. * * The outputs remain valid only for as long as the whole * `connection_string_parser` does. You can call `parse()` as many times as * you like. The calls will produce distinct outputs but the ultimate string * pointers will be the same, and in the same order. * * The vectors will only contain values that were actually specified (as * opposed to ones that were left to their defaults), but they will have * enough room reserved to specify all possible options, plus a terminating * null that we may need to add. */ [[nodiscard]] std::array, 2u> parse() const; private: using opts_pointer = std::unique_ptr< pqxx::internal::pq::PQconninfoOption, void (*)(pqxx::internal::pq::PQconninfoOption *)>; opts_pointer m_options; }; } // namespace pqxx::internal #endif libpqxx-8.0.1/include/pqxx/internal/conversions.hxx000066400000000000000000000755051516427024100225650ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_CONVERSIONS_HXX #define PQXX_INTERNAL_CONVERSIONS_HXX #include #include #include #include #include #include #include #include #include #include #include "pqxx/encoding_group.hxx" #include "pqxx/strconv.hxx" /* Internal helpers for string conversion, and conversion implementations. * * Do not include this header directly. The libpqxx headers do it for you. */ namespace pqxx::internal { /// Convert a number in [0, 9] to its ASCII digit. PQXX_PURE inline constexpr char number_to_digit(int i) noexcept { PQXX_ASSUME(i >= 0); PQXX_ASSUME(i <= 9); return static_cast(i + '0'); } /// Compute numeric value of given textual digit (assuming that it is a digit). /** The digit must be a base-10 digit. */ PQXX_PURE inline constexpr int digit_to_number(char c) noexcept { PQXX_ASSUME(c >= '0'); PQXX_ASSUME(c <= '9'); return c - '0'; } /// Summarize buffer overrun. /** Don't worry about the exact parameter types: the sizes will be reasonably * small, and nonnegative. */ PQXX_LIBEXPORT std::string state_buffer_overrun(int have_bytes, int need_bytes); template PQXX_INLINE_COV inline std::string state_buffer_overrun(HAVE have_bytes, NEED need_bytes) { return state_buffer_overrun( static_cast(have_bytes), static_cast(need_bytes)); } /// Throw exception for attempt to convert SQL NULL to given type. [[noreturn]] PQXX_COLD PQXX_LIBEXPORT void throw_null_conversion(std::string const &type, sl); /// Throw exception for attempt to convert SQL NULL to given type. [[noreturn]] PQXX_COLD PQXX_LIBEXPORT void throw_null_conversion(std::string_view type, sl); /// Deliberately nonfunctional conversion traits for `char` types. /** There are no string conversions for `char` and its signed and unsigned * variants. Such a conversion would be dangerously ambiguous: should we treat * it as text, or as a small integer? It'd be an open invitation for bugs. * * But the error message when you get this wrong is very cryptic. So, we * derive dummy @ref string_traits implementations from this dummy type, and * ensure that the compiler disallows their use. The compiler error message * will at least contain a hint of the root of the problem. */ template struct disallowed_ambiguous_char_conversion { static constexpr std::size_t size_buffer(CHAR_TYPE const &) noexcept = delete; static constexpr std::string_view to_buf(std::span, CHAR_TYPE const &, ctx = {}) noexcept = delete; static CHAR_TYPE from_string(std::string_view, ctx = {}) = delete; }; template PQXX_LIBEXPORT extern std::string to_string_float(T, ctx = {}); /// Generic implementation for `into_buf()`, on top of `to_buf()`. template [[deprecated("into_buf() is no longer part of the string conversion API.")]] inline char * generic_into_buf(char *begin, char *end, T const &value, ctx c = {}) { zview text{to_buf({begin, end}, value, c)}; auto const space{end - begin}; // Include the trailing zero. auto const len = std::size(text) + 1; if (std::cmp_greater(len, space)) throw conversion_overrun{ std::format("Not enough buffer space to insert {}.", name_type()) + state_buffer_overrun(space, len), c.loc}; std::memmove(begin, std::data(text), len); return begin + len; } /// Generic implementation for `into_buf()`, on top of `to_buf()`. template [[deprecated("into_buf() is no longer part of the string conversion API.")]] inline std::size_t generic_into_buf(std::span buf, T const &value, ctx c = {}) { auto const begin{std::data(buf)}; zview text{to_buf(buf, value, c)}; auto const space{std::size(buf)}; // Include the trailing zero. auto const len = std::size(text) + 1; if (std::cmp_greater(len, space)) throw conversion_overrun{ std::format("Not enough buffer space to insert {}. ", name_type()) + state_buffer_overrun(space, len), c.loc}; std::memmove(begin, std::data(text), len); return len; } /// String traits for builtin floating-point types. /** It _would_ make sense to define this directly as the definition for * `pqxx::string_traits` where `T` is a `std::floating_point`. However * Visual Studio 2022 does not seem to accept that syntax. * * So instead, we create a separate base class for `std::floating_point` types * and then derive specialisations of `pqxx::string_traits` from that. */ template struct float_string_traits { PQXX_LIBEXPORT static T from_string(std::string_view text, ctx = {}); PQXX_LIBEXPORT static std::string_view to_buf(std::span buf, T const &value, ctx c = {}); // Return a nonnegative integral value's number of decimal digits. static constexpr std::size_t digits10(std::size_t value) noexcept { if (value < 10) return 1; else return 1 + digits10(value / 10); } PQXX_INLINE_COV static constexpr std::size_t size_buffer(T const &) noexcept { using lims = std::numeric_limits; // See #328 for a detailed discussion on the maximum number of digits. // // In a nutshell: for the big cases, the scientific notation is always // the shortest one, and therefore the one that to_chars will pick. // // So... How long can the scientific notation get? 1 (for sign) + 1 (for // decimal point) + 1 (for 'e') + 1 (for exponent sign) + max_digits10 + // max number of digits in the exponent + 1 (terminating zero). // // What's the max number of digits in the exponent? It's the max number of // digits out of the most negative exponent and the most positive one. // // The longest positive exponent is easy: 1 + ceil(log10(max_exponent10)). // (The extra 1 is because 10^n takes up 1 + n digits, not n.) // // The longest negative exponent is a bit harder: min_exponent10 gives us // the smallest power of 10 which a normalised version of T can represent. // But the smallest denormalised power of 10 that T can represent is // another max_digits10 powers of 10 below that. It also needs room for a // a minus sign. // // All this stuff messes with my head a bit because it's on the order of // log10(log10(n)). It's easy to get the number of logs wrong. auto const max_pos_exp{digits10(lims::max_exponent10)}; // Really want std::abs(lims::min_exponent10), but MSVC 2017 apparently has // problems with std::abs. So we use -lims::min_exponent10 instead. auto const max_neg_exp{ digits10(lims::max_digits10 - lims::min_exponent10)}; return 1 + // Sign. 1 + // Decimal point. std::numeric_limits::max_digits10 + // Mantissa digits. 1 + // Exponent "e". 1 + // Exponent sign. // Spell this weirdly to stop Windows compilers from reading this as // a call to their "max" macro when NOMINMAX is not defined. (std::max)(max_pos_exp, max_neg_exp); // Exponent digits. } }; /// String traits for builtin integer types. /** This does not cover `bool` or (unlike `std::integral`) the `char` types. * * Once upon a time this was a partial specialisation of `string_traits` for * the `pqxx::internal::integer` concept, but MSVC 2026 had a mysterious * problem with that (see #1160). So, we had to revert to a much clunkier way * of creating those specialisations. */ template struct integer_string_traits { PQXX_LIBEXPORT static T from_string(std::string_view text, ctx = {}); PQXX_LIBEXPORT static std::string_view to_buf(std::span buf, T const &value, ctx c = {}); PQXX_INLINE_ONLY static constexpr std::size_t size_buffer(T const &) noexcept { /** Includes a sign if needed; the number of base-10 digits which the type * can reliably represent; and the one extra base-10 digit which the type * can only partially represent. */ return std::is_signed_v + std::numeric_limits::digits10 + 1; } }; } // namespace pqxx::internal namespace pqxx { /// The built-in arithmetic types do not have inherent null values. /** Not-a-Number values (or NaNs for short) behave a lot like an SQL null, but * they are not nulls. A non-null SQL float can be NaN. */ template requires std::is_arithmetic_v struct nullness final : no_null {}; template inline constexpr bool is_unquoted_safe{true}; template inline constexpr bool is_unquoted_safe{true}; #define PQXX_SPECIALIZE_INT_TRAIT(typ) \ template<> \ struct string_traits final \ : pqxx::internal::integer_string_traits \ {} PQXX_SPECIALIZE_INT_TRAIT(short); PQXX_SPECIALIZE_INT_TRAIT(unsigned short); PQXX_SPECIALIZE_INT_TRAIT(int); PQXX_SPECIALIZE_INT_TRAIT(unsigned); PQXX_SPECIALIZE_INT_TRAIT(long); PQXX_SPECIALIZE_INT_TRAIT(unsigned long); PQXX_SPECIALIZE_INT_TRAIT(long long); PQXX_SPECIALIZE_INT_TRAIT(unsigned long long); #undef PQXX_SPECIALIZE_INT_TRAIT template<> struct string_traits final : pqxx::internal::float_string_traits {}; template<> struct string_traits final : pqxx::internal::float_string_traits {}; template<> struct string_traits final : pqxx::internal::float_string_traits {}; template<> struct string_traits final { PQXX_LIBEXPORT static bool from_string(std::string_view text, ctx c = {}); static constexpr zview to_buf(std::span, bool const &value, ctx = {}) noexcept { return value ? "true"_zv : "false"_zv; } static constexpr std::size_t size_buffer(bool const &) noexcept { return 5; } }; template<> inline constexpr bool is_unquoted_safe{true}; template struct nullness> final { static constexpr bool has_null = true; /// Technically, you could have an optional of an always-null type. static constexpr bool always_null = pqxx::always_null(); [[nodiscard]] PQXX_PURE static constexpr bool is_null(std::optional const &v) noexcept { return ((not v.has_value()) or pqxx::is_null(*v)); } [[nodiscard]] PQXX_PURE static constexpr std::optional null() noexcept { return {}; } }; template inline constexpr format param_format(std::optional const &value) { return param_format(*value); } template struct string_traits> final { static std::string_view to_buf(std::span buf, std::optional const &value, ctx c = {}) { if (pqxx::is_null(value)) return {}; else // (No need to check: if the optional were empty, it'd be null.) // NOLINTNEXTLINE(bugprone-unchecked-optional-access) return pqxx::to_buf(buf, *value, c); } static std::optional from_string(std::string_view text, ctx c = {}) { return std::optional{std::in_place, pqxx::from_string(text, c)}; } static std::size_t size_buffer(std::optional const &value) noexcept { if (pqxx::is_null(value)) return 0; else // (No need to check: if the optional were empty, it'd be null.) // NOLINTNEXTLINE(bugprone-unchecked-optional-access) return pqxx::size_buffer(value.value()); } }; template inline constexpr bool is_unquoted_safe>{is_unquoted_safe}; template struct nullness> final { static constexpr bool has_null = (pqxx::has_null() or ...); static constexpr bool always_null = (pqxx::always_null() and ...); [[nodiscard]] PQXX_PURE static constexpr bool is_null(std::variant const &value) noexcept { return value.valueless_by_exception() or std::visit( [](auto const &i) noexcept { return nullness>::is_null(i); }, value); } // We don't support `null()` for `std::variant`. /** It would be technically possible to have a `null` in the case where just * one of the types has a null, but it gets complicated and arbitrary. */ static constexpr std::variant null() = delete; }; template struct string_traits> final { static std::string_view to_buf(std::span buf, std::variant const &value, ctx c = {}) { return std::visit( [buf, c](auto const &i) { using field_t = std::remove_cvref_t; return pqxx::to_buf(buf, i, c); }, value); } static std::size_t size_buffer(std::variant const &value) noexcept { if (pqxx::is_null(value)) return 0; else return std::visit( [](auto const &i) noexcept { return pqxx::size_buffer(i); }, value); } /** There's no from_string for std::variant. We could have one with a rule * like "pick the first type which fits the value," but we'd have to look * into how natural that API feels to users. */ static std::variant from_string(std::string_view, ctx = {}) = delete; }; template inline constexpr format param_format(std::variant const &value) { return std::visit([](auto &v) { return param_format(v); }, value); } template inline constexpr bool is_unquoted_safe>{ (is_unquoted_safe and ...)}; template inline T from_string(std::stringstream const &text, ctx c = {}) { return from_string(text.str(), c); } template<> struct string_traits final { [[deprecated("Do not convert nulls.")]] static constexpr zview to_buf(std::span, std::nullptr_t const &, ctx = {}) noexcept { return {}; } [[deprecated("Do not convert nulls.")]] static constexpr std::size_t size_buffer(std::nullptr_t = nullptr) noexcept { return 0; } static std::nullptr_t from_string(std::string_view, ctx = {}) = delete; }; template<> struct string_traits final { [[deprecated("Do not convert nulls.")]] static constexpr zview to_buf(char *, char *, std::nullopt_t const &) noexcept { return {}; } [[deprecated("Do not convert nulls.")]] static constexpr std::size_t size_buffer(std::nullopt_t) noexcept { return 0; } static std::nullopt_t from_string(std::string_view, ctx = {}) = delete; }; template<> struct string_traits final { [[deprecated("Do not convert nulls.")]] static constexpr zview to_buf(char *, char *, std::monostate const &) noexcept { return {}; } [[deprecated("Do not convert nulls.")]] static constexpr std::size_t size_buffer(std::monostate) noexcept { return 0; } [[deprecated("Do not convert nulls.")]] static std::monostate from_string(std::string_view, ctx = {}) = delete; }; template<> inline constexpr bool is_unquoted_safe{true}; template<> struct nullness final { static constexpr bool has_null = true; static constexpr bool always_null = false; [[nodiscard]] PQXX_PURE PQXX_ZARGS static constexpr bool is_null(char const *t) noexcept { return t == nullptr; } [[nodiscard]] PQXX_PURE static constexpr char const *null() noexcept { return nullptr; } }; /// String traits for C-style string ("pointer to char const"). /** This conversion is not bidirectional. You can convert a C-style string to * an SQL string, but not the other way around. * * The reason for this is the terminating zero. The incoming SQL string is a * `std::string_view`, which may or may not have a zero at the end. (And * there's no reliable way of checking, since the next memory position may not * be a valid address. Even if there happens to be a zero there, it isn't * necessarily part of the same block of mmory.) */ template<> struct string_traits final { static char const *from_string(std::string_view text, ctx = {}) = delete; constexpr PQXX_ZARGS static std::string_view to_buf(std::span, char const *const &value, ctx = {}) noexcept { return value; } PQXX_ZARGS static constexpr std::size_t size_buffer(char const *value) noexcept { if (pqxx::is_null(value)) return 0; else // std::char_traits::length() is like std::strlen(), but constexpr. return std::char_traits::length(value); } }; template<> struct nullness final { static constexpr bool has_null = true; static constexpr bool always_null = false; [[nodiscard]] PQXX_PURE static constexpr bool is_null(char const *t) noexcept { return t == nullptr; } [[nodiscard]] PQXX_PURE static constexpr char *null() { return nullptr; } }; /// String traits for non-const C-style string ("pointer to char"). /** This conversion is not bidirectional. You can convert a `char *` to an * SQL string, but not vice versa. * * There are two reasons. One is the fact that an SQL string arrives in the * form of a `std::string_view`; there is no guarantee of a trailing zero. * * The other reason is constness. We can't give you a non-const pointer into * a string that was handed into the conversion as `const`. */ template<> struct string_traits final { static std::string_view to_buf(std::span buf, char *const &value, ctx c = {}) { return pqxx::to_buf(buf, value, c); } static std::size_t size_buffer(char *const &value) noexcept { if (pqxx::is_null(value)) return 0; else return pqxx::size_buffer(const_cast(value)); } static char *from_string(std::string_view, ctx = {}) = delete; }; template struct nullness final : no_null {}; /// String traits for C-style string constant ("pointer to array of char"). /** @warning This assumes that every array-of-char is a C-style string literal. * So, it must include a trailing zero. and it must have static duration. */ template struct string_traits final { static constexpr zview to_buf(std::span, char const (&value)[N], ctx = {}) noexcept { return zview{value, N - 1}; } static constexpr std::size_t size_buffer(char const (&)[N]) noexcept { return N; } /// Don't allow conversion to this type. static void from_string(std::string_view, ctx = {}) = delete; }; template<> struct nullness final : no_null {}; template<> struct string_traits final { PQXX_INLINE_ONLY static std::string from_string(std::string_view text, ctx = {}) { return std::string{text}; } PQXX_INLINE_ONLY static std::string_view to_buf(std::span, std::string const &value, ctx = {}) { return {std::data(value), std::size(value)}; } PQXX_INLINE_ONLY static constexpr std::size_t size_buffer(std::string const &value) noexcept { return std::size(value); } }; /// There's no real null value for `std::string_view`. /** A `string_view` may have a null data pointer, which is analogous to a null * `char` pointer, but the standard does not really seem to guarantee that it * is distinct from other empty string views. */ template<> struct nullness final : no_null {}; /// String traits for `string_view`. /** @warning This conversion does not store the string's contents anywhere. * When you convert a string to a `std::string_view`, _do not access the * resulting view after the original string has been destroyed. The contents * will no longer be valid, even though tests may not make this obvious. */ template<> struct string_traits final { PQXX_INLINE_ONLY static constexpr std::size_t size_buffer(std::string_view const &value) noexcept { return std::size(value); } PQXX_INLINE_ONLY static std::string_view to_buf(std::span, std::string_view const &value, ctx = {}) { return value; } PQXX_INLINE_ONLY static std::string_view from_string(std::string_view value, ctx = {}) { return value; } }; template<> struct nullness final : no_null {}; /// String traits for `zview`. template<> struct string_traits final { PQXX_INLINE_ONLY static constexpr std::size_t size_buffer(std::string_view const &value) noexcept { return std::size(value); } static constexpr zview to_buf(std::span, zview const &value, ctx = {}) { return value; } /// Don't convert to this type. There may not be a terminating zero. /** There is no valid way to figure out here whether there is a terminating * zero. Even if there is one, that may just be the first byte of an * entirely separately allocated piece of memory. */ static zview from_string(std::string_view, ctx = {}) = delete; }; template<> struct nullness final : no_null {}; template<> struct string_traits final { static std::size_t size_buffer(std::stringstream const &) = delete; static std::stringstream from_string(std::string_view text, ctx = {}) { std::stringstream stream; stream.write(text.data(), std::streamsize(std::size(text))); return stream; } static std::string_view to_buf(std::span, std::stringstream const &, ctx = {}) = delete; }; template<> struct nullness final : all_null {}; template<> struct nullness final : all_null {}; template<> struct nullness final : all_null {}; template struct nullness> final { static constexpr bool has_null = true; static constexpr bool always_null = false; [[nodiscard]] PQXX_PURE static constexpr bool is_null(std::unique_ptr const &t) noexcept { return not t or pqxx::is_null(*t); } [[nodiscard]] PQXX_PURE static constexpr std::unique_ptr null() noexcept { return {}; } }; template struct string_traits> final { static std::unique_ptr from_string(std::string_view text, ctx c = {}) { return std::make_unique(pqxx::from_string(text, c)); } static std::string_view to_buf( std::span buf, std::unique_ptr const &value, ctx c = {}) { if (not value) internal::throw_null_conversion(name_type>(), c.loc); return pqxx::to_buf(buf, *value, c); } static std::size_t size_buffer(std::unique_ptr const &value) noexcept { if (pqxx::is_null(value)) return 0; else return pqxx::size_buffer(*value.get()); } }; template inline format param_format(std::unique_ptr const &value) { return param_format(*value); } template inline constexpr bool is_unquoted_safe>{ is_unquoted_safe}; template struct nullness> final { static constexpr bool has_null = true; static constexpr bool always_null = false; [[nodiscard]] PQXX_PURE static constexpr bool is_null(std::shared_ptr const &t) noexcept { return not t or pqxx::is_null(*t); } [[nodiscard]] PQXX_PURE static constexpr std::shared_ptr null() noexcept { return {}; } }; template struct string_traits> final { static std::shared_ptr from_string(std::string_view text, ctx c = {}) { return std::make_shared(pqxx::from_string(text, c)); } static std::string_view to_buf(std::span buf, std::shared_ptr const &value, ctx c = {}) { if (not value) internal::throw_null_conversion(name_type>(), c.loc); return pqxx::to_buf(buf, *value, c); } static std::size_t size_buffer(std::shared_ptr const &value) noexcept { if (pqxx::is_null(value)) return 0; else return pqxx::size_buffer(*value); } }; template format param_format(std::shared_ptr const &value) { return param_format(*value); } template inline constexpr bool is_unquoted_safe>{ is_unquoted_safe}; template struct nullness final : no_null {}; template struct string_traits final { static std::size_t size_buffer(DATA const &value) noexcept { return internal::size_esc_bin(std::size(value)); } static std::string_view to_buf(std::span buf, DATA const &value, ctx c = {}) { // Budget for this type is precise. auto const budget{size_buffer(value)}; if (std::cmp_less(std::size(buf), budget)) throw conversion_overrun{ "Not enough buffer space to escape binary data.", c.loc}; internal::esc_bin(value, buf); // The budget included a terminating zero, which we do not include in the // view. return {std::data(buf), budget - 1}; } /// Convert a string to binary data. static DATA from_string(std::string_view text, ctx c = {}) { auto const size{pqxx::internal::size_unesc_bin(std::size(text))}; DATA buf{}; if constexpr (requires { buf.resize(std::size_t{}); }) { // Make `buf` allocate the number of bytes we need to store. buf.resize(size); } else { // There's no suitable `DATA::resize()`. But perhaps the caller has // ensured that `DATA` is a type that inherently has the right size. // Might a `std::array` for instance. if (std::size(buf) != size) throw conversion_error{ std::format( "Can't convert binary data from SQL text to {}: I don't know how " "to " "resize that type.", name_type()), c.loc}; } pqxx::internal::unesc_bin(text, buf, c.loc); return buf; } }; } // namespace pqxx namespace pqxx::internal { template inline std::size_t array_into_buf( std::span buf, TYPE const &value, std::size_t budget, ctx c = {}); /// Base class for `string_traits` specialisations for nonbinary ranges. /** We use the same code for the `pqxx::array` traits, and I'm not sure how to * delegate directly to a specialisation for a broader concept. */ template struct nonbinary_range_traits { using elt_type = std::remove_cvref_t>; using elt_traits = string_traits; static constexpr zview s_null{"NULL"}; static std::size_t size_buffer(T const &value) noexcept { if constexpr (is_unquoted_safe) return 3 + std::accumulate( std::begin(value), std::end(value), std::size_t{}, [](std::size_t acc, elt_type const &elt) { // Budget for each element includes a terminating zero. // We won't actually be wanting those, but don't subtract // that one byte: we want room for a separator instead. // However, std::size(s_null) doesn't account for the // terminating zero, so add one to make s_null pay for its // own separator. return acc + (pqxx::is_null(elt) ? (std::size(s_null) + 1) : elt_traits::size_buffer(elt)); }); else return 3 + std::accumulate( std::begin(value), std::end(value), std::size_t{}, [](std::size_t acc, elt_type const &elt) { // Opening and closing quotes, plus worst-case escaping, // plus one byte for the separator. std::size_t const elt_size{ pqxx::is_null(elt) ? std::size(s_null) : elt_traits::size_buffer(elt)}; return acc + 2 * elt_size + 3; }); } static std::string_view to_buf(std::span buf, T const &value, ctx c = {}) { auto const sz{ pqxx::internal::array_into_buf(buf, value, size_buffer(value), c)}; return {std::data(buf), sz}; } }; } // namespace pqxx::internal namespace pqxx { template struct nullness final : no_null {}; /// String traits for SQL arrays. /** This is a very generic implementation, It doesn't carry enough type * information about the container to support _parsing_ of a string into an * array of a more or less arbitrary C++ type, but it's handy for converting * various container types _to_ strings. */ template struct string_traits final : pqxx::internal::nonbinary_range_traits {}; /// We don't know how to pass array params in binary format, so pass as text. template inline constexpr format param_format(T const &) { return format::text; } /// A contiguous range of `std::byte` is a binary string; other ranges are not. template inline constexpr format param_format(T const &) { return format::binary; } template inline constexpr bool is_sql_array{true}; template PQXX_INLINE_COV inline std::string to_string(TYPE const &value, ctx c) { if (is_null(value)) throw conversion_error{ std::format("Attempt to convert null to a string.", name_type()), c.loc}; if constexpr (pqxx::always_null()) { // Have to separate out this case: some functions in the "regular" code // may not exist in the "always null" case. PQXX_UNREACHABLE; // C++23: The return may not be needed when std::unreachable is available. return {}; } else { std::string buf; // We can't just reserve() space; modifying the terminating zero leads to // undefined behaviour. buf.resize(pqxx::size_buffer(value)); std::size_t const stop{pqxx::into_buf(buf, value, c)}; buf.resize(stop); return buf; } } template<> inline std::string to_string(float const &value, ctx c) { return pqxx::internal::to_string_float(value, c); } template<> inline std::string to_string(double const &value, ctx c) { return pqxx::internal::to_string_float(value, c); } template<> inline std::string to_string(long double const &value, ctx c) { return pqxx::internal::to_string_float(value, c); } // clang-tidy rule bug: // NOLINTNEXTLINE(misc-unused-parameters) template<> inline std::string to_string(std::stringstream const &value, ctx) { return value.str(); } template inline void into_string(T const &value, std::string &out, ctx c = {}) { if (is_null(value)) throw conversion_error{ std::format("Attempt to convert null {} to a string.", name_type()), c.loc}; // We can't just reserve() data; modifying the terminating zero leads to // undefined behaviour. out.resize(size_buffer(value)); auto const data{out.data()}; auto const end{into_buf({data, std::size(out)}, value, c)}; out.resize(static_cast(end - data)); } } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/internal/encodings.hxx000066400000000000000000000277751516427024100221740ustar00rootroot00000000000000/** Internal string encodings support for libpqxx * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_INTERNAL_ENCODINGS_HXX #define PQXX_INTERNAL_ENCODINGS_HXX #include #include #include #include #include "pqxx/encoding_group.hxx" #include "pqxx/strconv.hxx" namespace pqxx { PQXX_DECLARE_ENUM_CONVERSION(encoding_group); } // namespace pqxx namespace pqxx::internal { /// Return PostgreSQL's name for encoding enum value. PQXX_PURE char const *name_encoding(int encoding_id) noexcept; /// Convert libpq encoding enum value to its libpqxx group. PQXX_PURE PQXX_LIBEXPORT encoding_group enc_group(int /* libpq encoding ID */, sl); /// Extract byte from buffer, return as unsigned char. /** Don't generate out-of-line copies; they complicate profiling. */ PQXX_PURE PQXX_INLINE_ONLY constexpr inline unsigned char get_byte(std::string_view buffer, std::size_t offset) noexcept { assert(offset < std::size(buffer)); return static_cast(buffer[offset]); } /// Throw an error reporting that input text is not properly encoded. /** @param encoding_name Either a name for the expected encoding, or a * placeholder for it. * @param buffer The full input text. * @param start The starting offset for the incorrect character. * @param count The number of bytes in the incorrect character. Must not * exceed the size of the buffer. */ [[noreturn]] PQXX_COLD PQXX_LIBEXPORT PQXX_ZARGS void throw_for_encoding_error( char const *encoding_name, std::string_view buffer, std::size_t start, std::size_t count, sl loc); /// Throw an error reporting that the input is truncated in mid-character. /** This happens when a multibyte character is supposed to span more bytes * than there are left in the buffer. * * @param encoding_name Either a name for the expected encoding, or a * placeholder for it. * @param buffer The full input text. * @param start The starting offset for the incorrect character. */ [[noreturn]] PQXX_COLD PQXX_LIBEXPORT PQXX_ZARGS void throw_for_truncated_character( char const *encoding_name, std::string_view buffer, std::size_t start, sl loc); /// Does value lie between bottom and top, inclusive? /** Don't generate out-of-line copies; they complicate profiling. */ PQXX_PURE PQXX_INLINE_ONLY constexpr inline bool between_inc(unsigned char value, unsigned bottom, unsigned top) noexcept { return value >= bottom and value <= top; } /// Wrapper struct template for "find next glyph" functions. /** When we use this, all we really want is a function pointer. But that * won't work, because the template specialisation we use will only work (under * current C++ rules) for a struct or class, not for a function. */ template struct glyph_scanner final { /// Find the next glyph in `buffer` _after_ position `start`. /** The starting point must lie inside the view. */ static constexpr inline std::size_t call(std::string_view, std::size_t start, sl); }; /// Find any of the ASCII characters in `NEEDLE` in `haystack`. /** Scans through `haystack` until it finds a single-byte character that * matches any of the values in `NEEDLE`. * * Returns the offset of the character it finds, or the end of the `haystack` * otherwise. */ template PQXX_INLINE_COV inline constexpr std::size_t find_ascii_char(std::string_view haystack, std::size_t here, sl loc) { // We only know how to search for ASCII characters. It's an optimisation // assumption in the code below. static_assert((... and ((NEEDLE & 0x80) == 0))); auto const sz{std::size(haystack)}; auto const data{std::data(haystack)}; while (here < sz) { // Look up the next character boundary. This can be quite costly, so we // desperately want the call inlined. auto next{glyph_scanner::call(haystack, here, loc)}; PQXX_ASSUME(next > here); // (For some reason gcc had a problem with a right-fold here. But clang // was fine.) // // In all supported encodings, if a character's first byte is in the ASCII // range, that means it's a single-byte character. It follows that when we // find a match at a position that's the beginning of a character, we do // not need to check that we're in a single-byte character. We are. // // So, we only ever need to check each character's first byte, and if it // doesn't match, move on to the next character. // // As an optimisation for "ASCII-safe" encodings however, we just check // every byte in the text. It's going to be faster than finding character // boundaries first. In these encodings, a multichar byte never contains // any bytes in the ASCII range at all. if ((... or (data[here] == NEEDLE))) return here; // Nope, no hit. Move on. here = next; } return sz; } /// ASCII, Latin-1, UTF-8, and the like. /** These are the "ASCII-safe" encodings. Safe in the sense that in correctly * encoded text, there can never be a byte that happens to have the same * numeric value has an ASCII character we might be looking for. * * This applies to UTF-8, Latin-* (iso-8859-*), other single-byte encodings, * and probably more. So when we're scanning text in these encodings for one * or more special ASCII characters, we can just walk through it byte by byte. * That might _sound_ slower, but it's actually a lot more efficient than * constantly checking the values of the bytes and deciding when to jump ahead * by one or two bytes. */ template<> struct glyph_scanner final { PQXX_INLINE_ONLY PQXX_PURE static constexpr std::size_t call(std::string_view, std::size_t start, sl) noexcept { return start + 1; } }; /// Common encoding pattern: 1-byte ASCII, or 2-byte starting with high byte. /** Both BIG5 and Unified Hangul Code (UHC) work like this. The details vary, * with both having different sub-ranges where no valid characters exist, but * we don't check for those. We simply don't care. Caring is inefficient. * * What we do care about is that when a byte has a value that looks like a * special ASCII character we're trying to find, we know exactly whether it is * that ASCII character, or just a byte inside a multibyte character. * * With UHC, the second byte in a character is always either outside the ASCII * range or in one of the two ASCII letter ranges (A-Z and a-z). So as long as * we're not searching for letters, we actually use @ref ascii_safe there * instead. */ template<> struct glyph_scanner final { PQXX_INLINE_ONLY static constexpr std::size_t call(std::string_view buffer, std::size_t start, sl loc) { auto const byte1{get_byte(buffer, start)}; if (byte1 < 0x80) { // Single-byte ASCII subset. return start + 1; } else if (start + 2 <= std::size(buffer)) { // Two-byte character. Not all combinations are valid, but that's not // our concern. All that matters to libpqxx is that it not mistake an // ASCII-like value in the second byte for a special character, or vice // versa. return start + 2; } else { // We do need to ensure that the string does not end in the middle of // a character, or an attacker could "steal" a special ASCII character // that comes directly after the end of the input, and escape the bounds // of the text that way. [[unlikely]] throw_for_truncated_character( "variable-width two-byte encoding", buffer, start, loc); } } }; /// GB18030 and its older subsets, including GBK. /** Chinese variable-width encoding of up to 4 bytes per character. * * See https://en.wikipedia.org/wiki/GB_18030#Mapping */ template<> struct glyph_scanner final { PQXX_INLINE_ONLY static constexpr std::size_t call(std::string_view buffer, std::size_t start, sl loc) { auto const byte1{get_byte(buffer, start)}; if (byte1 < 0x80) return start + 1; auto const sz{std::size(buffer)}; if (byte1 == 0x80) throw_for_encoding_error("GB18030", buffer, start, sz - start, loc); if (start + 2 > sz) [[unlikely]] throw_for_truncated_character("GB18030", buffer, start, loc); auto const byte2{get_byte(buffer, start + 1)}; if (between_inc(byte2, 0x40, 0xfe)) { if (byte2 == 0x7f) [[unlikely]] throw_for_encoding_error("GB18030", buffer, start, 2, loc); return start + 2; } if (start + 4 > sz) [[unlikely]] throw_for_truncated_character("GB18030", buffer, start, loc); if ( between_inc(byte2, 0x30, 0x39) and between_inc(get_byte(buffer, start + 2), 0x81, 0xfe) and between_inc(get_byte(buffer, start + 3), 0x30, 0x39)) return start + 4; [[unlikely]] throw_for_encoding_error("GB18030", buffer, start, 4, loc); } }; /// Shift-JIS family of encodings. /** These are variable-width encodings with 1-byte and 2-byte characters, but * with a twist: Katakana is mapped in the above-ASCII range _as single-byte * characters._ * * If it weren't for that twist, this would be just like @ref two_tier. */ template<> struct glyph_scanner final { PQXX_INLINE_ONLY static constexpr std::size_t call(std::string_view buffer, std::size_t start, sl loc) { auto const byte1{get_byte(buffer, start)}; if (byte1 < 0x80) // ASCII subset (though some characters changed). return start + 1; if (between_inc(byte1, 0xa1, 0xdf)) // Katakana, also single-byte characters. return start + 1; // We're a bit strict at checking the first byte, because this is a // relatively complex encoding. We don't want to get fooled by some // extension we don't know about. An error and a user complaint is still // better than a lurking bug. if ( not between_inc(byte1, 0x81, 0x9f) and not between_inc(byte1, 0xe0, 0xfc)) [[unlikely]] throw_for_encoding_error("SJIS", buffer, start, 1, loc); if (start + 2 > std::size(buffer)) [[unlikely]] throw_for_truncated_character("SJIS", buffer, start, loc); return start + 2; } }; /// Look up a character search function for an encoding group. /** We only define a few individual instantiations of this function, as needed. * * Returns a pointer to a function which looks for the first instance of any of * the ASCII characters in `NEEDLE`. Returns its offset, or the end of the * `haystack` if it found none. * * @warn All of the characters in `NEEDLE` need to be ASCII characters, and * they _cannot be letters._ This is needed because it enables a more * efficient implementation of UHC support. */ template PQXX_PURE PQXX_RETURNS_NONNULL PQXX_INLINE_COV constexpr inline char_finder_func * get_char_finder(encoding_group enc, sl loc) { // All characters in NEEDLE must be ASCII. static_assert((... and (static_cast(NEEDLE) < 0x80))); // We don't support searching for a NEEDLE that's a letter. This allows us // to lump UHC in with the more efficient ASCII-safe group. static_assert((... and not between_inc(NEEDLE, 'A', 'Z'))); static_assert((... and not between_inc(NEEDLE, 'a', 'z'))); switch (enc) { case encoding_group::unknown: throw pqxx::argument_error{ "Tried to read text without knowing its encoding.", loc}; case encoding_group::ascii_safe: return pqxx::internal::find_ascii_char< encoding_group::ascii_safe, NEEDLE...>; case encoding_group::two_tier: return pqxx::internal::find_ascii_char< encoding_group::two_tier, NEEDLE...>; case encoding_group::gb18030: return pqxx::internal::find_ascii_char; case encoding_group::sjis: return pqxx::internal::find_ascii_char; default: throw pqxx::internal_error{ std::format("Unexpected encoding group: {}.", to_string(enc)), loc}; } } } // namespace pqxx::internal #endif libpqxx-8.0.1/include/pqxx/internal/gates/000077500000000000000000000000001516427024100205535ustar00rootroot00000000000000libpqxx-8.0.1/include/pqxx/internal/gates/connection-errorhandler.hxx000066400000000000000000000012571516427024100261350ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_CONNECTION_ERRORHANDLER_HXX #define PQXX_INTERNAL_GATES_CONNECTION_ERRORHANDLER_HXX #include namespace pqxx { class connection; class errorhandler; } // namespace pqxx namespace pqxx::internal::gate { class PQXX_PRIVATE connection_errorhandler final : callgate { friend class pqxx::errorhandler; explicit constexpr connection_errorhandler(reference x) noexcept : super(x) {} void register_errorhandler(errorhandler *h) { home().register_errorhandler(h); } void unregister_errorhandler(errorhandler *h) { home().unregister_errorhandler(h); } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/connection-largeobject.hxx000066400000000000000000000017321516427024100257250ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_CONNECTION_LARGEOBJECT_HXX #define PQXX_INTERNAL_GATES_CONNECTION_LARGEOBJECT_HXX #include #include namespace pqxx { class blob; class largeobject; } // namespace pqxx namespace pqxx::internal::gate { class PQXX_PRIVATE connection_largeobject final : callgate { friend class pqxx::blob; friend class pqxx::largeobject; explicit constexpr connection_largeobject(reference x) noexcept : super(x) {} PQXX_PURE [[nodiscard]] pq::PGconn *raw_connection() const noexcept { return home().raw_connection(); } }; class PQXX_PRIVATE const_connection_largeobject final : callgate { friend class pqxx::blob; friend class pqxx::largeobject; explicit constexpr const_connection_largeobject(reference x) noexcept : super(x) {} [[nodiscard]] std::string error_message() const { return home().err_msg(); } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/connection-notification_receiver.hxx000066400000000000000000000014661516427024100300220ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_CONNECTION_NOTIFICATION_RECEIVER_HXX #define PQXX_INTERNAL_GATES_CONNECTION_NOTIFICATION_RECEIVER_HXX #include #include "pqxx/connection.hxx" namespace pqxx { class notification_receiver; } // namespace pqxx namespace pqxx::internal::gate { class PQXX_PRIVATE connection_notification_receiver final : callgate { friend class pqxx::notification_receiver; explicit constexpr connection_notification_receiver(reference x) noexcept : super(x) {} void add_receiver(notification_receiver *receiver, sl loc) { home().add_receiver(receiver, loc); } void remove_receiver(notification_receiver *receiver, sl loc) noexcept { home().remove_receiver(receiver, loc); } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/connection-pipeline.hxx000066400000000000000000000017441516427024100252540ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_CONNECTION_PIPELINE_HXX #define PQXX_INTERNAL_GATES_CONNECTION_PIPELINE_HXX #include #include "pqxx/pipeline.hxx" namespace pqxx::internal::gate { class PQXX_PRIVATE connection_pipeline final : callgate { friend class pqxx::pipeline; explicit constexpr connection_pipeline(reference x) noexcept : super(x) {} PQXX_ZARGS void start_exec(char const query[]) { home().start_exec(query); } [[nodiscard]] pqxx::internal::pq::PGresult *get_result() { return home().get_result(); } void cancel_query(sl loc) { home().cancel_query(loc); } bool consume_input() noexcept { return home().consume_input(); } [[nodiscard]] bool is_busy() const noexcept { return home().is_busy(); } [[nodiscard]] int encoding_id(sl loc) const { return home().encoding_id(loc); } [[nodiscard]] auto get_notice_waiters() const { return home().m_notice_waiters; } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/connection-sql_cursor.hxx000066400000000000000000000011251516427024100256340ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_CONNECTION_SQL_CURSOR_HXX #define PQXX_INTERNAL_GATES_CONNECTION_SQL_CURSOR_HXX #include namespace pqxx::internal { class sql_cursor; } // namespace pqxx::internal namespace pqxx::internal::gate { class PQXX_PRIVATE connection_sql_cursor final : callgate { friend class pqxx::internal::sql_cursor; explicit constexpr connection_sql_cursor(reference x) noexcept : super(x) {} PQXX_ZARGS result exec(char const query[], sl loc) { return home().exec(query, loc); } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/connection-stream_from.hxx000066400000000000000000000012711516427024100257600ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_CONNECTION_STREAM_FROM_HXX #define PQXX_INTERNAL_GATES_CONNECTION_STREAM_FROM_HXX #include namespace pqxx::internal { template class stream_query; } // namespace pqxx::internal #include "pqxx/connection.hxx" namespace pqxx::internal::gate { class PQXX_PRIVATE connection_stream_from final : callgate { friend class pqxx::stream_from; template friend class pqxx::internal::stream_query; explicit constexpr connection_stream_from(reference x) noexcept : super{x} {} auto read_copy_line(sl loc) { return home().read_copy_line(loc); } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/connection-stream_to.hxx000066400000000000000000000011331516427024100254340ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_CONNECTION_STREAM_TO_HXX #define PQXX_INTERNAL_GATES_CONNECTION_STREAM_TO_HXX #include #include "pqxx/stream_to.hxx" namespace pqxx::internal::gate { class PQXX_PRIVATE connection_stream_to final : callgate { friend class pqxx::stream_to; explicit constexpr connection_stream_to(reference x) noexcept : super(x) {} void write_copy_line(std::string_view line, sl loc) { home().write_copy_line(line, loc); } void end_copy_write(sl loc) { home().end_copy_write(loc); } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/connection-transaction.hxx000066400000000000000000000027001516427024100257650ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_CONNECTION_TRANSACTION_HXX #define PQXX_INTERNAL_GATES_CONNECTION_TRANSACTION_HXX #include namespace pqxx { class connection; } // namespace pqxx namespace pqxx::internal::gate { class PQXX_PRIVATE connection_transaction final : callgate { friend class pqxx::transaction_base; explicit constexpr connection_transaction(reference x) noexcept : super(x) {} template result exec(STRING const &query, std::string_view desc, sl loc) { return home().exec(query, desc, loc); } template result exec(STRING query, sl loc) { return home().exec(query, "", loc); } void register_transaction(transaction_base *t) { home().register_transaction(t); } void unregister_transaction(transaction_base *t) noexcept { home().unregister_transaction(t); } auto read_copy_line(sl loc) { return home().read_copy_line(loc); } void write_copy_line(std::string_view line, sl loc) { home().write_copy_line(line, loc); } void end_copy_write(sl loc) { home().end_copy_write(loc); } result exec_prepared( std::string_view statement, internal::c_params const &args, sl loc) { return home().exec_prepared(statement, args, loc); } result exec_params(std::string_view query, internal::c_params const &args, sl loc) { return home().exec_params(query, args, loc); } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/errorhandler-connection.hxx000066400000000000000000000007371516427024100261370ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_ERRORHANDLER_CONNECTION_HXX #define PQXX_INTERNAL_GATES_ERRORHANDLER_CONNECTION_HXX #include namespace pqxx::internal::gate { class PQXX_PRIVATE errorhandler_connection final : callgate { friend class pqxx::connection; explicit constexpr errorhandler_connection(reference x) noexcept : super(x) {} void unregister() noexcept { home().unregister(); } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/field_ref-const_row_iterator.hxx000066400000000000000000000010771516427024100271540ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_FIELD_REF_CONST_ROW_ITERATOR_HXX #define PQXX_INTERNAL_GATES_FIELD_REF_CONST_ROW_ITERATOR_HXX #include namespace pqxx { class field_ref; } // namespace pqxx namespace pqxx::internal::gate { class PQXX_PRIVATE field_ref_const_row_iterator final : callgate { friend class pqxx::const_row_iterator; explicit constexpr field_ref_const_row_iterator(reference x) noexcept : super(x) {} void offset(row_difference_type d) { home().offset(d); } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/icursor_iterator-icursorstream.hxx000066400000000000000000000016671516427024100276150ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_ICURSOR_ITERATOR_ICURSORSTREAM_HXX #define PQXX_INTERNAL_GATES_ICURSOR_ITERATOR_ICURSORSTREAM_HXX #include namespace pqxx::internal::gate { class PQXX_PRIVATE icursor_iterator_icursorstream final : callgate { friend class pqxx::icursorstream; explicit constexpr icursor_iterator_icursorstream(reference x) noexcept : super(x) {} [[nodiscard]] icursor_iterator::difference_type pos() const noexcept { return home().pos(); } [[nodiscard]] icursor_iterator *get_prev() const noexcept { return home().m_prev; } void set_prev(icursor_iterator *i) noexcept { home().m_prev = i; } [[nodiscard]] icursor_iterator *get_next() const noexcept { return home().m_next; } void set_next(icursor_iterator *i) { home().m_next = i; } void fill(result const &r) { home().fill(r); } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/icursorstream-icursor_iterator.hxx000066400000000000000000000016671516427024100276150ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_ICURSORSTREAM_ICURSOR_ITERATOR_HXX #define PQXX_INTERNAL_GATES_ICURSORSTREAM_ICURSOR_ITERATOR_HXX #include namespace pqxx::internal::gate { class PQXX_PRIVATE icursorstream_icursor_iterator final : callgate { friend class pqxx::icursor_iterator; explicit constexpr icursorstream_icursor_iterator(reference x) noexcept : super(x) {} void insert_iterator(icursor_iterator *i) noexcept { home().insert_iterator(i); } void remove_iterator(icursor_iterator *i) const noexcept { home().remove_iterator(i); } icursorstream::size_type forward() { return home().forward(); } icursorstream::size_type forward(icursorstream::size_type n) { return home().forward(n); } void service_iterators(icursorstream::difference_type p, sl loc) { home().service_iterators(p, loc); } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/result-connection.hxx000066400000000000000000000010571516427024100247620ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_RESULT_CONNECTION_HXX #define PQXX_INTERNAL_GATES_RESULT_CONNECTION_HXX #include namespace pqxx::internal::gate { class PQXX_PRIVATE result_connection final : callgate { friend class pqxx::connection; explicit constexpr result_connection(reference x) noexcept : super(x) {} [[nodiscard]] explicit operator bool() const noexcept { return bool(home()); } [[nodiscard]] bool operator!() const noexcept { return not home(); } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/result-creation.hxx000066400000000000000000000015771516427024100244360ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_RESULT_CREATION_HXX #define PQXX_INTERNAL_GATES_RESULT_CREATION_HXX #include namespace pqxx::internal::gate { class PQXX_PRIVATE result_creation final : callgate { friend class pqxx::connection; friend class pqxx::pipeline; explicit constexpr result_creation(reference x) noexcept : super(x) {} [[nodiscard]] static result create( std::shared_ptr const &rhs, std::shared_ptr const &query, std::shared_ptr ¬ice_waiters, encoding_group enc) { return {rhs, query, notice_waiters, enc}; } void check_status(std::string_view desc, sl loc) const { return home().check_status(desc, loc); } void check_status(sl loc) const { return home().check_status("", loc); } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/result-field_ref.hxx000066400000000000000000000023321516427024100245370ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_RESULT_FIELD_REF_HXX #define PQXX_INTERNAL_GATES_RESULT_FIELD_REF_HXX #include namespace pqxx::internal::gate { class PQXX_PRIVATE result_field_ref final : callgate { friend class pqxx::field_ref; explicit constexpr result_field_ref(reference x) : super(x) {} [[nodiscard]] PQXX_PURE char const * get_value(result_size_type row_num, row_size_type col_num) const noexcept { return home().get_value(row_num, col_num); } [[nodiscard]] PQXX_PURE bool get_is_null(result_size_type row_num, row_size_type col_num) const noexcept { return home().get_is_null(row_num, col_num); } [[nodiscard]] PQXX_PURE field_size_type get_length(result_size_type row_num, row_size_type col_num) const noexcept { return home().get_length(row_num, col_num); } [[nodiscard]] oid column_type(row_size_type col_num, sl loc) const { return home().column_type(col_num, loc); } [[nodiscard]] oid column_table(row_size_type col_num, sl loc) const { return home().column_table(col_num, loc); } [[nodiscard]] encoding_group encoding() const noexcept { return home().m_encoding; } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/result-pipeline.hxx000066400000000000000000000007611516427024100244310ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_RESULT_PIPELINE_HXX #define PQXX_INTERNAL_GATES_RESULT_PIPELINE_HXX #include namespace pqxx::internal::gate { class PQXX_PRIVATE result_pipeline final : callgate { friend class pqxx::pipeline; explicit constexpr result_pipeline(reference x) noexcept : super(x) {} [[nodiscard]] std::shared_ptr query_ptr() const { return home().query_ptr(); } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/result-sql_cursor.hxx000066400000000000000000000006041516427024100250140ustar00rootroot00000000000000#include namespace pqxx::internal::gate { class PQXX_PRIVATE result_sql_cursor final : callgate { friend class pqxx::internal::sql_cursor; constexpr result_sql_cursor(reference x) noexcept : super(x) {} [[nodiscard]] char const *cmd_status() const noexcept { return home().cmd_status(); } }; } // namespace pqxx::internal::gate libpqxx-8.0.1/include/pqxx/internal/gates/row_ref-const_result_iterator.hxx000066400000000000000000000011051516427024100273770ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_ROW_REF_CONST_RESULT_ITERATOR_HXX #define PQXX_INTERNAL_GATES_ROW_REF_CONST_RESULT_ITERATOR_HXX #include namespace pqxx { class row_ref; } // namespace pqxx namespace pqxx::internal::gate { class PQXX_PRIVATE row_ref_const_result_iterator final : callgate { friend class pqxx::const_result_iterator; explicit constexpr row_ref_const_result_iterator(reference x) noexcept : super(x) {} void offset(result_difference_type d) { home().offset(d); } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/row_ref-result.hxx000066400000000000000000000010541516427024100242630ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_ROW_REF_RESULT_HXX #define PQXX_INTERNAL_GATES_ROW_REF_RESULT_HXX #include namespace pqxx { class row_ref; } // namespace pqxx namespace pqxx::internal::gate { class PQXX_PRIVATE row_ref_result final : callgate { friend class pqxx::result; explicit constexpr row_ref_result(reference x) noexcept : super(x) {} template [[nodiscard]] TUPLE as_tuple(sl loc) const { return home().as_tuple(loc); } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/row_ref-row.hxx000066400000000000000000000010721516427024100235540ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_ROW_REF_ROW_HXX #define PQXX_INTERNAL_GATES_ROW_REF_ROW_HXX #include namespace pqxx::internal::gate { class PQXX_PRIVATE row_ref_row final : callgate { friend class pqxx::row; explicit constexpr row_ref_row(reference x) noexcept : super(x) {} template void extract_fields(Tuple &t, std::index_sequence seq, ctx c) const { return home().extract_fields(t, seq, c); } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/gates/transaction-transaction_focus.hxx000066400000000000000000000016541516427024100273610ustar00rootroot00000000000000#ifndef PQXX_INTERNAL_GATES_TRANSACTION_TRANSACTION_FOCUS_HXX #define PQXX_INTERNAL_GATES_TRANSACTION_TRANSACTION_FOCUS_HXX #include #include "pqxx/transaction_base.hxx" namespace pqxx::internal::gate { class PQXX_PRIVATE transaction_transaction_focus final : callgate { friend class pqxx::transaction_focus; explicit constexpr transaction_transaction_focus(reference x) noexcept : super(x) {} void register_focus(transaction_focus *focus) { home().register_focus(focus); } void unregister_focus(transaction_focus *focus) noexcept { home().unregister_focus(focus); } void register_pending_error(zview error, sl loc) { home().register_pending_error(error, loc); } void register_pending_error(std::string &&error, sl loc) { home().register_pending_error(std::move(error), loc); } }; } // namespace pqxx::internal::gate #endif libpqxx-8.0.1/include/pqxx/internal/header-post.hxx000066400000000000000000000013401516427024100224120ustar00rootroot00000000000000// NOLINT(llvm-header-guard) /* Compiler deficiency workarounds for compiling libpqxx headers. * * To be included at the end of each libpqxx header, in order to restore the * client program's settings. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ // NO GUARDS HERE! This code should be included every time! #if defined(_MSC_VER) # pragma warning(pop) // Restore compiler's warning state #endif #if !defined(PQXX_HEADER_PRE) # error "Include pqxx/internal/header-post.hxx AFTER its 'pre' counterpart." #endif #undef PQXX_HEADER_PRE libpqxx-8.0.1/include/pqxx/internal/header-pre.hxx000066400000000000000000000157141516427024100222250ustar00rootroot00000000000000// NOLINT(llvm-header-guard) /* Compiler settings for compiling libpqxx headers, and workarounds for all. * * Include this before including any other libpqxx headers from within libpqxx. * And to balance it out, also include header-post.hxx at the end of the batch * of headers. * * The public libpqxx headers (e.g. ``) include this already; * there's no need to do this from within an application. * * Include this file at the highest aggregation level possible to avoid nesting * and to keep things simple. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #if __has_include() # include #endif // NO GUARD HERE! This part should be included every time this file is. #if defined(_MSC_VER) // Save compiler's warning state, and set warning level 4 for maximum // sensitivity to warnings. # pragma warning(push, 4) // Visual C++ generates some entirely unreasonable warnings. Disable them. # pragma warning(disable : 4061 4251 4275 4275 4511 4512 4514 4623 4625) # pragma warning(disable : 4626 4702 4820 4868 5026 5027 5031 5045 6294) #endif // _MSC_VER #if defined(PQXX_HEADER_PRE) # error "Avoid nesting #include of pqxx/internal/header-pre.hxx." #endif #define PQXX_HEADER_PRE // Workarounds & definitions that need to be included even in library's headers #include "pqxx/config-compiler.h" // MSVC has a nonstandard definition of __cplusplus. #if defined(_MSC_VER) # define PQXX_CPLUSPLUS _MSVC_LANG #else # define PQXX_CPLUSPLUS __cplusplus #endif #if __has_cpp_attribute(gnu::pure) /// Declare function "pure": no side effects, only reads globals and its args. /** Be careful with exceptions. The compiler may elide calls, which may stop * an exception from happening; or reorder them, moving a call outside of a * `try` block that was meant to catch the exception. */ # define PQXX_PURE [[gnu::pure]] #else # define PQXX_PURE /* pure */ #endif #if __has_cpp_attribute(gnu::cold) /// Tell the compiler to optimise a function for size, not speed. # define PQXX_COLD [[gnu::cold]] #else # define PQXX_COLD /* cold */ #endif #if __has_cpp_attribute(gnu::always_inline) /// Never generate an out-of-line version of this inline function. # define PQXX_INLINE_ONLY [[gnu::always_inline]] #elif __has_cpp_attribute(msvc::forceinline) /// Never generate an out-of-line version of this inline function. # define PQXX_INLINE_ONLY [[msvc::forceinline]] #else # define PQXX_INLINE_ONLY /* always inline */ #endif /// Don't generate out-of-line version of inline function for coverage runs. /** This helps avoid a lot of false positives with gcov. The out-of-line * function never gets executed, and so its code is all marked as not covered * by the test suite. The code may get executed, but all inline. * * We're only defining this for gcc, since that's the compiler we use for test * coverage analysis. */ #if defined(PQXX_COVERAGE) && __has_cpp_attribute(gnu::always_inline) # define PQXX_INLINE_COV [[gnu::always_inline]] #else # define PQXX_INLINE_COV /* inline-only on coverage runs */ #endif /// Never inline this function. /** Bear in mind that this only works for the specific compilers for which we * know non-standard attributes that achieve this. */ #if __has_cpp_attribute(gnu::noinline) # define PQXX_NOINLINE [[gnu::noinline]] #elif __has_cpp_attribute(msvc::noinline) # define PQXX_NOINLINE [[msvc::noinline]] #else # define PQXX_NOINLINE /* noinline */ #endif #if __has_cpp_attribute(gnu::returns_nonnull) /// For functions returning a pointer: the pointer is never null. # define PQXX_RETURNS_NONNULL [[gnu::returns_nonnull]] #else # define PQXX_RETURNS_NONNULL /* returns nonnull */ #endif #if __has_cpp_attribute(gnu::null_terminated_string_arg) /// Function argument n (counted starting from 1) is a zero-terminated string. # define PQXX_ZARG(n) [[gnu::null_terminated_string_arg((n))]] #else # define PQXX_ZARG(n) /* null-terminated string arg */ #endif // Not all gcc versions we're seeing support the argument-less version. #if defined(PQXX_HAVE_ZARGS) /// This function's C-style string arguments are zero-terminated. # define PQXX_ZARGS [[gnu::null_terminated_string_arg]] #else # define PQXX_ZARGS /* null-terminated string args */ #endif // Workarounds for Windows #ifdef _WIN32 /* For now, export DLL symbols if _DLL is defined. This is done automatically * by the compiler when linking to the dynamic version of the runtime library, * according to "gzh" */ # if defined(PQXX_SHARED) && !defined(PQXX_LIBEXPORT) # define PQXX_LIBEXPORT __declspec(dllimport) # endif // PQXX_SHARED && !PQXX_LIBEXPORT // Workarounds for Microsoft Visual C++ # ifdef _MSC_VER // Suppress vtables on abstract classes. # define PQXX_NOVTABLE __declspec(novtable) // Automatically link with the appropriate libpq (static or dynamic, debug or // release). The default is to use the release DLL. Define PQXX_PQ_STATIC to // link to a static version of libpq, and _DEBUG to link to a debug version. // The two may be combined. # if defined(PQXX_AUTOLINK) # if defined(PQXX_PQ_STATIC) # ifdef _DEBUG # pragma comment(lib, "libpqd") # else # pragma comment(lib, "libpq") # endif # else # ifdef _DEBUG # pragma comment(lib, "libpqddll") # else # pragma comment(lib, "libpqdll") # endif # endif # endif // If we're not compiling libpqxx itself, automatically link with the // appropriate libpqxx library. To link with the libpqxx DLL, define // PQXX_SHARED; the default is to link with the static library. A static link // is the recommended practice. // // The preprocessor macro PQXX_INTERNAL is used to detect whether we // are compiling the libpqxx library itself. When you compile the library // yourself using your own project file, make sure to include this macro. # if defined(PQXX_AUTOLINK) && !defined(PQXX_INTERNAL) # ifdef PQXX_SHARED # ifdef _DEBUG # pragma comment(lib, "libpqxxD") # else # pragma comment(lib, "libpqxx") # endif # else // !PQXX_SHARED # ifdef _DEBUG # pragma comment(lib, "libpqxx_staticD") # else # pragma comment(lib, "libpqxx_static") # endif # endif # endif # endif // _MSC_VER #elif defined(PQXX_HAVE_GCC_VISIBILITY) // !_WIN32 # define PQXX_LIBEXPORT [[gnu::visibility("default")]] # define PQXX_PRIVATE [[gnu::visibility("hidden")]] #endif // PQXX_HAVE_GCC_VISIBILITY #ifndef PQXX_LIBEXPORT # define PQXX_LIBEXPORT /* libexport */ #endif #ifndef PQXX_PRIVATE # define PQXX_PRIVATE /* private */ #endif #ifndef PQXX_NOVTABLE # define PQXX_NOVTABLE /* novtable */ #endif // C++23: Assume support. #if defined(PQXX_HAVE_ASSUME) # define PQXX_ASSUME(condition) [[assume(condition)]] #else # define PQXX_ASSUME(condition) while (false) #endif libpqxx-8.0.1/include/pqxx/internal/ignore-deprecated-post.hxx000066400000000000000000000005451516427024100245510ustar00rootroot00000000000000// NOLINT(llvm-header-guard) /// End a code block started by "ignore-deprecated-pre.hxx". #if !defined(PQXX_IGNORING_DEPRECATED) # error "Ended an 'ignore-deprecated' block while none was active." #endif #if defined(__GNUC__) # pragma GCC diagnostic pop #endif // __GNUC__ #ifdef _MSC_VER # pragma warning(pop) #endif #undef PQXX_IGNORING_DEPRECATED libpqxx-8.0.1/include/pqxx/internal/ignore-deprecated-pre.hxx000066400000000000000000000016721516427024100243540ustar00rootroot00000000000000// NOLINT(llvm-header-guard) /** Start a block of deprecated code which may call other deprecated code. * * Most compilers will emit warnings when deprecated code is invoked from * non-deprecated code. But some compilers (notably gcc) will always emit the * warning even when the calling code is also deprecated. * * This header starts a block where those warnings are suppressed. It can be * included inside a code block. * * Always match the #include with a closing #include of * "ignore-deprecated-post.hxx". To avoid mistakes, keep the enclosed area as * small as possible. */ #if defined(PQXX_IGNORING_DEPRECATED) # error "Started an 'ignore-deprecated' block inside another." #endif #define PQXX_IGNORING_DEPRECATED #if defined(__GNUC__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif // __GNUC__ #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable : 4996) #endif libpqxx-8.0.1/include/pqxx/internal/result_iter.hxx000066400000000000000000000073711516427024100225520ustar00rootroot00000000000000/** Result loops. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_INTERNAL_RESULT_ITER_HXX #define PQXX_INTERNAL_RESULT_ITER_HXX #include #include "pqxx/internal/gates/row_ref-result.hxx" #include "pqxx/strconv.hxx" namespace pqxx { class result; } // namespace pqxx namespace pqxx::internal { // TODO: Replace with generator? // TODO: Separate type for `end()` iterator. /// Iterator for looped unpacking of a result. /** A default-constructed `result_iter` denotes the `end()` of any iteration. */ template class result_iter final { public: using value_type = std::tuple; /// Construct an "end" iterator. result_iter() = default; result_iter(result_iter const &) = delete; result_iter(result_iter &&) = delete; ~result_iter() = default; result_iter &operator=(result_iter const &) = delete; result_iter &operator=(result_iter &&) = delete; explicit result_iter(result const &home, sl loc = sl::current()) : m_home{&home}, m_size{std::size(home)} { if (not std::empty(home)) read(loc); } result_iter &operator++() { PQXX_ASSUME(m_home != nullptr); PQXX_ASSUME(m_index <= m_size); // TODO: Would be nice to get at least the result's creation location. sl const loc{sl::current()}; ++m_index; if (m_index >= m_size) m_home = nullptr; else if (m_home != nullptr) [[likely]] read(loc); return *this; } /// Comparison only works for comparing to end(). bool operator==(result_iter const &rhs) const noexcept { return m_home == rhs.m_home; } bool operator!=(result_iter const &rhs) const noexcept { return not(*this == rhs); } value_type const &operator*() const noexcept { return m_value; } private: void read(sl loc) { (*m_home)[m_index].convert(m_value, loc); } result const *m_home{nullptr}; result::size_type m_index{0}; result::size_type m_size{0}; value_type m_value; }; /// Iterator for implementing @ref pqxx::result::iter(). template class result_iteration final { public: using iterator = result_iter; explicit result_iteration(result home) : m_home{std::move(home)} { m_home.expect_columns(sizeof...(TYPE)); } [[nodiscard]] iterator begin() const { if (std::empty(m_home)) return end(); else return iterator{m_home}; } [[nodiscard]] iterator end() const { return {}; } private: // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) pqxx::result const m_home; }; } // namespace pqxx::internal template inline auto pqxx::result::iter() const { return pqxx::internal::result_iteration{*this}; } // A for_each iteration of a result. // // This is a strange place to define an inline member function on result, but // ordering of definitions leaves no better place for it. template inline void pqxx::result::for_each(CALLABLE &&func, sl loc) const { using args_tuple = internal::args_t; constexpr auto sz{std::tuple_size_v}; static_assert( sz > 0, "Callback for for_each must take parameters, one for each column in the " "result."); auto const cols{this->columns()}; if (sz != cols) throw usage_error{ std::format( "Callback to for_each takes {} parameter(s), but result set has {} " "field(s).", sz, cols), loc}; using pass_tuple = pqxx::internal::strip_types_t; for (auto const r : *this) std::apply( func, pqxx::internal::gate::row_ref_result{r}.as_tuple(loc)); } #endif libpqxx-8.0.1/include/pqxx/internal/result_iterator.hxx000066400000000000000000000227501516427024100234360ustar00rootroot00000000000000/* Definitions for the pqxx::result class and support classes. * * pqxx::result represents the set of result rows from a database query. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_INTERNAL_RESULT_ITERATOR_HXX #define PQXX_INTERNAL_RESULT_ITERATOR_HXX #include "pqxx/row.hxx" /* Result iterator. * * Don't include this header from your own application; it is included for you * by other libpqxx headers. */ namespace pqxx { /// Iterator for rows in a result. Use as result::const_iterator. /** A result, once obtained, cannot be modified. Therefore all iterators on a * result are const iterators. * * @warning You must not destroy or move a @ref result object while any * iterators are still active on it, or on any of its rows. */ class PQXX_LIBEXPORT const_result_iterator { public: using iterator_category = std::random_access_iterator_tag; using value_type = row_ref const; using pointer = row_ref const *; using reference = row_ref; using size_type = result_size_type; using difference_type = result_difference_type; /// Create an iterator, but in an unusable state. const_result_iterator() noexcept = default; /// Copy an iterator. const_result_iterator(const_result_iterator const &) noexcept = default; /// Move an iterator. const_result_iterator(const_result_iterator &&) noexcept = default; /// Create an iterator pointing at a row. const_result_iterator(result const &r, result_size_type i) noexcept : m_row{r, i} {} /// Create an iterator pointing at a row. explicit const_result_iterator(row_ref const &r) noexcept : m_row{r.home(), r.row_number()} {} ~const_result_iterator() = default; reference operator[](difference_type d) const { return *(*this + d); } /** * @name Dereferencing operators * * An iterator "points to" its current row. */ //@{ /// Dereference the iterator. [[nodiscard]] PQXX_RETURNS_NONNULL pointer operator->() const noexcept { return &m_row; } /// Dereference the iterator. [[nodiscard]] reference operator*() const noexcept { return m_row; } //@} /** * @name Manipulations */ //@{ const_result_iterator &operator=(const_result_iterator const &) = default; const_result_iterator &operator=(const_result_iterator &&) = default; const_result_iterator operator++(int) &; PQXX_INLINE_ONLY const_result_iterator &operator++() { pqxx::internal::gate::row_ref_const_result_iterator{m_row}.offset(1); return *this; } const_result_iterator operator--(int) &; PQXX_INLINE_ONLY const_result_iterator &operator--() { pqxx::internal::gate::row_ref_const_result_iterator(m_row).offset(-1); return *this; } const_result_iterator &operator+=(difference_type i) { pqxx::internal::gate::row_ref_const_result_iterator(m_row).offset(i); return *this; } const_result_iterator &operator-=(difference_type i) { pqxx::internal::gate::row_ref_const_result_iterator(m_row).offset(-i); return *this; } /// Interchange two iterators in an exception-safe manner. void swap(const_result_iterator &other) noexcept { std::swap(m_row, other.m_row); } //@} /** * @name Comparisons */ //@{ [[nodiscard]] bool operator==(const_result_iterator const &i) const { return (&m_row.home() == &i.m_row.home()) and (m_row.row_number() == i.m_row.row_number()); } [[nodiscard]] bool operator!=(const_result_iterator const &i) const { return not(*this == i); } [[nodiscard]] bool operator<(const_result_iterator const &i) const { // Only needs to work when iterating the same result. return m_row.row_number() < i.m_row.row_number(); } [[nodiscard]] bool operator<=(const_result_iterator const &i) const { // Only needs to work when iterating the same result. return m_row.row_number() <= i.m_row.row_number(); } [[nodiscard]] bool operator>(const_result_iterator const &i) const { return m_row.row_number() > i.m_row.row_number(); } [[nodiscard]] bool operator>=(const_result_iterator const &i) const { return m_row.row_number() >= i.m_row.row_number(); } //@} /** * @name Arithmetic operators */ //@{ [[nodiscard]] inline const_result_iterator operator+(difference_type) const; friend const_result_iterator operator+(difference_type, const_result_iterator const &); [[nodiscard]] inline const_result_iterator operator-(difference_type) const; [[nodiscard]] inline difference_type operator-(const_result_iterator const &) const; //@} private: row_ref m_row; }; /// Reverse iterator for result. Use as result::const_reverse_iterator. class PQXX_LIBEXPORT const_reverse_result_iterator final : private const_result_iterator { public: using super = const_result_iterator; using iterator_type = const_result_iterator; using iterator_type::difference_type; using iterator_type::iterator_category; using iterator_type::pointer; using value_type = iterator_type::value_type; using reference = iterator_type::reference; /// Create an iterator, but in an unusable state. const_reverse_result_iterator() noexcept = default; const_reverse_result_iterator( const_reverse_result_iterator const &) noexcept = default; const_reverse_result_iterator(const_reverse_result_iterator &&) noexcept = default; /// Copy a reverse iterator from a regular iterator. PQXX_INLINE_ONLY explicit const_reverse_result_iterator( const_result_iterator const &rhs) : const_result_iterator{rhs} { super::operator--(); } ~const_reverse_result_iterator() = default; /// Return the underlying "regular" iterator (as per standard library). [[nodiscard]] const_result_iterator base() const noexcept; /** * @name Dereferencing operators */ //@{ /// Dereference iterator. using const_result_iterator::operator->; /// Dereference iterator. using const_result_iterator::operator*; //@} /** * @name Field access */ //@{ using const_result_iterator::operator[]; //@} /** * @name Manipulations */ //@{ const_reverse_result_iterator & operator=(const_reverse_result_iterator const &) noexcept = default; const_reverse_result_iterator & operator=(const_reverse_result_iterator &&) noexcept = default; const_reverse_result_iterator &operator++() { iterator_type::operator--(); return *this; } const_reverse_result_iterator operator++(int) &; const_reverse_result_iterator &operator--() { iterator_type::operator++(); return *this; } const_reverse_result_iterator operator--(int) &; const_reverse_result_iterator &operator+=(difference_type i) { iterator_type::operator-=(i); return *this; } const_reverse_result_iterator &operator-=(difference_type i) { iterator_type::operator+=(i); return *this; } void swap(const_reverse_result_iterator &other) noexcept { const_result_iterator::swap(other); } //@} /** * @name Arithmetic operators */ //@{ [[nodiscard]] const_reverse_result_iterator operator+(difference_type i) const { return const_reverse_result_iterator(base() - i); } [[nodiscard]] const_reverse_result_iterator operator-(difference_type i) { return const_reverse_result_iterator(base() + i); } [[nodiscard]] difference_type operator-(const_reverse_result_iterator const &rhs) const { return rhs.const_result_iterator::operator-(*this); } //@} /** * @name Comparisons */ //@{ [[nodiscard]] bool operator==(const_reverse_result_iterator const &rhs) const noexcept { return iterator_type::operator==(rhs); } [[nodiscard]] bool operator!=(const_reverse_result_iterator const &rhs) const noexcept { return not operator==(rhs); } [[nodiscard]] bool operator<(const_reverse_result_iterator const &rhs) const { return iterator_type::operator>(rhs); } [[nodiscard]] bool operator<=(const_reverse_result_iterator const &rhs) const { return iterator_type::operator>=(rhs); } [[nodiscard]] bool operator>(const_reverse_result_iterator const &rhs) const { return iterator_type::operator<(rhs); } [[nodiscard]] bool operator>=(const_reverse_result_iterator const &rhs) const { return iterator_type::operator<=(rhs); } //@} }; inline const_result_iterator const_result_iterator::operator+(result::difference_type o) const { return { m_row.home(), size_type(result::difference_type(m_row.row_number()) + o)}; } inline const_result_iterator operator+(result::difference_type o, const_result_iterator const &i) { return i + o; } inline const_result_iterator const_result_iterator::operator-(result::difference_type o) const { return { m_row.home(), result_size_type(result::difference_type(m_row.row_number()) - o)}; } PQXX_INLINE_ONLY inline result::difference_type const_result_iterator::operator-(const const_result_iterator &i) const { return result::difference_type(m_row.row_number() - i->row_number()); } PQXX_INLINE_ONLY inline const_result_iterator result::end() const noexcept { return {*this, size()}; } inline const_result_iterator result::cend() const noexcept { return end(); } inline const_reverse_result_iterator operator+(result::difference_type n, const_reverse_result_iterator const &i) { return const_reverse_result_iterator{i.base() - n}; } } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/internal/sql_cursor.hxx000066400000000000000000000104631516427024100224010ustar00rootroot00000000000000/** Internal wrapper for SQL cursors. Supports higher-level cursor classes. * * DO NOT INCLUDE THIS FILE DIRECTLY. Other headers include it for you. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_INTERNAL_SQL_CURSOR_HXX #define PQXX_INTERNAL_SQL_CURSOR_HXX namespace pqxx::internal { /// Cursor with SQL positioning semantics. /** Thin wrapper around an SQL cursor, with SQL's ideas of positioning. * * SQL cursors have pre-increment/pre-decrement semantics, with on either end * of the result set a special position that does not repesent a row. This * class models SQL cursors for the purpose of implementing more C++-like * semantics on top. * * Positions of actual rows are numbered starting at 1. Position 0 exists but * does not refer to a row. There is a similar non-row position at the end of * the result set. * * Don't use this at home. You deserve better. Use the stateless_cursor * instead. */ class PQXX_LIBEXPORT sql_cursor final : public cursor_base { public: sql_cursor( transaction_base &t, std::string_view query, std::string_view cname, cursor_base::access_policy ap, cursor_base::update_policy up, cursor_base::ownership_policy op, bool hold, sl = sl::current()); sql_cursor( transaction_base &t, std::string_view cname, cursor_base::ownership_policy op, sl = sl::current()); sql_cursor(sql_cursor const &) = delete; sql_cursor(sql_cursor &&) = delete; ~sql_cursor() noexcept; sql_cursor &operator=(sql_cursor const &) = delete; sql_cursor &operator=(sql_cursor &&) = delete; result fetch(difference_type rows, difference_type &displacement, sl); PQXX_INLINE_COV result fetch(difference_type rows, sl loc) { difference_type d = 0; return fetch(rows, d, loc); } difference_type move(difference_type rows, difference_type &displacement, sl); PQXX_INLINE_COV difference_type move(difference_type rows, sl loc) { difference_type d = 0; return move(rows, d, loc); } /// Current position, or -1 for unknown /** * The starting position, just before the first row, counts as position zero. * * Position may be unknown if (and only if) this cursor was adopted, and has * never hit its starting position (position zero). */ PQXX_INLINE_COV [[nodiscard]] difference_type pos() const noexcept { return m_pos; } /// End position, or -1 for unknown /** * Returns the final position, just after the last row in the result set. The * starting position, just before the first row, counts as position zero. * * End position is unknown until it is encountered during use. */ PQXX_INLINE_COV [[nodiscard]] difference_type endpos() const noexcept { return m_endpos; } /// Return zero-row result for this cursor. PQXX_INLINE_COV [[nodiscard]] result const &empty_result() const noexcept { return m_empty_result; } void close(sl loc); PQXX_PURE [[nodiscard]] constexpr sl created_loc() const noexcept { return m_created_loc; } private: difference_type adjust(difference_type hoped, difference_type actual); static std::string stridestring(difference_type); /// Initialize cached empty result. Call only at beginning or end! void init_empty_result(transaction_base &, sl); /// Connection in which this cursor lives. connection &m_home; /// Zero-row result from this cursor (or plain empty one if cursor is /// adopted) result m_empty_result; result m_cached_current_row; /// Will this cursor object destroy its SQL cursor when it dies? cursor_base::ownership_policy m_ownership; /// At starting position (-1), somewhere in the middle (0), or past end (1) int m_at_end; /// Position, or -1 for unknown difference_type m_pos; /// End position, or -1 for unknown difference_type m_endpos = -1; /// The `std::source_location` for where this cursor was created. sl m_created_loc; }; PQXX_LIBEXPORT result_size_type obtain_stateless_cursor_size(sql_cursor &, sl); PQXX_LIBEXPORT result stateless_cursor_retrieve( sql_cursor &, result::difference_type size, result::difference_type begin_pos, result::difference_type end_pos, sl); } // namespace pqxx::internal #endif libpqxx-8.0.1/include/pqxx/internal/statement_parameters.hxx000066400000000000000000000044421516427024100244340ustar00rootroot00000000000000/** Common implementation for statement parameter lists. * * These are used for both prepared statements and parameterized statements. * * DO NOT INCLUDE THIS FILE DIRECTLY. Other headers include it for you. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_INTERNAL_STATEMENT_PARAMETERS_HXX #define PQXX_INTERNAL_STATEMENT_PARAMETERS_HXX #include #include #include #include #include "pqxx/strconv.hxx" #include "pqxx/util.hxx" namespace pqxx::internal { template constexpr inline auto const iterator_identity{ [](decltype(*std::declval()) x) { return x; }}; /// Internal type: encode statement parameters. /** Compiles arguments for prepared statements and parameterised queries into * a format that can be passed into libpq. * * Objects of this type are meant to be short-lived: a `c_params` lives and * dies entirely within the call to execute. So, for example, if you pass in a * non-null pointer as a parameter, @ref params may simply use that pointer as * a parameter value, without arranging longer-term storage for the data to * which it points. All values referenced by parameters must remain "live" * until the parameterised or prepared statement has been executed. */ struct PQXX_LIBEXPORT c_params final { c_params() = default; /// Copying these objects is pointless and expensive. Don't do it. c_params(c_params const &) = delete; c_params(c_params &&) = default; ~c_params() = default; c_params &operator=(c_params const &) = delete; c_params &operator=(c_params &&) = default; /// Pre-allocate storage for `n` parameters. void reserve(std::size_t n) &; // NOLINTBEGIN(misc-non-private-member-variables-in-classes) /// As used by libpq: pointers to parameter values. std::vector values; /// As used by libpq: lengths of non-null arguments, in bytes. std::vector lengths; /// As used by libpq: effectively boolean "is this a binary parameter?" std::vector formats; // NOLINTEND(misc-non-private-member-variables-in-classes) }; } // namespace pqxx::internal #endif libpqxx-8.0.1/include/pqxx/internal/stream_iterator.hxx000066400000000000000000000052771516427024100234200ustar00rootroot00000000000000/** Stream iterators. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_INTERNAL_STREAM_ITERATOR_HXX #define PQXX_INTERNAL_STREAM_ITERATOR_HXX #include namespace pqxx { template class stream_query; } // namespace pqxx namespace pqxx::internal { /// Input iterator for stream_from. /** Just barely enough to support range-based "for" loops on stream_from. * Don't assume that any of the usual behaviour works beyond that. */ template class stream_from_input_iterator final { using stream_t = stream_from; public: using value_type = std::tuple; /// Construct an "end" iterator. stream_from_input_iterator() = default; explicit stream_from_input_iterator(stream_t &home, sl loc) : m_home(&home) { advance(loc); } stream_from_input_iterator(stream_from_input_iterator const &) = default; stream_from_input_iterator(stream_from_input_iterator &&) = default; stream_from_input_iterator &operator++() { advance(sl::current()); return *this; } ~stream_from_input_iterator() = default; stream_from_input_iterator & operator=(stream_from_input_iterator const &) = default; stream_from_input_iterator & operator=(stream_from_input_iterator &&) = default; value_type const &operator*() const noexcept { return m_value; } /// Comparison only works for comparing to end(). bool operator==(stream_from_input_iterator const &rhs) const noexcept { return m_home == rhs.m_home; } /// Comparison only works for comparing to end(). bool operator!=(stream_from_input_iterator const &rhs) const noexcept { return not(*this == rhs); } private: void advance(sl loc) { if (m_home == nullptr) throw usage_error{"Moving stream_from iterator beyond end().", loc}; if (not((*m_home) >> m_value)) m_home = nullptr; } stream_t *m_home{nullptr}; value_type m_value; }; // TODO: Use separate type for end(). // TODO: Replace with generator? /// Iteration over a @ref stream_query. template class stream_input_iteration final { public: using stream_t = stream_from; using iterator = stream_from_input_iterator; explicit stream_input_iteration(stream_t &home) : m_home{home} {} [[nodiscard]] iterator begin(sl loc = sl::current()) const { return iterator{m_home, loc}; } [[nodiscard]] iterator end() const { return {}; } private: // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) stream_t &m_home; }; } // namespace pqxx::internal #endif libpqxx-8.0.1/include/pqxx/internal/stream_query.hxx000066400000000000000000000262211516427024100227240ustar00rootroot00000000000000/* Definition of the pqxx::internal::stream_query class. * * Enables optimized batch reads from a database table. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transaction_base instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_INTERNAL_STREAM_QUERY_HXX #define PQXX_INTERNAL_STREAM_QUERY_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include "pqxx/internal/encodings.hxx" #include "pqxx/internal/gates/connection-stream_from.hxx" #include "pqxx/transaction_focus.hxx" namespace pqxx { class transaction_base; } // namespace pqxx namespace pqxx::internal { /// The `end()` iterator for a `stream_query`. class stream_query_end_iterator {}; // TODO: Can we use generators, and maybe get speedup from HALO? /// Stream query results from the database. Used by transaction_base::stream. /** For larger data sets, retrieving data this way is likely to be faster than * executing a query and then iterating and converting the rows' fields. You * will also be able to start processing before all of the data has come in. * (For smaller result sets though, a stream is likely to be a bit slower.) * * A `stream_query` stream is strongly typed. You specify the columns' types * while instantiating the stream_query template. * * Not all kinds of query will work in a stream. But straightforward `SELECT` * and `UPDATE ... RETURNING` queries should work. The class uses PostgreSQL's * `COPY` command, so see the documentation for that command to get the full * details. * * There are other downsides. If the stream encounters an error, it may leave * the entire connection in an unusable state, so you'll have to give the * whole thing up. Finally, opening a stream puts the connection in a special * state, so you won't be able to do many other things with the connection or * the transaction while the stream is open. * * Usually you'll want the `stream` convenience wrapper in * @ref transaction_base, so you don't need to deal with this class directly. * * @warning While a stream is active, you cannot execute queries, open a * pipeline, etc. on the same transaction. A transaction can have at most one * object of a type derived from @ref pqxx::transaction_focus active on it at a * time. */ template class stream_query final : transaction_focus { public: using line_handle = std::unique_ptr; /// Execute `query` on `tx`, stream results. inline stream_query( transaction_base &tx, std::string_view query, conversion_context c); stream_query(stream_query const &) = delete; stream_query(stream_query &&) = delete; stream_query &operator=(stream_query const &) = delete; stream_query &operator=(stream_query &&) = delete; ~stream_query() noexcept { try { close(); } catch (std::exception const &e) { reg_pending_error(e.what(), sl::current()); } } /// Has this stream reached the end of its data? [[nodiscard]] bool done() const & noexcept { return m_char_finder == nullptr; } /// Begin iterator. Only for use by "range for." [[nodiscard]] inline auto begin() &; /// End iterator. Only for use by "range for." /** The end iterator is a different type than the regular iterator. It * simplifies the comparisons: we know at compile time that we're comparing * to the end pointer. */ [[nodiscard]] auto end() const & { return stream_query_end_iterator{}; } /// Parse and convert the latest line of data we received. std::tuple parse_line(std::string_view line) & { assert(not done()); auto const line_size{std::size(line)}; // This function uses m_row as a buffer, across calls. The only reason for // it to carry over across calls is to avoid reallocation. // Make room for unescaping the line. It's a pessimistic size. // Unusually, we're storing terminating zeroes *inside* the string. // This is the only place where we modify m_row. MAKE SURE THE BUFFER DOES // NOT GET RESIZED while we're working, because we're working with views // into its buffer. m_row.resize(line_size + 1); std::size_t offset{0u}; char *write{m_row.data()}; // DO NOT shrink m_row to fit. We're carrying views pointing into the // buffer. (Also, how useful would shrinking really be?) // Folding expression: scan and unescape each field, and convert it to its // requested type. std::tuple data{parse_field(line, offset, write, m_ctx)...}; assert(offset == line_size + 1u); return data; } /// Read a COPY line from the server. std::pair read_line(sl) &; private: /// Look up a char_finder_func. /** This is the only encoding-dependent code in the class. All we need to * store after that is this function pointer. */ PQXX_PURE PQXX_RETURNS_NONNULL static inline char_finder_func * get_finder(transaction_base const &tx, sl); /// Scan and unescape a field into the row buffer. /** The row buffer is `m_row`. * * @param line The line of COPY output. * @param offset The current scanning position inside `line`. * @param write The current writing position in the row buffer. * * @return new `offset`; new `write`; and a `string_view` on the unescaped * field text in the row buffer. * * The `string_view`'s data pointer will be nullptr for a null field. * * After reading the final field in a row, if all goes well, offset should be * one greater than the size of the line, pointing at the terminating zero. */ std::tuple read_field(std::string_view line, std::size_t offset, char *write, ctx c) { #if !defined(NDEBUG) auto const line_size{std::size(line)}; #endif assert(offset <= line_size); char const *lp{std::data(line)}; // The COPY line now ends in a tab. (We replace the trailing newline with // that to simplify the loop here.) assert(lp[line_size] == '\t'); assert(lp[line_size + 1] == '\0'); if ((lp[offset] == '\\') and (lp[offset + 1] == 'N')) { // Null field. Consume the "\N" and the field separator. offset += 3; assert(offset <= (line_size + 1)); assert(lp[offset - 1] == '\t'); // Return a null value. There's nothing to write into m_row. return {offset, write, {}}; } // Beginning of the field text in the row buffer. char const *const field_begin{write}; // We're relying on several assumptions just for making the main loop // condition work: // * The COPY line ends in a newline. // * Multibyte characters never start with an ASCII-range byte. // * We can index a view beyond its bounds (but within its address space). // // Effectively, the newline acts as a final field separator. while (lp[offset] != '\t') { assert(lp[offset] != '\0'); // Beginning of the next character of interest (or the end of the line). // It may be right where we start searching, and this won't loop forever // since the previous iteration (if any) put us right _after_ the // previous character of interest. auto const stop_char{m_char_finder(line, offset, c.loc)}; PQXX_ASSUME(stop_char >= offset); assert(stop_char < (line_size + 1)); // Copy the text we have so far. It's got no special characters in it. std::memcpy(write, &lp[offset], stop_char - offset); write += (stop_char - offset); offset = stop_char; // We're still within the line. char const special{lp[offset]}; if (special == '\\') { // Escape sequence. // Consume the backslash. ++offset; assert(offset < line_size); // The database will only escape ASCII characters, so we assume that // we're dealing with a single-byte character. char const escaped{lp[offset]}; // I think this is a valid way to check for the high bit: the shift // may be signed or unsigned (implementation-defined for char), but // either way we get a zero if the bit is clear or nonzero if it's set. assert((escaped >> 7) == 0); ++offset; *write++ = unescape_char(escaped); } else { // Field separator. Fall out of the loop. assert(special == '\t'); } } // Hit the end of the field. assert(lp[offset] == '\t'); *write = '\0'; ++write; ++offset; return { offset, write, {field_begin, static_cast(write - field_begin - 1)}}; } /// Parse the next field. /** Unescapes the field into the row buffer (m_row), and converts it to its * TARGET type. * * Using non-const reference parameters here, so we can propagate side * effects across a fold expression. * * @param line The latest COPY line. * @param offset The current parsing offset in `line`. The function will * update this value. * @param write The current writing position in the row buffer. The * function will update this value. * @return Field value converted to TARGET type. */ template TARGET parse_field(std::string_view line, std::size_t &offset, char *&write, ctx c) { using field_type = std::remove_cvref_t; assert(offset <= std::size(line)); auto [new_offset, new_write, text]{read_field(line, offset, write, c)}; PQXX_ASSUME(new_offset > offset); PQXX_ASSUME(new_write >= write); offset = new_offset; write = new_write; if constexpr (pqxx::always_null()) { if (std::data(text) != nullptr) throw conversion_error{std::format( "Streaming a non-null value into a {}, which must always be null.", name_type())}; } else if (std::data(text) == nullptr) { if constexpr (has_null()) return make_null(); else internal::throw_null_conversion(name_type(), c.loc); } else [[likely]] { // Don't ever try to convert a non-null value to nullptr_t! return from_string(text, c); } } /// If this stream isn't already closed, close it now. void close() noexcept { if (not done()) { m_char_finder = nullptr; unregister_me(); } } /// Callback for finding next special character (or end of line). /** This pointer doubles as an indication that we're done. We set it to * `nullptr` when the iteration is finished, and that's how we can know that * there are no more rows to be iterated. */ char_finder_func *m_char_finder; /// Current row's fields' text, combined into one reusable string. /** We carry this buffer over from one invocation to the next, not because we * need the data, but just so we can re-use the space. It saves us having to * re-allocate it every time. */ std::string m_row; /// Caller source location, encoding group, possibly more. conversion_context const m_ctx; }; } // namespace pqxx::internal #endif libpqxx-8.0.1/include/pqxx/internal/stream_query_impl.hxx000066400000000000000000000114561516427024100237510ustar00rootroot00000000000000/* Code for parts of pqxx::internal::stream_query. * * These definitions need to be in a separate file in order to iron out * circular dependencies between headers. */ #ifndef PQXX_INTERNAL_STREAM_QUERY_IMPL_HXX #define PQXX_INTERNAL_STREAM_QUERY_IMPL_HXX namespace pqxx::internal { template inline stream_query::stream_query( transaction_base &tx, std::string_view query, conversion_context c) : transaction_focus{tx, "stream_query"}, m_char_finder{get_finder(tx, c.loc)}, m_ctx{c} { auto const r{tx.exec(std::format("COPY ({}) TO STDOUT", query), m_ctx.loc)}; r.expect_columns(sizeof...(TYPE), m_ctx.loc); r.expect_rows(0, m_ctx.loc); register_me(); } template PQXX_RETURNS_NONNULL inline char_finder_func * stream_query::get_finder(transaction_base const &tx, sl loc) { auto const group{tx.conn().get_encoding_group(loc)}; return get_char_finder<'\t', '\\'>(group, loc); } // TODO: Replace with generator? Could be faster (local vars vs. members). /// Minimal iterator for stream_query. /** Just barely enough to support range-based "for" loops on @ref stream_query. * It's so minimal, it isn't even an `input_iterator`. * * Do not assume that anything beyond that works: post-increment, comparison to * anything other than `end()`, assignment between iterators on different * streams, and probably several more common and sensible things to do with * iterators are all anathema here. */ template class stream_query_iterator final { using stream_t = stream_query; public: using value_type = std::tuple; using difference_type = long; stream_query_iterator(stream_t &home, sl loc) : m_home(&home), m_line{typename stream_query::line_handle( nullptr, pqxx::internal::pq::pqfreemem)}, m_created_loc{loc} { consume_line(loc); } stream_query_iterator(stream_query_iterator const &) = delete; stream_query_iterator(stream_query_iterator &&) = delete; ~stream_query_iterator() = default; stream_query_iterator &operator=(stream_query_iterator const &) = delete; stream_query_iterator &operator=(stream_query_iterator &&) = delete; /// Pre-increment. /** We don't even support post-increment, because we only do what's needed * for range-based `for` loops. */ stream_query_iterator &operator++() & { assert(not done()); consume_line(m_created_loc); return *this; } /// Dereference. There's no caching in here, so don't repeat calls. value_type operator*() const { return m_home->parse_line(std::string_view{m_line.get(), m_line_size}); } /// Are we at the end? bool operator==(stream_query_end_iterator) const noexcept { return done(); } /// Do we have more iterations to go? bool operator!=(stream_query_end_iterator) const noexcept { return not done(); } friend bool operator==(stream_query_end_iterator, stream_query_iterator const &i) { return i.done(); } friend bool operator!=(stream_query_end_iterator, stream_query_iterator const &i) { return not i.done(); } private: /// Have we finished? [[nodiscard]] bool done() const noexcept { return m_home->done(); } /// Read a line from the stream, store it in the iterator. /** Replaces the newline at the end with a tab, as a sentinel to simplify * (and thus hopefully speed up) the field parsing loop. */ void consume_line(sl loc) & { auto [line, size]{m_home->read_line(loc)}; m_line = std::move(line); m_line_size = size; if (m_line) { // We know how many fields to expect. Replace the newline at the end // with the field separator, so the parsing loop only needs to scan for a // tab, not a tab or a newline. char *const ptr{m_line.get()}; assert(ptr[size] == '\n'); ptr[size] = '\t'; } } stream_t *const m_home = nullptr; /// Last COPY line we read, allocated by libpq. typename stream_t::line_handle m_line; /// Length of the last COPY line we read. std::size_t m_line_size = 0u; /// A `std::source_location` for where this object was created. sl const m_created_loc; }; template inline auto stream_query::begin() & { return stream_query_iterator{*this, m_ctx.loc}; } template inline std::pair::line_handle, std::size_t> stream_query::read_line(sl loc) & { assert(not done()); internal::gate::connection_stream_from gate{trans().conn()}; try { auto line{gate.read_copy_line(loc)}; if (not line.first) [[unlikely]] { // This is how we get told the iteration is finished. close(); } return line; } catch (std::exception const &) { close(); throw; } } } // namespace pqxx::internal #endif libpqxx-8.0.1/include/pqxx/internal/wait.hxx000066400000000000000000000034531516427024100211520ustar00rootroot00000000000000#if !defined(PQXX_WAIT_HXX) # define PQXX_WAIT_HXX # include "pqxx/types.hxx" namespace pqxx::internal { /// Wait. /** This is normally `std::this_thread::sleep_for()`. But MinGW's `thread` * header doesn't work, so we must be careful about including it. */ PQXX_LIBEXPORT void wait_for(unsigned int microseconds); /// Wait for a socket to be ready for reading/writing, or timeout. /** All waits are finite. It is not guaranteed that this will wait for the * full time specified, e.g. because the process receives a signal. The * calling code MUST be prepared to handle an occasional premature return. * * _Why does this not wait forever?_ Mainly so that you do not forget to * handle premature returns, and write subtly buggy code that appears to work * fine in testing! * * _Okay, but why don't you _handle_ signals and continue to wait?_ Because * how the application handles signals is the application's business. It's not * up to libpqxx to mess with that. Perhaps you _want_ to return early after * some particular signal. Perhaps you don't for some other signal. * * _But what if I need to minimise wakeups to save power or CPU time?_ It * probably won't make much of a difference whether it's just libpqxx waking up * or your own code waking up as well. What you can do is pass a longer wait * time, so it happens less often. * * Increasing wait times can help, but there are diminishing returns. It will * reduce this particular overhead in your application, until some other source * of overhead becomes more significant. At that point... stop increasing the * wait time and go fix that other thing! */ PQXX_LIBEXPORT void wait_fd( int fd, bool for_read, bool for_write, unsigned seconds = 1, unsigned microseconds = 0, sl = sl::current()); } // namespace pqxx::internal #endif libpqxx-8.0.1/include/pqxx/isolation000066400000000000000000000004471516427024100175650ustar00rootroot00000000000000/** Transaction isolation levels. * * Policies and traits describing SQL transaction isolation levels */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/isolation.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/isolation.hxx000066400000000000000000000052711516427024100203730ustar00rootroot00000000000000/* Definitions for transaction isolation levels, and such. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/isolation instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_ISOLATION_HXX #define PQXX_ISOLATION_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include "pqxx/util.hxx" namespace pqxx { /// Should a transaction be read-only, or read-write? /** No, this is not an isolation level. So it really doesn't belong here. * But it's not really worth a separate header. */ enum class write_policy { read_only, read_write }; /// Transaction isolation levels. /** These are as defined in the SQL standard. But there are a few notes * specific to PostgreSQL. * * First, postgres does not support "read uncommitted." The lowest level you * can get is "read committed," which is better. PostgreSQL is built on the * MVCC paradigm, which guarantees "read committed" isolation without any * additional performance overhead, so there was no point in providing the * lower level. * * Second, "repeatable read" also makes more isolation guarantees than the * standard requires. According to the standard, this level prevents "dirty * reads" and "nonrepeatable reads," but not "phantom reads." In postgres, * it actually prevents all three. * * Third, "serializable" is only properly supported starting at postgres 9.1. * If you request "serializable" isolation on an older backend, you will get * the same isolation as in "repeatable read." It's better than the * "repeatable read" defined in the SQL standard, but not a complete * implementation of the standard's "serializable" isolation level. * * In general, a lower isolation level will allow more surprising interactions * between ongoing transactions, but improve performance. A higher level * gives you more protection from subtle concurrency bugs, but sometimes it * may not be possible to complete your transaction without avoiding paradoxes * in the data. In that case a transaction may fail, and the application will * have to re-do the whole thing based on the latest state of the database. * (If you want to retry your code in that situation, have a look at the * transactor framework.) * * Study the levels and design your application with the right level in mind. */ enum isolation_level { // PostgreSQL only has the better isolation levels. // read_uncommitted, read_committed, repeatable_read, serializable, }; } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/largeobject000066400000000000000000000004561516427024100200450ustar00rootroot00000000000000/** Large Objects interface. * * Supports direct access to large objects, as well as through I/O streams */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/largeobject.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/largeobject.hxx000066400000000000000000000614121516427024100206520ustar00rootroot00000000000000/* Large Objects interface. Deprecated; use blob instead. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_LARGEOBJECT_HXX #define PQXX_LARGEOBJECT_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include "pqxx/dbtransaction.hxx" // This whole header is deprecated, so there's not much point checking these. // // NOLINTBEGIN( // cppcoreguidelines-avoid-const-or-ref-data-members, // fuchsia-multiple-inheritance // ) namespace pqxx { // This class is deprecated. // LCOV_EXCL_START /// Identity of a large object. /** @deprecated Use the @ref blob class instead. * * Encapsulates the identity of a large object. * * A largeobject must be accessed only from within a backend transaction, but * the object's identity remains valid as long as the object exists. */ class PQXX_LIBEXPORT largeobject { public: using size_type = large_object_size_type; /// Refer to a nonexistent large object (similar to what a null pointer /// does). [[deprecated("Use blob instead.")]] largeobject() noexcept = default; /// Create new large object. /** @param t Backend transaction in which the object is to be created. */ [[deprecated("Use blob instead.")]] explicit largeobject(dbtransaction &t); /// Wrap object with given oid. /** Convert combination of a transaction and object identifier into a * large object identity. Does not affect the database. * @param o Object identifier for the given object. */ [[deprecated("Use blob instead.")]] explicit largeobject(oid o) noexcept : m_id{o} {} /// Import large object from a local file. /** Creates a large object containing the data found in the given file. * @param t Backend transaction in which the large object is to be created. * @param file A filename on the client program's filesystem. */ [[deprecated("Use blob instead.")]] largeobject( dbtransaction &t, std::string_view file); // NOLINTBEGIN(google-explicit-constructor,hicpp-explicit-conversions) /// Take identity of an opened large object. /** Copy identity of already opened large object. Note that this may be done * as an implicit conversion. * @param o Already opened large object to copy identity from. */ [[deprecated("Use blob instead.")]] largeobject( largeobjectaccess const &o) noexcept; // NOLINTEND(google-explicit-constructor,hicpp-explicit-conversions) /// Object identifier. /** The number returned by this function identifies the large object in the * database we're connected to (or oid_none is returned if we refer to the * null object). */ [[nodiscard]] oid id() const noexcept { return m_id; } /** * @name Identity comparisons * * These operators compare the object identifiers of large objects. This has * nothing to do with the objects' actual contents; use them only for keeping * track of containers of references to large objects and such. */ //@{ /// Compare object identities /** @warning Only valid between large objects in the same database. */ [[nodiscard]] bool operator==(largeobject const &other) const { return m_id == other.m_id; } /// Compare object identities /** @warning Only valid between large objects in the same database. */ [[nodiscard]] bool operator!=(largeobject const &other) const { return m_id != other.m_id; } /// Compare object identities /** @warning Only valid between large objects in the same database. */ [[nodiscard]] bool operator<=(largeobject const &other) const { return m_id <= other.m_id; } /// Compare object identities /** @warning Only valid between large objects in the same database. */ [[nodiscard]] bool operator>=(largeobject const &other) const { return m_id >= other.m_id; } /// Compare object identities /** @warning Only valid between large objects in the same database. */ [[nodiscard]] bool operator<(largeobject const &other) const { return m_id < other.m_id; } /// Compare object identities /** @warning Only valid between large objects in the same database. */ [[nodiscard]] bool operator>(largeobject const &other) const { return m_id > other.m_id; } //@} /// Export large object's contents to a local file /** Writes the data stored in the large object to the given file. * @param t Transaction in which the object is to be accessed * @param file A filename on the client's filesystem */ void to_file(dbtransaction &t, std::string_view file) const; /// Delete large object from database /** Unlike its low-level equivalent cunlink, this will throw an exception if * deletion fails. * @param t Transaction in which the object is to be deleted */ void remove(dbtransaction &t) const; protected: PQXX_PURE [[nodiscard]] static internal::pq::PGconn * raw_connection(dbtransaction const &T); PQXX_PRIVATE [[nodiscard]] std::string reason(connection const &, int err) const; private: oid m_id = oid_none; }; /// Accessor for large object's contents. /** @deprecated Use the `blob` class instead. */ class PQXX_LIBEXPORT largeobjectaccess final : private largeobject { public: using largeobject::size_type; using off_type = size_type; using pos_type = size_type; /// Open mode: `in`, `out` (can be combined using "bitwise or"). /** According to the C++ standard, these should be in `std::ios_base`. We * take them from derived class `std::ios` instead, which is easier on the * eyes. * * Historical note: taking it from std::ios was originally a workaround for a * problem with gcc 2.95. */ using openmode = std::ios::openmode; /// Default open mode: in, out, binary. static constexpr auto default_mode{ std::ios::in | std::ios::out | std::ios::binary}; /// Seek direction: `beg`, `cur`, `end`. using seekdir = std::ios::seekdir; /// Create new large object and open it. /** * @param t Backend transaction in which the object is to be created. * @param mode Access mode, defaults to ios_base::in | ios_base::out | * ios_base::binary. */ [[deprecated("Use blob instead.")]] explicit largeobjectaccess( dbtransaction &t, openmode mode = default_mode); /// Open large object with given oid. /** Convert combination of a transaction and object identifier into a * large object identity. Does not affect the database. * @param t Transaction in which the object is to be accessed. * @param o Object identifier for the given object. * @param mode Access mode, defaults to ios_base::in | ios_base::out | * ios_base::binary. */ [[deprecated("Use blob instead.")]] largeobjectaccess( dbtransaction &t, oid o, openmode mode = default_mode); /// Open given large object. /** Open a large object with the given identity for reading and/or writing. * @param t Transaction in which the object is to be accessed. * @param o Identity for the large object to be accessed. * @param mode Access mode, defaults to ios_base::in | ios_base::out | * ios_base::binary. */ [[deprecated("Use blob instead.")]] largeobjectaccess( dbtransaction &t, largeobject o, openmode mode = default_mode); /// Import large object from a local file and open it. /** Creates a large object containing the data found in the given file. * @param t Backend transaction in which the large object is to be created. * @param file A filename on the client program's filesystem. * @param mode Access mode, defaults to ios_base::in | ios_base::out. */ [[deprecated("Use blob instead.")]] largeobjectaccess( dbtransaction &t, std::string_view file, openmode mode = default_mode); largeobjectaccess() = delete; largeobjectaccess(largeobjectaccess const &) = delete; largeobjectaccess(largeobjectaccess &&) = delete; ~largeobjectaccess() noexcept { close(); } largeobjectaccess &operator=(largeobjectaccess const &) = delete; largeobjectaccess &operator=(largeobjectaccess &&) = delete; /// Object identifier. /** The number returned by this function uniquely identifies the large object * in the context of the database we're connected to. */ using largeobject::id; /// Export large object's contents to a local file. /** Writes the data stored in the large object to the given file. * @param file A filename on the client's filesystem. */ void to_file(std::string_view file) const { largeobject::to_file(m_trans, file); } using largeobject::to_file; /** * @name High-level access to object contents. */ //@{ /// Write data to large object. /** @warning The size of a write is currently limited to 2GB. * * @param buf Data to write. * @param len Number of bytes from Buf to write. */ void write(char const buf[], std::size_t len); /// Write string to large object. /** If not all bytes could be written, an exception is thrown. * @param buf Data to write; no terminating zero is written. */ void write(std::string_view buf) { write(std::data(buf), std::size(buf)); } /// Read data from large object. /** Throws an exception if an error occurs while reading. * @param buf Location to store the read data in. * @param len Number of bytes to try and read. * @return Number of bytes read, which may be less than the number requested * if the end of the large object is reached. */ size_type read(char buf[], std::size_t len); /// Seek in large object's data stream. /** Throws an exception if an error occurs. * @return The new position in the large object */ size_type seek(size_type dest, seekdir dir); /// Report current position in large object's data stream. /** Throws an exception if an error occurs. * @return The current position in the large object. */ [[nodiscard]] size_type tell() const; //@} /** * @name Low-level access to object contents. * * These functions provide a more "C-like" access interface, returning * special values instead of throwing exceptions on error. These functions * are generally best avoided in favour of the high-level access functions, * which behave more like C++ functions should. * * Due to libpq's underlying API, some operations are limited to "int" * sizes, typically 2 GB, even though a large object can grow much larger. */ //@{ /// Seek in large object's data stream. /** Does not throw exception in case of error; inspect return value and * `errno` instead. * @param dest Offset to go to. * @param dir Origin to which dest is relative: ios_base::beg (from beginning * of the object), ios_base::cur (from current access position), or * ios_base;:end (from end of object). * @return New position in large object, or -1 if an error occurred. */ pos_type cseek(off_type dest, seekdir dir) noexcept; /// Write to large object's data stream. /** Does not throw exception in case of error; inspect return value and * `errno` instead. * @param buf Data to write. * @param len Number of bytes to write. * @return Number of bytes actually written, or -1 if an error occurred. */ off_type cwrite(char const buf[], std::size_t len) noexcept; /// Read from large object's data stream. /** Does not throw exception in case of error; inspect return value and * `errno` instead. * @param buf Area where incoming bytes should be stored. * @param len Number of bytes to read. * @return Number of bytes actually read, or -1 if an error occurred.. */ off_type cread(char buf[], std::size_t len) noexcept; /// Report current position in large object's data stream. /** Does not throw exception in case of error; inspect return value and * `errno` instead. * @return Current position in large object, of -1 if an error occurred. */ [[nodiscard]] pos_type ctell() const noexcept; //@} /** * @name Error/warning output */ //@{ /// Issue message to transaction's notice processor. void process_notice(zview) noexcept; //@} using largeobject::remove; using largeobject::operator==; using largeobject::operator!=; using largeobject::operator<; using largeobject::operator<=; using largeobject::operator>; using largeobject::operator>=; private: PQXX_PRIVATE [[nodiscard]] std::string reason(int err) const; [[nodiscard]] internal::pq::PGconn *raw_connection() const { return largeobject::raw_connection(m_trans); } PQXX_PRIVATE void open(openmode mode); void close() noexcept; dbtransaction &m_trans; int m_fd = -1; }; // NOLINTBEGIN(cppcoreguidelines-owning-memory) /// Streambuf to use large objects in standard I/O streams. /** @deprecated Access large objects directly using the @ref blob class. * * The standard streambuf classes provide uniform access to data storage such * as files or string buffers, so they can be accessed using standard input or * output streams. This streambuf implementation provided similar access to * large objects, so they could be read and written using the same stream * classes. * * This functionality was considered too fragile and complex, so it has been * replaced with a single, much simpler class. */ template> class largeobject_streambuf final : public std::basic_streambuf { using size_type = largeobject::size_type; public: using char_type = CHAR; using traits_type = TRAITS; using int_type = typename traits_type::int_type; using pos_type = typename traits_type::pos_type; using off_type = typename traits_type::off_type; using openmode = largeobjectaccess::openmode; using seekdir = largeobjectaccess::seekdir; /// Default open mode: in, out, binary. static constexpr auto default_mode{ std::ios::in | std::ios::out | std::ios::binary}; #include "pqxx/internal/ignore-deprecated-pre.hxx" [[deprecated("Use blob instead.")]] largeobject_streambuf( dbtransaction &t, largeobject o, openmode mode = default_mode, size_type buf_size = 512) : m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr} { initialize(mode); } #include "pqxx/internal/ignore-deprecated-post.hxx" [[deprecated("Use blob instead.")]] largeobject_streambuf( dbtransaction &t, oid o, openmode mode = default_mode, size_type buf_size = 512) : m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr} { initialize(mode); } largeobject_streambuf(largeobject_streambuf const &) = delete; largeobject_streambuf(largeobject_streambuf &&) = delete; ~largeobject_streambuf() noexcept override { delete[] m_p; delete[] m_g; } largeobject_streambuf &operator=(largeobject_streambuf const &) = delete; largeobject_streambuf &operator=(largeobject_streambuf &&) = delete; /// For use by large object stream classes. void process_notice(zview const &s) { m_obj.process_notice(s); } protected: int sync() override { // setg() sets eback, gptr, egptr. this->setg(this->eback(), this->eback(), this->egptr()); return overflow(eof()); } pos_type seekoff(off_type offset, seekdir dir, openmode) override { return adjust_eof(m_obj.cseek(largeobjectaccess::off_type(offset), dir)); } pos_type seekpos(pos_type pos, openmode) override { largeobjectaccess::pos_type const newpos{ m_obj.cseek(largeobjectaccess::off_type(pos), std::ios::beg)}; return adjust_eof(newpos); } int_type overflow(int_type ch = eof()) override { auto *const pp{this->pptr()}; if (pp == nullptr) return eof(); auto *const pb{this->pbase()}; int_type res{0}; if (pp > pb) { auto const write_sz{pp - pb}; auto const written_sz{ m_obj.cwrite(pb, static_cast(pp - pb))}; if (std::cmp_less_equal(written_sz, 0)) throw internal_error{ "pqxx::largeobject: write failed " "(is transaction still valid on write or flush?), " "libpq reports error"}; else if (write_sz != written_sz) throw internal_error{std::format( "pqxx::largeobject: write failed " "(is transaction still valid on write or flush?), {}/{} " "bytes written", written_sz, write_sz)}; auto const out{adjust_eof(written_sz)}; if constexpr (std::is_arithmetic_v) res = check_cast(out, "largeobject position"sv); else res = int_type(out); } this->setp(m_p, m_p + m_bufsize); // Write that one more character, if it's there. if (ch != eof()) { *this->pptr() = static_cast(ch); this->pbump(1); } return res; } int_type underflow() override { if (this->gptr() == nullptr) return eof(); auto *const eb{this->eback()}; auto const res{adjust_eof( m_obj.cread(this->eback(), static_cast(m_bufsize)))}; this->setg( eb, eb, eb + (res == eof() ? 0 : static_cast(res))); return (res == eof() or res == 0) ? eof() : traits_type::to_int_type(*eb); } private: /// Shortcut for traits_type::eof(). static constexpr int_type eof() { return traits_type::eof(); } /// Helper: change error position of -1 to EOF (probably a no-op). template static std::streampos adjust_eof(INTYPE pos) { bool const at_eof{pos == -1}; if constexpr (std::is_arithmetic_v) { return check_cast( (at_eof ? eof() : pos), "large object seek"sv); } else { return std::streampos(at_eof ? eof() : pos); } } void initialize(openmode mode) { if ((mode & std::ios::in) != 0) { m_g = new char_type[unsigned(m_bufsize)]; this->setg(m_g, m_g, m_g); } if ((mode & std::ios::out) != 0) { m_p = new char_type[unsigned(m_bufsize)]; this->setp(m_p, m_p + m_bufsize); } } size_type const m_bufsize; largeobjectaccess m_obj; /// Get & put buffers. char_type *m_g, *m_p; }; // NOLINTEND(cppcoreguidelines-owning-memory) /// Input stream that gets its data from a large object. /** @deprecated Access large objects directly using the @ref blob class. * * This class worked like any other istream, but to read data from a large * object. It supported all formatting and streaming operations of * `std::istream`. * * This functionality was considered too fragile and complex, so it has been * replaced with a single, much simpler class. */ template> class basic_ilostream final : public std::basic_istream { using super = std::basic_istream; public: using char_type = CHAR; using traits_type = TRAITS; using int_type = typename traits_type::int_type; using pos_type = typename traits_type::pos_type; using off_type = typename traits_type::off_type; #include "pqxx/internal/ignore-deprecated-pre.hxx" /// Create a basic_ilostream. /** * @param t Transaction in which this stream is to exist. * @param o Large object to access. * @param buf_size Size of buffer to use internally (optional). */ [[deprecated("Use blob instead.")]] basic_ilostream( dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) : super{nullptr}, m_buf{t, o, std::ios::in | std::ios::binary, buf_size} { super::init(&m_buf); } #include "pqxx/internal/ignore-deprecated-post.hxx" /// Create a basic_ilostream. /** * @param t Transaction in which this stream is to exist. * @param o Identifier of a large object to access. * @param buf_size Size of buffer to use internally (optional). */ [[deprecated("Use blob instead.")]] basic_ilostream( dbtransaction &t, oid o, largeobject::size_type buf_size = 512) : super{nullptr}, m_buf{t, o, std::ios::in | std::ios::binary, buf_size} { super::init(&m_buf); } private: largeobject_streambuf m_buf; }; using ilostream = basic_ilostream; /// Output stream that writes data back to a large object. /** @deprecated Access large objects directly using the @ref blob class. * * This worked like any other ostream, but to write data to a large object. * It supported all formatting and streaming operations of `std::ostream`. * * This functionality was considered too fragile and complex, so it has been * replaced with a single, much simpler class. */ template> class basic_olostream final : public std::basic_ostream { using super = std::basic_ostream; public: using char_type = CHAR; using traits_type = TRAITS; using int_type = typename traits_type::int_type; using pos_type = typename traits_type::pos_type; using off_type = typename traits_type::off_type; #include "pqxx/internal/ignore-deprecated-pre.hxx" /// Create a basic_olostream. /** * @param t transaction in which this stream is to exist. * @param o a large object to access. * @param buf_size size of buffer to use internally (optional). */ [[deprecated("Use blob instead.")]] basic_olostream( dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) : super{nullptr}, m_buf{t, o, std::ios::out | std::ios::binary, buf_size} { super::init(&m_buf); } #include "pqxx/internal/ignore-deprecated-post.hxx" /// Create a basic_olostream. /** * @param t transaction in which this stream is to exist. * @param o a large object to access. * @param buf_size size of buffer to use internally (optional). */ [[deprecated("Use blob instead.")]] basic_olostream( dbtransaction &t, oid o, largeobject::size_type buf_size = 512) : super{nullptr}, m_buf{t, o, std::ios::out | std::ios::binary, buf_size} { super::init(&m_buf); } basic_olostream(basic_olostream const &) = delete; basic_olostream(basic_olostream &&) = delete; ~basic_olostream() override { try { m_buf.pubsync(); m_buf.pubsync(); } catch (std::exception const &e) { m_buf.process_notice(e.what()); } } basic_olostream &operator=(basic_olostream const &) = delete; basic_olostream &operator=(basic_olostream &&) = delete; private: largeobject_streambuf m_buf; }; using olostream = basic_olostream; /// Stream that reads and writes a large object. /** @deprecated Access large objects directly using the @ref blob class. * * This worked like a std::iostream, but to read data from, or write data to, a * large object. It supported all formatting and streaming operations of * `std::iostream`. * * This functionality was considered too fragile and complex, so it has been * replaced with a single, much simpler class. */ template> class basic_lostream final : public std::basic_iostream { using super = std::basic_iostream; public: using char_type = CHAR; using traits_type = TRAITS; using int_type = typename traits_type::int_type; using pos_type = typename traits_type::pos_type; using off_type = typename traits_type::off_type; /// Create a basic_lostream. /** * @param t Transaction in which this stream is to exist. * @param o Large object to access. * @param buf_size Size of buffer to use internally (optional). */ [[deprecated("Use blob instead.")]] basic_lostream( dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) : super{nullptr}, m_buf{ t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size} { super::init(&m_buf); } /// Create a basic_lostream. /** * @param t Transaction in which this stream is to exist. * @param o Large object to access. * @param buf_size Size of buffer to use internally (optional). */ [[deprecated("Use blob instead.")]] basic_lostream( dbtransaction &t, oid o, largeobject::size_type buf_size = 512) : super{nullptr}, m_buf{ t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size} { super::init(&m_buf); } basic_lostream() = delete; basic_lostream(basic_lostream const &) = delete; basic_lostream(basic_lostream &&) = delete; ~basic_lostream() override { try { m_buf.pubsync(); m_buf.pubsync(); } catch (std::exception const &e) { m_buf.process_notice(e.what()); } } basic_lostream &operator=(basic_lostream const &) = delete; basic_lostream &operator=(basic_lostream &&) = delete; private: largeobject_streambuf m_buf; }; using lostream = basic_lostream; // LCOV_EXCL_STOP } // namespace pqxx // NOLINTEND( // cppcoreguidelines-avoid-const-or-ref-data-members, // fuchsia-multiple-inheritance // ) #endif libpqxx-8.0.1/include/pqxx/nontransaction000066400000000000000000000004541516427024100206220ustar00rootroot00000000000000/** pqxx::nontransaction class. * * pqxx::nontransaction provides nontransactional database access. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/nontransaction.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/nontransaction.hxx000066400000000000000000000065131516427024100214320ustar00rootroot00000000000000/* Definition of the pqxx::nontransaction class. * * pqxx::nontransaction provides nontransactional database access * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/nontransaction instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_NONTRANSACTION_HXX #define PQXX_NONTRANSACTION_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include "pqxx/connection.hxx" #include "pqxx/result.hxx" #include "pqxx/transaction.hxx" namespace pqxx { using namespace std::literals; /// Simple "transaction" class offering no transactional integrity. /** * @ingroup transactions * * nontransaction, like transaction or any other transaction_base-derived * class, provides access to a database through a connection. Unlike its * siblings, however, nontransaction does not maintain any kind of * transactional integrity. This may be useful eg. for read-only access to the * database that does not require a consistent, atomic view on its data; or for * operations that are not allowed within a backend transaction, such as * creating tables. * * For queries that update the database, however, a real transaction is likely * to be faster unless the transaction consists of only a single record update. * * Also, you can keep a nontransaction open for as long as you like. Actual * back-end transactions are limited in lifespan, and will sometimes fail just * because they took too long to execute or were left idle for too long. This * will not happen with a nontransaction (although the connection may still * time out, e.g. when the network is unavailable for a very long time). * * Any query executed in a nontransaction is committed immediately, and neither * commit() nor abort() has any effect as far as the database is concerned. * Just like other transaction types, however, the nontransaction remains * attached to the @ref pqxx::connection until you commit, abort, or destroy * it. Just like a regular transaction, it is a @ref transaction_focus, of * which no more than one can be active for any given connection at any given * time. * * Database features that require a backend transaction, such as cursors or * large objects, will not work in a nontransaction. */ class PQXX_LIBEXPORT nontransaction final : public transaction_base { public: /// Constructor. /** Create a "dummy" transaction. * @param cx Connection in which this "transaction" will operate. * @param tname Optional tname for the transaction, beginning with a letter * and containing only letters and digits. */ explicit nontransaction( connection &cx, std::string_view tname = ""sv, sl loc = sl::current()) : transaction_base{cx, tname, std::shared_ptr{}, loc} { register_transaction(); } nontransaction() = delete; nontransaction(nontransaction const &) = delete; nontransaction(nontransaction &&) = delete; ~nontransaction() override { close(sl::current()); } nontransaction &operator=(nontransaction const &) = delete; nontransaction &operator=(nontransaction &&) = delete; private: void do_commit(sl) override {} }; } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/notification000066400000000000000000000004711516427024100202470ustar00rootroot00000000000000/** pqxx::notification_receiver functor interface. * * pqxx::notification_receiver handles incoming notifications. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/notification.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/notification.hxx000066400000000000000000000073761516427024100210700ustar00rootroot00000000000000/* Definition of the pqxx::notification_receiver functor interface. * * pqxx::notification_receiver handles incoming notifications. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/notification instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_NOTIFICATION_HXX #define PQXX_NOTIFICATION_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include "pqxx/types.hxx" namespace pqxx { // This code is deprecated. // LCOV_EXCL_START /// "Observer" base class for notifications. /** @addtogroup notification Notifications and Receivers * * To listen on a notification issued using the NOTIFY command, derive your own * class from notification_receiver and define its function-call operator to * perform whatever action you wish to take when the given notification * arrives. Then create an object of that class and pass it to your connection. * DO NOT use raw SQL to listen for notifications, or your attempts to listen * won't be resumed when a connection fails--and you'll have no way to notice. * * Notifications never arrive inside a transaction, not even in a * nontransaction. Therefore, you are free to open a transaction of your own * inside your receiver's function invocation operator. * * Notifications you are listening for may arrive anywhere within libpqxx code, * but be aware that **PostgreSQL defers notifications occurring inside * transactions.** (This was done for excellent reasons; just think about what * happens if the transaction where you happen to handle an incoming * notification is later rolled back for other reasons). So if you're keeping * a transaction open, don't expect any of your receivers on the same * connection to be notified. * * (For very similar reasons, outgoing notifications are also not sent until * the transaction that sends them commits.) * * Multiple receivers on the same connection may listen on a notification of * the same name. An incoming notification is processed by invoking all * receivers (zero or more) of the same name. */ class PQXX_LIBEXPORT PQXX_NOVTABLE notification_receiver { public: /// Register the receiver with a connection. /** * @param cx Connnection to operate on. * @param channel Name of the notification to listen for. */ [[deprecated("Use pqxx::connection::listen() instead.")]] notification_receiver( connection &cx, std::string_view channel, sl loc = sl::current()); notification_receiver(notification_receiver const &) = delete; notification_receiver(notification_receiver &&) = delete; /// Deregister the receiver. virtual ~notification_receiver(); notification_receiver &operator=(notification_receiver const &) = delete; notification_receiver &operator=(notification_receiver &&) = delete; /// The channel that this receiver listens on. [[nodiscard]] std::string const &channel() const & { return m_channel; } /// Overridable: action to invoke when notification arrives. /** * @param payload An optional string that may have been passed to the NOTIFY * command. * @param backend_pid Process ID of the database backend process that served * our connection when the notification arrived. The actual process ID * behind the connection may have changed by the time this method is called. */ virtual void operator()(std::string const &payload, int backend_pid) = 0; protected: [[nodiscard]] connection &conn() const noexcept { return m_conn; } private: connection &m_conn; std::string m_channel; }; // LCOV_EXCL_STOP } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/params000066400000000000000000000004671516427024100170510ustar00rootroot00000000000000/** Helper classes for passing statement parameters. * * Use these for prepared statements and parameterised statements. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/params.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/params.hxx000066400000000000000000000265531516427024100176630ustar00rootroot00000000000000/* Helpers for prepared statements and parameterised statements. * * See @ref connection and @ref transaction_base for more. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_PARAMS_HXX #define PQXX_PARAMS_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include #include "pqxx/internal/statement_parameters.hxx" #include "pqxx/types.hxx" namespace pqxx::internal { /// Identity function for @ref encoding_group, for regularity. PQXX_PURE [[nodiscard]] inline constexpr pqxx::encoding_group get_encoding_group(encoding_group const &enc, sl = sl::current()) noexcept { return enc; } /// Return client encoding from @ref conversion_context. /** Also accepts a `source_location` argument, but ignores it in favour of the * one embedded in the `conversion_context`. */ PQXX_PURE [[nodiscard]] inline constexpr pqxx::encoding_group get_encoding_group(ctx c, sl = sl::current()) noexcept { return c.enc; } /// Return connection's current client encoding. [[nodiscard]] PQXX_LIBEXPORT pqxx::encoding_group get_encoding_group(connection const &, sl = sl::current()); /// Return transaction's connection's current client encoding. [[nodiscard]] PQXX_LIBEXPORT pqxx::encoding_group get_encoding_group(transaction_base const &, sl = sl::current()); } // namespace pqxx::internal namespace pqxx { /// Build a parameter list for a parameterised or prepared statement. /** When calling a parameterised statement or a prepared statement, in many * cases you can pass parameters into the statement in the form of a * `pqxx::params` object. */ class PQXX_LIBEXPORT params final { public: params() = default; // NOLINTBEGIN(google-explicit-constructor,hicpp-explicit-conversions) /// Pre-populate a `params` with `args`. Feel free to add more later. /** @note As a first parameter, we recommend passing an @ref encoding_group, * or a @ref connection, or a @ref transaction_base (or a more specific * transaction type derived from it), or a @ref conversion_context. The * `params` will use this to obtain the client encoding. (It will not be * passed as a parameter; it's just there as a source of the encoding * information). In most cases you won't need this, but there are exceptions * where a complex object can't be passed otherwise. To keep things clear, * we recommend passing it in the general case so that you never run into * exceptions about encoding being unknown. */ template params(First &&first, Args &&...args) { sl loc; if constexpr (std::is_same_v, conversion_context>) loc = first.loc; else loc = sl::current(); if constexpr (requires(encoding_group eg) { eg = pqxx::internal::get_encoding_group(first); }) { // First argument is a source of an encoding group, not a parameter. m_enc = pqxx::internal::get_encoding_group(first); append_pack(loc, std::forward(args)...); } else { // The first argument is just a regular parameter. Append it first. append_pack( loc, std::forward(first), std::forward(args)...); } } // NOLINTEND(google-explicit-constructor,hicpp-explicit-conversions) /// Pre-allocate room for at least `n` parameters. /** This is not needed, but it may improve efficiency. * * Reserve space if you're going to add parameters individually, and you've * got some idea of how many there are going to be. It may save some * memory re-allocations. */ void reserve(std::size_t n) &; /// Get the number of parameters currently in this `params`. [[nodiscard]] constexpr auto size() const noexcept { return m_params.size(); } /// Get the number of parameters (signed). /** Unlike `size()`, this is not yet `noexcept`. That's because C++17's * `std::vector` does not have a `ssize()` member function. These member * functions are `noexcept`, but `std::size()` and `std::ssize()` are * not. */ [[nodiscard]] constexpr auto ssize() const { return std::ssize(m_params); } /// Append a null value. void append(sl = sl::current()) &; /// Append a non-null zview parameter. /** The underlying data must stay valid for as long as the `params` * remains active. */ void append(zview, sl = sl::current()) &; /// Append a non-null string parameter. /** Copies the underlying data into internal storage. For best efficiency, * use the @ref zview variant if you can, or `std::move()` */ void append(std::string const &, sl = sl::current()) &; /// Append a non-null string parameter. void append(std::string &&, sl = sl::current()) &; /// Append a non-null binary parameter. /** The underlying data must stay valid for as long as the `params` * remains active. */ void append(bytes_view, sl = sl::current()) &; /// Append a non-null binary parameter. /** The `data` object must stay in place and unchanged, for as long as the * `params` remains active. */ template void append(DATA const &data, sl loc = sl::current()) & { append(binary_cast(data), loc); } /// Append a non-null binary parameter. void append(bytes &&, sl = sl::current()) &; /// Append all parameters in `value`. void append(params const &value, sl = sl::current()) &; /// Append all parameters in `value`. void append(params &&value, sl = sl::current()) &; /// Append a non-null parameter, converting it to its string /// representation. template void append([[maybe_unused]] TYPE const &value, sl loc = sl::current()) & { // TODO: Pool storage for multiple string conversions in one buffer? if constexpr (pqxx::always_null()) { m_params.emplace_back(); } else if (is_null(value)) { m_params.emplace_back(); } else { // TODO: Block-allocate storage for parameters. m_params.emplace_back( entry{to_string(value, conversion_context{m_enc, loc})}); } } /// Append all elements of `range` as parameters. template void append_multi(RANGE const &range, sl loc = sl::current()) & { if constexpr (std::ranges::sized_range) reserve(std::size(*this) + std::size(range)); for (auto &value : range) append(value, loc); } /// For internal use: Generate a `params` object for use in calls. /** The params object encapsulates the pointers which we will need to pass * to libpq when calling a parameterised or prepared statement. * * The pointers in the params will refer to storage owned by either the * params object, or the caller. This is not a problem because a * `c_params` object is guaranteed to live only while the call is going on. * As soon as we climb back out of that call tree, we're done with that * data. */ [[nodiscard]] pqxx::internal::c_params make_c_params(sl loc) const; private: /// Append a pack of params. template void append_pack(sl loc, Args &&...args) { reserve(size() + sizeof...(args)); ((this->append(std::forward(args), loc)), ...); } /// Append a pack of params: trivial case. /** (Only here to silence annoying warnings about unused parameters.) */ void append_pack(sl) const noexcept {} // The way we store a parameter depends on whether it's binary or text // (most types are text), and whether we're responsible for storing the // contents. using entry = std::variant; std::vector m_params; encoding_group m_enc{encoding_group::unknown}; static constexpr std::string_view s_overflow{ "Statement parameter length overflow."sv}; }; /// Generate parameter placeholders for use in an SQL statement. /** When you want to pass parameters to a prepared statement or a parameterised * statement, you insert placeholders into the SQL. During invocation, the * database replaces those with the respective parameter values you passed. * * The placeholders look like `$1` (for the first parameter value), `$2` (for * the second), and so on. You can just write those directly in your * statement. But for those rare cases where it becomes difficult to track * which number a placeholder should have, you can use a `placeholders` object * to count and generate them in order. */ template class placeholders final { public: /// Maximum number of parameters we support. static inline constexpr unsigned int max_params{ (std::numeric_limits::max)()}; placeholders() { static constexpr auto initial{"$1\0"sv}; initial.copy(std::data(m_buf), std::size(initial)); } /// Read an ephemeral version of the current placeholder text. /** @warning Changing the current placeholder number will overwrite this. * Use the view immediately, or lose it. */ [[nodiscard]] constexpr zview view() const & noexcept { return zview{std::data(m_buf), m_len}; } /// Read the current placeholder text, as a `std::string`. /** This will be slightly slower than converting to a `zview`. With most * C++ implementations however, until you get into ridiculous numbers of * parameters, the string will benefit from the Short String Optimization, or * SSO. */ [[nodiscard]] std::string get() const { return std::string(std::data(m_buf), m_len); } /// Move on to the next parameter. void next(sl loc = sl::current()) & { conversion_context const c{{}, loc}; if (m_current >= max_params) throw range_error{ std::format( "Too many parameters in one statement: limit is {}.", max_params), loc}; PQXX_ASSUME(m_current > 0); ++m_current; if (m_current % 10 == 0) { // Carry the 1. Don't get too clever for this relatively rare // case, just rewrite the entire number. Leave the $ in place // though. char *const data{std::data(m_buf)}; auto const written{pqxx::into_buf( {data + 1, data + std::size(m_buf) - 1}, m_current, c)}; std::size_t const end{1 + written}; assert(end < std::size(m_buf)); data[end] = '\0'; m_len = check_cast(end, "placeholders counter", loc); } else [[likely]] { // Shortcut for the common case: just increment that last digit. ++m_buf.at(m_len - 1); } } /// Return the current placeholder number. The initial placeholder is 1. [[nodiscard]] COUNTER count() const noexcept { return m_current; } private: /// Current placeholder number. Starts at 1. COUNTER m_current = 1; /// Length of the current placeholder string, not including trailing zero. COUNTER m_len = 2; /// Text buffer where we render the placeholders, with a trailing zero. /** We keep reusing this for every subsequent placeholder, just because we * don't like string allocations. * * Maximum length is the maximum base-10 digits that COUNTER can fully * represent, plus 1 more for the extra digit that it can only partially * fill up, plus room for the dollar sign and the trailing zero. */ std::array::digits10 + 3> m_buf; }; } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/pipeline000066400000000000000000000004061516427024100173640ustar00rootroot00000000000000/** pqxx::pipeline class. * * Throughput-optimized query interface. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/pipeline.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/pipeline.hxx000066400000000000000000000205011516427024100201700ustar00rootroot00000000000000/* Definition of the pqxx::pipeline class. * * Throughput-optimized mechanism for executing queries. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/pipeline instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_PIPELINE_HXX #define PQXX_PIPELINE_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include #include #include "pqxx/transaction_base.hxx" namespace pqxx { // TODO: libpq 14 introduced a similar "pipeline mode." Can we use that? /// Processes several queries in FIFO manner, optimized for high throughput. /** Use a pipeline if you want to keep doing useful work while your queries are * executing. Result retrieval is decoupled from execution request; queries * "go in at the front" and results "come out the back." * * Actually, you can retrieve the results in any order if you want, but it may * lead to surprising "time travel" effects if any of the queries fails. In * particular, syntax errors in the queries can confuse things and show up too * early in the stream of results. * * Generally, if any of the queries fails, it will throw an exception at the * point where you request its result. But it may happen earlier, especially * if you request results out of chronological order. * * @warning While a pipeline is active, you cannot execute queries, open * streams, etc. on the same transaction. A transaction can have at most one * object of a type derived from @ref pqxx::transaction_focus active on it at a * time. */ class PQXX_LIBEXPORT pipeline final : public transaction_focus { public: /// Identifying numbers for queries. using query_id = long; pipeline(pipeline const &) = delete; pipeline &operator=(pipeline const &) = delete; pipeline(pipeline &&) = delete; pipeline &operator=(pipeline &&) = delete; /// Start a pipeline. explicit pipeline(transaction_base &t, sl loc = sl::current()) : transaction_focus{t, s_classname}, m_created_loc{loc} { init(loc); } /// Start a pipeline. Assign it a name, for more helpful error messages. pipeline( transaction_base &t, std::string_view tname, sl loc = sl::current()) : transaction_focus{t, s_classname, tname}, m_created_loc{loc} { init(loc); } /// Close the pipeline. ~pipeline() noexcept; /// Add query to the pipeline. /** Queries accumulate in the pipeline, which sends them to the backend in a * batch separated by semicolons. The queries you insert must not use this * trick themselves, or the pipeline will get hopelessly confused! * * @return Identifier for this query, unique only within this pipeline. */ query_id insert(std::string_view, sl = sl::current()) &; /// Wait for all ongoing or pending operations to complete, and detach. /** Detaches from the transaction when done. * * This does not produce the queries' results, so it may not report any * errors which may have occurred in their execution. To be sure that your * statements succeeded, call @ref retrieve until the pipeline is empty. */ void complete(sl = sl::current()); /// Forget all ongoing or pending operations and retrieved results. /** Queries already sent to the backend may still be completed, depending * on implementation and timing. * * Any error state (unless caused by an internal error) will also be cleared. * This is mostly useful in a nontransaction, since a backend transaction is * aborted automatically when an error occurs. * * Detaches from the transaction when done. */ void flush(sl = sl::current()); /// Cancel ongoing query, if any. /** May cancel any or all of the queries that have been inserted at this * point whose results have not yet been retrieved. If the pipeline lives in * a backend transaction, that transaction may be left in a nonfunctional * state in which it can only be aborted. * * Therefore, either use this function in a nontransaction, or abort the * transaction after calling it. */ void cancel(sl = sl::current()); /// Is result for given query available? [[nodiscard]] bool is_finished(query_id) const; /// Retrieve result for given query. /** If the query failed for whatever reason, this will throw an exception. * The function will block if the query has not finished yet. * @warning If results are retrieved out-of-order, i.e. in a different order * than the one in which their queries were inserted, errors may "propagate" * to subsequent queries. */ result retrieve(query_id qid, sl loc = sl::current()) { return retrieve(m_queries.find(qid), loc).second; } /// Retrieve oldest unretrieved result (possibly wait for one). /** @return The query's identifier and its result set. */ std::pair retrieve(sl = sl::current()); [[nodiscard]] bool empty() const noexcept { return std::empty(m_queries); } /// Set maximum number of queries to retain before issuing them to backend. /** The pipeline will perform better if multiple queries are issued at once, * but retaining queries until the results are needed (as opposed to issuing * them to the backend immediately) may negate any performance benefits the * pipeline can offer. * * Recommended practice is to set this value no higher than the number of * queries you intend to insert at a time. * @param retain_max A nonnegative "retention capacity;" passing zero will * cause queries to be issued immediately * @return Old retention capacity */ int retain(int retain_max = 2) &; /// Resume retained query emission. Harmless when not needed. void resume(sl loc = sl::current()) &; private: struct PQXX_PRIVATE Query final { explicit Query(std::string_view q) : query{std::make_shared(q)} {} // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) std::shared_ptr query; // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) result res; }; using QueryMap = std::map; void init(sl); void attach(); void detach(); /// Upper bound to query id's. static constexpr query_id qid_limit() noexcept { // Parenthesise this to work around an eternal Visual C++ problem: // Without the extra parentheses, unless NOMINMAX is defined, the // preprocessor will mistake this "max" for its annoying built-in macro // of the same name. return (std::numeric_limits::max)(); } /// Create new query_id. PQXX_PRIVATE query_id generate_id(); [[nodiscard]] bool have_pending() const noexcept { return m_issuedrange.second != m_issuedrange.first; } PQXX_PRIVATE void issue(sl); /// The given query failed; never issue anything beyond that. void set_error_at(query_id qid) noexcept { if (qid < m_error) [[unlikely]] m_error = qid; } /// Throw pqxx::internal_error. [[noreturn]] PQXX_PRIVATE void internal_error(std::string const &err, sl); PQXX_PRIVATE bool obtain_result(bool expect_none, sl); PQXX_PRIVATE void obtain_dummy(sl); PQXX_PRIVATE void get_further_available_results(sl); PQXX_PRIVATE void check_end_results(); /// Receive any results that happen to be available; it's not urgent. PQXX_PRIVATE void receive_if_available(sl loc); /// Receive results, up to stop if possible. PQXX_PRIVATE void receive(pipeline::QueryMap::const_iterator stop, sl); std::pair retrieve(pipeline::QueryMap::iterator, sl); QueryMap m_queries; std::pair m_issuedrange; int m_retain = 0; int m_num_waiting = 0; query_id m_q_id = 0; /// Is there a "dummy query" pending? bool m_dummy_pending = false; /// Point at which an error occurred; no results beyond it will be available query_id m_error = qid_limit(); /// Encoding. /** We store this in the object to avoid the risk of exceptions at awkward * moments. */ encoding_group m_encoding{encoding_group::unknown}; /// A `std::source_location` for where this pipeline was created. sl m_created_loc; static constexpr std::string_view s_classname{"pipeline"}; }; } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/pqxx000066400000000000000000000015751516427024100165670ustar00rootroot00000000000000/// Convenience header: include all libpqxx definitions. #include "pqxx/internal/header-pre.hxx" #include "pqxx/array.hxx" #include "pqxx/blob.hxx" #include "pqxx/connection.hxx" #include "pqxx/cursor.hxx" #include "pqxx/errorhandler.hxx" #include "pqxx/except.hxx" #include "pqxx/largeobject.hxx" #include "pqxx/nontransaction.hxx" #include "pqxx/notification.hxx" #include "pqxx/params.hxx" #include "pqxx/pipeline.hxx" #include "pqxx/prepared_statement.hxx" #include "pqxx/range.hxx" #include "pqxx/result.hxx" #include "pqxx/internal/result_iterator.hxx" #include "pqxx/internal/result_iter.hxx" #include "pqxx/robusttransaction.hxx" #include "pqxx/row.hxx" #include "pqxx/stream_from.hxx" #include "pqxx/stream_to.hxx" #include "pqxx/subtransaction.hxx" #include "pqxx/time.hxx" #include "pqxx/transaction.hxx" #include "pqxx/transactor.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/prepared_statement000066400000000000000000000004651516427024100214520ustar00rootroot00000000000000/// Marker type to indicate that a string is the name of a prepared statement. #include "pqxx/internal/header-pre.hxx" // This include is deprecated. It will go away. // Include if you need it. #include "params.hxx" #include "pqxx/prepared_statement.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/prepared_statement.hxx000066400000000000000000000064071516427024100222620ustar00rootroot00000000000000/* Definition of the pqxx::prepped. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/prepared_statement instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_PREPARED_STATEMENT_HXX #define PQXX_PREPARED_STATEMENT_HXX namespace pqxx { /** * @name Prepared statements * * These are very similar to parameterised statements. The difference is * that you prepare a statement in advance, before you execute it, giving it an * identifying name. You can then call it by this name, as many times as you * like, passing in separate sets of argument values appropriate for each call. * * You prepare a statement on the connection, using * @ref pqxx::connection::prepare(). But you then call the statement in a * transaction, by calling * @ref pqxx::transaction_base::exec(pqxx::prepped, pqxx::params). * * The @ref pqxx::prepped type is really just a zero-terminated string, but * wrapped in its own type. This type only exists for one reason: it indicates * that the string is not an SQL statement itself, but the _name_ of a prepared * statement. * * See \ref prepared for a full discussion. * * @warning Beware of "nul" bytes. Any string you pass as a parameter will * end at the first char with value zero. If you pass a string that contains * a zero byte, the last byte in the value will be the one just before the * zero. If you need a zero byte, you're dealing with binary strings, not * regular strings. Represent binary strings on the SQL side as `BYTEA` * (or as large objects). On the C++ side, use types like `pqxx::bytes` or * `pqxx::bytes_view` or `std::vector`. Also, consider large * objects on the SQL side and @ref blob on the C++ side. * * @warning Passing the wrong number of parameters to a prepared or * parameterised statement will _break the connection._ The usual exception * that occurs in this situation is @ref pqxx::protocol_violation. It's a * subclass of @ref pqxx::broken_connection, but where `broken_connection` * usually indicates a networking problem, `protocol_violation` indicates * that the communication with the server has deviated from protocol. Once * something like that happens, communication is broken and there is nothing * for it but to discard the connection. A networking problem is usually * worth retrying, but a protocol violation is not. Once the two ends of the * connection disagree about where they are in their conversation, they can't * get back on track. This is beyond libpqxx's control. */ //@{ /// A string that is the name of a prepared statement. /** * When calling on libpqxx to execute a prepared statement, wrap its name in * a `prepped` object to indicate to libpqxx that it is a statement name, not * SQL. * * The string must be like a C-style string: it should contain no bytes with * value zero, but it must have a single byte with value zero directly behind * it in memory. */ class PQXX_LIBEXPORT prepped final : public std::string_view { public: explicit constexpr prepped(std::string_view name) noexcept : std::string_view{name} {} }; } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/range000066400000000000000000000003521516427024100166530ustar00rootroot00000000000000/** Client-side support for SQL range types. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/range.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/range.hxx000066400000000000000000000443361516427024100174730ustar00rootroot00000000000000#ifndef PQXX_RANGE_HXX #define PQXX_RANGE_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include #include #include "pqxx/internal/array-composite.hxx" namespace pqxx { /// An _unlimited_ boundary value to a @ref pqxx::range. /** Use this as a lower or upper bound for a range if the range should extend * to infinity on that side. * * An unlimited boundary is always inclusive of "infinity" values, if the * range's value type supports them. */ struct no_bound final { template [[nodiscard]] constexpr bool extends_down_to(TYPE const &) const noexcept { return true; } template [[nodiscard]] constexpr bool extends_up_to(TYPE const &) const noexcept { return true; } }; /// Concept: `T` supports copying, and less-than operator. template concept has_less = std::copy_constructible and requires(T n) { n < n; }; /// Concept: `T` supports equality comparison. template concept has_equal = requires(T n) { n == n; }; /// An _inclusive_ boundary value to a @ref pqxx::range. /** Use this as a lower or upper bound for a range if the range should include * the value. */ template class inclusive_bound final { // (Putting private section first to work around bug in gcc < 10: see #665.) private: TYPE m_value; public: inclusive_bound() = delete; constexpr explicit inclusive_bound( TYPE const &value, sl loc = sl::current()) : m_value{value} { if (is_null(value)) throw argument_error{"Got null value as an inclusive range bound.", loc}; } [[nodiscard]] constexpr TYPE const &get() const & noexcept { return m_value; } /// Would this bound, as a lower bound, include value? [[nodiscard]] constexpr bool extends_down_to(TYPE const &value) const noexcept(noexcept(value < m_value)) { return not(value < m_value); } /// Would this bound, as an upper bound, include value? [[nodiscard]] constexpr bool extends_up_to(TYPE const &value) const noexcept(noexcept(value < m_value)) { return not(m_value < value); } }; /// An _exclusive_ boundary value to a @ref pqxx::range. /** Use this as a lower or upper bound for a range if the range should _not_ * include the value. */ template class exclusive_bound final { // (Putting private section first to work around bug in gcc < 10: see #665.) private: TYPE m_value; public: exclusive_bound() = delete; constexpr explicit exclusive_bound( TYPE const &value, sl loc = sl::current()) : m_value{value} { if (is_null(value)) throw argument_error{"Got null value as an exclusive range bound.", loc}; } [[nodiscard]] constexpr TYPE const &get() const & noexcept { return m_value; } /// Would this bound, as a lower bound, include value? [[nodiscard]] constexpr bool extends_down_to(TYPE const &value) const noexcept(noexcept(m_value < value)) { return m_value < value; } /// Would this bound, as an upper bound, include value? [[nodiscard]] constexpr bool extends_up_to(TYPE const &value) const noexcept(noexcept(value < m_value)) { return value < m_value; } }; /// A range boundary value. /** A range bound is either no bound at all; or an inclusive bound; or an * exclusive bound. Pass one of the three to the constructor. */ template class range_bound final { // (Putting private section first to work around bug in gcc < 10: see #665.) private: std::variant, exclusive_bound> m_bound; static constexpr bool equal(TYPE const &lhs, TYPE const &rhs) { if constexpr (requires { lhs == rhs; }) // TYPE supports equality comparison. return lhs == rhs; else // Oh well. We do require less-than comparison, so use that. return not((lhs < rhs) or (rhs < lhs)); } public: range_bound() = delete; // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions) constexpr range_bound(no_bound) noexcept : m_bound{} {} // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions) constexpr range_bound(inclusive_bound const &bound) noexcept( noexcept(inclusive_bound{bound})) : m_bound{bound} {} // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions) constexpr range_bound(exclusive_bound const &bound) noexcept( noexcept(exclusive_bound{bound})) : m_bound{bound} {} constexpr range_bound(range_bound const &) noexcept( noexcept(inclusive_bound{ std::declval const &>()}) and noexcept(exclusive_bound{ std::declval const &>()})) = default; constexpr range_bound(range_bound &&) = default; ~range_bound() = default; constexpr bool operator==(range_bound const &rhs) const { if (this->is_limited()) return ( rhs.is_limited() and (this->is_inclusive() == rhs.is_inclusive()) and equal(*this->value(), *rhs.value())); else return not rhs.is_limited(); } constexpr bool operator!=(range_bound const &rhs) const noexcept(noexcept(*this == rhs)) { return not(*this == rhs); } range_bound &operator=(range_bound const &) = default; range_bound &operator=(range_bound &&) = default; /// Is this a finite bound? [[nodiscard]] constexpr bool is_limited() const noexcept { return not std::holds_alternative(m_bound); } /// Is this boundary an inclusive one? [[nodiscard]] constexpr bool is_inclusive() const noexcept { return std::holds_alternative>(m_bound); } /// Is this boundary an exclusive one? [[nodiscard]] constexpr bool is_exclusive() const noexcept { return std::holds_alternative>(m_bound); } /// Would this bound, as a lower bound, include `value`? [[nodiscard]] constexpr bool extends_down_to(TYPE const &value) const { return std::visit( [&value](auto const &bound) noexcept(noexcept(bound.extends_down_to( value))) { return bound.extends_down_to(value); }, m_bound); } /// Would this bound, as an upper bound, include `value`? [[nodiscard]] constexpr bool extends_up_to(TYPE const &value) const { return std::visit( [&value](auto const &bound) noexcept(noexcept( bound.extends_up_to(value))) { return bound.extends_up_to(value); }, m_bound); } /// Return bound value, or `nullptr` if it's not limited. [[nodiscard]] constexpr TYPE const *value() const & noexcept { return std::visit( [](auto const &bound) noexcept { using bound_t = std::decay_t; if constexpr (std::is_same_v) return static_cast(nullptr); else return &bound.get(); }, m_bound); } }; /// A C++ equivalent to PostgreSQL's range types. /** You can use this as a client-side representation of a "range" in SQL. * * PostgreSQL defines several range types, differing in the data type over * which they range. You can also define your own range types. * * Usually you'll want the server to deal with ranges. But on occasions where * you need to work with them client-side, you may want to use @ref * pqxx::range. (In cases where all you do is pass them along to the server * though, it's not worth the complexity. In that case you might as well treat * ranges as just strings.) * * For documentation on PostgreSQL's range types, see: * https://www.postgresql.org/docs/current/rangetypes.html * * The value type `TYPE` must typically be copyable and default-constructible, * and support the less-than (`<`) and equals (`==`) comparisons, but there * can be rare cases where they need not be. */ template class range final { // (Putting private section first to work around bug in gcc < 10: see #665.) private: range_bound m_lower, m_upper; public: /// Create a range. /** For each of the two bounds, pass a @ref no_bound, @ref inclusive_bound, * or * @ref exclusive_bound. */ constexpr range( range_bound lower, range_bound upper, sl loc = sl::current()) : m_lower{lower}, m_upper{upper} { if ( lower.is_limited() and upper.is_limited() and (*upper.value() < *lower.value())) throw range_error{ std::format( "Range's lower bound ({}) is greater than its upper bound ({}).", to_string(*lower.value()), to_string(*upper.value())), loc}; } /// Create an empty range. /** SQL has a separate literal to denote an empty range, but any range which * encompasses no values is an empty range. */ constexpr range() noexcept(noexcept(exclusive_bound{TYPE{}})) : m_lower{exclusive_bound{TYPE{}}}, m_upper{exclusive_bound{TYPE{}}} {} ~range() = default; constexpr bool operator==(range const &rhs) const noexcept( noexcept(this->lower_bound() == rhs.lower_bound()) and noexcept(this->upper_bound() == rhs.upper_bound()) and noexcept(this->empty())) { return (this->lower_bound() == rhs.lower_bound() and this->upper_bound() == rhs.upper_bound()) or (this->empty() and rhs.empty()); } constexpr bool operator!=(range const &rhs) const noexcept(noexcept(*this == rhs)) { return not(*this == rhs); } range(range const &) = default; range(range &&) = default; range &operator=(range const &) = default; range &operator=(range &&) = default; /// Is this range clearly empty? /** An empty range encompasses no values. * * It is possible to "fool" this. For example, if your range is of an * integer type and has exclusive bounds of 0 and 1, it encompasses no values * but its `empty()` will return false. The PostgreSQL implementation, by * contrast, will notice that it is empty. Similar things can happen for * floating-point types, but with more subtleties and edge cases. */ [[nodiscard]] constexpr bool empty() const noexcept( noexcept(m_lower.is_exclusive()) and noexcept(m_lower.is_limited()) and noexcept(*m_lower.value() < *m_upper.value())) { return (m_lower.is_exclusive() or m_upper.is_exclusive()) and m_lower.is_limited() and m_upper.is_limited() and not(*m_lower.value() < *m_upper.value()); } /// Does this range encompass `value`? [[nodiscard]] constexpr bool contains(TYPE value) const noexcept( noexcept(m_lower.extends_down_to(value)) and noexcept(m_upper.extends_up_to(value))) { return m_lower.extends_down_to(value) and m_upper.extends_up_to(value); } /// Does this range encompass all of `other`? /** This function is not particularly smart. It does not know, for example, * that integer ranges `[0,9]` and `[0,10)` contain the same values. */ [[nodiscard]] constexpr bool contains(range const &other) const noexcept(noexcept((*this & other) == other)) { return (*this & other) == other; } [[nodiscard]] constexpr range_bound const & lower_bound() const & noexcept { return m_lower; } [[nodiscard]] constexpr range_bound const & upper_bound() const & noexcept { return m_upper; } /// Intersection of two ranges. /** Returns a range describing those values which are in both ranges. */ constexpr range operator&(range const &other) const { range_bound lower{no_bound{}}; if (not this->lower_bound().is_limited()) lower = other.lower_bound(); else if (not other.lower_bound().is_limited()) lower = this->lower_bound(); else if (*this->lower_bound().value() < *other.lower_bound().value()) lower = other.lower_bound(); else if (*other.lower_bound().value() < *this->lower_bound().value()) lower = this->lower_bound(); else if (this->lower_bound().is_exclusive()) lower = this->lower_bound(); else lower = other.lower_bound(); range_bound upper{no_bound{}}; if (not this->upper_bound().is_limited()) upper = other.upper_bound(); else if (not other.upper_bound().is_limited()) upper = this->upper_bound(); else if (*other.upper_bound().value() < *this->upper_bound().value()) upper = other.upper_bound(); else if (*this->upper_bound().value() < *other.upper_bound().value()) upper = this->upper_bound(); else if (this->upper_bound().is_exclusive()) upper = this->upper_bound(); else upper = other.upper_bound(); if ( lower.is_limited() and upper.is_limited() and (*upper.value() < *lower.value())) return {}; else return {lower, upper}; } // NOLINTBEGIN(google-explicit-constructor,hicpp-explicit-conversions) /// Convert to another base type. template operator range() const { range_bound lower{no_bound{}}, upper{no_bound{}}; if (lower_bound().is_inclusive()) lower = inclusive_bound{*lower_bound().value()}; else if (lower_bound().is_exclusive()) lower = exclusive_bound{*lower_bound().value()}; if (upper_bound().is_inclusive()) upper = inclusive_bound{*upper_bound().value()}; else if (upper_bound().is_exclusive()) upper = exclusive_bound{*upper_bound().value()}; return {lower, upper}; } // NOLINTEND(google-explicit-constructor,hicpp-explicit-conversions) }; /// String conversions for a @ref range type. /** Conversion assumes an ASCII-safe encoding. */ template struct string_traits> final { [[nodiscard]] static std::string_view to_buf(std::span buf, range const &value, ctx c = {}) { if (value.empty()) { if (std::cmp_less_equal(std::size(buf), std::size(s_empty))) throw conversion_overrun{s_overrun.c_str(), c.loc}; return s_empty; } else { if (std::cmp_less(std::size(buf), 4)) throw conversion_overrun{s_overrun.c_str(), c.loc}; std::span tmp{buf}; // C++26: Use at(). tmp[0] = (static_cast(value.lower_bound().is_inclusive() ? '[' : '(')); tmp = tmp.subspan(1); TYPE const *lower{value.lower_bound().value()}; // Convert bound (but go back to overwrite that trailing zero). if (lower != nullptr) tmp = tmp.subspan(pqxx::into_buf(tmp, *lower)); // C++26: Use at(). tmp[0] = ','; tmp = tmp.subspan(1); TYPE const *upper{value.upper_bound().value()}; // Convert bound (but go back to overwrite that trailing zero). if (upper != nullptr) tmp = tmp.subspan(pqxx::into_buf(tmp, *upper, c)); if (std::cmp_less(std::size(tmp), 2)) throw conversion_overrun{s_overrun.c_str(), c.loc}; tmp[0] = static_cast(value.upper_bound().is_inclusive() ? ']' : ')'); tmp = tmp.subspan(1); return { std::data(buf), static_cast(std::data(tmp) - std::data(buf))}; } } [[nodiscard]] static inline range from_string(std::string_view text, sl loc = sl::current()) { if (std::size(text) < 3) throw pqxx::conversion_error{err_bad_input(text), loc}; switch (text[0]) { case '[': case '(': break; case 'e': case 'E': if ( (std::size(text) != std::size(s_empty)) or (text[1] != 'm' and text[1] != 'M') or (text[2] != 'p' and text[2] != 'P') or (text[3] != 't' and text[3] != 'T') or (text[4] != 'y' and text[4] != 'Y')) throw pqxx::conversion_error{err_bad_input(text), loc}; return {}; break; default: throw pqxx::conversion_error{err_bad_input(text), loc}; } // The field parser uses this to track which field it's parsing, and // when not to expect a field separator. // clang-tidy rule bug: // NOLINTNEXTLINE(misc-const-correctness) std::size_t index{0}; // The last field we expect to see. static constexpr std::size_t last{1}; // Current parsing position. We skip the opening parenthesis or bracket. // clang-tidy rule bug: // NOLINTNEXTLINE(misc-const-correctness) std::size_t pos{1}; // The string may leave out either bound to indicate that it's unlimited. std::optional lower, upper; // We reuse the same field parser we use for composite values and arrays. auto const field_parser{ pqxx::internal::specialize_parse_composite_field>( conversion_context{encoding_group::ascii_safe, loc})}; field_parser(index, text, pos, lower, last, loc); field_parser(index, text, pos, upper, last, loc); // We need one more character: the closing parenthesis or bracket. if (pos != std::size(text)) throw pqxx::conversion_error{err_bad_input(text), loc}; char const closing{text[pos - 1]}; if (closing != ')' and closing != ']') throw pqxx::conversion_error{err_bad_input(text), loc}; range_bound lower_bound{no_bound{}}, upper_bound{no_bound{}}; if (lower) { bool const left_inc{text[0] == '['}; if (left_inc) lower_bound = inclusive_bound{*lower}; else lower_bound = exclusive_bound{*lower}; } if (upper) { bool const right_inc{closing == ']'}; if (right_inc) upper_bound = inclusive_bound{*upper}; else upper_bound = exclusive_bound{*upper}; } return {lower_bound, upper_bound}; } [[nodiscard]] static inline constexpr std::size_t size_buffer(range const &value) noexcept { TYPE const *lower{value.lower_bound().value()}, *upper{value.upper_bound().value()}; std::size_t const lsz{ lower == nullptr ? 0 : pqxx::size_buffer(*lower) - 1}, usz{upper == nullptr ? 0 : pqxx::size_buffer(*upper) - 1}; if (value.empty()) return std::size(s_empty) + 1; else return 1 + lsz + 1 + usz + 2; } private: static constexpr zview s_empty{"empty"_zv}; static constexpr auto s_overrun{"Not enough space in buffer for range."_zv}; /// Compose error message for invalid range input. static std::string err_bad_input(std::string_view text) { return std::format("Invalid range input: '{}'.", text); } }; /// A range type does not have an innate null value. template struct nullness> final : no_null> {}; } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/result000066400000000000000000000010511516427024100170720ustar00rootroot00000000000000/** pqxx::result class and support classes. * * pqxx::result represents the set of result rows from a database query. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/result.hxx" // Now include some types which depend on result, but which the user will // expect to see defined after including this header. #include "pqxx/internal/result_iterator.hxx" #include "pqxx/field.hxx" #include "pqxx/internal/result_iter.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/result.hxx000066400000000000000000000530301516427024100177040ustar00rootroot00000000000000/* Definitions for the pqxx::result class and support classes. * * pqxx::result represents the set of result rows from a database query. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_RESULT_HXX #define PQXX_RESULT_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include #include #include #include #include #include "pqxx/except.hxx" #include "pqxx/types.hxx" #include "pqxx/util.hxx" #include "pqxx/zview.hxx" #include "pqxx/internal/encodings.hxx" namespace pqxx::internal { PQXX_LIBEXPORT void clear_result(pq::PGresult const *) noexcept; } // namespace pqxx::internal namespace pqxx::internal::gate { class result_connection; class result_creation; class result_field_ref; class result_pipeline; class result_row; class result_sql_cursor; } // namespace pqxx::internal::gate namespace pqxx::internal { // 9.0: Remove this, just use the notice handler in connection/result. /// Various callbacks waiting for a notice to come in. struct notice_waiters final { // NOLINTBEGIN(misc-non-private-member-variables-in-classes) std::function notice_handler; std::list errorhandlers; // NOLINTEND(misc-non-private-member-variables-in-classes) notice_waiters() = default; notice_waiters(notice_waiters const &) = delete; notice_waiters(notice_waiters &&) = delete; ~notice_waiters() = default; notice_waiters &operator=(notice_waiters const &) = delete; notice_waiters &operator=(notice_waiters &&) = delete; }; } // namespace pqxx::internal namespace pqxx { class row_ref; class field_ref; /// Result set containing data returned by a query or command. /** This behaves as a container (as defined by the C++ standard library) and * provides random access const iterators to iterate over its rows. You can * also access a row by indexing a `result R` by the row's zero-based * number: * * ```cxx * for (result::size_type i=0; i < std::size(R); ++i) Process(R[i]); * ``` * * Result sets in libpqxx are lightweight, reference-counted wrapper objects * which are relatively small and cheap to copy. Think of a result object as * a "smart pointer" to an underlying result set. * * @warning The result set that a result object points to is not thread-safe. * If you copy a result object, it still refers to the same underlying result * set. So never copy, destroy, query, or otherwise access a result while * another thread may be copying, destroying, querying, or otherwise accessing * the same result set--even if it is doing so through a different result * object! */ class PQXX_LIBEXPORT result final { public: using size_type = result_size_type; using difference_type = result_difference_type; using reference = row_ref; using const_iterator = const_result_iterator; using pointer = const_iterator; using iterator = const_iterator; using const_reverse_iterator = const_reverse_result_iterator; using reverse_iterator = const_reverse_iterator; result() noexcept = default; result(result const &rhs) noexcept = default; result(result &&rhs) noexcept = default; ~result() = default; /// Assign one result to another. /** Copying results is cheap: it copies only smart pointers, but the actual * data stays in the same place. */ result &operator=(result const &rhs) noexcept = default; /// Assign one result to another, invaliding the old one. result &operator=(result &&rhs) noexcept = default; /** * @name Comparisons * * @warning The meaning of these comparisons has changed in 8.0. The _old_ * comparisons went through the results' data (but not metadata!) and looked * for differences. This was fairly arbitrary and a potential performance * trap. * * A `result` is essentially a reference-counted pointer to a data structure * that we received from the database. When you copy a result (through * assignment or copy construction) you get a second reference to the same * underlying data structure. * * This can be important because efficient code will use all kinds of direct * references to that data: @ref row_ref, @ref field_ref, `std::string_vew`, * @ref zview, raw C-style string pointers. Those all stay valid even when * you copy your `result` and destroy the original, because all you really * did was replace one smart pointer with another. The actual data * structure underneath stays exactly where it was. * * (This may also help explain why we have @ref row and @ref field classes on * the one hand, and @ref row_ref, @ref field_ref, and iterators on the * other. @ref row and @ref field contain their own copy of the `result`. * Those other classes carry just a _pointer_ to the `result`.) * * The meaning of the `result` comparison operators is: _Do these two * `result` objects refer to the same underlying data structure?_ */ //@{ /// Compare two results for equality. [[nodiscard]] bool operator==(result const &rhs) const noexcept { return rhs.m_data == m_data; } /// Compare two results for inequality. [[nodiscard]] bool operator!=(result const &rhs) const noexcept { return not operator==(rhs); } //@} /** * @name Iteration * * A `result` acts like a container of rows. Each row in turn acts like a * container of fields. */ //@{ /// Iterate rows, reading them directly into a tuple of "TYPE...". /** Converts the fields to values of the given respective types. * * Use this only with a ranged "for" loop. The iteration produces * std::tuple which you can "unpack" to a series of `auto` * variables. */ template auto iter() const; [[nodiscard]] PQXX_PURE const_reverse_iterator rbegin() const noexcept; [[nodiscard]] PQXX_PURE const_reverse_iterator crbegin() const noexcept; [[nodiscard]] PQXX_PURE const_reverse_iterator rend() const noexcept; [[nodiscard]] PQXX_PURE const_reverse_iterator crend() const noexcept; [[nodiscard]] PQXX_PURE const_iterator begin() const noexcept; [[nodiscard]] PQXX_PURE const_iterator cbegin() const noexcept; [[nodiscard]] PQXX_PURE inline const_iterator end() const noexcept; [[nodiscard]] PQXX_PURE inline const_iterator cend() const noexcept; [[nodiscard]] PQXX_PURE row_ref front() const noexcept; [[nodiscard]] PQXX_PURE row_ref back() const noexcept; [[nodiscard]] PQXX_PURE size_type size() const noexcept; [[nodiscard]] PQXX_PURE bool empty() const noexcept; [[nodiscard]] PQXX_PURE size_type capacity() const noexcept { return size(); } //@} /// Exchange two `result` values in an exception-safe manner. /** If the swap fails, the two values will be exactly as they were before. * * The swap is not necessarily thread-safe. */ void swap(result &) noexcept; /// Index a result by number to get to a row. /** This returns a @ref row object. Generally you should not keep the row * around as a variable, but if you do, make sure that your variable is a * `row`, not a `row&`. * * If you are working in C++23 or better, the two-dimensional indexing * operator is likely to be more efficient. Otherwise, consider @ref at(). */ [[nodiscard]] PQXX_PURE row_ref operator[](size_type i) const noexcept; #if defined(PQXX_HAVE_MULTIDIM) /// Index a result by row number and column number to get to a field. [[nodiscard]] PQXX_PURE field_ref operator[](size_type row_num, row_size_type col_num) const noexcept; #endif // PQXX_HAVE_MULTIDIM /// Index a row by number, but check that the row number is valid. [[nodiscard]] row_ref at(size_type, sl = sl::current()) const; /// Index a field by row number and column number. [[nodiscard]] field_ref at(size_type, row_size_type, sl = sl::current()) const; /// Let go of the result's data. /** Use this if you need to deallocate the result data earlier than you can * destroy the `result` object itself. * * Multiple `result` objects can refer to the same set of underlying data. * The underlying data will be deallocated once all `result` objects that * refer to it are cleared or destroyed. */ void clear() noexcept { m_data.reset(); m_query = nullptr; } /** * @name Column information */ //@{ /// Number of columns in result. [[nodiscard]] PQXX_PURE row_size_type columns() const noexcept; /// Number of given column (throws exception if it doesn't exist). /** By default, as everywhere in PostgreSQL, upper-case letters in * identifiers get converted to lower-case, and of course special characters * such as quotes also cause problems. * * Therefore, if the column name may contain any upper-case letters that you * do not want lower-cased, or special characters, escape and quote it first: * `myresult.column_number(mytransaction.quote_name(name))`. */ [[nodiscard]] row_size_type column_number(zview name, sl = sl::current()) const; /// Name of column with this number (throws exception if it doesn't exist). [[nodiscard]] PQXX_RETURNS_NONNULL char const * column_name(row_size_type number, sl = sl::current()) const &; /// Server-side storage size for field of column's type, in bytes. /** Returns the size of the server's internal representation of the column's * data type. A negative value indicates the data type is variable-length. */ [[nodiscard]] int column_storage(row_size_type number, sl = sl::current()) const; /// Type modifier of the column with this number. /** The meaning of modifier values is type-specific; they typically indicate * precision or size limits. * * _Use this only if you know what you're doing._ Most applications do not * need it, and most types do not use modifiers. * * The value -1 indicates "no information available." * * @warning There is no check for errors, such as an invalid column number. */ [[nodiscard]] int column_type_modifier(row_size_type number) const noexcept; /// Return column's type, as an OID from the system catalogue. [[nodiscard]] oid column_type(row_size_type col_num, sl = sl::current()) const; /// Return column's type, as an OID from the system catalogue. /** By default, as everywhere in PostgreSQL, upper-case letters in * identifiers get converted to lower-case, and of course special characters * such as quotes also cause problems. * * Therefore, if the column name may contain any upper-case letters that you * do not want lower-cased, or special characters, escape and quote it first: * `myresult.column_type(mytransaction.quote_name(col_name))`. */ [[nodiscard]] oid column_type(zview col_name, sl loc = sl::current()) const { return column_type(column_number(col_name, loc)); } /// What table did this column come from? [[nodiscard]] oid column_table(row_size_type col_num, sl = sl::current()) const; /// What table did this column come from? /** By default, as everywhere in PostgreSQL, upper-case letters in * identifiers get converted to lower-case, and of course special characters * such as quotes also cause problems. * * Therefore, if the column name may contain any upper-case letters that you * do not want lower-cased, or special characters, escape and quote it first: * `myresult.column_table(mytransaction.quote_name(name))`. */ [[nodiscard]] oid column_table(zview col_name, sl loc = sl::current()) const { return column_table(column_number(col_name, loc), loc); } /// What column in its table did this column come from? [[nodiscard]] row_size_type table_column(row_size_type col_num, sl = sl::current()) const; /// What column in its table did this column come from? /** By default, as everywhere in PostgreSQL, upper-case letters in * identifiers get converted to lower-case, and of course special characters * such as quotes also cause problems. * * Therefore, if the column name may contain any upper-case letters that you * do not want lower-cased, or special characters, escape and quote it first: * `myresult.table_column(mytransaction.quote_name(col_name))`. */ [[nodiscard]] row_size_type table_column(zview col_name, sl loc = sl::current()) const { return table_column(column_number(col_name), loc); } //@} /// Query that produced this result, if available (empty string otherwise) [[nodiscard]] PQXX_PURE std::string const &query() const & noexcept; /// If command was an `INSERT` of 1 row, return oid of the inserted row. /** @return Identifier of inserted row if exactly one row was inserted, or * @ref oid_none otherwise. */ [[nodiscard]] PQXX_PURE oid inserted_oid(sl = sl::current()) const; /// Number of rows affected by the SQL command whose result this is. /** Returns the number of rows affected _if_ the command was a `SELECT`, * `CREATE TABLE AS`, `INSERT`, `UPDATE`, `DELETE`, `MERGE`, `MOVE`, `FETCH`, * or `COPY`; or an `EXECUTE` or a parameterised or prepared statement that * did an `INSERT`, `UPDATE`, `DELETE`, or `MERGE`. * * Otherwise, returns zero. */ [[nodiscard]] PQXX_PURE size_type affected_rows() const; /// Run `func` on each row, passing the row's fields as parameters. /** Goes through the rows from first to last. You provide a callable `func`. * * For each row in the `result`, `for_each` will call `func`. It converts * the row's fields to the types of `func`'s parameters, and pass them to * `func`. * * (Therefore `func` must have a _single_ signature. It can't be a generic * lambda, or an object of a class with multiple overloaded function call * operators. Otherwise, `for_each` will have no way to detect a parameter * list without ambiguity.) * * If any of your parameter types is `std::string_view`, it refers to the * underlying storage of this `result`. * * If any of your parameter types is a reference type, its argument will * refer to a temporary value which only lives for the duration of that * single invocation to `func`. If the reference is an lvalue reference, it * must be `const`. * * For example, this queries employee names and salaries from the database * and prints how much each would like to earn instead: * ```cxx * tx.exec("SELECT name, salary FROM employee").for_each( * [](std::string_view name, float salary){ * std::cout << name << " would like " << salary * 2 << ".\n"; * }) * ``` * * If `func` throws an exception, processing stops at that point and * propagates the exception. * * @throws pqxx::usage_error if `func`'s number of parameters does not match * the number of columns in this result. * * The parameter types must have conversions from PostgreSQL's string format * defined; see @ref datatypes. */ template inline void for_each(CALLABLE &&func, sl = sl::current()) const; // NOLINTBEGIN(modernize-use-nodiscard) /// Check that result contains exactly `n` rows. /** @return The result itself, for convenience. * @throw @ref unexpected_rows if the actual count is not equal to `n`. */ result const &expect_rows(size_type n, sl loc = sl::current()) const { auto const sz{size()}; if (sz != n) { // TODO: See whether result contains a generated statement. if (not m_query or m_query->empty()) throw unexpected_rows{ std::format("Expected {} row(s) from query, got {}.", n, sz), loc}; else throw unexpected_rows{ std::format( "Expected {} row(s) from query '{}', got {}.", n, *m_query, sz), loc}; } return *this; } /// Check that result contains exactly 1 row, and return that row. /** A @ref row is less efficient than a @ref row_ref, but will ensure that * the underlying result data stays valid for as long as the @ref row object * exists. * * @throw @ref unexpected_rows if the actual count is not equal to `n`. */ row one_row(sl = sl::current()) const; /// Check that result contains exactly 1 row, and return a reference to it. /** You must ensure that the @ref result object stays valid, and does not * move, whenever you access the row. * * @throw @ref unexpected_rows if the actual count is not equal to `n`. */ row_ref one_row_ref(sl = sl::current()) const; /// Expect that result contains at most one row, and return as optional. /** Returns an empty `std::optional` if the result is empty, or if it has * exactly one row, a `std::optional` containing the row. * * @throw @ref unexpected_rows is the row count is not 0 or 1. */ std::optional opt_row(sl = sl::current()) const; /// Expect that result contains at most one row, and return as optional. /** Returns an empty `std::optional` if the result is empty, or if it has * exactly one row, a `std::optional` containing the row. * * @throw @ref unexpected_rows is the row count is not 0 or 1. */ std::optional opt_row_ref(sl = sl::current()) const; /// Expect that result contains no rows. Return result for convenience. result const &no_rows(sl loc = sl::current()) const { expect_rows(0, loc); return *this; } /// Expect that result consists of exactly `cols` columns. /** @return The result itself, for convenience. * @throw @ref usage_error otherwise. */ result const & expect_columns(row_size_type cols, sl loc = sl::current()) const { auto const actual{columns()}; if (actual != cols) { // TODO: See whether result contains a generated statement. if (not m_query or m_query->empty()) throw usage_error{ std::format( "Expected {} column(s) from query, got {}.", cols, actual), loc}; else throw usage_error{ std::format( "Expected {} column(s) from query '{}', got {}.", cols, *m_query, actual), loc}; } return *this; } /// Expect that result consists of exactly 1 row and 1 column; return it. /** A @ref field is less efficient than a @ref field_ref, but will ensure * that the underlying result data stays valid for as long as the @ref field * object exists. * * @throw @ref usage_error otherwise. */ field one_field(sl = sl::current()) const; /// Expect that result consists of exactly 1 row and 1 column; return it. /** You must ensure that the @ref result object stays valid, and does not * move, whenever you access the row. * * @throw @ref usage_error otherwise. */ field_ref one_field_ref(sl = sl::current()) const; // NOLINTEND(modernize-use-nodiscard) /// Retrieve encoding group for this result's client encoding. [[nodiscard]] encoding_group get_encoding_group() const noexcept { return m_encoding; } private: using data_pointer = std::shared_ptr; /// Check that there's exactly row of data, or throw @ref unexpected_rows. void check_one_row(sl loc) const { auto const sz{size()}; if (sz != 1) { if (not m_query or m_query->empty()) throw unexpected_rows{ std::format("Expected 1 row from query, got {}.", sz), loc}; else throw unexpected_rows{ std::format("Expected 1 row from query '{}', got {}.", *m_query, sz), loc}; } } /// Underlying libpq result set. data_pointer m_data; friend class pqxx::internal::gate::result_pipeline; PQXX_PURE [[nodiscard]] std::shared_ptr query_ptr() const noexcept { return m_query; } // TODO: Could we colocate some members in a single struct? /// Query string. std::shared_ptr m_query; /// The connection's notice handler. /** We're not actually using this, but we need a copy here so that the * actual function does not get deallocated if the connection is destroyed * while this result still exists. */ std::shared_ptr m_notice_waiters; encoding_group m_encoding = encoding_group::unknown; static std::string const s_empty_string; friend class pqxx::internal::gate::result_field_ref; PQXX_PURE PQXX_RETURNS_NONNULL [[nodiscard]] char const * get_value(size_type row, row_size_type col) const noexcept; PQXX_PURE [[nodiscard]] bool get_is_null(size_type row, row_size_type col) const noexcept; PQXX_PURE [[nodiscard]] field_size_type get_length(size_type, row_size_type) const noexcept; friend class pqxx::internal::gate::result_creation; result( std::shared_ptr const &rhs, std::shared_ptr const &query, std::shared_ptr const &waiters, encoding_group enc); PQXX_PRIVATE void check_status(std::string_view desc, sl loc) const; friend class pqxx::internal::gate::result_connection; friend class pqxx::internal::gate::result_row; bool operator!() const noexcept { return m_data.get() == nullptr; } // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions) operator bool() const noexcept { return m_data.get() != nullptr; } [[noreturn]] PQXX_COLD PQXX_PRIVATE void throw_sql_error(std::string const &Err, std::string const &Query, sl) const; PQXX_PURE PQXX_PRIVATE [[nodiscard]] int errorposition() const; PQXX_PRIVATE [[nodiscard]] std::string status_error(sl) const; friend class pqxx::internal::gate::result_sql_cursor; PQXX_PURE [[nodiscard]] char const *cmd_status() const noexcept; }; } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/robusttransaction000066400000000000000000000004631516427024100213460ustar00rootroot00000000000000/** pqxx::robusttransaction class. * * pqxx::robusttransaction is a slower but safer transaction class. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/robusttransaction.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/robusttransaction.hxx000066400000000000000000000105121516427024100221500ustar00rootroot00000000000000/* Definition of the pqxx::robusttransaction class. * * pqxx::robusttransaction is a slower but safer transaction class. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/robusttransaction instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_ROBUSTTRANSACTION_HXX #define PQXX_ROBUSTTRANSACTION_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include "pqxx/dbtransaction.hxx" namespace pqxx::internal { /// Helper base class for the @ref pqxx::robusttransaction class template. class PQXX_LIBEXPORT PQXX_NOVTABLE basic_robusttransaction : public dbtransaction { public: basic_robusttransaction(basic_robusttransaction const &) = delete; basic_robusttransaction(basic_robusttransaction &&) = delete; ~basic_robusttransaction() override = 0; basic_robusttransaction &operator=(basic_robusttransaction const &) = delete; basic_robusttransaction &operator=(basic_robusttransaction &&) = delete; protected: basic_robusttransaction(connection &cx, zview begin_command, sl); private: using IDType = unsigned long; std::string m_conn_string; std::string m_xid; int m_backendpid = -1; void init(zview begin_command, sl); // @warning This function will become `final`. void do_commit(sl) override; }; } // namespace pqxx::internal namespace pqxx { /** * @ingroup transactions * * @{ */ /// Slightly slower, better-fortified version of transaction. /** Requires PostgreSQL 10 or better. * * robusttransaction is similar to transaction, but spends more time and effort * to deal with the hopefully rare case that the connection to the backend is * lost just while it's trying to commit. In such cases, the client does not * know whether the backend (on the other side of the broken connection) * managed to commit the transaction. * * When this happens, robusttransaction tries to reconnect to the database and * figure out what happened. * * This service level was made optional since you may not want to pay the * overhead where it is not necessary. Certainly the use of this class makes * no sense for local connections, or for transactions that read the database * but never modify it, or for noncritical database manipulations. * * Besides being slower, it's also more complex. Which means that in practice * a robusttransaction could actually fail more instead of less often than a * normal transaction. What robusttransaction tries to achieve is to give you * certainty, not just be more successful per se. */ template class robusttransaction final : public internal::basic_robusttransaction { public: /** Create robusttransaction of given name. * @param cx Connection inside which this robusttransaction should live. * @param tname optional human-readable name for this transaction. */ robusttransaction(connection &cx, std::string_view tname) : internal::basic_robusttransaction{ cx, pqxx::internal::begin_cmd, tname} {} /** Create robusttransaction of given name. * @param cx Connection inside which this robusttransaction should live. * @param tname optional human-readable name for this transaction. */ robusttransaction(connection &cx, std::string &&tname) : internal::basic_robusttransaction{ cx, pqxx::internal::begin_cmd, std::move(tname)} {} /** Create robusttransaction of given name. * @param cx Connection inside which this robusttransaction should live. */ explicit robusttransaction(connection &cx, sl loc = sl::current()) : internal::basic_robusttransaction{ cx, pqxx::internal::begin_cmd, loc} {} robusttransaction(robusttransaction const &) = delete; robusttransaction(robusttransaction &&) = delete; ~robusttransaction() noexcept override { close(sl::current()); } robusttransaction &operator=(robusttransaction const &) = delete; robusttransaction &operator=(robusttransaction &&) = delete; }; /** * @} */ } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/row000066400000000000000000000004301516427024100163630ustar00rootroot00000000000000/** pqxx::row class. * * pqxx::row refers to a row in a result. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/result.hxx" #include "pqxx/row.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/row.hxx000066400000000000000000001042271516427024100172020ustar00rootroot00000000000000/* Definitions for the pqxx::result class and support classes. * * pqxx::result represents the set of result rows from a database query. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_ROW_HXX #define PQXX_ROW_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include "pqxx/except.hxx" #include "pqxx/field.hxx" #include "pqxx/result.hxx" namespace pqxx::internal { template class result_iter; } // namespace pqxx::internal namespace pqxx::internal::gate { class row_ref_const_result_iterator; class row_ref_result; class row_ref_row; } // namespace pqxx::internal::gate namespace pqxx { class field_ref; /// Lightweight reference to one row in a result. /** Like @ref row, represents one row in a query result set. Unlike with * @ref row, however, for as long as you're using a `row_ref`, the @ref result * object to which it refers must... * 1. remain valid, i.e. you can't destroy it; * 2. and in the same place in memory, i.e. you can't move it; * 3. and keep the same value, i.e. you can't assign to it. * * When you use `row_ref`, it is your responsibility to ensure all that. * * A `row_ref` is one way of accessing the fields themselves. */ class PQXX_LIBEXPORT row_ref final { public: using size_type = row_size_type; using difference_type = row_difference_type; using const_iterator = const_row_iterator; using iterator = const_iterator; using reference = field_ref; using pointer = field_ref const *; using const_reverse_iterator = const_reverse_row_iterator; using reverse_iterator = const_reverse_iterator; row_ref() = default; row_ref(row_ref const &) = default; row_ref(row_ref &&) = default; row_ref(result const &res, result_size_type index) : m_result{&res}, m_index{index} {} ~row_ref() = default; row_ref &operator=(row_ref const &) noexcept = default; row_ref &operator=(row_ref &&) noexcept = default; /** * @name Comparison * * Equality between two @ref row_ref objects means that they both refer to * the same row in _the exact same @ref result object._ * * So, if you copy a @ref result, even though the two copies refer to the * exact same underlying data structure, a `row_ref` in the one will never be * equal to a `row_ref` in the other. * * ```cxx * void test_equality(pqxx::result const &r1) * { * pqxx::result const r2{r1}; * if (not r1.empty()) * { * assert(r1[0] == r1[0]); * assert(r2[0] != r1[0]); * } * } * ``` */ //@{ [[nodiscard]] PQXX_PURE bool operator==(row_ref const &rhs) const noexcept { return rhs.m_result == m_result and rhs.m_index == m_index; } [[nodiscard]] PQXX_PURE bool operator!=(row_ref const &rhs) const noexcept { return not operator==(rhs); } //@} [[nodiscard]] const_iterator cbegin() const noexcept; [[nodiscard]] const_iterator begin() const noexcept; [[nodiscard]] const_iterator end() const noexcept; [[nodiscard]] const_iterator cend() const noexcept; /** * @name Field access */ //@{ [[nodiscard]] reference front() const noexcept; [[nodiscard]] reference back() const noexcept; [[nodiscard]] const_reverse_row_iterator crbegin() const noexcept; [[nodiscard]] const_reverse_row_iterator rbegin() const noexcept; [[nodiscard]] const_reverse_row_iterator crend() const noexcept; [[nodiscard]] const_reverse_row_iterator rend() const noexcept; [[nodiscard]] PQXX_PURE reference operator[](size_type i) const noexcept { return {home(), row_number(), i}; } #if defined(PQXX_HAVE_MULTIDIM) // TODO: There's a proposal to permit a default value for loc. /** Address field by name. * * @warning This is much slower than indexing by number, or iterating. * * @warning This function is marked as "pure." This means that if it fails, * depending on your compiler, the exception may occur in a different place * than you expected. The compiler may even find scenarios where it can * avoid calling this operator, meaning that the exception does not happen at * all. If you need more deterministic exception behaviour, use @ref at(). */ [[nodiscard]] PQXX_PURE reference operator[](zview col_name, sl) const; #endif // PQXX_HAVE_MULTIDIM /** Address field by name. * @warning This is much slower than indexing by number, or iterating. * * @warning This function is marked as "pure." This means that if it fails, * depending on your compiler, the exception may occur in a different place * than you expected. The compiler may even find scenarios where it can * avoid calling this operator, meaning that the exception does not happen at * all. If you need more deterministic exception behaviour, use @ref at(). */ [[nodiscard]] PQXX_PURE reference operator[](zview col_name) const; /// Address a field by number, but check that the number is in range. [[nodiscard]] reference at(size_type i, sl loc = sl::current()) const { if (m_result == nullptr) throw usage_error{"Indexing uninitialised row.", loc}; if (std::cmp_less(i, 0)) throw usage_error{"Negative column index.", loc}; auto const sz{size()}; if (std::cmp_greater_equal(i, sz)) throw range_error{ std::format( "Column index out of range: {} in a result of {} column(s).", i, sz), loc}; return operator[](i); } /// Address field by name. /** @warning This is much slower than indexing by number, or iterating. * * This function could perhaps be marked as "pure," but in clang and some gcc * configurations this may move exceptions out of `try` blocks that are meant * to catch them. */ [[nodiscard]] reference at(zview col_name, sl loc = sl::current()) const { if (m_result == nullptr) throw usage_error{"Indexing uninitialised row.", loc}; return operator[](column_number(col_name, loc)); } [[nodiscard]] PQXX_PURE size_type size() const noexcept { return home().columns(); } /// Row number, assuming this is a real row and not end()/rend(). [[nodiscard]] PQXX_PURE constexpr result::size_type row_number() const noexcept { return m_index; } /** * @name Column information */ //@{ /// Number of given column (throws exception if it doesn't exist). /** This function could perhaps be marked as "pure," but in clang and some * gcc configurations this may move exceptions out of `try` blocks that are * meant to catch them. */ [[nodiscard]] size_type column_number(zview col_name, sl = sl::current()) const; /// Return a column's type. /** This function could perhaps be marked as "pure," but in clang and some * gcc configurations this may move exceptions out of `try` blocks that are * meant to catch them. */ [[nodiscard]] oid column_type(size_type col_num, sl loc = sl::current()) const { return home().column_type(col_num, loc); } /// Return a column's type. /** This function could perhaps be marked as "pure," but in clang and some * gcc configurations this may move exceptions out of `try` blocks that are * meant to catch them. */ [[nodiscard]] oid column_type(zview col_name, sl loc = sl::current()) const { return column_type(column_number(col_name, loc), loc); } /// What table did this column come from? /** This function could perhaps be marked as "pure," but in clang and some * gcc configurations this may move exceptions out of `try` blocks that are * meant to catch them. */ [[nodiscard]] oid column_table(size_type col_num, sl = sl::current()) const; /// What table did this column come from? /** This function could perhaps be marked as "pure," but in clang and some * gcc configurations this may move exceptions out of `try` blocks that are * meant to catch them. */ [[nodiscard]] oid column_table(zview col_name, sl loc = sl::current()) const { return column_table(column_number(col_name, loc), loc); } /// What column number in its table did this result column come from? /** A meaningful answer can be given only if the column in question comes * directly from a column in a table. If the column is computed in any * other way, a logic_error will be thrown. * * @param col_num a zero-based column number in this result set * @return a zero-based column number in originating table */ [[nodiscard]] size_type table_column(size_type col_num, sl loc = sl::current()) const { return home().table_column(col_num, loc); } /// What column number in its table did this result column come from? [[nodiscard]] size_type table_column(zview col_name, sl loc = sl::current()) const { return table_column(column_number(col_name, loc), loc); } //@} /// Extract entire row's values into a tuple. /** Converts to the types of the tuple's respective fields. * * The types in the tuple must have conversions from PostgreSQL's text format * defined; see @ref datatypes. * * @throw usage_error If the number of columns in the row does not match * the number of fields in `t`. */ template void to(Tuple &t, sl loc = sl::current()) const { check_size(std::tuple_size_v, loc); convert(t, loc); } /// Extract entire row's values into a tuple. /** Converts to the types of the tuple's respective fields. * * The types must have conversions from PostgreSQL's text format defined; * see @ref datatypes. * * @throw usage_error If the number of columns in the row does not match * the number of fields in `t`. */ template [[nodiscard]] std::tuple as(sl loc = sl::current()) const { return as_tuple>(loc); } /// Convert to a given tuple of values, /** Useful in cases where we have a full tuple of field types, but * not a parameter pack. * * `TUPLE` should be a tuple type, with the same number of elements as the * result has columns. * * @throw usage_error If the number of columns in the `row` does not match * the number of fields in `TUPLE`. */ template [[nodiscard]] TUPLE as_tuple(sl loc = sl::current()) const requires(requires(TUPLE t) { std::get<0>(t); }) { check_size(std::tuple_size_v, loc); using seq = std::make_index_sequence>; return get_tuple(seq{}, loc); } /// The @ref result object to which this `row_ref` refers. [[nodiscard]] PQXX_PURE result const &home() const noexcept { return *m_result; } private: friend class pqxx::internal::gate::row_ref_const_result_iterator; friend class pqxx::internal::gate::row_ref_result; /// Move to another row (positive for forwards, negative for backwards). void offset(difference_type d) noexcept { m_index += d; } /// Throw @ref usage_error if row size is not `expected`. void check_size(size_type expected, sl loc) const { if (size() != expected) throw usage_error{ std::format( "Tried to extract {} field(s) from a row of {}.", expected, size()), loc}; } template friend class pqxx::internal::result_iter; /// Convert entire row to tuple fields, without checking row size. template void convert(Tuple &t, sl loc) const { extract_fields( t, std::make_index_sequence>{}, conversion_context{home().get_encoding_group(), loc}); } friend class pqxx::internal::gate::row_ref_row; template void extract_fields(Tuple &t, std::index_sequence, ctx c) const { (extract_value(t, c), ...); } template void extract_value(Tuple &t, ctx) const; /// Convert row's values as a new tuple. template [[nodiscard]] auto get_tuple(std::index_sequence, sl) const { return std::make_tuple(get_field()...); } /// Extract and convert a field. template [[nodiscard]] auto get_field() const { return (*this)[index].as>(); } /// Result set of which this is one row. result const *m_result = nullptr; /// Row number. /** * You'd expect this to be unsigned, but due to the way reverse iterators * are related to regular iterators, it must be allowed to underflow to -1. */ result::size_type m_index = -1; }; } // namespace pqxx #include "pqxx/internal/gates/row_ref-const_result_iterator.hxx" #include "pqxx/internal/gates/row_ref-row.hxx" namespace pqxx { /// Reference to one row in a result. /** A `row` is a reference to one particular row of data in a query result set * (represented by a @ref result object). * * This is like a @ref row_ref, except (as far as this class is concerned) it * is safe to destroy the @ref result object or move it to a different place in * memory. That's because unlike `row_ref`, a `row` contains its own copy of * the internal smart pointer referring to the actual data in memory. You do * pay a performance price for this, so prefer @ref row_ref where possible. * * A row also acts as a container, mapping column numbers or names to field * values: * * ```cxx * cout << row["date"].c_str() << ": " << row["name"].c_str() << endl; * ``` */ class PQXX_LIBEXPORT row final { public: // TODO: Set iterator nested types using std::iterator_traits. using size_type = row_size_type; using difference_type = row_difference_type; using reference = field_ref; using pointer = const_row_iterator; using const_iterator = const_row_iterator; using iterator = const_iterator; using const_reverse_iterator = const_reverse_row_iterator; using reverse_iterator = const_reverse_iterator; row() noexcept = default; row(row &&) noexcept = default; row(row const &) noexcept = default; explicit row(row_ref const &ref) : m_result{ref.home()}, m_index{ref.row_number()}, m_end{std::size(ref)} {} ~row() = default; row &operator=(row const &) noexcept = default; row &operator=(row &&) noexcept = default; /** * @name Comparison * * @warning The meaning of the comparison operators has changed in 8.0. The * _old_ behaviour was to go through all the data in the two rows (but not * the metadata) and look for differences. This was never fully specified. * * Equality between two @ref row objects means that they refer to the same * row in the same data structure that we originally received from the * database. So the two may have been created from different @ref result * objects, so long as those are both copies of (or the same as) the same * original @ref result that you received from the database. * * ```cxx * void test_row_equality(pqxx::result const &r1) * { * pqxx::result r2{r1}; * pqxx::row row1{r1[0]}, row2{r2}; * assert(row1 == row2); * } * ``` */ //@{ [[nodiscard]] PQXX_PURE bool operator==(row const &rhs) const noexcept { return rhs.m_result == m_result and rhs.m_index == m_index; } [[nodiscard]] PQXX_PURE bool operator!=(row const &rhs) const noexcept { return not operator==(rhs); } //@} /** * @name Iteration * * A row acts like a container of fields. */ //@{ [[nodiscard]] PQXX_PURE const_iterator begin() const noexcept; [[nodiscard]] PQXX_PURE const_iterator cbegin() const noexcept; [[nodiscard]] PQXX_PURE const_iterator end() const noexcept; [[nodiscard]] PQXX_PURE const_iterator cend() const noexcept; [[nodiscard]] PQXX_PURE const_reverse_row_iterator rbegin() const noexcept; [[nodiscard]] PQXX_PURE const_reverse_row_iterator crbegin() const noexcept; [[nodiscard]] PQXX_PURE const_reverse_row_iterator rend() const noexcept; [[nodiscard]] PQXX_PURE const_reverse_row_iterator crend() const noexcept; //@} /** * @name Field access */ //@{ [[nodiscard]] field_ref front() const noexcept; [[nodiscard]] field_ref back() const noexcept; //@} /** @warning This function is marked as "pure." This means that if it * fails, depending on your compiler, the exception may occur in a different * place than you expected. The compiler may even find scenarios where it * can avoid calling this operator, meaning that the exception does not * happen at all. If you need more deterministic exception behaviour, use * @ref at(). */ [[nodiscard]] PQXX_PURE field_ref operator[](size_type) const noexcept; #if defined(PQXX_HAVE_MULTIDIM) /** Address field by name. * @warning This is much slower than indexing by number, or iterating. * * @warning This function is marked as "pure." This means that if it fails, * depending on your compiler, the exception may occur in a different place * than you expected. The compiler may even find scenarios where it can * avoid calling this operator, meaning that the exception does not happen at * all. If you need more deterministic exception behaviour, use @ref at(). */ [[nodiscard]] PQXX_PURE field_ref operator[](zview col_name, sl loc) const { // TODO: There's a proposal to permit a default value for loc. // Visual Studio 2022 says it has multi-dimensional indexing, but issues a // bogus warning that this comma is a sequence operator and the first value // is meaningless. If that were true, well, row_ref has no operator[] that // takes just a source_location anyway so the call would have failed. // Clearly the warning is a lie. # if defined(_MSC_VER) # pragma warning(push) # pragma warning(disable : 4548) # endif return as_row_ref()[col_name, loc]; # if defined(_MSC_VER) # pragma warning(pop) # endif } #endif /** Address field by name. * @warning This is much slower than indexing by number, or iterating. * * @warning This function is marked as "pure." This means that if it fails, * depending on your compiler, the exception may occur in a different place * than you expected. The compiler may even find scenarios where it can * avoid calling this operator, meaning that the exception does not happen at * all. If you need more deterministic exception behaviour, use @ref at(). */ [[nodiscard]] PQXX_PURE field_ref operator[](zview col_name) const { return as_row_ref()[col_name]; } /// Address a field by number, but check that the number is in range. [[nodiscard]] field_ref at(size_type, sl = sl::current()) const; /** Address field by name. * @warning This is much slower than indexing by number, or iterating. */ [[nodiscard]] field_ref at(zview col_name, sl = sl::current()) const; [[nodiscard]] PQXX_PURE constexpr size_type size() const noexcept { return m_end; } /// Row number, assuming this is a real row and not end()/rend(). [[nodiscard, deprecated("Use row_number().")]] constexpr result::size_type rownumber() const noexcept { return m_index; } /// Row number, assuming this is a real row and not end()/rend(). [[nodiscard]] PQXX_PURE constexpr result::size_type row_number() const noexcept { return m_index; } /** * @name Column information */ //@{ /// Number of given column (throws exception if it doesn't exist). [[nodiscard]] size_type column_number(zview col_name, sl loc = sl::current()) const { return as_row_ref().column_number(col_name, loc); } /// Return a column's type. [[nodiscard]] oid column_type(size_type col_num, sl loc = sl::current()) const { return as_row_ref().column_type(col_num, loc); } /// Return a column's type. [[nodiscard]] oid column_type(zview col_name, sl loc = sl::current()) const { return column_type(column_number(col_name, loc), loc); } /// What table did this column come from? [[nodiscard]] oid column_table(size_type col_num, sl loc = sl::current()) const { return as_row_ref().column_table(col_num, loc); } /// What table did this column come from? [[nodiscard]] oid column_table(zview col_name, sl loc = sl::current()) const { return column_table(column_number(col_name, loc), loc); } /// What column number in its table did this result column come from? /** A meaningful answer can be given only if the column in question comes * directly from a column in a table. If the column is computed in any * other way, a logic_error will be thrown. * * @param col_num a zero-based column number in this result set * @return a zero-based column number in originating table */ [[nodiscard]] size_type table_column(size_type col, sl loc = sl::current()) const { return as_row_ref().table_column(col, loc); } /// What column number in its table did this result column come from? [[nodiscard]] size_type table_column(zview col_name, sl loc = sl::current()) const { return as_row_ref().table_column(col_name, loc); } //@} [[nodiscard]] PQXX_PURE constexpr result::size_type num() const noexcept { return row_number(); } /// Extract entire row's values into a tuple. /** Converts to the types of the tuple's respective fields. * * The types in the tuple must have conversions from PostgreSQL's text format * defined; see @ref datatypes. * * @throw usage_error If the number of columns in the row does not match * the number of fields in `t`. */ template void to(Tuple &t, sl loc = sl::current()) const { check_size(std::tuple_size_v, loc); convert(t, loc); } /// Extract entire row's values into a tuple. /** Converts to the types of the tuple's respective fields. * * The types must have conversions from PostgreSQL's text format defined; * see @ref datatypes. * * @throw usage_error If the number of columns in the row does not match * the number of fields in `t`. */ template [[nodiscard]] std::tuple as(sl loc = sl::current()) const { return as_row_ref().as(loc); } /// Convert to a given tuple of values, /** Useful in cases where we have a full tuple of field types, but * not a parameter pack. * * `TUPLE` should be a tuple type, with the same number of elements as the * result has columns. * * @throw usage_error If the number of columns in the `row` does not match * the number of fields in `TUPLE`. */ template [[nodiscard]] TUPLE as_tuple(sl loc = sl::current()) const requires(requires(TUPLE t) { std::get<0>(t); }) { return as_row_ref().as_tuple(loc); } [[deprecated("Swap iterators, not rows.")]] void swap(row &) noexcept; private: /// Return @ref row_ref for this row. /** @warning The @ref row_ref holds a reference to the @ref result object * _inside this `row` object._ So if you change that, the @ref row_ref * becomes invalid. */ [[nodiscard]] row_ref as_row_ref() const noexcept { return {m_result, row_number()}; } row(result r, result_size_type index, size_type cols) noexcept; /// Throw @ref usage_error if row size is not `expected`. void check_size(size_type expected, sl loc) const { if (size() != expected) throw usage_error{ std::format( "Tried to extract {} field(s) from a row of {}.", expected, size()), loc}; } /// The @ref pqxx::result of which this is a row. [[nodiscard]] result const &home() const { return m_result; } /// Convert entire row to tuple fields, without checking row size. template void convert(Tuple &t, sl loc) const { auto ref{as_row_ref()}; pqxx::internal::gate::row_ref_row{ref}.extract_fields( t, std::make_index_sequence>{}, conversion_context{home().get_encoding_group(), loc}); } // TODO: Define gate. friend class field; /// Result set of which this is one row. result m_result; /// Row number. /** * You'd expect this to be unsigned, but due to the way reverse iterators * are related to regular iterators, it must be allowed to underflow to -1. */ result::size_type m_index = 0; /// Number of columns in the row. size_type m_end = 0; }; /// Iterator for fields in a row. Use as row::const_iterator. /** @warning Do not destroy or move the @ref result object while you're * iterating it. It will invalidate all iterators on the entire result. They * will no longer refer to valid memory, and your application may crash, or * worse, read the wrong data. */ class PQXX_LIBEXPORT const_row_iterator { public: using iterator_category = std::random_access_iterator_tag; using value_type = field_ref const; using pointer = field_ref const *; using size_type = row_size_type; using difference_type = row_difference_type; using reference = field_ref; const_row_iterator() noexcept = default; const_row_iterator(row_ref const &t, row_size_type c) noexcept : m_field{t.home(), t.row_number(), c} {} explicit const_row_iterator(field_ref const &f) noexcept : m_field{f} {} const_row_iterator(const_row_iterator const &) noexcept = default; const_row_iterator(const_row_iterator &&) noexcept = default; ~const_row_iterator() = default; /// Current column number, if the iterator is pointing at a valid field. PQXX_PURE [[nodiscard]] size_type col() const noexcept { return m_field.column_number(); } /** * @name Dereferencing operators */ //@{ [[nodiscard]] PQXX_PURE PQXX_RETURNS_NONNULL constexpr pointer operator->() const noexcept { return &m_field; } [[nodiscard]] PQXX_PURE reference operator*() const noexcept { return m_field; } //@} /** * @name Manipulations */ //@{ const_row_iterator &operator=(const_row_iterator const &) noexcept = default; const_row_iterator &operator=(const_row_iterator &&) noexcept = default; const_row_iterator operator++(int) & noexcept; const_row_iterator &operator++() noexcept { pqxx::internal::gate::field_ref_const_row_iterator(m_field).offset(1); return *this; } const_row_iterator operator--(int) & noexcept; const_row_iterator &operator--() noexcept { pqxx::internal::gate::field_ref_const_row_iterator(m_field).offset(-1); return *this; } const_row_iterator &operator+=(difference_type n) noexcept { pqxx::internal::gate::field_ref_const_row_iterator(m_field).offset(n); return *this; } const_row_iterator &operator-=(difference_type n) noexcept { pqxx::internal::gate::field_ref_const_row_iterator(m_field).offset(-n); return *this; } //@} /** * @name Comparisons */ //@{ [[nodiscard]] bool operator==(const_row_iterator const &i) const noexcept { return col() == i.col(); } [[nodiscard]] bool operator!=(const_row_iterator const &i) const noexcept { return col() != i.col(); } [[nodiscard]] bool operator<(const_row_iterator const &i) const noexcept { return col() < i.col(); } [[nodiscard]] bool operator<=(const_row_iterator const &i) const noexcept { return col() <= i.col(); } [[nodiscard]] bool operator>(const_row_iterator const &i) const noexcept { return col() > i.col(); } [[nodiscard]] bool operator>=(const_row_iterator const &i) const noexcept { return col() >= i.col(); } //@} /** * @name Arithmetic operators */ //@{ [[nodiscard]] inline const_row_iterator operator+(difference_type) const noexcept; friend const_row_iterator operator+(difference_type, const_row_iterator const &) noexcept; [[nodiscard]] inline const_row_iterator operator-(difference_type) const noexcept; [[nodiscard]] inline difference_type operator-(const_row_iterator const &) const noexcept; [[nodiscard]] inline field_ref operator[](difference_type offset) const noexcept { return *(*this + offset); } //@} private: field_ref m_field; }; /// Reverse iterator for a row. Use as row::const_reverse_iterator. class PQXX_LIBEXPORT const_reverse_row_iterator final : private const_row_iterator { public: using super = const_row_iterator; using iterator_type = const_row_iterator; using iterator_type::difference_type; using iterator_type::iterator_category; using iterator_type::pointer; using value_type = iterator_type::value_type; using reference = iterator_type::reference; const_reverse_row_iterator() noexcept = default; const_reverse_row_iterator(const_reverse_row_iterator const &) noexcept = default; const_reverse_row_iterator(const_reverse_row_iterator &&) noexcept = default; explicit const_reverse_row_iterator(super const &rhs) noexcept : const_row_iterator{rhs} { super::operator--(); } ~const_reverse_row_iterator() = default; [[nodiscard]] PQXX_PURE iterator_type base() const noexcept; /** * @name Dereferencing operators */ //@{ using iterator_type::operator->; using iterator_type::operator*; //@} /** * @name Manipulations */ //@{ const_reverse_row_iterator & operator=(const_reverse_row_iterator const &r) noexcept = default; const_reverse_row_iterator & operator=(const_reverse_row_iterator &&r) noexcept = default; const_reverse_row_iterator operator++() noexcept { iterator_type::operator--(); return *this; } const_reverse_row_iterator operator++(int) & noexcept; const_reverse_row_iterator &operator--() noexcept { iterator_type::operator++(); return *this; } const_reverse_row_iterator operator--(int) &; const_reverse_row_iterator &operator+=(difference_type i) noexcept { iterator_type::operator-=(i); return *this; } const_reverse_row_iterator &operator-=(difference_type i) noexcept { iterator_type::operator+=(i); return *this; } //@} /** * @name Arithmetic operators */ //@{ [[nodiscard]] const_reverse_row_iterator operator+(difference_type i) const noexcept { return const_reverse_row_iterator{base() - i}; } [[nodiscard]] const_reverse_row_iterator operator-(difference_type i) noexcept { return const_reverse_row_iterator{base() + i}; } [[nodiscard]] difference_type operator-(const_reverse_row_iterator const &rhs) const noexcept { return rhs.const_row_iterator::operator-(*this); } [[nodiscard]] inline field_ref operator[](difference_type offset) const noexcept { return *(*this + offset); } //@} /** * @name Comparisons */ //@{ [[nodiscard]] bool operator==(const_reverse_row_iterator const &rhs) const noexcept { return iterator_type::operator==(rhs); } [[nodiscard]] bool operator!=(const_reverse_row_iterator const &rhs) const noexcept { return !operator==(rhs); } [[nodiscard]] bool operator<(const_reverse_row_iterator const &rhs) const noexcept { return iterator_type::operator>(rhs); } [[nodiscard]] bool operator<=(const_reverse_row_iterator const &rhs) const noexcept { return iterator_type::operator>=(rhs); } [[nodiscard]] bool operator>(const_reverse_row_iterator const &rhs) const noexcept { return iterator_type::operator<(rhs); } [[nodiscard]] bool operator>=(const_reverse_row_iterator const &rhs) const noexcept { return iterator_type::operator<=(rhs); } //@} }; const_row_iterator const_row_iterator::operator+(difference_type o) const noexcept { return { {m_field.home(), m_field.row_number()}, static_cast( static_cast(m_field.column_number()) + o)}; } inline const_row_iterator operator+( const_row_iterator::difference_type o, const_row_iterator const &i) noexcept { return i + o; } inline const_row_iterator const_row_iterator::operator-(difference_type o) const noexcept { return { {m_field.home(), m_field.row_number()}, static_cast( static_cast(m_field.column_number()) - o)}; } inline const_row_iterator::difference_type const_row_iterator::operator-(const_row_iterator const &i) const noexcept { return difference_type(m_field.column_number() - i.m_field.column_number()); } template inline void row_ref::extract_value(Tuple &t, ctx c) const { using field_type = std::remove_cvref_t(t))>; field_ref const f{*m_result, m_index, index}; std::get(t) = from_string(f, c); } inline row_ref::const_iterator row_ref::cbegin() const noexcept { return {{home(), row_number()}, 0}; } inline row_ref::const_iterator row_ref::begin() const noexcept { return cbegin(); } inline row_ref::const_iterator row_ref::cend() const noexcept { return {{home(), row_number()}, home().columns()}; } inline row_ref::const_iterator row_ref::end() const noexcept { return cend(); } inline row_ref::const_reverse_iterator row_ref::crbegin() const noexcept { return const_reverse_iterator{end()}; } inline row_ref::const_reverse_iterator row_ref::rbegin() const noexcept { return crbegin(); } inline row_ref::const_reverse_iterator row_ref::crend() const noexcept { return const_reverse_iterator{begin()}; } inline row_ref::const_reverse_iterator row_ref::rend() const noexcept { return crend(); } inline field_ref row_ref::front() const noexcept { return {home(), row_number(), 0}; } inline field_ref row_ref::back() const noexcept { return {home(), row_number(), home().columns() - 1}; } inline row_size_type row_ref::column_number(zview col_name, sl loc) const { return home().column_number(col_name, loc); } inline oid row_ref::column_table(row_size_type col_num, sl loc) const { return home().column_table(col_num, loc); } inline row::const_iterator row::cbegin() const noexcept { return as_row_ref().cbegin(); } inline row::const_iterator row::begin() const noexcept { return cbegin(); } inline row::const_iterator row::cend() const noexcept { return {{m_result, row_number()}, m_end}; } inline row::const_iterator row::end() const noexcept { return cend(); } inline row::const_reverse_iterator row::crbegin() const noexcept { return const_reverse_iterator{end()}; } inline row::const_reverse_iterator row::rbegin() const noexcept { return crbegin(); } inline row::const_reverse_iterator row::crend() const noexcept { return const_reverse_iterator{begin()}; } inline row::const_reverse_iterator row::rend() const noexcept { return crend(); } } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/separated_list000066400000000000000000000003641516427024100205650ustar00rootroot00000000000000/** Helper similar to Python's @c str.join(). */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/separated_list.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/separated_list.hxx000066400000000000000000000066041516427024100213760ustar00rootroot00000000000000/* Helper similar to Python's `str.join()`. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/separated_list instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_SEPARATED_LIST_HXX #define PQXX_SEPARATED_LIST_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include "pqxx/strconv.hxx" // TODO: Optimise buffer allocation using random_access_range/iterator. // C++23: Use std::ranges::views::join_with()? namespace pqxx { /** * @defgroup utility Utility functions */ //@{ /// Represent sequence of values as a string, joined by a given separator. /** * Use this to turn e.g. the numbers 1, 2, and 3 into a string "1, 2, 3". * * @param sep separator string (to be placed between items) * @param begin beginning of items sequence * @param end end of items sequence * @param access functor defining how to dereference sequence elements */ template [[nodiscard]] inline std::string separated_list( std::string_view sep, ITER begin, ITER end, ACCESS access, ctx c = {}) { if (end == begin) return {}; auto next{begin}; ++next; if (next == end) return to_string(access(begin), c); // From here on, we've got at least 2 elements -- meaning that we need sep. std::size_t budget{0}; for (ITER cnt{begin}; cnt != end; ++cnt) budget += pqxx::size_buffer(access(cnt)); budget += static_cast(std::distance(begin, end)) * std::size(sep); std::string result; result.resize(budget); char *const data{result.data()}; char *stop{data + budget}; std::size_t here{pqxx::into_buf({data, stop}, access(begin))}; for (++begin; begin != end; ++begin) { here = pqxx::internal::copy_chars(sep, result, here, sl::current()); here += pqxx::into_buf({data + here, stop}, access(begin)); } result.resize(here); return result; } /// Render sequence as a string, using given separator between items. template [[nodiscard]] inline std::string separated_list(std::string_view sep, ITER begin, ITER end, ctx c = {}) { return separated_list(sep, begin, end, [](ITER i) { return *i; }, c); } /// Render items in a container as a string, using given separator. template [[nodiscard]] inline std::string separated_list(std::string_view sep, CONTAINER &&con, ctx c = {}) { return separated_list(sep, std::begin(con), std::end(con), c); } /// Render items in a tuple as a string, using given separator. template [[nodiscard]] inline std::string separated_list( std::string_view sep, TUPLE const &t, ACCESS const &access, ctx c = {}) { std::string out{to_string(access(&std::get(t)), c)}; if constexpr (INDEX < std::tuple_size::value - 1) { out.append(sep); out.append(separated_list(sep, t, access, c)); } return out; } template [[nodiscard]] inline std::string separated_list(std::string_view sep, TUPLE const &t, ctx c = {}) { return separated_list(sep, t, [](TUPLE const &tup) { return *tup; }, c); } //@} } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/strconv000066400000000000000000000003421516427024100172540ustar00rootroot00000000000000/** String conversion definitions. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/strconv.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/strconv.hxx000066400000000000000000000725221516427024100200730ustar00rootroot00000000000000/* String conversion definitions. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stringconv instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_STRCONV_HXX #define PQXX_STRCONV_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include #include #include #include #include #include #include #include "pqxx/encoding_group.hxx" #include "pqxx/except.hxx" #include "pqxx/util.hxx" #include "pqxx/zview.hxx" namespace pqxx { /** * @defgroup stringconversion String conversion * * The PostgreSQL server accepts and represents data in string form. It has * its own formats for various data types. The string conversions define how * various C++ types translate to and from their respective PostgreSQL text * representations. * * Each conversion is defined by a specialisations of @c string_traits. It * gets complicated if you want top performance, but until you do, all you * really need to care about when converting values between C++ in-memory * representations such as @c int and the postgres string representations is * the @c pqxx::to_string and @c pqxx::from_string functions. * * If you need to convert a type which is not supported out of the box, you'll * need to define your own specialisations for these templates, similar to the * ones defined here and in `pqxx/conversions.hxx`. Any conversion code which * "sees" your specialisation will now support your conversion. In particular, * you'll be able to read result fields into a variable of the new type. */ //@{ // TODO: Drop `ENABLE` in 9.x. /// Traits describing a type's "null value," if any. /** Some C++ types have a special value or state which correspond directly to * SQL's NULL. * * The @c nullness traits describe whether it exists, and whether a particular * value is null. * * @warning The `ENABLE` parameter is deprecated. It exists to enable use of * `std::enable_if`. As of C++20, use `requires` or a concept instead. */ template struct nullness final { /// Does this type have a null value? static bool has_null; /// Is this type always null? /** This is only the case for a few types, such as `std::nullptr_t`. */ static constexpr bool always_null = false; /// Is @c value a null? PQXX_PURE static bool is_null(TYPE const &value); /// Return a null value. /** Don't use this in generic code to compare a value and see whether it is * null. Some types may have multiple null values which do not compare as * equal, or may define a null value which is not equal to anything including * itself, like in SQL. */ [[nodiscard]] PQXX_PURE static TYPE null(); }; /// Nullness traits describing a type which does not have a null value. template struct no_null { /// Does @c TYPE have a "built-in null value"? /** For example, a pointer can equal @c nullptr, which makes a very natural * representation of an SQL null value. For such types, the code sometimes * needs to make special allowances. * * for most types, such as @c int or @c std::string, there is no built-in * null. If you want to represent an SQL null value for such a type, you * would have to wrap it in something that does have a null value. For * example, you could use @c std::optional for "either an @c int or a * null value." */ static constexpr bool has_null = false; /// Are all values of this type null? /** There are a few special C++ types which are always null - mainly * @c std::nullptr_t. */ static constexpr bool always_null = false; /// Does a given value correspond to an SQL null value? /** Most C++ types, such as @c int or @c std::string, have no inherent null * value. But some types such as C-style string pointers do have a natural * equivalent to an SQL null. */ [[nodiscard]] PQXX_PURE static constexpr bool is_null(TYPE const &) noexcept { return false; } }; /// Nullness traits describing a type whose values are always null. /** If you're writing a `nullness` specialisation for such a type, you can * optionally derive it from this type to save yourself a bit of code. * * The second template parameter specifies a compile-time constant null value * of this type. */ template struct all_null { /// Does `TYPE` have a null value? static constexpr bool has_null = true; /// Is `TYPE` _always_ null? static constexpr bool always_null = true; /// Is the given `TYPE` value a null? [[nodiscard]] PQXX_PURE static constexpr bool is_null(TYPE const &) noexcept { return true; } /// Return a sample null value. Requires `TYPE` to be default-constructible. [[nodiscard]] PQXX_PURE static constexpr TYPE null() { return null_value; } }; /// Contextual parameters for string conversions implementations. /** These are some "extra" items that libpqxx may be able to pass to a string * conversion operation in order to provide it with extra information. * * Yes, these could simply have been extra parameters in the conversion API, * but that makes it harder to add new features (which existing conversions * can often safely ignore) without breaking compatibility. * * This type was introduced in libpqxx 8. The older conversion API does not * know about it, so older code will just have a default-constructed context. */ struct conversion_context final { // NOLINTBEGIN(misc-non-private-member-variables-in-classes) /// Encoding group describing the client text encoding. /** This will not tell you what the exact _encoding_ is. All libpqxx cares * about is how to parse text in a given encoding, so that it can reliably * detect escape characters, closing quotes, and so on. It has no need to * "understand" the text beyond that. */ encoding_group enc = encoding_group::unknown; /// A `std::source_location` for the call. /** When libpqxx throws an error, it will generally try to include this * information to help you debug the problem. However this is not always * possible. * * Generally it will be helpful to pass the location where the client called * into libpqxx. However if you don't pass a source location, this will use * the location in the source code where you created this `ctx`. */ sl loc = sl::current(); // NOLINTEND(misc-non-private-member-variables-in-classes) // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions) constexpr conversion_context(sl lc = sl::current()) : loc{lc} {} explicit constexpr conversion_context( encoding_group e, sl l = sl::current()) : enc{e}, loc{l} {} }; /// Convenience alias: `const` reference to a @ref pqxx::conversion_context. /** Because we need to squeeze this type into lots of function signatures, it * helps to have a very terse name for it. */ using ctx = conversion_context const &; /// Traits class for use in string conversions. /** Specialize this template for a type for which you wish to add to_string * and from_string support. * * String conversions are not meant to work for nulls. Check for null before * converting a value of @c TYPE to a string, or vice versa, and handle them * separately. */ template struct string_traits final { /// Estimate how much buffer space is needed to represent value as SQL text. /** The estimate may be a little pessimistic, if it saves time. */ [[nodiscard]] static inline std::size_t size_buffer(TYPE const &value) noexcept; /// Return a @c string_view representing `value` in SQL text. /** Produces a view on a PostgreSQL string representation for @c value. * * @warning A null value has no string representation. Do not pass a null. * * Uses `buf` to store string contents, _if needed._ The returned * `string view` may point somewhere inside that buffer, or to a * compile-time constant, or just directly to `value`. Even if the string * does live in `buf`, it may not start at the exact _beginning_ of `buf`. * * The resulting view stays valid for as long as both the buffer space to * which `buf` points, and `value`, remain accessible and unmodified. * * @throws pqxx::conversion_overrun if `buf` is not large enough. For * maximum performance, this is a conservative estimate. It may complain * about a buffer which is actually large enough for your value, if an exact * check would be too expensive. * * If there is no support for converting this type to an SQL string, simply * leave this function out of the struct. */ [[nodiscard]] static inline std::string_view to_buf(std::span buf, TYPE const &value, ctx = {}); /// Parse a string representation of a @c TYPE value. /** Throws @c conversion_error if @c value does not meet the expected format * for a value of this type. * * @warning A null value has no string representation. Do not parse a null. * * @warning If you convert a string to `std::string_view`, you're basically * just getting a pointer into the original buffer. So, the `string_view` * will become invalid when the original string's lifetime ends, or when it * gets overwritten. Do not access the `string_view` after that! * * If there is no support for converting from an SQL string to this type, * simply leave this function out of the struct. */ [[nodiscard]] static inline TYPE from_string(std::string_view text, ctx = {}); // TODO: Move is_unquoted_safe into the traits after all? }; // C++26: Use "=delete" with reason. /// String traits for a forbidden type conversion. /** If you have a C++ type for which you explicitly wish to forbid SQL * conversion, you can derive a @ref pqxx::string_traits specialisation for * that type from this struct. Any attempt to convert the type will then fail * to build, and produce an error referring to this type. It may help debug * build errors. */ template struct forbidden_conversion { [[noreturn]] static std::string_view to_buf(std::span, TYPE const &, ctx = {}) = delete; [[noreturn]] static TYPE from_string(std::string_view, ctx = {}) = delete; [[noreturn]] static std::size_t size_buffer(TYPE const &) noexcept = delete; }; /// You cannot convert a `char` to/from SQL. /** Converting this type may seem simple enough, but it's ambiguous: Did you * mean the `char` value as a small integer? If so, did you mean it to be * signed or unsigned? (The C++ Standard allows the system to implement `char` * as either a signed type or an unsigned type.) Or were you thinking of a * single-character string (and if so, using what encoding)? Or perhaps it's * just a raw byte value? * * If you meant it as an integer, use an appropriate integral type such as * `int` or `short` or `unsigned int` etc. * * If you wanted a single-character string, use `std::string_view` (or a * similar type such as `std::string`). * * Or if you had a raw byte in mind, try `pqxx::bytes_view` instead. */ template<> struct string_traits final : forbidden_conversion {}; /// You cannot convert an `unsigned char` to/from SQL. /** Converting this type may seem simple enough, but it's ambiguous: Did you * mean the `char` value as a small integer? Or were you thinking of a * single-character string (and if so, using what encoding)? Or perhaps it's * just a raw byte value? * * If you meant it as an integer, use an appropriate integral type such as * `int` or `short` or `unsigned int` etc. * * If you wanted a single-character string, use `std::string_view` (or a * similar type such as `std::string`). * * Or if you had a raw byte in mind, try `pqxx::bytes_view` instead. */ template<> struct string_traits final : forbidden_conversion {}; /// You cannot convert a `signed char` to/from SQL. /** Converting this type may seem simple enough, but it's ambiguous: Did you * mean the value as a small integer? Or were you thinking of a * single-character string (and if so, in what encoding)? Or perhaps it's just * a raw byte value? * * If you meant it as an integer, use an appropriate integral type such as * `int` or `short` etc. * * If you wanted a single-character string, use `std::string_view` (or a * similar type such as `std::string`). * * Or if you had a raw byte in mind, try `pqxx::bytes_view` instead. */ template<> struct string_traits final : forbidden_conversion {}; /// You cannot convert a `std::byte` to/from SQL. /** To convert a raw byte value, use a `bytes_view`. * * For example, to convert a byte `b` from C++ to SQL, convert the value * `pqxx::bytes_view{&b, 1}` instead. */ template<> struct string_traits final : forbidden_conversion {}; /// Nullness: Enums do not have an inherent null value. template struct nullness final : no_null {}; } // namespace pqxx namespace pqxx::internal { /// Signature for string_traits::to_buf() in libpqxx 7. template concept to_buf_7 = requires(zview out, char *begin, char *end, TYPE const &value) { out = string_traits::to_buf(begin, end, value); }; /// Signature for string_traits::to_buf() in libpqxx 8. template concept to_buf_8 = requires( std::string_view out, std::span buf, TYPE const &value, ctx c) { out = string_traits::to_buf(buf, value, c); out = string_traits::to_buf(buf, value); }; /// Signature for string_traits::from_string() in libpqxx 8. template concept from_string_8 = requires(std::string_view text, ctx c) { TYPE{string_traits::from_string(text, c)}; TYPE{string_traits::from_string(text)}; }; /// Signature for string_traits::from_string() in libpqxx 7. /** This is actually identical to the new format, except the latter accepts an * optional @ref conversion_context argument. */ template concept from_string_7 = requires(std::string_view text) { TYPE{string_traits::from_string(text)}; }; } // namespace pqxx::internal namespace pqxx { /// Estimate how much buffer space is needed to represent values as a string. /** The estimate may be a little pessimistic, if it saves time. */ template [[nodiscard]] inline constexpr std::size_t size_buffer(TYPE const &...value) noexcept { return (string_traits>::size_buffer(value) + ...); } /// Is the libpqxx 8 version of `to_buf()` supported for `TYPE`? /** The @ref pqxx::string_traits specialisation for `TYPE` must support either * the 7.x `to_buf` API or the 8.x one. * * The real reason this function exists is to make the compiler check for API * compliance... and if necessary, give a _helpful_ error message. For that, a * `requires` is better than a `static_assert()`. However, we can't use it in * the calling function's signature, since it requires a definition for the * relevant specialisation of @ref pqxx::string_traits _before_ the calling * function's. That complicates things. */ template requires(pqxx::internal::to_buf_7 or pqxx::internal::to_buf_8) consteval bool supports_to_buf_8() { return requires { requires pqxx::internal::to_buf_8; }; } /// Represent `value` as SQL text, optionally using `buf` as storage. /** This calls string_traits::to_buf(), but bridges some API version * differences. */ template [[nodiscard]] inline std::string_view to_buf(std::span buf, TYPE const &value, ctx c = {}) { using traits = string_traits; if constexpr (supports_to_buf_8()) { return traits::to_buf(buf, value, c); } else { auto const begin{std::data(buf)}, end{begin + std::size(buf)}; return traits::to_buf(begin, end, value); } } /// Write an SQL representation of `value` into `buf`. /** This calls @ref string_traits::to_buf(), but bridges some API version * differences. * * @return The number of SQL text bytes written into `buf`. There is no * terminating zero. */ template [[nodiscard]] inline std::size_t into_buf(std::span buf, TYPE const &value, ctx c = {}) { auto const data{std::data(buf)}; std::string_view out{to_buf(buf, value, c)}; auto const sz{std::size(out)}; // Be careful to use a memory "move," not a "copy." Source and destination // may overlap (or be identical). if (not std::empty(out)) [[likely]] { if (std::cmp_greater(std::size(out), std::size(buf))) throw conversion_overrun{ std::format( "Buffer too small to convert {} value to string (needs a {}-byte " "buffer).", name_type(), std::size(out)), c.loc}; std::memmove(data, std::data(out), sz); } return sz; } /// Is the libpqxx 8 version of `from_string()` supported for `TYPE`? /** The @ref pqxx::string_traits specialisation for `TYPE` must support either * the 7.x `to_buf` API or the 8.x one. */ template requires( pqxx::internal::from_string_7 or pqxx::internal::from_string_8) consteval bool supports_from_string_8() { return requires { requires pqxx::internal::from_string_8; }; } /// Parse a value in postgres' text format as a TYPE. /** If the form of the value found in the string does not match the expected * type, e.g. if a decimal point is found when converting to an integer type, * the conversion fails. Overflows (e.g. converting "9999999999" to a 16-bit * C++ type) are also treated as errors. If in some cases this behaviour * should be inappropriate, convert to something bigger such as @c long @c int * first and then truncate the resulting value. * * Only the simplest possible conversions are supported. Fancy features like * hexadecimal or octal, spurious signs, or exponent notation won't work. * Whitespace is not stripped away. Only the kinds of strings that come out of * PostgreSQL and out of to_string() can be converted. */ template [[nodiscard]] inline TYPE from_string(std::string_view text, ctx c = {}) { if constexpr (supports_from_string_8()) return string_traits::from_string(text, c); else return string_traits::from_string(text); } // clang-tidy rule bug: // NOLINTBEGIN(misc-unused-parameters) /// "Convert" a std::string_view to a std::string_view. /** Just returns its input. * * @warning Of course the result is only valid for as long as the original * string remains valid! Never access the string referenced by the return * value after the original has been destroyed. */ template<> [[nodiscard]] inline std::string_view from_string(std::string_view text, ctx) { return text; } // NOLINTEND(misc-unused-parameters) /// Attempt to convert postgres-generated string to given built-in object. /** This is like the single-argument form of the function, except instead of * returning the value, it sets @c value. * * You may find this more convenient in that it infers the type you want from * the argument you pass. But there are disadvantages: it requires an * assignment operator, and it may be less efficient. */ template inline void from_string(std::string_view text, T &value, ctx c = {}) { value = from_string(text, c); } /// Convert a value to a readable string that PostgreSQL will understand. /** The conversion does no special formatting, and ignores any locale settings. * The resulting string will be human-readable and in a format suitable for use * in SQL queries. It won't have niceties such as "thousands separators" * though. */ template inline std::string to_string(TYPE const &value, ctx c = {}); } // namespace pqxx namespace pqxx::internal { /// Helper class for defining enum conversions. /** The conversion will convert enum values to numeric strings, and vice versa. * * @warning These numeric strings do not actually help you with the database, * where enum values are textual strings. Once we have reflection in C++26, it * should become easier to provide real support. * * To define a string conversion for an enum type, derive a @c string_traits * specialisation for the enum from this struct. * * There's usually an easier way though: the @ref PQXX_DECLARE_ENUM_CONVERSION * macro. Use `enum_traits` manually only if you need to customise your * traits type in more detail. */ template struct enum_traits { using impl_type = std::underlying_type_t; [[nodiscard]] static constexpr std::string_view to_buf(std::span buf, ENUM const &value, ctx c = {}) { return pqxx::to_buf(buf, to_underlying(value), c); } [[nodiscard]] static ENUM from_string(std::string_view text, ctx c = {}) { return static_cast(pqxx::from_string(text, c)); } [[nodiscard]] static constexpr std::size_t size_buffer(ENUM const &value) noexcept { return pqxx::size_buffer(to_underlying(value)); } private: // C++23: Replace with std::to_underlying. static constexpr impl_type to_underlying(ENUM const &value) noexcept { return static_cast(value); } }; } // namespace pqxx::internal /// Macro: Define a string conversion for an enum type. /** This specialises the @ref pqxx::string_traits and @ref pqxx::name_type * templates, so use it in the @ref pqxx namespace. * * For example: * * #include * #include * enum X { xa, xb }; * namespace pqxx { PQXX_DECLARE_ENUM_CONVERSION(x); } * int main() { std::cout << pqxx::to_string(xa) << std::endl; } */ #define PQXX_DECLARE_ENUM_CONVERSION(ENUM) \ template<> \ [[maybe_unused, deprecated("Use name_type() instead of type_name.")]] \ constexpr inline std::string_view type_name{#ENUM}; \ template<> inline constexpr std::string_view name_type() noexcept \ { \ return #ENUM; \ } \ template<> \ struct string_traits final : pqxx::internal::enum_traits \ {} namespace pqxx { /// Convert multiple values to strings inside a single buffer. /** There must be enough room for all values, or this will throw * @c conversion_overrun. You can obtain a conservative estimate of the buffer * space required by calling @c size_buffer() on the values. * * The @c std::string_view results may point into the buffer, so don't assume * that they will remain valid after you destruct or move the buffer. */ template [[nodiscard, deprecated("Pass span and string_view.")]] inline std::vector to_buf(char *begin, char const *end, TYPE... value) { assert(begin <= end); // We can't construct the span as {begin, end} because end points to const. // Works fine on gcc 13, but clang 18 vomits huge cryptic errors. // clang-tidy rule bug: // NOLINTNEXTLINE(misc-const-correctness) std::span buf{ begin, check_cast( end - begin, "string_view too large.", sl::current())}; std::size_t here{0u}; return {[&here, buf](auto v) { auto start{here}; here += pqxx::into_buf(buf.subspan(start), v); assert(start < here); assert(here <= std::size(buf)); // C++26: Use buf.at(). assert(buf[here - 1] == '\0'); // Exclude the trailing zero out of the string_view. auto len{here - start - 1}; return std::string_view{std::data(buf) + start, len}; }(value)...}; } /// Convert multiple values to strings inside a single buffer. /** There must be enough room for all values, or this will throw * @c conversion_overrun. You can obtain a conservative estimate of the buffer * space required by calling @c size_buffer() on the values. * * The @c std::string_view results may point into the buffer, so don't assume * that they will remain valid after you destruct or move the buffer. */ template inline std::vector to_buf_multi(ctx c, std::span buf, TYPE... value) { // TODO: Would it be worth merging consecutive identical strings? std::size_t here{0u}; return {[&here, buf, &c](auto v) { auto start{here}; here += pqxx::into_buf(buf.subspan(start), v, c); assert(start < here); assert(here <= std::size(buf)); // C++26: Use buf.at(). auto const len{here - start}; return std::string_view{std::data(buf) + start, len}; }(value)...}; } /// Convert multiple values to strings inside a single buffer. /** There must be enough room for all values, or this will throw * @c conversion_overrun. You can obtain a conservative estimate of the buffer * space required by calling @c size_buffer() on the values. * * The @c std::string_view results may point into the buffer, so don't assume * that they will remain valid after you destruct or move the buffer. * * @warning This version of the function does not take a * @ref pqxx::conversion_context argument. Prefer the version that does take * one, and pass (insofar as possible) a @ref pqxx::encoding_group and a * `std::source_location`. */ template inline std::vector to_buf_multi(std::span buf, TYPE... value) { // TODO: Would it be worth merging consecutive identical strings? std::size_t here{0u}; conversion_context c{}; return {[&here, buf, &c](auto v) { auto start{here}; here += pqxx::into_buf(buf.subspan(start), v, c); assert(start < here); assert(here <= std::size(buf)); // C++26: Use buf.at(). auto const len{here - start}; return std::string_view{std::data(buf) + start, len}; }(value)...}; } /// Convert a value to a readable string that PostgreSQL will understand. /** This variant of to_string can sometimes save a bit of time in loops, by * re-using a std::string for multiple conversions. */ template inline void into_string(TYPE const &value, std::string &out); /// Does `TYPE` have one or more inherent null values? /** Some types, such as pointers, have natural null values built in. Most * types do not: an integer is never null (even if it may be zero), a C++ * string is never null (even if it may be empty), and so on. * * This is different from an SQL field _containing_ a null value, but in * libpqxx you can treat them pretty much the same. */ template [[nodiscard]] inline constexpr bool has_null() noexcept { using base_type = std::remove_cvref_t; return nullness::has_null; } /// Is a value of `TYPE` always null? /** This is the case for some special types, such as `std::nullopt_t`. */ template [[nodiscard]] inline constexpr bool always_null() noexcept { using base_type = std::remove_cvref_t; return nullness::always_null; } /// Is `value` a null? template [[nodiscard]] inline constexpr bool is_null(TYPE const &value) noexcept { using base_type = std::remove_cvref_t; if constexpr (always_null()) return true; else return nullness::is_null(value); } /// Return a null value of `TYPE`. /** Only available for types that _have_ a null value. * * There may be multiple null values, or even ones that look the same but * which don't compare as equal, as is the case in SQL. */ template [[nodiscard]] inline constexpr TYPE make_null() requires(pqxx::has_null()) { using base_type = std::remove_cvref_t; return nullness::null(); } /// Does this type translate to an SQL array? /** Specialisations may override this to be true for container types. * * This may not always be a black-and-white choice. For instance, a * @c std::string is a container, but normally it translates to an SQL string, * not an SQL array. */ template inline constexpr bool is_sql_array{false}; /// Can we use this type in arrays and composite types without quoting them? /** Define this as @c true only if values of @c TYPE can never contain any * special characters that might need escaping or confuse the parsing of array * or composite * types, such as commas, quotes, parentheses, braces, newlines, * and so on. * * When converting a value of such a type to a string in an array or a field in * a composite type, we do not need to add quotes, nor escape any special * characters. * * This is just an optimisation, so it defaults to @c false to err on the side * of slow correctness. */ template inline constexpr bool is_unquoted_safe{false}; /// Element separator between SQL array elements of this type. template inline constexpr char array_separator{','}; /// What's the preferred format for passing non-null parameters of this type? /** This affects how we pass parameters of @c TYPE when calling parameterised * statements or prepared statements. * * Generally we pass parameters in text format, but binary strings are the * exception. We also pass nulls in binary format, so this function need not * handle null values. */ template inline constexpr format param_format(TYPE const &) { return format::text; } //@} } // namespace pqxx #include "pqxx/internal/conversions.hxx" #endif libpqxx-8.0.1/include/pqxx/stream_from000066400000000000000000000004551516427024100201010ustar00rootroot00000000000000/** pqxx::stream_from class. * * pqxx::stream_from enables optimized batch reads from a database table. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/stream_from.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/stream_from.hxx000066400000000000000000000325441516427024100207130ustar00rootroot00000000000000/* Definition of the pqxx::stream_from class. * * pqxx::stream_from enables optimized batch reads from a database table. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_from instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_STREAM_FROM_HXX #define PQXX_STREAM_FROM_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include #include #include "pqxx/connection.hxx" #include "pqxx/encoding_group.hxx" #include "pqxx/except.hxx" #include "pqxx/internal/stream_iterator.hxx" #include "pqxx/separated_list.hxx" #include "pqxx/transaction_focus.hxx" namespace pqxx { class transaction_base; /// Pass this to a `stream_from` constructor to stream table contents. /** @deprecated Use @ref transaction_base::stream instead of stream_from. */ constexpr from_table_t from_table; /// Pass this to a `stream_from` constructor to stream query results. /** @deprecated Use transaction_base::stream instead of stream_from. */ constexpr from_query_t from_query; /// Stream data from the database. /** @deprecated Use @ref transaction_base::stream. * * For larger data sets, retrieving data this way is likely to be faster than * executing a query and then iterating and converting the rows fields. You * will also be able to start processing before all of the data has come in. * * There are also downsides. Not all kinds of query will work in a stream. * But straightforward `SELECT` and `UPDATE ... RETURNING` queries should work. * This function makes use of @ref pqxx::stream_from, which in turn uses * PostgreSQL's `COPY` command, so see the documentation for those to get the * full details. * * There are other downsides. If there stream encounters an error, it may * leave the entire connection in an unusable state, so you'll have to give the * whole thing up. Finally, opening a stream puts the connection in a special * state, so you won't be able to do many other things with the connection or * the transaction while the stream is open. * * There are two ways of starting a stream: you stream either all rows in a * table (using one of the factories, `table()` or `raw_table()`), or the * results of a query (using the `query()` factory). * * Usually you'll want the `stream` convenience wrapper in * @ref transaction_base, * so you don't need to deal with this class directly. * * @warning While a stream is active, you cannot execute queries, open a * pipeline, etc. on the same transaction. A transaction can have at most one * object of a type derived from @ref pqxx::transaction_focus active on it at a * time. */ class PQXX_LIBEXPORT stream_from final : transaction_focus { public: using raw_line = std::pair, std::size_t>; /// Factory: Execute query, and stream the results. /** The query can be a SELECT query or a VALUES query; or it can be an * UPDATE, INSERT, or DELETE with a RETURNING clause. * * The query is executed as part of a COPY statement, so there are additional * restrictions on what kind of query you can use here. See the PostgreSQL * documentation for the COPY command: * * https://www.postgresql.org/docs/current/sql-copy.html */ [[deprecated("Use transaction_base::stream instead.")]] static stream_from query(transaction_base &tx, std::string_view q) { #include "pqxx/internal/ignore-deprecated-pre.hxx" return {tx, from_query, q}; #include "pqxx/internal/ignore-deprecated-post.hxx" } /** * @name Streaming data from tables * * You can use `stream_from` to read a table's contents. This is a quick * and easy way to read a table, but it comes with limitations. It cannot * stream from a view, only from a table. It does not support conditions. * And there are no guarantees about ordering. If you need any of those * things, consider streaming from a query instead. */ //@{ /// Factory: Stream data from a pre-quoted table and columns. /** Use this factory if you need to create multiple streams using the same * table path and/or columns list, and you want to save a bit of work on * composing the internal SQL statement for starting the stream. It lets you * compose the string representations for the table path and the columns * list, so you can compute these once and then re-use them later. * * @param tx The transaction within which the stream will operate. * @param path Name or path for the table upon which the stream will * operate. If any part of the table path may contain special * characters or be case-sensitive, quote the path using * pqxx::connection::quote_table(). * @param columns Columns which the stream will read. They should be * comma-separated and, if needed, quoted. You can produce the string * using pqxx::connection::quote_columns(). If you omit this argument, * the stream will read all columns in the table, in schema order. */ [[deprecated("Use transaction_base::stream instead.")]] static stream_from raw_table( transaction_base &tx, std::string_view path, std::string_view columns = ""sv); /// Factory: Stream data from a given table. /** This is the convenient way to stream from a table. */ [[deprecated("Use transaction_base::stream instead.")]] static stream_from table( transaction_base &tx, table_path path, std::initializer_list columns = {}); //@} /// Execute query, and stream over the results. /** @deprecated Use factory function @ref query instead. */ [[deprecated("Use transaction_base::stream instead.")]] stream_from( transaction_base &, from_query_t, std::string_view query); /// Stream all rows in table, all columns. /** @deprecated Use factories @ref table or @ref raw_table instead. */ [[deprecated("Use transaction_base::stream instead.")]] stream_from( transaction_base &, from_table_t, std::string_view table); /// Stream given columns from all rows in table. /** @deprecated Use factories @ref table or @ref raw_table instead. */ template [[deprecated("Use transaction_base::stream instead.")]] stream_from( transaction_base &, from_table_t, std::string_view table, Iter columns_begin, Iter columns_end); /// Stream given columns from all rows in table. /** @deprecated Use factory function @ref query instead. */ template [[deprecated("Use transaction_base::stream() instead.")]] stream_from( transaction_base &tx, from_table_t, std::string_view table, Columns const &columns); #include "pqxx/internal/ignore-deprecated-pre.hxx" /// @deprecated Use factories @ref table or @ref raw_table instead. [[deprecated("Use transaction_base::stream instead.")]] stream_from( transaction_base &tx, std::string_view table) : stream_from{tx, from_table, table} {} #include "pqxx/internal/ignore-deprecated-post.hxx" /// @deprecated Use factories @ref table or @ref raw_table instead. template [[deprecated("Use transaction_base::stream instead.")]] stream_from( transaction_base &tx, std::string_view table, Columns const &columns) : stream_from{tx, from_table, table, columns} {} /// @deprecated Use factories @ref table or @ref raw_table instead. template [[deprecated("Use transaction_base::stream instead.")]] stream_from( transaction_base &, std::string_view table, Iter columns_begin, Iter columns_end); stream_from(stream_from const &) = delete; stream_from(stream_from &&) = delete; ~stream_from() noexcept; stream_from &operator=(stream_from const &) = delete; stream_from &operator=(stream_from &&) = delete; // NOLINTBEGIN(google-explicit-constructor,hicpp-explicit-conversions) // LCOV_EXCL_START /// May this stream still produce more data? [[nodiscard]] constexpr operator bool() const noexcept { return not m_finished; } // LCOV_EXCL_STOP // NOLINTEND(google-explicit-constructor,hicpp-explicit-conversions) /// Has this stream produced all the data it is going to produce? [[nodiscard]] constexpr bool operator!() const noexcept { return m_finished; } /// Finish this stream. Call this before continuing to use the connection. /** Consumes all remaining lines, and closes the stream. * * This may take a while if you're abandoning the stream before it's done, so * skip it in error scenarios where you're not planning to use the connection * again afterwards. */ void complete(sl = sl::current()); /// Read one row into a tuple. /** Converts the row's fields into the fields making up the tuple. * * For a column which can contain nulls, be sure to give the corresponding * tuple field a type which can be null. For example, to read a field as * `int` when it may contain nulls, read it as `std::optional`. * Using `std::shared_ptr` or `std::unique_ptr` will also work. */ template stream_from &operator>>(Tuple &); /// Doing this with a `std::variant` is going to be horrifically borked. template stream_from &operator>>(std::variant &) = delete; /// Iterate over this stream. Supports range-based "for" loops. /** Produces an input iterator over the stream. * * Do not call this yourself. Use it like "for (auto data : stream.iter())". */ template [[nodiscard]] auto iter() & { return pqxx::internal::stream_input_iteration{*this}; } /// Read a row. Return fields as views, valid until you read the next row. /** Returns `nullptr` when there are no more rows to read. Do not attempt * to read any further rows after that. * * Do not access the vector, or the storage referenced by the views, after * closing or completing the stream, or after attempting to read a next row. * * If any of the views' data pointer is null, that means that the * corresponding SQL field is null. * * @warning The return type may change in the future, to support C++20 * coroutine-based usage. */ std::vector const *read_row(sl loc = sl::current()) &; /// Read a raw line of text from the COPY command. /** @warning Do not use this unless you really know what you're doing. */ raw_line get_raw_line(sl); private: // TODO: Clean up this signature once we cull the deprecated constructors. /// @deprecated stream_from( transaction_base &tx, std::string_view table, std::string_view columns, from_table_t); // TODO: Clean up this signature once we cull the deprecated constructors. /// @deprecated stream_from( transaction_base &, std::string_view unquoted_table, std::string_view columns, from_table_t, int); template void extract_fields(Tuple &t, std::index_sequence, sl loc) const { (extract_value(t, loc), ...); } pqxx::internal::char_finder_func *m_char_finder; /// Current row's fields' text, combined into one reusable string. std::string m_row; /// The current row's fields. std::vector m_fields; bool m_finished = false; void close(); template void extract_value(Tuple &, sl loc) const; /// Read a line of COPY data, write `m_row` and `m_fields`. void parse_line(sl); }; template inline stream_from::stream_from( transaction_base &tx, from_table_t, std::string_view table_name, Columns const &columns) : stream_from{ tx, from_table, table_name, std::begin(columns), std::end(columns)} {} template inline stream_from::stream_from( transaction_base &tx, from_table_t, std::string_view table, Iter columns_begin, Iter columns_end) : stream_from{ tx, table, separated_list(",", columns_begin, columns_end), from_table, 1} {} template inline stream_from &stream_from::operator>>(Tuple &t) { sl const loc{sl::current()}; if (m_finished) [[unlikely]] return *this; static constexpr auto tup_size{std::tuple_size_v}; m_fields.reserve(tup_size); parse_line(loc); if (m_finished) [[unlikely]] return *this; if (std::size(m_fields) != tup_size) throw usage_error{std::format( "Tried to extract {} field(s) from a stream of {}.", tup_size, std::size(m_fields))}; extract_fields(t, std::make_index_sequence{}, loc); return *this; } template inline void stream_from::extract_value(Tuple &t, sl loc) const { using field_type = std::remove_cvref_t(t))>; assert(index < std::size(m_fields)); if constexpr (always_null()) { if (std::data(m_fields[index]) != nullptr) throw conversion_error{"Streaming non-null value into null field.", loc}; } else if (std::data(m_fields[index]) == nullptr) { if constexpr (has_null()) std::get(t) = make_null(); else internal::throw_null_conversion(name_type(), loc); } else { // Don't ever try to convert a non-null value to nullptr_t! std::get(t) = from_string(m_fields[index]); } } } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/stream_to000066400000000000000000000004471516427024100175610ustar00rootroot00000000000000/** pqxx::stream_to class. * * pqxx::stream_to enables optimized batch updates to a database table. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/stream_to.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/stream_to.hxx000066400000000000000000000441001516427024100203610ustar00rootroot00000000000000/* Definition of the pqxx::stream_to class. * * pqxx::stream_to enables optimized batch updates to a database table. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_to.hxx instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_STREAM_TO_HXX #define PQXX_STREAM_TO_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include "pqxx/separated_list.hxx" #include "pqxx/transaction_base.hxx" namespace pqxx { /// Efficiently write data directly to a database table. /** If you wish to insert rows of data into a table, you can compose INSERT * statements and execute them. But it's slow and tedious, and you need to * worry about quoting and escaping the data. * * If you're just inserting a single row, it probably won't matter much. You * can use prepared or parameterised statements to take care of the escaping * for you. But if you're inserting large numbers of rows you will want * something better. * * Inserting rows one by one using INSERT statements involves a lot of * pointless overhead, especially when you are working with a remote database * server over the network. You may end up sending each row over the network * as a separate query, and waiting for a reply. Do it "in bulk" using * `stream_to`, and you may find that it goes many times faster. Sometimes * you gain orders of magnitude in speed. * * Here's how it works: you create a `stream_to` stream to start writing to * your table. You will probably want to specify the columns. Then, you * feed your data into the stream one row at a time. And finally, you call the * stream's @ref complete function to tell it to finalise the operation, wait * for completion, and check for errors. * * (You _must_ complete the stream before committing or aborting the * transaction. The connection is in a special state while the stream is * active, where it can't process commands, and can't commit or abort a * transaction.) * * So how do you feed a row of data into the stream? There's several ways, but * the preferred one is to call its @ref write_values. Pass the field values * as arguments. Doesn't matter what type they are, as long as libpqxx knows * how to convert them to PostgreSQL's text format: `int`, `std::string` or * `std:string_view`, `float` and `double`, `bool`... lots of basic types * are supported. If some of the values are null, feel free to use * `std::optional`, `std::shared_ptr`, or `std::unique_ptr`. * * The arguments' types don't even have to match the fields' SQL types. If you * want to insert an `int` into a `DECIMAL` column, that's your choice -- it * will produce a `DECIMAL` value which happens to be integral. Insert a * `float` into a `VARCHAR` column? That's fine, you'll get a string whose * contents happen to read like a number. And so on. You can even insert * different types of value in the same column on different rows. If you have * a code path where a particular field is always null, just insert `nullptr`. * * There is another way to insert rows: the `<<` ("shift-left") operator. * It's not as fast and it doesn't support variable arguments: each row must be * either a `std::tuple` or something iterable, such as a `std::vector`, or * anything else with a `begin()` and `end()`. * * @warning While a stream is active, you cannot execute queries, open a * pipeline, etc. on the same transaction. A transaction can have at most one * object of a type derived from @ref pqxx::transaction_focus active on it at a * time. */ class PQXX_LIBEXPORT stream_to final : transaction_focus { public: /// Create a `stream_to` writing to a named table and columns. /** Use this to stream data to a table, where the list of columns is known at * compile time. * * @param tx The transaction within which the stream will operate. * @param path A @ref table_path designating the target table. * @param columns Optionally, the columns to which the stream should write. * If you do not pass this, the stream will write to all columns in the * table, in schema order. */ static stream_to table( transaction_base &tx, table_path path, std::initializer_list columns = {}) { auto const &cx{tx.conn()}; return raw_table(tx, cx.quote_table(path), cx.quote_columns(columns)); } /// Create a `stream_to` writing to a named table and columns. /** Use this version to stream data to a table, when the list of columns is * not known at compile time. * * @param tx The transaction within which the stream will operate. * @param path A @ref table_path designating the target table. * @param columns The columns to which the stream should write. */ template static stream_to table(transaction_base &tx, table_path path, COLUMNS const &columns) { auto const &cx{tx.conn()}; return stream_to::raw_table( tx, cx.quote_table(path), tx.conn().quote_columns(columns)); } /// Create a `stream_to` writing to a named table and columns. /** Use this version to stream data to a table, when the list of columns is * not known at compile time. * * @param tx The transaction within which the stream will operate. * @param path A @ref table_path designating the target table. * @param columns The columns to which the stream should write. */ template static stream_to table(transaction_base &tx, std::string_view path, COLUMNS const &columns) { return stream_to::raw_table(tx, path, tx.conn().quote_columns(columns)); } /// Stream data to a pre-quoted table and columns. /** This factory can be useful when it's not convenient to provide the * columns list in the form of a `std::initializer_list`, or when the list * of columns is simply not known at compile time. * * Also use this if you need to create multiple streams using the same table * path and/or columns list, and you want to save a bit of work on composing * the internal SQL statement for starting the stream. It lets you compose * the string representations for the table path and the columns list, so you * can compute these once and then re-use them later. * * @param tx The transaction within which the stream will operate. * @param path Name or path for the table upon which the stream will * operate. If any part of the table path may contain special * characters or be case-sensitive, quote the path using * pqxx::connection::quote_table(). * @param columns Columns to which the stream will write. They should be * comma-separated and, if needed, quoted. You can produce the string * using pqxx::connection::quote_columns(). If you omit this argument, * the stream will write all columns in the table, in schema order. */ static stream_to raw_table( transaction_base &tx, std::string_view path, std::string_view columns = "", sl loc = sl::current()) { return {tx, path, columns, loc}; } stream_to(stream_to const &) = delete; // Some false positives from clang-tidy checks in this constructor. The // initial base-class move moves only the embedded base-class object, not the // individual member variables that fall outside the base class. // Also there's one deliberate invalidation step of the moved-from object, // which is also being flagged as a potential use-after-move. // NOLINTBEGIN(bugprone-use-after-move,hicpp-invalid-access-moved) stream_to(stream_to &&other) : // (This first step only moves the transaction_focus base-class // object.) transaction_focus{std::move(other)}, m_buffer{std::move(other.m_buffer)}, m_field_buf{std::move(other.m_field_buf)}, m_finder{other.m_finder}, m_created_loc{other.m_created_loc}, m_finished{other.m_finished} { other.m_finished = true; } // NOLINTEND(bugprone-use-after-move,hicpp-invalid-access-moved) ~stream_to() noexcept; stream_to &operator=(stream_to const &) = delete; stream_to &operator=(stream_to &&) = delete; // NOLINTBEGIN(google-explicit-constructor,hicpp-explicit-conversions) /// Does this stream still need to @ref complete()? [[nodiscard]] constexpr operator bool() const noexcept { return not m_finished; } // NOLINTEND(google-explicit-constructor,hicpp-explicit-conversions) /// Has this stream been through its concluding @c complete()? [[nodiscard]] constexpr bool operator!() const noexcept { return m_finished; } /// Complete the operation, and check for errors. /** Always call this to close the stream in an orderly fashion, even after * an error. (In the case of an error, abort the transaction afterwards.) * * The only circumstance where it's safe to skip this is after an error, if * you're discarding the entire connection. */ void complete(sl loc = sl::current()); /// Insert a row of data. /** Returns a reference to the stream, so you can chain the calls. * * The @c row can be a tuple, or any type that can be iterated. Each * item becomes a field in the row, in the same order as the columns you * specified when creating the stream. * * If you don't already happen to have your fields in the form of a tuple or * container, prefer @c write_values. It's faster and more convenient. */ template stream_to &operator<<(Row const &row) { write_row(row, m_created_loc); return *this; } /// Stream a `stream_from` straight into a `stream_to`. /** This can be useful when copying between different databases. If the * source and the destination are on the same database, you'll get better * performance doing it all in a regular query. */ stream_to &operator<<(stream_from &); /// Insert a row of data, given in the form of a @c std::tuple or container. /** The @c row can be a tuple, or any type that can be iterated. Each * item becomes a field in the row, in the same order as the columns you * specified when creating the stream. * * The preferred way to insert a row is @c write_values. */ template void write_row(Row const &row, sl loc = sl::current()) { fill_buffer( row, conversion_context{trans().conn().get_encoding_group(loc), loc}); write_buffer(loc); } /// Insert values as a row. /** This is the recommended way of inserting data. Pass your field values, * of any convertible type. */ template void write_values(Ts const &...fields) { fill_buffer(fields...); write_buffer(m_created_loc); } private: /// Stream a pre-quoted table name and columns list. stream_to( transaction_base &tx, std::string_view path, std::string_view columns, sl); /// Reusable buffer for a row. Saves doing an allocation for each row. std::string m_buffer; /// Reusable buffer for converting/escaping a field. std::string m_field_buf; /// Callback to find the special characters we need to watch out for. internal::char_finder_func *m_finder; /// The `std::source_location` for where this stream was created. sl m_created_loc; /// Has this stream finished? bool m_finished = false; /// Write a row of raw text-format data into the destination table. void write_raw_line(std::string_view, sl); /// Write a row of data from @c m_buffer into the destination table. /** Resets the buffer for the next row. */ void write_buffer(sl); /// COPY encoding for a null field, plus subsequent separator. static constexpr std::string_view null_field{"\\N\t"}; /// Estimate buffer space needed for a field which is always null. template static constexpr std::size_t estimate_buffer(T const &) requires(pqxx::always_null()) { return std::size(null_field); } /// Estimate buffer space needed for field f. /** The estimate is not very precise. We don't actually know how much space * we'll need once the escaping comes in. */ template static constexpr std::size_t estimate_buffer(T const &field) requires(not pqxx::always_null()) { return is_null(field) ? std::size(null_field) : size_buffer(field); } /// Append escaped version of @c data to @c m_buffer, plus a tab. void escape_field_to_buffer(std::string_view data, sl loc); /// Append string representation for @c f to @c m_buffer. /** This is for the general case, where the field may contain a value. * * Also appends a tab. The tab is meant to be a separator, not a terminator, * so if you write any fields at all, you'll end up with one tab too many * at the end of the buffer. */ template void append_to_buffer(Field const &f, ctx c) requires(not pqxx::always_null()) { // We append each field, terminated by a tab. That will leave us with // one tab too many, assuming we write any fields at all; we remove that // at the end. if (is_null(f)) { // Easy. Append null and tab in one go. m_buffer.append(null_field); } else { // Convert f into m_buffer. auto const budget{estimate_buffer(f)}; // We're not using is_unquoted_safe for this, because in this context, // a tab counts as a special character that needs escaping. if constexpr (std::is_arithmetic_v) { // Specially optimised for "safe" types, which never need any // escaping. Convert straight into m_buffer. auto const offset{std::size(m_buffer)}; // Also include room to append the tab. auto const total{offset + budget + 1}; m_buffer.resize(total); auto const data{m_buffer.data()}; std::size_t const end{ offset + into_buf({data + offset, data + total}, f, c)}; assert((end + 1) < std::size(m_buffer)); m_buffer[end] = '\t'; // Shrink to fit. Keep the tab though. m_buffer.resize(end + 1); } else if constexpr ( std::is_same_v or std::is_same_v or std::is_same_v) { // This string may need escaping. m_field_buf.resize(budget); escape_field_to_buffer(f, c.loc); } else if constexpr ( std::is_same_v> or std::is_same_v> or std::is_same_v>) { // Optional string. It's not null (we checked for that above), so... // Treat like a string. m_field_buf.resize(budget); // No need to check whether f has a value; if it didn't, the is_null(f) // check at the top would have evaluated as true. // NOLINTNEXTLINE(bugprone-unchecked-optional-access) escape_field_to_buffer(f.value(), c.loc); } // TODO: Support deleter template argument on unique_ptr. else if constexpr ( std::is_same_v> or std::is_same_v> or std::is_same_v> or std::is_same_v> or std::is_same_v> or std::is_same_v>) { // TODO: Generalise this. // Effectively also an optional string. It's not null (we checked // for that above). m_field_buf.resize(budget); escape_field_to_buffer(*f, c.loc); } else { // This field needs to be converted to a string, and after that, // escaped as well. m_field_buf.resize(budget); escape_field_to_buffer(to_buf(m_field_buf, f, c), c.loc); } } } /// Append string representation for a null field to @c m_buffer. /** This special case is for types which are always null. * * Also appends a tab. The tab is meant to be a separator, not a terminator, * so if you write any fields at all, you'll end up with one tab too many * at the end of the buffer. */ template void append_to_buffer(Field const &, ctx) requires(pqxx::always_null()) { m_buffer.append(null_field); } /// Write raw COPY line into @c m_buffer, based on a container of fields. template void fill_buffer(Container const &cont, ctx c) requires(not std::is_same_v< std::remove_cv_t, char>) { // To avoid unnecessary allocations and deallocations, we run through c // twice: once to determine how much buffer space we may need, and once to // actually write it into the buffer. std::size_t budget{0}; for (auto const &f : cont) budget += estimate_buffer(f); m_buffer.reserve(budget); for (auto const &f : cont) append_to_buffer(f, c); } /// Estimate how many buffer bytes we need to write tuple. template static std::size_t budget_tuple(Tuple const &t, std::index_sequence) { return (estimate_buffer(std::get(t)) + ...); } /// Write tuple of fields to @c m_buffer. template void append_tuple(Tuple const &t, std::index_sequence, ctx c) { (append_to_buffer(std::get(t), c), ...); } /// Write raw COPY line into @c m_buffer, based on a tuple of fields. template void fill_buffer(std::tuple const &t, ctx c) { using indexes = std::make_index_sequence; m_buffer.reserve(budget_tuple(t, indexes{})); append_tuple(t, indexes{}, c); } /// Write raw COPY line into @c m_buffer, based on varargs fields. template void fill_buffer(const Ts &...fields) { conversion_context const c{ trans().conn().get_encoding_group(m_created_loc), m_created_loc}; (..., append_to_buffer(fields, c)); } static constexpr std::string_view s_classname{"stream_to"}; }; } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/subtransaction000066400000000000000000000004711516427024100206200ustar00rootroot00000000000000/** pqxx::subtransaction class. * * pqxx::subtransaction is a nested transaction, i.e. one inside a transaction. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/subtransaction.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/subtransaction.hxx000066400000000000000000000073331516427024100214320ustar00rootroot00000000000000/* Definition of the pqxx::subtransaction class. * * pqxx::subtransaction is a nested transaction, i.e. one within a transaction. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/subtransaction instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_SUBTRANSACTION_HXX #define PQXX_SUBTRANSACTION_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include "pqxx/dbtransaction.hxx" namespace pqxx { // NOLINTBEGIN(fuchsia-multiple-inheritance) /** * @ingroup transactions */ /// "Transaction" nested within another transaction /** A subtransaction can be executed inside a backend transaction, or inside * another subtransaction. This can be useful when, for example, statements in * a transaction may harmlessly fail and you don't want them to abort the * entire transaction. Here's an example of how a temporary table may be * dropped before re-creating it, without failing if the table did not exist: * * ```cxx * void do_job(pqxx::connection &cx) * { * std::string const temptable = "fleetingtable"; * * pqxx::work tx(cx, "do_job"); * do_firstpart(tx); * * // Attempt to delete our temporary table if it already existed. * // (In reality you would just use the IF EXISTS option to DROP TABLE.) * try * { * pqxx::subtransaction S(tx, "droptemp"); * S.exec0("DROP TABLE " + temptable); * S.commit(); * } * catch (pqxx::undefined_table const &) * { * // Table did not exist. Which is what we were hoping to achieve anyway. * // Carry on without regrets. * } * * // S may have gone into a failed state and been destroyed, but the * // upper-level transaction tx is still fine. We can continue to use it. * tx.exec( * "CREATE TEMP TABLE " + temptable + "(bar integer, splat varchar)" * ).no_rows(); * * do_lastpart(tx); * } * ``` * * (This is just an example. If you really wanted to do drop a table without * an error if it doesn't exist, you'd use DROP TABLE IF EXISTS.) * * There are no isolation levels inside a transaction. They are not needed * because all actions within the same backend transaction are always performed * sequentially anyway. * * @warning While the subtransaction is "live," you cannot execute queries or * open streams etc. on its parent transaction. A transaction can have at most * one object of a type derived from @ref pqxx::transaction_focus active on it * at a time. */ class PQXX_LIBEXPORT subtransaction final : public transaction_focus, public dbtransaction { public: /// Nest a subtransaction nested in another transaction. explicit subtransaction( dbtransaction &t, std::string_view tname, sl = sl::current()); /// Nest a subtransaction nested in another transaction. explicit subtransaction(dbtransaction &t, sl loc = sl::current()) : subtransaction(t, "", loc) {} /// Nest a subtransaction in another subtransaction. subtransaction( subtransaction &t, std::string_view name = ""sv, sl loc = sl::current()); subtransaction(subtransaction const &) = delete; subtransaction(subtransaction &&) = delete; ~subtransaction() noexcept override; subtransaction &operator=(subtransaction const &) = delete; subtransaction &operator=(subtransaction &&) = delete; private: [[nodiscard]] std::string quoted_name() const { return quote_name(transaction_focus::name()); } void do_commit(sl) override; }; // NOLINTEND(fuchsia-multiple-inheritance) } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/time000066400000000000000000000003361516427024100165170ustar00rootroot00000000000000/** Date/time string conversions. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/time.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/time.hxx000066400000000000000000000054371516427024100173340ustar00rootroot00000000000000/** Support for date/time values. * * At the moment this supports dates, but not times. */ #ifndef PQXX_TIME_HXX #define PQXX_TIME_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include #include "pqxx/strconv.hxx" #if defined(PQXX_HAVE_YEAR_MONTH_DAY) namespace pqxx { using namespace std::literals; template<> struct nullness final : no_null {}; /// String representation for a Gregorian date in ISO-8601 format. /** @warning Experimental. There may still be design problems, particularly * when it comes to BC years. * * PostgreSQL supports a choice of date formats, but libpqxx does not. The * other formats in turn support a choice of "month before day" versus "day * before month," meaning that it's not necessarily known which format a given * date is supposed to be. So I repeat: ISO-8601-style format only! * * Invalid dates will not convert. This includes February 29 on non-leap * years, which is why it matters that `year_month_day` represents a * _Gregorian_ date. * * The range of years is limited. At the time of writing, PostgreSQL 14 * supports years from 4713 BC to 294276 AD inclusive, and C++20 supports * a range of 32767 BC to 32767 AD inclusive. So in practice, years must fall * between 4713 BC and 32767 AD, inclusive. * * @warning Support for BC (or BCE) years is still experimental. I still need * confirmation on this issue: it looks as if C++ years are astronomical years, * which means they have a Year Zero. Regular BC/AD years do not have a year * zero, so the year 1 AD follows directly after 1 BC. * * So, what to our calendars (and to PostgreSQL) is the year "0001 BC" seems to * count as year "0" in a `std::chrono::year_month_day`. The year 0001 AD is * still equal to 1 as you'd expect, and all AD years work normally, but all * years before then are shifted by one. For instance, the year 543 BC would * be -542 in C++. */ template<> struct PQXX_LIBEXPORT string_traits final { [[nodiscard]] static std::string_view to_buf( std::span buf, std::chrono::year_month_day const &value, ctx c = {}); [[nodiscard]] static std::chrono::year_month_day from_string(std::string_view text, sl = sl::current()); [[nodiscard]] static std::size_t size_buffer(std::chrono::year_month_day const &) noexcept { static_assert(int{(std::chrono::year::min)()} >= -99999); static_assert(int{(std::chrono::year::max)()} <= 99999); return 5 + 1 + 2 + 1 + 2 + std::size(s_bc) + 1; } private: /// The "BC" suffix for years before 1 AD. static constexpr std::string_view s_bc{" BC"sv}; }; } // namespace pqxx #endif // PQXX_HAVE_YEAR_MONTH_DAY #endif libpqxx-8.0.1/include/pqxx/transaction000066400000000000000000000004441516427024100201060ustar00rootroot00000000000000/** pqxx::transaction class. * * pqxx::transaction represents a standard database transaction. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/transaction.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/transaction.hxx000066400000000000000000000076271516427024100207260ustar00rootroot00000000000000/* Definition of the pqxx::transaction class. * pqxx::transaction represents a standard database transaction. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transaction instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_TRANSACTION_HXX #define PQXX_TRANSACTION_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include "pqxx/dbtransaction.hxx" namespace pqxx::internal { /// Helper base class for the @ref pqxx::transaction class template. class PQXX_LIBEXPORT basic_transaction : public dbtransaction { protected: basic_transaction( connection &cx, zview begin_command, std::string_view tname, sl = sl::current()); basic_transaction( connection &cx, zview begin_command, std::string &&tname, sl = sl::current()); basic_transaction(connection &cx, zview begin_command, sl = sl::current()); private: void do_commit(sl) override; public: basic_transaction() = delete; basic_transaction(basic_transaction const &) = delete; basic_transaction(basic_transaction &&) = delete; // NOLINTNEXTLINE(cppcoreguidelines-virtual-class-destructor) ~basic_transaction() noexcept override = 0; basic_transaction &operator=(basic_transaction const &) = delete; basic_transaction &operator=(basic_transaction &&) = delete; }; } // namespace pqxx::internal namespace pqxx { /// transaction Standard back-end transaction, templatised on isolation level. /** @ingroup transactions * This is the type you'll normally want to use to represent a transaction on * the database. * * @tparam ISOLATION The transaction's "isolation level." This is a standard * SQL concept. The default in PostgreSQL (and in libpqxx) is READ COMMITTED. * @tparam READWRITE Whether this transaction is allowed to make changes to the * database. * * Usage example: double all wages. * * ```cxx * extern pqxx::connection cx; * pqxx::work tx(cx); * try * { * tx.exec("UPDATE employees SET wage=wage*2").no_rows(); * tx.commit(); // Do this inside "the" try block, right at the end. * } * catch (std::exception const &e) * { * std::cerr << e.what() << '\n'; * tx.abort(); // Usually not needed; same happens when tx's life ends. * } * ``` */ template< isolation_level ISOLATION = isolation_level::read_committed, write_policy READWRITE = write_policy::read_write> class transaction final : public internal::basic_transaction { public: /// Begin a transaction. /** * @param cx Connection for this transaction to operate on. * @param tname Optional name for transaction. Must begin with a letter and * may contain letters and digits only. */ transaction(connection &cx, std::string_view tname, sl loc = sl::current()) : internal::basic_transaction{ cx, internal::begin_cmd, tname, loc} {} /// Begin a transaction. /** * @param cx Connection for this transaction to operate on. * may contain letters and digits only. */ explicit transaction(connection &cx, sl loc = sl::current()) : internal::basic_transaction{ cx, internal::begin_cmd, loc} {} transaction(transaction const &) = delete; transaction(transaction &&) = delete; transaction &operator=(transaction const &) = delete; transaction &operator=(transaction &&) = delete; ~transaction() noexcept override { close(sl::current()); } }; /// The default transaction type. /** @ingroup transactions */ using work = transaction; /// Read-only transaction. /** @ingroup transactions */ using read_transaction = transaction; } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/transaction_base000066400000000000000000000005411516427024100210760ustar00rootroot00000000000000/** Base for the transaction classes. * * pqxx::transaction_base defines the interface for any abstract class that * represents a database transaction. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/transaction_base.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/transaction_base.hxx000066400000000000000000001450411516427024100217110ustar00rootroot00000000000000/* Common code and definitions for the transaction classes. * * pqxx::transaction_base defines the interface for any abstract class that * represents a database transaction. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transaction_base instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_TRANSACTION_BASE_HXX #define PQXX_TRANSACTION_BASE_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include /* End-user programs need not include this file, unless they define their own * transaction classes. This is not something the typical program should want * to do. * * However, reading this file is worthwhile because it defines the public * interface for the available transaction classes such as transaction and * nontransaction. */ #include "pqxx/connection.hxx" #include "pqxx/encoding_group.hxx" #include "pqxx/internal/stream_query.hxx" #include "pqxx/isolation.hxx" #include "pqxx/prepared_statement.hxx" #include "pqxx/result.hxx" #include "pqxx/row.hxx" #include "pqxx/util.hxx" namespace pqxx::internal::gate { class transaction_subtransaction; class transaction_sql_cursor; class transaction_stream_to; class transaction_transaction_focus; } // namespace pqxx::internal::gate namespace pqxx { using namespace std::literals; class transaction_focus; /** * @defgroup transactions Transaction classes * * All database access goes through instances of these classes. In libpqxx * you can't execute SQL directly on the connection object; that all happens * only on a transaction object. If you don't actually want to start a * transaction on the server, there's a @ref nontransaction class which * operates in _autocommit,_ i.e. without a transaction. * * (Why do you always need a transaction object? It ended up being the cleaner * choice in terms of interface design. It avoids a bunch of API maladies: * duplicating API between classes, messy inheritance, inviting mistakes by * making the transaction afterthought, and so on.) * * Like most other things in libpqxx, transactions follow RAII principles. * Creating a transaction object starts the transaction on the backend (if * appropriate), and to destroying one ends the transaction. But there's one * extra step: if you want to make the transaction's changes permanent, you * need to _commit_ it before you destroy it. If you destroy the transaction * object without committing, or if you call its `abort()` member function, * then any transaction type (other than @ref nontransaction) will roll back * its changes to the database instead. * * There is a choice of transaction types. To start with you'll probably want * to use @ref pqxx::work, represents a regular, vanilla transaction with the * default isolation level. * * All the actual transaction functionality, including all the functions for * executing SQL statements, lives in the abstract @ref transaction_base class. * It defines the API for each type of transaction. You create a transaction, * you use it by calling @ref transaction_base member functions, and then you * either commit or (in the case of failure) abort. If you destroy your * transaction object without doing either, it automatically aborts. * * Once you're done with your transaction, you can start a new one using the * same connection. But there can be only one main transaction going on on a * connection at any given time. (You _can_ have more "nested" transactions, * but I'm not counting those as "main" transactions here. See below.) * * The concrete transaction types, all derived from @ref transaction_base, are: * * First and foremost, the plain @ref pqxx::transaction template. Template * parameters let you select isolation level, and whether it should be * read-only. Two aliases are usually more convenient: @ref pqxx::work is a * regular, run-of-the-mill default transaction. @ref pqxx::read_transaction * is a read-only transaction that will not let you modify the database. * * Then there's @ref nontransaction. This one runs in autocommit, meaning * that we don't start any transaction at all. (Technically in this mode each * SQL command runs in its own little transaction, hence the term * "autocommit." There is no way to "undo" an SQL statement in this kind of * transaction.) Autocommit is sometimes a bit faster, and sometimes a bit * slower. Mainly you'll use it for specific operations that cannot be done * inside a database transaction, such as some kinds of schema changes. * * And then there's @ref pqxx::robusttransaction to help you deal with those * painful situations where you don't know for sure whether a transaction * actually succeeded. This can happen if you lose your network connection to * the database _just_ while you're trying to commit your transaction, before * you receive word about the outcome. You can re-connect and find out, but * what if the server is still executing the commit? * * You could say that @ref pqxx::robusttransaction is not more robust, exactly, * but it goes to some extra effort to try and figure these situations out and * give you clarity. Extra effort does actually mean more things that can go * wrong, and it may be a little slower, so investigate carefully before using * this transaction class. * * All of the transaction types that actually begin and commit/abort on the * database itself are derived from @ref pqxx::dbtransaction, which can be a * useful type if your code needs a reference to such a transaction but doesn't * need to enforce a particular one. These types are @ref transaction, * @ref pqxx::work, @ref pqxx::read_transaction, and * @ref pqxx::robusttransaction. * * Finally, there's @ref pqxx::subtransaction. This one is not at all like the * others: it can only exist inside a @ref pqxx::dbtransaction. (Which * includes @ref pqxx::subtransaction itself: you can nest them freely.) You * can only operate on the "innermost" active subtransaction at any given time, * until you either commit or abort it. Subtransactions are built on * _savepoints_ in the database; these are efficient to a point but do consume * some server resources. So use them when they make sense, e.g. to try an SQL * statement but continue your main transaction if it fails. But don't create * them in enormous numbers, or performance may start to suffer. */ /// Interface definition (and common code) for "transaction" classes. /** * @ingroup transactions * * Abstract base class for all transaction types. */ class PQXX_LIBEXPORT PQXX_NOVTABLE transaction_base { public: transaction_base() = delete; transaction_base(transaction_base const &) = delete; transaction_base(transaction_base &&) = delete; transaction_base &operator=(transaction_base const &) = delete; transaction_base &operator=(transaction_base &&) = delete; virtual ~transaction_base() = 0; /// Commit the transaction. /** Make the effects of this transaction definite. If you destroy a * transaction without invoking its @ref commit() first, that will implicitly * abort it. (For the @ref nontransaction class though, "commit" and "abort" * really don't do anything, hence its name.) * * There is, however, a minute risk that you might lose your connection to * the database at just the wrong moment here. In that case, libpqxx may be * unable to determine whether the database was able to complete the * transaction, or had to roll it back. In that scenario, @ref commit() will * throw an in_doubt_error. There is a different transaction class called * @ref robusttransaction which takes some special precautions to reduce this * risk. */ void commit(sl = sl::current()); /// Abort the transaction. /** No special effort is required to call this function; it will be called * implicitly when the transaction is destructed. */ void abort(sl = sl::current()); /** * @ingroup escaping-functions * * Use these when writing SQL queries that incorporate C++ values as SQL * constants. * * The functions you see here are just convenience shortcuts to the same * functions on the connection object. */ //@{ PQXX_ZARGS [[nodiscard]] std::string esc(char const str[], sl loc = sl::current()) { return conn().esc(str, loc); } /// Escape string for use as SQL string literal in this transaction. [[nodiscard]] std::string_view esc( std::string_view text, std::span buffer, sl loc = sl::current()) const { return conn().esc(text, buffer, loc); } /// Escape string for use as SQL string literal in this transaction. [[nodiscard]] std::string esc(std::string_view text, sl loc = sl::current()) const { return conn().esc(text, loc); } /// Escape binary string for use as SQL string literal. template [[nodiscard]] std::string esc(DATA const &data) const { return conn().esc(data); } /// Escape binary string for use as SQL string literal, into `buffer`. /** Use this variant when you want to re-use the same buffer across multiple * calls. If that's not the case, or convenience and simplicity are more * important, use the single-argument variant. * * For every byte in `data`, there must be at least two bytes of space in * `buffer`; plus there must be two bytes of space for a header and one for * a trailing zero. Throws @ref range_error if this space is not available. * * Returns a reference to the escaped string, which is actually stored in * `buffer`. */ template [[nodiscard]] zview esc(DATA const &data, std::span buffer, sl loc = sl::current()) const { return conn().esc(data, buffer, loc); } /// Escape binary string for use as SQL string literal, into `buffer`. template [[nodiscard, deprecated("Use esc(), not esc_raw(), even on binary data.")]] zview esc_raw(DATA const &data, sl loc = sl::current()) const { return conn().esc(data, loc); } /// Escape binary string for use as SQL string literal, into `buffer`. template [[nodiscard, deprecated("Use esc(), not esc_raw(), even on binary data.")]] zview esc_raw( DATA const &data, std::span buffer, sl loc = sl::current()) const { return conn().esc(data, buffer, loc); } /// Unescape binary data, e.g. from a `bytea` field. /** Takes a binary string as escaped by PostgreSQL, and returns a restored * copy of the original binary data. */ [[nodiscard]] bytes unesc_bin(zview text, sl loc = sl::current()) { return conn().unesc_bin(text, loc); } /// Unescape binary data, e.g. from a `bytea` field. /** Takes a binary string as escaped by PostgreSQL, and returns a restored * copy of the original binary data. */ PQXX_ZARGS [[nodiscard]] bytes unesc_bin(char const text[], sl loc = sl::current()) { return conn().unesc_bin(text, loc); } // TODO: "Into buffer" variant. /// Represent object as SQL string, including quoting & escaping. /** Nulls are recognized and represented as SQL nulls. */ template [[nodiscard]] std::string quote(T const &t, sl loc = sl::current()) const { return conn().quote(t, loc); } /// Binary-escape and quote a binary string for use as an SQL constant. /** For binary data you can also just use @ref quote(data). */ template [[nodiscard]] std::string quote_raw(DATA const &data, sl loc = sl::current()) const { return conn().quote_raw(data, loc); } // TODO: "Into buffer" variant. /// Escape an SQL identifier for use in a query. [[nodiscard]] std::string quote_name(std::string_view identifier) const { return conn().quote_name(identifier); } // TODO: "Into buffer" variant. /// Escape string for literal LIKE match. [[nodiscard]] std::string esc_like( std::string_view bin, char escape_char = '\\', sl loc = sl::current()) const { return conn().esc_like(bin, escape_char, loc); } //@} /** * @name Command execution * * There are many functions for executing (or "performing") a command (or * "query"). This is the most fundamental thing you can do in libpqxx, and * it always starts at a transaction class. * * Command execution can throw many types of exception, including sql_error, * broken_connection, and many sql_error subtypes such as * feature_not_supported or insufficient_privilege. But any exception thrown * by the C++ standard library may also occur here. All exceptions you will * see libpqxx throw are derived from std::exception. * * Most of the differences between the query execution functions are in how * they return the query's results. * * * The "query" functions run your query, wait for it to complete, and load * all of the results into memory on the client side. You can then access * rows of result data, converted to C++ types that you request. * * The "stream" functions execute your query in a completely different way. * Called _streaming queries,_ these don't support quite the full range of * SQL queries, and they're a bit slower to start. But they are * significantly _faster_ for queries that return larger numbers of rows. * They don't load the entire result set, so you can start processing data * as soon as the first row of data comes in from the database. This can * This can save you a lot of time. Processing itself may also be faster. * And of course, it also means you don't need enough memory to hold the * entire result set, just the row you're working on. * * The "exec" functions are a more low-level interface. Most of them * return a pqxx::result object. This is an object that contains all * information abouut the query's result: the data itself, but also the * number of rows in the result, the column names, the number of rows that * your query may have modified, and so on. */ //@{ /// Execute a command. /** * @param query Query or command to execute. * @return A result set describing the query's or command's result. */ [[deprecated("The desc parameter is going away.")]] result exec(std::string_view query, std::string_view desc, sl = sl::current()); // TODO: Wrap PQdescribePrepared(). result exec(std::string_view query, params const &parms, sl loc = sl::current()) { return internal_exec_params(query, parms.make_c_params(loc), loc); } /// Execute a command. /** * @param query Query or command to execute. * @return A result set describing the query's or command's result. */ result exec(std::string_view query, sl = sl::current()); /// Execute a command. /** * @param query Query or command to execute. * @param desc Optional identifier for query, to help pinpoint SQL errors. * @return A result set describing the query's or command's result. */ [[deprecated( "Pass your query as a std::string_view, not stringstream.")]] result exec(std::stringstream const &query, std::string_view desc) { #include "pqxx/internal/ignore-deprecated-pre.hxx" return exec(query.str(), desc); #include "pqxx/internal/ignore-deprecated-post.hxx" } /// Execute command, which should return zero rows of data. /** Works like @ref exec, but fails if the result contains data. It still * returns a result, however, which may contain useful metadata. * * @throw unexpected_rows If the query returned the wrong number of rows. */ [[deprecated("Use exec(string_view) and call no_rows() on the result.")]] result exec0(std::string_view query, std::string_view desc) { #include "pqxx/internal/ignore-deprecated-pre.hxx" return exec(query, desc).no_rows(); #include "pqxx/internal/ignore-deprecated-post.hxx" } /// Execute command, which should return zero rows of data. /** Works like @ref exec, but fails if the result contains data. It still * returns a result, however, which may contain useful metadata. * * @throw unexpected_rows If the query returned the wrong number of rows. */ [[deprecated("Use exec() and call no_rows() on the result.")]] result exec0(std::string_view query) { return exec(query).no_rows(); } /// Execute command returning a single row of data. /** Works like @ref exec, but requires the result to contain exactly one row. * The row can be addressed directly, without the need to find the first row * in a result set. * * @throw unexpected_rows If the query returned the wrong number of rows. */ [[deprecated("Use exec(string_view), and call one_row() on the result.")]] row exec1(std::string_view query, std::string_view desc) { #include "pqxx/internal/ignore-deprecated-pre.hxx" return exec(query, desc).one_row(); #include "pqxx/internal/ignore-deprecated-post.hxx" } /// Execute command returning a single row of data. /** Works like @ref exec, but requires the result to contain exactly one row. * The row can be addressed directly, without the need to find the first row * in a result set. * * @throw unexpected_rows If the query returned the wrong number of rows. */ [[deprecated("Use exec() instead, and call one_row() on the result.")]] row exec1(std::string_view query) { return exec(query).one_row(); } /// Execute command, expect given number of rows. /** Works like @ref exec, but checks that the result has exactly the expected * number of rows. * * @throw unexpected_rows If the query returned the wrong number of rows. */ [[deprecated("Use exec() instead, and call expect_rows() on the result.")]] result exec_n( result::size_type rows, std::string_view query, std::string_view desc); /// Execute command, expect given number of rows. /** Works like @ref exec, but checks that the result has exactly the expected * number of rows. * * @throw unexpected_rows If the query returned the wrong number of rows. */ [[deprecated("Use exec() instead, and call expect_rows() on the result.")]] result exec_n(result::size_type rows, std::string_view query) { #include "pqxx/internal/ignore-deprecated-pre.hxx" return exec(query, std::string_view{}).expect_rows(rows); #include "pqxx/internal/ignore-deprecated-post.hxx" } /// Perform query, expecting exactly 1 row with 1 field, and convert it. /** This is convenience shorthand for querying exactly one value from the * database. It returns that value, converted to the type you specify. */ template [[deprecated("The desc parameter is going away.")]] TYPE query_value(std::string_view query, std::string_view desc) { #include "pqxx/internal/ignore-deprecated-pre.hxx" return exec(query, desc).one_field().as(); #include "pqxx/internal/ignore-deprecated-post.hxx" } /// Perform query, expecting exactly 1 row with 1 field, and convert it. /** This is convenience shorthand for querying exactly one value from the * database. It returns that value, converted to the type you specify. * * @throw unexpected_rows If the query did not return exactly 1 row. * @throw usage_error If the row did not contain exactly 1 field. */ template TYPE query_value(std::string_view query, sl loc = sl::current()) { // The result and field_ref objects are temporaries, but under C++20 // lifetime rules they'll live until after we convert the field to TYPE. return exec(query, loc).one_field_ref(loc).as(loc); } /// Perform query returning exactly one row, and convert its fields. /** This is a convenient way of querying one row's worth of data, and * converting its fields to a tuple of the C++-side types you specify. * * @throw unexpected_rows If the query did not return exactly 1 row. * @throw usage_error If the number of columns in the result does not match * the number of fields in the tuple. */ template [[nodiscard]] std::tuple query1(std::string_view query, sl loc = sl::current()) { // The result and row_ref objects are temporaries, but under C++20 lifetime // rules they'll live until after we convert the field to TYPE. return exec(query, loc) .expect_columns(sizeof...(TYPE), loc) .one_row_ref(loc) .as(loc); } /// Query at most one row of data, and if there is one, convert it. /** If the query produced a row of data, this converts it to a tuple of the * C++ types you specify. Otherwise, this returns no tuple. * * @throw unexpected_rows If the query returned more than 1 row. * @throw usage_error If the number of columns in the result does not match * the number of fields in the tuple. */ template [[nodiscard]] std::optional> query01(std::string_view query, sl loc = sl::current()) { auto const res{exec(query, loc)}; std::optional const r{res.opt_row_ref(loc)}; if (r) return {r->as(loc)}; else return {}; } /// Execute a query, in streaming fashion; loop over the results row by row. /** Converts the rows to `std::tuple`, of the column types you specify. * * Use this with a range-based "for" loop. It executes the query, and * directly maps the resulting rows onto a `std::tuple` of the types you * specify. Unlike with the "exec" functions, processing can start before * all the data from the server is in. * * @warning You can't pass parmaeters to a streaming query. This is a * limitation at a lower level in the software stack. You can work around * this by defining a view or function that you can then call without * parameters in the streaming query; or you can compose query strings that * wrap the parameters in calls to @ref pqxx::transaction_base::quote() or * @ref pqxx::transaction_base::esc(). * * Streaming is also documented in @ref streams. * * The column types must all be types that have conversions from PostgreSQL's * text format defined. Many built-in types such as `int` or `std::string` * have pre-defined conversions; if you want to define your own conversions * for additional types, see @ref datatypes. * * `TYPE...` may include `std::string_view` and @ref zview fields (which will * be highly efficient), but the strings to which they point will only remain * valid until you extract the next row. After that, the memory holding the * string may be overwritten or deallocated. * * If any of the columns can be null, and you're converting it to a C++ type * which does not support a null value, you can wrap the type in a * `std::optional<>` (or if you prefer, a `std::shared_ptr<>` or a * `std::unique_ptr`). These templates do support null values, and libpqxx * will know how to convert to them. * * The stream lives entirely within the lifetime of the transaction. Make * sure you complete the stream before you destroy the transaction. Until * the stream has finished, the transaction and the connection are in a * special state where they cannot be used for anything else. * * @warning If the stream fails, you will have to destroy the transaction * and the connection. If this is a problem, use the "exec" functions * instead. * * Streaming your query is likely to be faster than the `exec()` methods for * queries that return lots of rows, but slower for ones that don't. You'll * be able to start useful processing sooner, before all the result data is * in. Also, `stream()` scales better in terms of memory usage: it only * needs to keep the current row in memory, not the whole result. The * "exec" functions read the entire result into memory at once. * * Your query executes as part of a COPY command, not as a stand-alone query, * so there are limitations to what you can do in the query. It can be * either a SELECT or VALUES query; or an INSERT, UPDATE, or DELETE with a * RETURNING clause. See the documentation for PostgreSQL's * [COPY command](https://www.postgresql.org/docs/current/sql-copy.html) for * the exact restrictions. */ template [[nodiscard]] auto stream(std::string_view query, sl loc = sl::current()) & { return pqxx::internal::stream_query{ *this, query, make_context(loc)}; } /// Perform a streaming query, and for each result row, call `func`. /** Here, `func` can be a function, a `std::function`, a lambda, or an * object that supports the function call operator. Of course `func` must * have an unambiguous signature; it can't be overloaded or generic. * * The `for_stream` function executes `query` in a stream similar to * @ref stream. Every time a row of data comes in from the server, it * converts the row's fields to the types of `func`'s respective parameters, * and calls `func` with those values. * * This will not work for all queries, but straightforward `SELECT` and * `UPDATE ... RETURNING` queries should work. Consult the documentation for * @ref pqxx::internal::stream_query and PostgreSQL's underlying `COPY` * command for the full details. * * Streaming a query like this is likely to be slower than the @ref exec() * functions for small result sets, but faster for larger result sets. So if * performance matters, you'll want to use `for_stream` if you query large * amounts of data, but not if you do lots of queries with small outputs. * * However, the transaction and the connection are in a special state while * the iteration is ongoing. If `func` throws an exception, or the iteration * fails in some way, the only way out is to destroy the transaction and the * connection. * * Each of the parameter types must have a conversion from PostgreSQL's text * format defined. To define conversions for additional types, see * @ref datatypes. */ template auto for_stream(std::string_view query, CALLABLE &&func, sl loc = sl::current()) { // TODO: Can we pass loc into func if appropriate? using param_types = pqxx::internal::strip_types_t>; param_types const *const sample{nullptr}; auto data_stream{stream_like(query, sample, loc)}; for (auto const &fields : data_stream) std::apply(func, fields); } template [[deprecated( "pqxx::transaction_base::for_each is now called for_stream.")]] auto for_each(std::string_view query, CALLABLE &&func, sl loc = sl::current()) { return for_stream(query, std::forward(func), loc); } /// Execute query, read full results, then iterate rows of data. /** Converts each row of the result to a `std::tuple` of the types you pass * as template arguments. (The number of template arguments must match the * number of columns in the query's result.) * * Example: * * ```cxx * for ( * auto [name, salary] : * tx.query( * "SELECT name, salary FROM employee" ) * ) * std::cout << name << " earns " << salary << ".\n"; * ``` * * You can't normally convert a field value to `std::string_view`, but this * is one of the places where you can. The underlying string to which the * `string_view` points exists only for the duration of the one iteration. * After that, the buffer that holds the actual string may have disappeared, * or it may contain a new string value. * * If you expect a lot of rows from your query, it's probably faster to use * transaction_base::stream() instead. Or if you need to access metadata of * the result, such as the number of rows in the result, or the number of * rows that your query updates, then you'll need to use * transaction_base::exec() instead. * * @return Something you can iterate using "range `for`" syntax. The actual * type details may change. */ template auto query(std::string_view query, sl loc = sl::current()) { return exec(query, loc).iter(); } /// Perform query, expect given number of rows, iterate results. template [[deprecated("Use query() instead, and call expect_rows() on the result.")]] auto query_n( result::size_type rows, std::string_view query, sl loc = sl::current()) { return exec(query, loc).expect_rows(rows, loc).iter(); } /// Execute a query, load the full result, and perform `func` for each row. /** Converts each row to data types matching `func`'s parameter types. The * number of columns in the result set must match the number of parameters. * * This is a lot like for_stream(). The differences are: * 1. It can execute some unusual queries that for_stream() can't. * 2. The `exec` functions are faster for small results, but slower for large * results. */ template void for_query(std::string_view query, CALLABLE &&func, sl loc = sl::current()) { exec(query).for_each(std::forward(func), loc); } /** * @name Parameterized statements * * You'll often need parameters in the queries you execute: "select the * car with this licence plate." If the parameter is a string, you need to * quote it and escape any special characters inside it, or it may become a * target for an SQL injection attack. If it's an integer (for example), * you need to convert it to a string, but in the database's format, without * locale-specific niceties such as "," separators between the thousands. * * Parameterised statements are an easier and safer way to do this. They're * like prepared statements, but for a single use. You don't need to name * them, and you don't need to prepare them first. * * Your query will include placeholders like `$1` and `$2` etc. in the places * where you want the arguments to go. Then, you pass the argument values * and the actual query is constructed for you. * * Pass the exact right number of parameters, and in the right order. The * parameters in the query don't have to be neatly ordered from `$1` to * `$2` to `$3` - but you must pass the argument for `$1` first, the one * for `$2` second, etc. * * @warning Beware of "nul" bytes. Any string you pass as a parameter will * end at the first char with value zero. If you pass a string that contains * a zero byte, the last byte in the value will be the one just before the * zero. */ //@{ /// Execute an SQL statement with parameters. /** This is like calling `exec()`, except it will substitute the first * parameter after `query` (the first in `args`) for a `$1` in the query, the * next one for `$2`, etc. */ template [[deprecated("Use exec(std::string_view, params) instead.")]] result exec_params(std::string_view query, Args &&...args) { return exec(query, params{*this, args...}, sl::current()); } // Execute parameterised statement, expect a single-row result. /** @throw unexpected_rows if the result does not consist of exactly one row. */ template [[deprecated("Use exec() instead, and call one_row() on the result.")]] row exec_params1(std::string_view query, Args &&...args) { return exec(query, params{*this, args...}).one_row(); } // Execute parameterised statement, expect a result with zero rows. /** @throw unexpected_rows if the result contains rows. */ template [[deprecated( "Use exec(string_view, params) and call no_rows() on the result.")]] result exec_params0(std::string_view query, Args &&...args) { return exec(query, params{*this, args...}).no_rows(); } // Execute parameterised statement, expect exactly a given number of rows. /** @throw unexpected_rows if the result contains the wrong number of rows. */ template [[deprecated("Use exec(), and call expect_rows() on the result.")]] result exec_params_n(std::size_t rows, std::string_view query, Args &&...args) { sl const loc{m_created_loc}; return exec(query, params{*this, args...}, loc) .expect_rows( check_cast(rows, "number of rows", loc), loc); } // Execute parameterised statement, expect exactly a given number of rows. /** @throw unexpected_rows if the result contains the wrong number of rows. */ template [[deprecated("Use exec(), and call expect_rows() on the result.")]] result exec_params_n(result::size_type rows, std::string_view query, Args &&...args) { return exec(query, params{*this, args...}).expect_rows(rows); } /// Execute parameterised query, read full results, iterate rows of data. /** Like @ref query, but the query can contain parameters. * * Converts each row of the result to a `std::tuple` of the types you pass * as template arguments. (The number of template arguments must match the * number of columns in the query's result.) * * Example: * * ```cxx * for ( * auto [name, salary] : * tx.query( * "SELECT name, salary FROM employee" ) * ) * std::cout << name << " earns " << salary << ".\n"; * ``` * * You can't normally convert a field value to `std::string_view`, but this * is one of the places where you can. The underlying string to which the * `string_view` points exists only for the duration of the one iteration. * After that, the buffer that holds the actual string may have disappeared, * or it may contain a new string value. * * If you expect a lot of rows from your query, it's probably faster to use * transaction_base::stream() instead. Or if you need to access metadata of * the result, such as the number of rows in the result, or the number of * rows that your query updates, then you'll need to use * transaction_base::exec() instead. * * @return Something you can iterate using "range `for`" syntax. The actual * type details may change. */ template auto query(std::string_view query, params const &parms, sl loc = sl::current()) { return exec(query, parms, loc).iter(); } /// Perform query parameterised, expect given number of rows, iterate /// results. /** Works like @ref query, but checks that the result has exactly the * expected number of rows. * * @throw unexpected_rows If the query returned the wrong number of rows. * * @return Something you can iterate using "range `for`" syntax. The actual * type details may change. */ template [[deprecated("Use exec(), and call expect_rows() & iter() on the result.")]] auto query_n(result::size_type rows, std::string_view query, params const &parms) { return exec(query, parms).expect_rows(rows).iter(); } /// Perform query, expecting exactly 1 row with 1 field, and convert it. /** This is convenience shorthand for querying exactly one value from the * database. It returns that value, converted to the type you specify. * * @throw unexpected_rows If the query did not return exactly 1 row. * @throw usage_error If the row did not contain exactly 1 field. */ template TYPE query_value( std::string_view query, params const &parms, sl loc = sl::current()) { // The result and field_ref objects are temporaries, but under C++20 // lifetime rules they'll live until after we convert the field to TYPE. return exec(query, parms, loc) .expect_columns(1, loc) .one_field_ref(loc) .as(loc); } /// Perform query returning exactly one row, and convert its fields. /** This is a convenient way of querying one row's worth of data, and * converting its fields to a tuple of the C++-side types you specify. * * @throw unexpected_rows If the query did not return exactly 1 row. * @throw usage_error If the number of columns in the result does not match * the number of fields in the tuple. */ template [[nodiscard]] std::tuple query1(std::string_view query, params const &parms, sl loc = sl::current()) { // The result and row_ref objects are temporaries, but under C++20 lifetime // rules they'll live until after we convert the field to TYPE. return exec(query, parms, loc).one_row_ref(loc).as(loc); } /// Query at most one row of data, and if there is one, convert it. /** If the query produced a row of data, this converts it to a tuple of the * C++ types you specify. Otherwise, this returns no tuple. * * @throw unexpected_rows If the query returned more than 1 row. * @throw usage_error If the number of columns in the result does not match * the number of fields in the tuple. */ template [[nodiscard]] std::optional> query01(std::string_view query, params const &parms, sl loc = sl::current()) { auto const res{exec(query, parms, loc)}; std::optional r{res.opt_row_ref(loc)}; if (r) return {r->as(loc)}; else return {}; } /// Execute a query, load the full result, and perform `func` for each row. /** The query may use parameters. So for example, the query may contain `$1` * to denote the first parameter value in `parms`, and so on. * * Converts each row to data types matching `func`'s parameter types. The * number of columns in the result set must match the number of parameters. * * This is a lot like for_stream(). The differences are: * 1. It can execute some unusual queries that for_stream() can't. * 2. The `exec` functions are faster for small results, but slower for large * results. */ template void for_query( std::string_view query, CALLABLE &&func, params const &parms, sl loc = sl::current()) { exec(query, parms, loc).for_each(std::forward(func), loc); } /// Send a notification. /** Convenience shorthand for executing a "NOTIFY" command. Most of the * logic for handling _incoming_ notifications is in @ref pqxx::connection * (particularly @ref pqxx::connection::listen), but _outgoing_ * notifications happen here. * * Unless this transaction is a nontransaction, the actual notification only * goes out once the outer transaction is committed. * * @param channel Name of the "channel" on which clients will need to be * listening in order to receive this notification. * * @param payload Optional argument string which any listeners will also * receive. If you leave this out, they will receive an empty string as the * payload. */ void notify( std::string_view channel, std::string_view payload, sl = sl::current()); /// Send a notification (without payload). /** Convenience shorthand for executing a "NOTIFY" command. Most of the * logic for handling _incoming_ notifications is in @ref pqxx::connection * (particularly @ref pqxx::connection::listen), but _outgoing_ * notifications happen here. * * Unless this transaction is a nontransaction, the actual notification only * goes out once the outer transaction is committed. * * @param channel Name of the "channel" on which clients will need to be * listening in order to receive this notification. */ void notify(std::string_view channel, sl loc = sl::current()) { notify(channel, {}, loc); } //@} /// Execute a prepared statement, with optional arguments. template [[deprecated("Use exec(prepped, params) instead.")]] result exec_prepared(zview statement, Args &&...args) { return exec(prepped{statement}, params{*this, args...}); } /// Execute a prepared statement taking no parameters. result exec(prepped statement, sl loc = sl::current()) { params const pp; return internal_exec_prepared(statement, pp.make_c_params(loc), loc); } /// Execute prepared statement, read full results, iterate rows of data. /** Like @ref query(std::string_view), but using a prepared statement. * * @return Something you can iterate using "range `for`" syntax. The actual * type details may change. */ template auto query(prepped statement, params const &parms, sl loc = sl::current()) { return exec(statement, parms, loc).iter(); } /// Execute prepared statement, read full results, iterate rows of data. /** Like @ref query(std::string_view), but using a prepared statement. * * @return Something you can iterate using "range `for`" syntax. The actual * type details may change. */ template auto query(prepped statement, sl loc = sl::current()) { return exec(statement, {}, loc).iter(); } /// Perform prepared statement returning exactly 1 value. /** This is just like @ref query_value(std::string_view), but using a * prepared statement. */ template TYPE query_value(prepped statement, params const &parms, sl loc = sl::current()) { // The result and field_ref objects are temporaries, but under C++20 // lifetime rules they'll live until after we convert the field to TYPE. return exec(statement, parms, loc) .expect_columns(1, loc) .one_field_ref(loc) .as(loc); } /// Perform prepared statement returning exactly 1 value. /** This is just like @ref query_value(std::string_view), but using a * prepared statement. */ template TYPE query_value(prepped statement, sl loc = sl::current()) { return exec(statement, {}, loc) .expect_columns(1, loc) .one_field_ref(loc) .as(loc); } /// Execute prepared statement, load result, perform `func` for each row. /** This is just like @ref for_query(std::string_view), but using a prepared * statement. */ template void for_query( prepped statement, CALLABLE &&func, params const &parms, sl loc = sl::current()) { exec(statement, parms, loc).for_each(std::forward(func), loc); } /// Execute prepared statement, load result, perform `func` for each row. /** This is just like @ref for_query(std::string_view), but using a prepared * statement. */ template void for_query(prepped statement, CALLABLE &&func, sl loc = sl::current()) { exec(statement, {}, loc).for_each(std::forward(func), loc); } /// Execute a prepared statement with parameters. result exec(prepped statement, params const &parms, sl loc = sl::current()) { return internal_exec_prepared(statement, parms.make_c_params(loc), loc); } /// Execute a prepared statement, and expect a single-row result. /** @throw pqxx::unexpected_rows if the result was not exactly 1 row. */ template [[deprecated( "Use exec(string_view, params) and call one_row() on the result.")]] row exec_prepared1(zview statement, Args &&...args) { sl const loc{m_created_loc}; return exec(prepped{statement}, params{*this, args...}).one_row(loc); } /// Execute a prepared statement, and expect a result with zero rows. /** @throw pqxx::unexpected_rows if the result contained rows. */ template [[deprecated( "Use exec(prepped, params), and call no_rows() on the result.")]] result exec_prepared0(zview statement, Args &&...args) { sl const loc{m_created_loc}; return exec(prepped{statement}, params{*this, args...}).no_rows(loc); } /// Execute a prepared statement, expect a result with given number of rows. /** @throw pqxx::unexpected_rows if the result did not contain exactly the * given number of rows. */ template [[deprecated( "Use exec(prepped, params), and call expect_rows() on the result.")]] result exec_prepared_n(result::size_type rows, zview statement, Args &&...args) { sl const loc{m_created_loc}; return exec(pqxx::prepped{statement}, params{*this, args...}) .expect_rows(rows, loc); } /** * @name Error/warning output */ //@{ /// Have connection process a warning message. PQXX_ZARGS void process_notice(char const msg[]) const { m_conn.process_notice(msg); } /// Have connection process a warning message. void process_notice(zview msg) const { m_conn.process_notice(msg); } //@} /// The connection in which this transaction lives. [[nodiscard]] constexpr connection &conn() const noexcept { return m_conn; } /// Set session variable using SQL "SET" command. /** @deprecated To set a transaction-local variable, execute an SQL `SET` * command. To set a session variable, use the connection's * @ref set_session_var function. * * @warning When setting a string value, you must make sure that the string * is "safe." If you call @ref quote() on the string, it will return a * safely escaped and quoted version for use as an SQL literal. * * @warning This function executes SQL. Do not try to set or get variables * while a pipeline or table stream is active. * * @param var The variable to set. * @param value The new value to store in the variable. This can be any SQL * expression. */ [[deprecated("Set transaction-local variables using SQL SET statements.")]] void set_variable(std::string_view var, std::string_view value); /// Read session variable using SQL "SHOW" command. /** @warning This executes SQL. Do not try to set or get variables while a * pipeline or table stream is active. */ [[deprecated("Read variables using SQL SHOW statements.")]] std::string get_variable(std::string_view); /// Transaction name, if you passed one to the constructor; or empty string. [[nodiscard]] constexpr std::string_view name() const & noexcept { return m_name; } protected: /// Create a transaction (to be called by implementation classes only). /** The name, if nonempty, must begin with a letter and may contain letters * and digits only. */ transaction_base( connection &, std::string_view, std::shared_ptr rollback_cmd, sl loc = sl::current()); /// Create a transaction (to be called by implementation classes only). /** Its rollback command will be "ROLLBACK". * * The name, if nonempty, must begin with a letter and may contain letters * and digits only. */ transaction_base( connection &cx, std::string_view tname, sl loc = sl::current()); /// Create a transaction (to be called by implementation classes only). explicit transaction_base(connection &cx, sl loc = sl::current()); /// Register this transaction with the connection. void register_transaction(); /// End transaction. To be called by implementing class' destructor. void close(sl = sl::current()) noexcept; /// To be implemented by derived implementation class: commit transaction. virtual void do_commit(sl) = 0; /// Transaction type-specific way of aborting a transaction. /** @warning This will become "final", since this function can be called * from the implementing class destructor. */ virtual void do_abort(sl); /// Set the rollback command. void set_rollback_cmd(std::shared_ptr cmd) { m_rollback_cmd = std::move(cmd); } /// Execute query on connection directly. result direct_exec(std::string_view, std::string_view desc, sl); result direct_exec(std::string_view query, sl loc) { return direct_exec(query, "", loc); } result direct_exec(std::shared_ptr, std::string_view desc, sl); result direct_exec(std::shared_ptr query, sl loc) { return direct_exec(std::move(query), "", loc); } // TODO: Can this be noexcept? /// The `std::source_location` for this transaction's creation. [[nodiscard]] sl created_loc() const { return m_created_loc; } private: enum class status { active, aborted, committed, in_doubt }; /// Compose a @ref conversion_context. /** Gets its @ref encoding_group from the @ref connection, but uses the * `std::source_location` that you pass. */ [[nodiscard]] conversion_context make_context(sl) const; PQXX_PRIVATE void check_pending_error(); result internal_exec_prepared( std::string_view statement, internal::c_params const &args, sl); result internal_exec_params( std::string_view query, internal::c_params const &args, sl); /// Describe this transaction to humans, e.g. "transaction 'foo'". [[nodiscard]] std::string description() const; friend class pqxx::internal::gate::transaction_transaction_focus; PQXX_PRIVATE void register_focus(transaction_focus *); PQXX_PRIVATE void unregister_focus(transaction_focus *) noexcept; PQXX_PRIVATE void register_pending_error(zview, sl) noexcept; PQXX_PRIVATE void register_pending_error(std::string &&, sl) noexcept; /// Like @ref stream(), but takes a tuple rather than a parameter pack. template auto stream_like( std::string_view query, std::tuple const *, sl loc = sl::current()) { return stream(query, loc); } connection &m_conn; /// Current "focus": a pipeline, a nested transaction, a stream... /** This pointer is used for only one purpose: sanity checks against mistakes * such as opening one while another is still active. */ transaction_focus const *m_focus = nullptr; std::string m_name; std::string m_pending_error; /// SQL command for aborting this type of transaction. std::shared_ptr m_rollback_cmd; status m_status = status::active; bool m_registered = false; /// A `std::source_location` for where this transaction object was created. sl m_created_loc; static constexpr std::string_view s_type_name{"transaction"sv}; }; } // namespace pqxx namespace pqxx::internal { /// The SQL command for starting a given type of transaction. template extern const zview begin_cmd; // These are not static members, so "constexpr" does not imply "inline". template<> inline constexpr zview begin_cmd{ "BEGIN"_zv}; template<> inline constexpr zview begin_cmd{ "BEGIN READ ONLY"_zv}; template<> inline constexpr zview begin_cmd{ "BEGIN ISOLATION LEVEL REPEATABLE READ"_zv}; template<> inline constexpr zview begin_cmd{ "BEGIN ISOLATION LEVEL REPEATABLE READ READ ONLY"_zv}; template<> inline constexpr zview begin_cmd{ "BEGIN ISOLATION LEVEL SERIALIZABLE"_zv}; template<> inline constexpr zview begin_cmd{ "BEGIN ISOLATION LEVEL SERIALIZABLE READ ONLY"_zv}; } // namespace pqxx::internal #include "pqxx/internal/stream_query_impl.hxx" #endif libpqxx-8.0.1/include/pqxx/transaction_focus000066400000000000000000000004071516427024100213040ustar00rootroot00000000000000/** * Transaction focus: types which monopolise a transaction's attention. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/types.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/transaction_focus.hxx000066400000000000000000000105551516427024100221170ustar00rootroot00000000000000/** Transaction focus: types which monopolise a transaction's attention. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_TRANSACTION_FOCUS_HXX #define PQXX_TRANSACTION_FOCUS_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include "pqxx/util.hxx" namespace pqxx { /// Base class for things that monopolise a transaction's attention. /** You probably won't need to use this class. But it can be useful to _know_ * that a given libpqxx class is derived from it. * * Pipelines, SQL statements, and data streams are examples of classes derived * from `transaction_focus`. In any given transaction, only one object of * such a class can be active at any given time. */ class PQXX_LIBEXPORT transaction_focus { public: #include "pqxx/internal/ignore-deprecated-pre.hxx" transaction_focus( transaction_base &t, std::string_view cname, std::string_view oname) : m_trans{&t}, m_classname{cname}, m_name{oname} {} transaction_focus( transaction_base &t, std::string_view cname, std::string &&oname) : m_trans{&t}, m_classname{cname}, m_name{std::move(oname)} {} transaction_focus(transaction_base &t, std::string_view cname) : m_trans{&t}, m_classname{cname} {} #include "pqxx/internal/ignore-deprecated-post.hxx" transaction_focus() = delete; transaction_focus(transaction_focus const &) = delete; transaction_focus &operator=(transaction_focus const &) = delete; ~transaction_focus() = default; /// Class name, for human consumption. [[nodiscard]] constexpr std::string_view classname() const noexcept { return m_classname; } /// Name for this object, if the caller passed one; empty string otherwise. [[nodiscard]] std::string_view name() const & noexcept { return m_name; } [[nodiscard]] std::string description() const { return pqxx::internal::describe_object(m_classname, m_name); } #include "pqxx/internal/ignore-deprecated-pre.hxx" transaction_focus(transaction_focus &&other) : m_trans{other.m_trans}, m_classname{other.m_classname}, m_registered{other.m_registered} { // This is a bit more complicated than you might expect. The transaction // has a backpointer to the focus, and we need to transfer that to the new // focus. move_name_and_registration(other); } transaction_focus &operator=(transaction_focus &&other) { if (&other != this) { if (m_registered) unregister_me(); m_trans = other.m_trans; m_classname = other.m_classname; move_name_and_registration(other); } return *this; } #include "pqxx/internal/ignore-deprecated-post.hxx" protected: void register_me(); void unregister_me() noexcept; void reg_pending_error(std::string const &, sl) noexcept; [[nodiscard]] bool registered() const noexcept { return m_registered; } #include "pqxx/internal/ignore-deprecated-pre.hxx" /// The transaction focused on this `transaction_focus`. [[nodiscard]] transaction_base &trans() noexcept { return *m_trans; } /// The transaction focused on this `transaction_focus`. [[nodiscard]] transaction_base const &trans() const noexcept { return *m_trans; } #include "pqxx/internal/ignore-deprecated-post.hxx" // NOLINTBEGIN( // cppcoreguidelines-non-private-member-variables-in-classes, // misc-non-private-member-variables-in-classes // ) [[deprecated( "This will become private. Use trans() instead.")]] transaction_base *m_trans; // NOLINTEND( // cppcoreguidelines-non-private-member-variables-in-classes, // misc-non-private-member-variables-in-classes // ) private: /// Perform part of a move operation. void move_name_and_registration(transaction_focus &other) { bool const reg{other.m_registered}; // Unregister the original while it still owns its name. if (reg) other.unregister_me(); // Now! Quick! Steal that name. m_name = std::move(other.m_name); // Now that we own the name, register ourselves instead. if (reg) this->register_me(); } std::string_view m_classname; std::string m_name; bool m_registered = false; }; } // namespace pqxx #endif libpqxx-8.0.1/include/pqxx/transactor000066400000000000000000000004511516427024100177370ustar00rootroot00000000000000/** pqxx::transactor class. * * pqxx::transactor is a framework-style wrapper for safe transactions. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/transactor.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/transactor.hxx000066400000000000000000000172461516427024100205570ustar00rootroot00000000000000/* Transactor framework, a wrapper for safely retryable transactions. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transactor instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_TRANSACTOR_HXX #define PQXX_TRANSACTOR_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include #include "pqxx/connection.hxx" #include "pqxx/transaction.hxx" namespace pqxx { /** * @defgroup transactor Transactor framework * * Sometimes a transaction can fail for completely transient reasons, such as a * conflict with another transaction in SERIALIZABLE isolation. The right way * to handle those failures is often just to re-run the transaction from * scratch. * * For example, your REST API might be handling each HTTP request in its own * database transaction, and if this kind of transient failure happens, you * simply want to "replay" the whole request, in a fresh transaction. * * You won't necessarily want to execute the exact same SQL commands with the * exact same data. Some of your SQL statements may depend on state that can * vary between retries. Data in the database may already have changed, for * instance. So instead of dumbly replaying the SQL, you re-run the same * application code that produced those SQL commands, from the start. * * The transactor framework makes it a little easier for you to do this safely, * and avoid typical pitfalls. You encapsulate the work that you want to do * into a callable that you pass to the @ref perform function. * * Here's how it works. You write your transaction code as a lambda or * function, which creates its own transaction object, does its work, and * commits at the end. You pass that callback to @ref pqxx::perform, which * runs it for you. * * If there's a failure inside your callback, there will be an exception. Your * transaction object goes out of scope and gets destroyed, so that it aborts * implicitly. Seeing this, @ref perform tries running your callback again. It * stops doing that when the callback succeeds, or when it has failed too many * times, or when there's an error that leaves the database in an unknown * state, such as a lost connection just while we're waiting for the database * to confirm a commit. It all depends on the type of exception. * * The callback takes no arguments. If you're using lambdas, the easy way to * pass arguments is for the lambda to "capture" them from your variables. * * Once your callback succeeds, it can return a result, and @ref perform will * return that result back to you. */ //@{ /// Simple way to execute a transaction with automatic retry. /** * Executes your transaction code as a callback. Repeats it until it completes * normally, or it throws an error other than the few libpqxx-generated * exceptions that the framework understands, or after a given number of failed * attempts, or if the transaction ends in an "in-doubt" state. * * (An in-doubt state is one where libpqxx cannot determine whether the server * finally committed a transaction or not. This can happen if the network * connection to the server is lost just while we're waiting for its reply to * a "commit" statement. The server may have completed the commit, or not, but * it can't tell you because there's no longer a connection. * * Using this still takes a bit of care. If your callback makes use of data * from the database, you'll probably have to query that data within your * callback. If the attempt to perform your callback fails, and the framework * tries again, you'll be in a new transaction and the data in the database may * have changed under your feet. * * Also be careful about changing variables or data structures from within * your callback. The run may still fail, and perhaps get run again. The * ideal way to do it (in most cases) is to return your result from your * callback, and change your program's data state only after @ref perform * completes successfully. * * @param callback Transaction code that can be called with no arguments. * @param attempts Maximum number of times to attempt performing callback. * Must be greater than zero. * @return Whatever your callback returns. */ template inline std::invoke_result_t perform(TRANSACTION_CALLBACK &&callback, int attempts, sl loc = sl::current()) { if (attempts <= 0) throw std::invalid_argument{ "Zero or negative number of attempts passed to pqxx::perform()."}; for (; attempts > 0; --attempts) { try { return std::invoke(callback); } catch (in_doubt_error const &) { // Not sure whether transaction went through or not. The last thing in // the world that we should do now is try again! throw; } catch (statement_completion_unknown const &) { // Not sure whether our last statement succeeded. Don't risk running it // again. throw; } catch (protocol_violation const &) { // This is a subclass of broken_connection, but it's not one where // retrying is likely to do us any good. throw; } catch (broken_connection const &) { // Connection failed. May be worth retrying, if the transactor opens its // own connection. if (attempts <= 1) throw; continue; } catch (transaction_rollback const &) { // Some error that may well be transient, such as serialization failure // or deadlock. Worth retrying. if (attempts <= 1) throw; continue; } } throw pqxx::internal_error{"No outcome reached on perform().", loc}; } /// Simple way to execute a transaction with automatic retry. /** * Executes your transaction code as a callback. Repeats it until it completes * normally, or it throws an error other than the few libpqxx-generated * exceptions that the framework understands, or after a given number of failed * attempts, or if the transaction ends in an "in-doubt" state. * * (An in-doubt state is one where libpqxx cannot determine whether the server * finally committed a transaction or not. This can happen if the network * connection to the server is lost just while we're waiting for its reply to * a "commit" statement. The server may have completed the commit, or not, but * it can't tell you because there's no longer a connection. * * Using this still takes a bit of care. If your callback makes use of data * from the database, you'll probably have to query that data within your * callback. If the attempt to perform your callback fails, and the framework * tries again, you'll be in a new transaction and the data in the database may * have changed under your feet. * * Also be careful about changing variables or data structures from within * your callback. The run may still fail, and perhaps get run again. The * ideal way to do it (in most cases) is to return your result from your * callback, and change your program's data state only after @ref perform * completes successfully. * * @param callback Transaction code that can be called with no arguments. * @param attempts Maximum number of times to attempt performing callback. * Must be greater than zero. * @return Whatever your callback returns. */ template inline std::invoke_result_t perform(TRANSACTION_CALLBACK &&callback, sl loc = sl::current()) { return perform(callback, 3, loc); } } // namespace pqxx //@} #endif libpqxx-8.0.1/include/pqxx/types000066400000000000000000000003551516427024100167260ustar00rootroot00000000000000/** * Basic typedefs and forward declarations. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/types.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/types.hxx000066400000000000000000000304751516427024100175420ustar00rootroot00000000000000/* Basic type aliases and forward declarations. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_TYPES_HXX #define PQXX_TYPES_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include #include #include #include #include #include #include #include #if defined(PQXX_HAVE_STACKTRACE) # include #endif #if defined(PQXX_HAVE_TYPE_DISPLAY) # include #endif namespace pqxx { /// Convenience alias for `std::source_location`. It's just too long. using sl = std::source_location; #if defined(PQXX_HAVE_STACKTRACE) /// Alias for `std::stacktrace`, for brevity. using st = std::stacktrace; #else /// There is no `std::stacktrace` on this system. Use a placeholder. struct stacktrace_placeholder final { constexpr stacktrace_placeholder() noexcept = default; constexpr stacktrace_placeholder(stacktrace_placeholder const &) noexcept = default; /// Defined just so static checkers don't complain about trivial moves. constexpr stacktrace_placeholder(stacktrace_placeholder &&) noexcept {} ~stacktrace_placeholder() noexcept = default; stacktrace_placeholder & operator=(stacktrace_placeholder const &) noexcept = default; stacktrace_placeholder & operator=(stacktrace_placeholder &&) noexcept = default; /// Placeholder for `std::stacktrace::current()`. [[nodiscard]] PQXX_PURE static constexpr stacktrace_placeholder current() noexcept { return {}; } }; /// Placeholder for future `std::stacktrace`. using st = stacktrace_placeholder; #endif /// PostgreSQL database row identifier. using oid = unsigned int; /// Number of rows in a result set. using result_size_type = int; /// Difference between result sizes. using result_difference_type = int; /// Number of fields in a row of database data. using row_size_type = int; /// Difference between row sizes. using row_difference_type = int; /// Number of bytes in a field of database data. using field_size_type = std::size_t; /// Number of bytes in a large object. using large_object_size_type = int64_t; // Forward declarations, to help break compilation dependencies. // These won't necessarily include all classes in libpqxx. class connection; class const_result_iterator; class const_reverse_result_iterator; class const_reverse_row_iterator; class const_row_iterator; class dbtransaction; // 9.0: Remove this. class errorhandler; class field; class largeobjectaccess; class notification_receiver; struct range_error; class result; class row; class stream_from; class transaction_base; /// Format code: is data text or binary? /** Binary-compatible with libpq's format codes. * * Why use an `int` for this when a single bit would be enough? Because this * maps directly to the C-level values used in libpq. */ enum class format : int { text = 0, binary = 1, }; /// Remove any constness, volatile, and reference-ness from a type. /** @deprecated Use `std::remove_cvref` instead. */ template using strip_t = std::remove_cvref_t; /// The type of a container's elements. /** At the time of writing there's a similar thing in `std::experimental`, * which we may or may not end up using for this. */ template using value_type = std::remove_cvref_t>; /// A type one byte in size. template concept char_sized = (sizeof(CHAR) == 1); /// Concept: Any type that we can read as a string of `char`. template concept char_string = std::ranges::contiguous_range and std::same_as>, char>; /// Concept: Anything we can iterate to get things we can read as strings. template concept char_strings = std::ranges::range and char_string>>; /// Concept: Anything we might want to treat as binary data. template concept potential_binary = std::ranges::contiguous_range and char_sized> and not std::is_reference_v>; /// Concept: Binary string, akin to @c std::string for binary data. /** Any type that satisfies this concept can represent an SQL BYTEA value. * * A @c binary has a @c begin(), @c end(), @c size(), and @data(). Each byte * is a @c std::byte, and they must all be laid out contiguously in memory so * we can reference them by a pointer. */ template concept binary = std::ranges::contiguous_range and std::same_as>, std::byte>; /// A series of something that's not bytes. template concept nonbinary_range = std::ranges::range and not std::same_as< std::remove_cvref_t>, std::byte> and not std::same_as< std::remove_cvref_t>, char>; /// Type alias for a view of bytes. using bytes_view = std::span; /// Type alias for a view of writable bytes. using writable_bytes_view = std::span; /// Concept: A value that's not just a reference to values elsewhere. /** This can be an important distinction when returning values. For example, * if a function creates a `std::string` in a local variable, it can't then * return a `std::string_view` referring to that string. By the time the * caller gets to it, the underlying data is no longer valid. * * In most cases these are decisions we make while writing code. But when * converting data to a caller-selected type, there are situations where it's * safe to return a view and there are situations where it's not. */ template concept not_borrowed = not std::is_reference_v and not std::is_pointer_v and not std::ranges::borrowed_range; /// Concept: A C++ `enum` type. template concept enum_type = std::is_enum_v; /// Marker for @ref stream_from constructors: "stream from table." /** @deprecated Use @ref stream_from::table() instead. */ struct from_table_t final {}; /// Marker for @ref stream_from constructors: "stream from query." /** @deprecated Use @ref stream_from::query() instead. */ struct from_query_t final {}; } // namespace pqxx namespace pqxx::internal { #if !defined(PQXX_HAVE_TYPE_DISPLAY) /// Attempt to demangle @c std::type_info::name() to something human-readable. /** Even though this function is `noexcept`, it is technically possible for the * construction of the return value to fail. I've never heard of this ever * happening, but if it does, there is no way to catch the exception anyway * because it happens before `main()`. * * So, if construction of the return value fails, there is no choice but to * terminate. */ PQXX_LIBEXPORT PQXX_ZARGS std::string demangle_type_name(char const[]) noexcept; #endif } // namespace pqxx::internal namespace pqxx { #include "pqxx/internal/ignore-deprecated-pre.hxx" #if defined(PQXX_HAVE_TYPE_DISPLAY) /// A human-readable name for a type, used in error messages and such. template [[deprecated("Use name_type() instead.")]] std::string const type_name{display_string_of(^^TYPE)}; #else /// A human-readable name for a type, used in error messages and such. /** Actually this may not always be very user-friendly. It uses * @c std::type_info::name(). On gcc-like compilers we try to demangle its * output. Visual Studio produces human-friendly names out of the box. * * This variable is not inline. Inlining it gives rise to "memory leak" * warnings from asan, the address sanitizer, possibly from use of * @c std::type_info::name. */ template [[deprecated("Use name_type() instead.")]] std::string const type_name{ pqxx::internal::demangle_type_name(typeid(TYPE).name())}; #endif #include "pqxx/internal/ignore-deprecated-post.hxx" /// Return human-readable name for `TYPE`. template inline constexpr std::string_view name_type() noexcept { #if defined(PQXX_HAVE_TYPE_DISPLAY) return display_string_of(^^TYPE); #else # include "pqxx/internal/ignore-deprecated-pre.hxx" return type_name; # include "pqxx/internal/ignore-deprecated-post.hxx" #endif } // Specialisations of name_type<>() follow. Some are tested, but because they // are so trivial, the coverage tools never notice that they get tested. // There's just no point running coverage for these. // LCOV_EXCL_START /// Specialisation to save on startup work & produce friendlier output. template<> PQXX_PURE constexpr inline std::string_view name_type() noexcept { return "std::string"; } /// Specialisation to save on startup work & produce friendlier output. template<> PQXX_PURE constexpr inline std::string_view name_type() noexcept { return "std::string_view"; } template<> PQXX_PURE constexpr inline std::string_view name_type() noexcept { return "char const *"; } /// Specialisation to save on startup work. template<> PQXX_PURE constexpr inline std::string_view name_type() noexcept { return "bool"; } /// Specialisation to save on startup work. template<> PQXX_PURE constexpr inline std::string_view name_type() noexcept { return "short"; } /// Specialisation to save on startup work. template<> PQXX_PURE constexpr inline std::string_view name_type() noexcept { return "int"; } /// Specialisation to save on startup work. template<> PQXX_PURE constexpr inline std::string_view name_type() noexcept { return "long"; } /// Specialisation to save on startup work. template<> PQXX_PURE constexpr inline std::string_view name_type() noexcept { return "long long"; } /// Specialisation to save on startup work. template<> PQXX_PURE constexpr inline std::string_view name_type() noexcept { return "unsigned short"; } /// Specialisation to save on startup work. template<> PQXX_PURE constexpr inline std::string_view name_type() noexcept { return "unsigned"; } /// Specialisation to save on startup work. template<> PQXX_PURE constexpr inline std::string_view name_type() noexcept { return "unsigned long"; } /// Specialisation to save on startup work. template<> PQXX_PURE constexpr inline std::string_view name_type() noexcept { return "unsigned long long"; } /// Specialisation to save on startup work. template<> PQXX_PURE constexpr inline std::string_view name_type() noexcept { return "float"; } /// Specialisation to save on startup work. template<> PQXX_PURE constexpr inline std::string_view name_type() noexcept { return "double"; } /// Specialisation to save on startup work. template<> PQXX_PURE constexpr inline std::string_view name_type() noexcept { return "long double"; } /// Specialisation to save on startup work. template<> PQXX_PURE constexpr inline std::string_view name_type() noexcept { return "std::nullptr_t"; } // LCOV_EXCL_STOP } // namespace pqxx namespace pqxx::internal { /// Concept: one of the "char" types. template concept char_type = std::same_as, char> or std::same_as, signed char> or std::same_as, unsigned char>; /// Concept: an integral number type. /** Unlike `std::integral`, this does not include the `char` types. */ template concept integer = std::integral and not char_type; } // namespace pqxx::internal /// Placeholders for libpq declarations. /** No actual libpq symbols are exposed in the application's compilation. It's * all abstracted away by libpqxx. * * Internally inside libpqxx, we cast these to their "real" types (the C ones) * when using them. */ namespace pqxx::internal::pq { /// Placeholder for libpq's connection type. using PGconn = void; /// Placeholder for libpq's result type. using PGresult = void; /// Placeholder for libpq's notification type. using PGnotify = void; /// Placeholder for libpq's notice processor type. using PQnoticeProcessor = void (*)(void *, char const *); /// Placeholder for libpq's PQconninfoOption type. using PQconninfoOption = void; } // namespace pqxx::internal::pq #endif libpqxx-8.0.1/include/pqxx/util000066400000000000000000000003501516427024100165320ustar00rootroot00000000000000/** Various utility definitions for libpqxx. */ // Actual definitions in .hxx file so editors and such recognize file type #include "pqxx/internal/header-pre.hxx" #include "pqxx/util.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/util.hxx000066400000000000000000000602251516427024100173470ustar00rootroot00000000000000/* Various utility definitions for libpqxx. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/util instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_UTIL_HXX #define PQXX_UTIL_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pqxx/except.hxx" #include "pqxx/types.hxx" #include "pqxx/version.hxx" /// The home of all libpqxx classes, functions, templates, etc. namespace pqxx {} // namespace pqxx // C++23: Retire wrapper. // PQXX_UNREACHABLE: equivalent to `std::unreachable()` if available. #if defined(__cpp_lib_unreachable) && __cpp_lib_unreachable # define PQXX_UNREACHABLE std::unreachable() #else # define PQXX_UNREACHABLE [[unlikely]] while (false) #endif /// Private namespace for libpqxx's internal use; do not access. /** This namespace hides definitions internal to libpqxx. These are not * supposed to be used by client programs, and they may change at any time * without notice. * * Conversely, if you find something in this namespace tremendously useful, by * all means do lodge a request for its publication. * * @warning Here be dragons! */ namespace pqxx::internal {} // namespace pqxx::internal namespace pqxx { using namespace std::literals; /// Cast a numeric value to another type, or throw if it underflows/overflows. /** Both types must be arithmetic types, and they must either be both integral * or both floating-point types. */ template inline TO check_cast(FROM value, std::string_view description, sl loc = sl::current()) requires( std::is_arithmetic_v and std::is_arithmetic_v and (std::is_integral_v == std::is_integral_v)) { // The rest of this code won't quite work for bool, but bool is trivially // convertible to other arithmetic types as far as I can see. if constexpr (std::is_same_v) return static_cast(value); using to_limits = std::numeric_limits; if constexpr (std::is_integral_v) { // Integral value. These are simple, but only thanks to the standard // library's safe comparison functions. if (std::cmp_less(value, to_limits::lowest())) throw range_error{ std::format( "Underflow casting {} from {} to {}: {}", value, name_type(), name_type(), description), loc}; if (std::cmp_greater(value, (to_limits::max)())) throw range_error{ std::format( "Overflow casting {} from {} to {}: {}", value, name_type(), name_type(), description), loc}; } else if (std::isinf(value)) { // Floating-point infinities. These will always exceed TO's upper or lower // limit, but that's fine; they will translate directly to a TO infinity. } else { // NaN, or a regular floating-point value. A NaN will never be less than // or greater than any value, such as TO's upper/lower bounds. if (value < to_limits::lowest()) throw range_error{ std::format( "Underflow casting {} from {} to {}: {}", value, name_type(), name_type(), description), loc}; if (value > (to_limits::max)()) throw range_error{ std::format( "Overflow casting {} from {} to {}: {}", value, name_type(), name_type(), description), loc}; } return static_cast(value); } // TODO: No longer useful as of PostgreSQL 17: libpq is always thread-safe. /// Descriptor of library's thread-safety model. /** This describes what the library knows about various risks to thread-safety. */ struct PQXX_LIBEXPORT thread_safety_model final { /// A human-readable description of any thread-safety issues. std::string description; /// Is the underlying libpq build thread-safe? bool safe_libpq = false; /// Is Kerberos thread-safe? /** @warning Is currently always `false`. * * If your application uses Kerberos, all accesses to libpqxx or Kerberos * must be serialized. Confine their use to a single thread, or protect it * with a global lock. */ bool safe_kerberos = false; }; /// Describe thread safety available in this build. [[nodiscard]] PQXX_LIBEXPORT thread_safety_model describe_thread_safety(); /// Custom `std::char_trast` if the compiler does not provide one. /** Needed for strings of bytes if the standard library lacks a generic * implementation or a specialisation for `std::byte`. They aren't strictly * required to provide either, and libc++ 19 removed its generic * implementation. * * @deprecated Because of these complications, and because standard strings * aren't really suited to binary data, you should use @ref pqxx::bytes or * @ref pqxx::bytes_view instead. This type will be removed. */ struct byte_char_traits final : std::char_traits { using char_type = std::byte; static void assign(std::byte &a, const std::byte &b) noexcept { a = b; } static bool eq(std::byte a, std::byte b) { return a == b; } static bool lt(std::byte a, std::byte b) { return a < b; } static int compare(const std::byte *a, const std::byte *b, std::size_t size) { return std::memcmp(a, b, size); } /// Deliberately undefined: "guess" the length of an array of bytes. /* This would be nonsense: we can't determine the length of a random sequence * of bytes. There is no terminating zero like there is for C strings. * * But `std::char_traits` requires us to provide this function, so we * declare it without defining it. */ static size_t length(const std::byte *data); PQXX_RETURNS_NONNULL static const std::byte * find(const std::byte *data, std::size_t size, const std::byte &value) { return static_cast( std::memchr(data, static_cast(value), size)); } PQXX_RETURNS_NONNULL static std::byte * move(std::byte *dest, const std::byte *src, std::size_t size) { return static_cast(std::memmove(dest, src, size)); } PQXX_RETURNS_NONNULL static std::byte * copy(std::byte *dest, const std::byte *src, std::size_t size) { return static_cast(std::memcpy(dest, src, size)); } PQXX_RETURNS_NONNULL static std::byte * assign(std::byte *dest, std::size_t size, std::byte value) { return static_cast( std::memset(dest, static_cast(value), size)); } /// Declared but not defined: makes no sense for binary data. static int_type not_eof(int_type value); static std::byte to_char_type(int_type value) { return std::byte(value); } static int_type to_int_type(std::byte value) { return int_type(value); } static bool eq_int_type(int_type a, int_type b) { return a == b; } /// Declared but not defined: makes no sense for binary data. static int_type eof(); }; // Supress warnings from potentially using a deprecated generic // std::char_traits. // Necessary for libc++ 18. #include "pqxx/internal/ignore-deprecated-pre.hxx" /// Type alias for a container containing bytes. using bytes = std::vector; #include "pqxx/internal/ignore-deprecated-post.hxx" /// Cast binary data to a type that libpqxx will recognise as binary. /** There are many different formats for storing binary data in memory. You * may have yours as a `std::string`, or a `std::vector`, or one of * many other types. In libpqxx we commend a container of `std::byte`. * * For libpqxx to recognise your data as binary, we recommend using a * `pqxx::bytes`, or a `pqxx::bytes_view`; but any contiguous block of * `std::byte` should do. * * Use `binary_cast` as a convenience helper to cast your data as a * `pqxx::bytes_view`. * * @warning You must keep the storage holding the actual data alive for as * long as you might use this function's return value. */ template inline bytes_view binary_cast(TYPE const &data) { using item_t = value_type; return std::as_bytes( std::span{std::data(data), std::size(data)}); } /// Construct a type that libpqxx will recognise as binary. /** Takes a data pointer and a size, without being too strict about their * types, and constructs a `pqxx::bytes_view` pointing to the same data. * * This makes it a little easier to turn binary data, in whatever form you * happen to have it, into binary data as libpqxx understands it. */ template bytes_view binary_cast(CHAR const *data, SIZE size) { return binary_cast(std::span{data, check_cast(size)}); } /// The "null" oid. constexpr oid oid_none{0}; /// Ignore an unused item. /** This should no longer be needed. In modern C++, use `[[maybe_unused]]`, * `std::ignore`, and/or the "`_`" (underscore) variable. */ template [[maybe_unused, deprecated("Use [[maybe_unused]], std::ignore, etc.")]] inline constexpr void ignore_unused(T &&...) noexcept {} // clang-tidy rule bug: // NOLINTBEGIN( // cppcoreguidelines-pro-bounds-array-to-pointer-decay, // hicpp-no-array-decay // ) /// Does string `haystack` contain `needle`? /** This is a wrapper for C++23 `haystack.contains(needle)`. It will * disappear when libpqxx requires C++23 or better. */ template inline bool str_contains(HAYSTACK const &haystack, NEEDLE const &needle) requires( std::same_as or std::same_as) { // C++23: Replace with `haystack.contains(needle)`. Retire wrapper. return haystack.find(needle) != HAYSTACK::npos; } // NOLINTEND( // cppcoreguidelines-pro-bounds-array-to-pointer-decay, // hicpp-no-array-decay // ) /// Concept: something that works like a `std::source_location`. /** Needed only so we can test this against test doubles. For any other * purpose, read just `std::source_location` (or @ref pqxx::sl for short). */ template concept c_source_location = requires(SL const loc) { { loc.file_name() } -> std::convertible_to; { loc.function_name() } -> std::convertible_to; { loc.line() } -> std::convertible_to; { loc.column() } -> std::convertible_to; }; /// Represent a `std::source_location` as human-readable text. /** The text is also machine-readable to the extent that many IDEs will let * you click on the text to let you navigate easily to that location in the * source code. */ template PQXX_PURE inline std::string source_loc(LOC const &loc) { char const *const file{loc.file_name()}; assert(file != nullptr); char const *const func{loc.function_name()}; unsigned const line{loc.line()}, column{loc.column()}; // (The standard says this can't be null, but let's be conservative.) bool const have_func{func != nullptr and *func != '\0'}, have_line{line > 0}, have_column{column > 0}; if (have_func and have_line and have_column) { return std::format("{}:{}:{}: ({})", file, line, column, func); } else if (have_func and have_line) { return std::format("{}:{}: ({})", file, line, func); } else if (have_line and have_column) { return std::format("{}:{}:{}:", file, line, column); } else if (have_func) { // (In this case we don't care whether we have a column.) return std::format("{}: ({})", file, func); } else if (have_line) { return std::format("{}:{}:", file, line); } else { return std::format("{}:", file); } } } // namespace pqxx namespace pqxx::internal { using namespace std::literals; /// Check library binary version against application's expectations. /** Helps detect version mismatches between libpqxx headers and the libpqxx * library binary. * * Sometimes users run into trouble linking their code against libpqxx because * they build their own libpqxx, but the system also has a different version * installed; or, they install a dynamically linked application with a * mismatched libpqxx binary. * * This function's definition is in the libpqxx binary, so it knows the version * as it stood when the libpqxx binary was compiled. The calling binary * contains a call to this function (inlined from @ref check_version()), * passing the version numbers as they applied when the application was * compiled. That's why they're called "the app's" version components. */ PQXX_NOINLINE PQXX_LIBEXPORT int check_libpqxx_version( int apps_major, int apps_minor, int apps_patch, std::string_view apps_version); /// Get a raw C string pointer. PQXX_ZARGS inline constexpr char const *as_c_string(char const str[]) noexcept { return str; } /// Get a raw C string pointer. template inline constexpr char const *as_c_string(char (&str)[N]) noexcept { return str; } /// Get a raw C string pointer. template inline constexpr char const *as_c_string(char const (&str)[N]) noexcept { return str; } /// Get a raw C string pointer. inline constexpr char const *as_c_string(std::string const &str) noexcept { return str.c_str(); } // LCOV_EXCL_START /// A safer and more generic replacement for `std::isdigit`. /** Turns out `std::isdigit` isn't as easy to use as it sounds. It takes an * `int`, but requires it to be nonnegative. Which means it's an outright * liability on systems where `char` is signed. */ template inline constexpr bool is_digit(CHAR c) noexcept { return (c >= '0') and (c <= '9'); } #if !defined(NDEBUG) static_assert(is_digit('0')); static_assert(is_digit('1')); static_assert(is_digit('9')); static_assert(not is_digit('a')); static_assert(not is_digit('f')); static_assert(not is_digit('z')); static_assert(not is_digit(' ')); #endif // LCOV_EXCL_STOP /// Describe an object for humans, based on class name and optional name. /** Interprets an empty name as "no name given." */ [[nodiscard]] std::string describe_object(std::string_view class_name, std::string_view name); /// Check validity of registering a new "guest" in a "host." /** The host might be e.g. a connection, and the guest a transaction. The * host can only have one guest at a time, so it is an error to register a new * guest while the host already has a guest. * * If the new registration is an error, this function throws a descriptive * exception. * * Pass the old guest (if any) and the new guest (if any), for both, a type * name (at least if the guest is not null), and optionally an object name * (but which may be omitted if the caller did not assign one). */ void check_unique_register( void const *old_guest, std::string_view old_class, std::string_view old_name, void const *new_guest, std::string_view new_class, std::string_view new_name); /// Like @ref check_unique_register, but for un-registering a guest. /** Pass the guest which was registered, as well as the guest which is being * unregistered, so that the function can check that they are the same one. */ void check_unique_unregister( void const *old_guest, std::string_view old_class, std::string_view old_name, void const *new_guest, std::string_view new_class, std::string_view new_name); /// Compute buffer size needed to escape binary data for use as a BYTEA. /** This uses the hex-escaping format. The return value includes room for the * "\x" prefix. */ PQXX_PURE inline constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept { assert(std::cmp_less( binary_bytes, (std::numeric_limits::max)() / 2u)); return 2 + (2 * binary_bytes) + 1; } /// Compute binary size from the size of its escaped version. /** Do not include a terminating zero in `escaped_bytes`. */ PQXX_PURE inline constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept { if (escaped_bytes < 2u) [[unlikely]] return 0; else return (escaped_bytes - 2) / 2; } /// Hex-escape binary data into a buffer. /** The buffer must have room for `size_esc_bin(std::size(binary_data))` bytes, * and the function will write exactly that number of bytes into the buffer. * This includes a trailing zero. */ PQXX_LIBEXPORT void esc_bin(bytes_view binary_data, std::span buffer) noexcept; /// Hex-escape binary data into a buffer. /** The buffer must have room for `size_esc_bin(std::size(binary_data))` bytes, * and the function will write exactly that number of bytes into the buffer. * This includes a trailing zero. */ template inline void esc_bin(T &&binary_data, std::span buffer) noexcept { esc_bin(binary_cast(binary_data), buffer); } /// Hex-escape binary data into a std::string. PQXX_LIBEXPORT std::string esc_bin(bytes_view binary_data); /// Reconstitute binary data from its escaped version. PQXX_LIBEXPORT void unesc_bin(std::string_view escaped_data, std::span buffer, sl loc); /// Reconstitute binary data from its escaped version. PQXX_LIBEXPORT bytes unesc_bin(std::string_view escaped_data, sl loc); /// Helper for determining a function's parameter types. /** This function has no definition. It's not meant to be actually called. * It's just there for pattern-matching in the compiler, so we can use its * hypothetical return value. */ template std::tuple args_f(RETURN (&func)(ARGS...)); /// Helper for determining a `std::function`'s parameter types. /** This function has no definition. It's not meant to be actually called. * It's just there for pattern-matching in the compiler, so we can use its * hypothetical return value. */ template std::tuple args_f(std::function const &); /// Helper for determining a member function's parameter types. /** This function has no definition. It's not meant to be actually called. * It's just there for pattern-matching in the compiler, so we can use its * hypothetical return value. */ template std::tuple member_args_f(RETURN (CLASS::*)(ARGS...)); /// Helper for determining a const member function's parameter types. /** This function has no definition. It's not meant to be actually called. * It's just there for pattern-matching in the compiler, so we can use its * hypothetical return value. */ template std::tuple member_args_f(RETURN (CLASS::*)(ARGS...) const); /// Helper for determining a callable type's parameter types. /** This specialisation should work for lambdas. * * This function has no definition. It's not meant to be actually called. * It's just there for pattern-matching in the compiler, so we can use its * hypothetical return value. */ template auto args_f(CALLABLE const &f) -> decltype(member_args_f(&CALLABLE::operator())); /// A callable's parameter types, as a tuple. template using args_t = decltype(args_f(std::declval())); /// Apply `std::remove_cvref_t` to each of a tuple type's component types. /** This function has no definition. It is not meant to be called, only to be * used to deduce the right types. */ template std::tuple...> strip_types(std::tuple const &); /// Take a tuple type and apply std::remove_cvref_t to its component types. template using strip_types_t = decltype(strip_types(std::declval())); // LCOV_EXCL_START /// Return original byte for escaped character. PQXX_PURE inline constexpr char unescape_char(char escaped) noexcept { switch (escaped) { case 'b': // Backspace. [[unlikely]] return '\b'; case 'f': // Form feed [[unlikely]] return '\f'; case 'n': // Line feed. return '\n'; case 'r': // Carriage return. return '\r'; case 't': // Horizontal tab. return '\t'; case 'v': // Vertical tab. return '\v'; default: break; } // Regular character ("self-escaped"). return escaped; } #if !defined(NDEBUG) static_assert(unescape_char('a') == 'a'); static_assert(unescape_char('b') == '\b'); static_assert(unescape_char('f') == '\f'); static_assert(unescape_char('n') == '\n'); static_assert(unescape_char('r') == '\r'); static_assert(unescape_char('t') == '\t'); static_assert(unescape_char('v') == '\v'); static_assert(unescape_char('z') == 'z'); #endif // LCOV_EXCL_STOP /// Helper for avoiding type trouble with `strerror_r()`/`strerror_s()`. /** Extracts the error string from a `strerror_s()` or a POSIX-style * `streror_r()` outcome. * * The problem is with `strerror_r()`, really. There's a GNU version which * returns the error string as a `char *`; and there's a POSIX version which * writes the error string into `buffer` and returns a status code. * * Not all compilers will let us handle that with a "if constexpr" on the * return type. In particular, clang 17 on a Mac complains. it insists on * even the non-applicable branch returning the right type. So, instead of * having an `if constexpr` with an `else`, we _overload_ functions for the two * alternatives. */ [[maybe_unused]] PQXX_COLD inline char const * make_strerror_rs_result(int err_result, std::span buffer) { if (err_result == 0) return std::data(buffer); else return "Unknown error; could not retrieve error string."; } /// Helper for avoiding type trouble with `strerror_r()`/`strerror_s()`. /** Extracts the error string from a GNU-style `strerror_r()` outcome. * * There's another overload for th `strerror_s()` and POSIX-style * `strerror_r()` case. */ [[maybe_unused]] PQXX_COLD PQXX_ZARGS inline char const * make_strerror_rs_result(char const *err_result, std::span) { return err_result; } /// Get error string for a given @c errno value. [[nodiscard]] PQXX_COLD inline char const *error_string( [[maybe_unused]] int err_num, [[maybe_unused]] std::span buffer) { // Not entirely clear whether strerror_s will be in std or global namespace. // NOLINTNEXTLINE(google-build-using-namespace) using namespace std; #if defined(PQXX_HAVE_STERROR_S) || defined(PQXX_HAVE_STRERROR_R) # if defined(PQXX_HAVE_STRERROR_S) auto const err_result{ strerror_s(std::data(buffer), std::size(buffer), err_num)}; # else auto const err_result{ strerror_r(err_num, std::data(buffer), std::size(buffer))}; # endif return make_strerror_rs_result(err_result, buffer); #else // Fallback case, hopefully for no actual platforms out there. return "(No error information available.)"; #endif } /// Copy text from `src` into `buf` at offset `dst_offset`. /** This is a wrapper for `std::string_view::copy()` with a few changes. * * First, it checks for overruns and throws @ref pqxx::conversion_overrun if * needed. (To that end, the destination is a `std::span`, not a raw pointer.) * * Second, it takes an offset _into the destination buffer,_ i.e. you can tell * it where in the destination buffer the copy should write, but there's no * parameter to influence which part of `src` you want to copy. You always * copy the whole thing. * * Third, it returns not the number of bytes it copied, but rather, the offset * into `dst` that's right behind the last copied byte. * * If `terminate` is true, also writes a terminating zero. */ template inline std::size_t copy_chars( std::string_view src, std::span dst, std::size_t dst_offset, sl loc) { auto const sz{std::size(src)}; if (std::cmp_greater( dst_offset + sz + std::size_t(terminate), std::size(dst))) throw conversion_overrun{ std::format( "Text copy exceeded buffer space: tried to copy {} bytes '{}' into a " "buffer of {} bytes, at offset {}.", sz, src, std::size(dst), dst_offset), loc}; auto at{dst_offset + src.copy(std::data(dst) + dst_offset, sz)}; if constexpr (terminate) dst[at++] = '\0'; return at; } } // namespace pqxx::internal namespace pqxx::internal::pq { /// Wrapper for `PQfreemem()`, with C++ linkage. PQXX_LIBEXPORT void pqfreemem(void const *) noexcept; } // namespace pqxx::internal::pq #endif libpqxx-8.0.1/include/pqxx/version000066400000000000000000000003301516427024100172400ustar00rootroot00000000000000/** libpqxx version info. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/version.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/version.hxx000066400000000000000000000041031516427024100200500ustar00rootroot00000000000000/* Version info for libpqxx. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/version instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_VERSION_HXX #define PQXX_VERSION_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include namespace pqxx { /// Full libpqxx version string. constexpr inline std::string_view const version{"8.0.1"}; /// Libpqxx ABI version string: major and minor version, but no patch. /** For example, for libpqxx 9.3.1, this will be "9.3". * * @warning Many factors can influence the library's ABI, including compiler, * compiler version, and compilation options. An ABI can also change radically * during release candidate development. So don't count fully on it. */ constexpr inline std::string_view const abi_version{"8.0"}; /// Major libpqxx version number. (E.g. for libpqxx 9.3.1, this will be 9.) constexpr inline int const version_major{8}; /// Minor libpqxx version number. (E.g. for libpqxx 9.3.1, this will be 3.) constexpr inline int const version_minor{0}; /// Libpqxx patch version number. (E.g. for libpqxx 9.3.1, this will be 1.) /** For "special" versions such as pre-releases, the last component of the * version string is not a simple number, and `version_patch` will be -1. */ constexpr inline int const version_patch{1}; } // namespace pqxx // NOLINTBEGIN(modernize-macro-to-enum) /// Full libpqxx version string. @deprecated Use @ref pqxx::version instead. #define PQXX_VERSION "8.0.1" /// Library ABI version. @deprecated Use @ref pqxx::abi_version instead. #define PQXX_ABI "8.0" /// Major version number. @deprecated Use @ref pqxx::version_major instead. #define PQXX_VERSION_MAJOR 8 /// Minor version number. @deprecated Use @ref pqxx::version_minor instead. #define PQXX_VERSION_MINOR 0 // NOLINTEND(modernize-macro-to-enum) #endif libpqxx-8.0.1/include/pqxx/version.hxx.template000066400000000000000000000042301516427024100216630ustar00rootroot00000000000000/* Version info for libpqxx. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/version instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_VERSION_HXX #define PQXX_VERSION_HXX #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include namespace pqxx { /// Full libpqxx version string. constexpr inline std::string_view const version{"@PQXXVERSION@"}; /// Libpqxx ABI version string: major and minor version, but no patch. /** For example, for libpqxx 9.3.1, this will be "9.3". * * @warning Many factors can influence the library's ABI, including compiler, * compiler version, and compilation options. An ABI can also change radically * during release candidate development. So don't count fully on it. */ constexpr inline std::string_view const abi_version{"@PQXX_ABI@"}; /// Major libpqxx version number. (E.g. for libpqxx 9.3.1, this will be 9.) constexpr inline int const version_major{@PQXX_MAJOR@}; /// Minor libpqxx version number. (E.g. for libpqxx 9.3.1, this will be 3.) constexpr inline int const version_minor{@PQXX_MINOR@}; /// Libpqxx patch version number. (E.g. for libpqxx 9.3.1, this will be 1.) /** For "special" versions such as pre-releases, the last component of the * version string is not a simple number, and `version_patch` will be -1. */ constexpr inline int const version_patch{@PQXX_PATCH@}; } // namespace pqxx // NOLINTBEGIN(modernize-macro-to-enum) /// Full libpqxx version string. @deprecated Use @ref pqxx::version instead. #define PQXX_VERSION "@PQXXVERSION@" /// Library ABI version. @deprecated Use @ref pqxx::abi_version instead. #define PQXX_ABI "@PQXX_ABI@" /// Major version number. @deprecated Use @ref pqxx::version_major instead. #define PQXX_VERSION_MAJOR @PQXX_MAJOR@ /// Minor version number. @deprecated Use @ref pqxx::version_minor instead. #define PQXX_VERSION_MINOR @PQXX_MINOR@ // NOLINTEND(modernize-macro-to-enum) #endif libpqxx-8.0.1/include/pqxx/zview000066400000000000000000000003441516427024100167240ustar00rootroot00000000000000/** Zero-terminated string view class. */ // Actual definitions in .hxx file so editors and such recognize file type. #include "pqxx/internal/header-pre.hxx" #include "pqxx/zview.hxx" #include "pqxx/internal/header-post.hxx" libpqxx-8.0.1/include/pqxx/zview.hxx000066400000000000000000000154141516427024100175360ustar00rootroot00000000000000/* Zero-terminated string view. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/zview instead. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_ZVIEW_HXX #define PQXX_ZVIEW_HXX #include #include #include #include #include "pqxx/types.hxx" namespace pqxx { class zview; /// Concept: T is a known zero-terminated string type. /** There's no unified API for these string types. It's just a check for some * known types. Any code that makes use of the concept will still have to * support each of these individually. */ template concept ZString = (std::is_convertible_v, char const *> or std::is_convertible_v, zview> or std::is_convertible_v) and not std::is_convertible_v; /// Marker-type wrapper: zero-terminated `std::string_view`. /** @warning Use this only if the underlying string is zero-terminated. * * When you construct a zview, you are promising that the data pointer is * non-null, and the underlying string is zero-terminated. It otherwise * behaves exactly like a `std::string_view`. * * The terminating zero is not "in" the string, so it does not count as part of * the view's length. * * The added guarantee lets the view be used as a C-style string, which often * matters since libpqxx builds on top of a C library. For this reason, zview * also adds a @ref c_str method. */ class PQXX_LIBEXPORT zview final : public std::string_view { public: /// Default constructor produces a zero-terminated empty string. constexpr zview() noexcept : zview{""} {} /// Convenience overload: construct using pointer and signed length. /** Even though you specify the length, there must still be a zero byte just * beyond that length, at `text[len]`. */ PQXX_ZARGS constexpr zview(char const text[], std::ptrdiff_t len) noexcept( noexcept(std::string_view{text, static_cast(len)})) : std::string_view{text, static_cast(len)} { invariant(); } /// Convenience overload: construct using pointer and signed length. constexpr zview(char text[], std::ptrdiff_t len) noexcept( noexcept(std::string_view{text, static_cast(len)})) : std::string_view{text, static_cast(len)} { invariant(); } /// Explicitly promote a `string_view` to a `zview`. /** @warning This is not just a type conversion. It's the caller making a * promise that the string is zero-terminated. */ explicit constexpr zview(std::string_view other) noexcept : std::string_view{other} { invariant(); } // clang-tidy rule bug: // NOLINTBEGIN( // cppcoreguidelines-pro-bounds-array-to-pointer-decay, // hicpp-no-array-decay // ) /// Construct from any initialiser you might use for `std::string_view`. /** @warning Only do this if you are sure that the string is zero-terminated. */ template explicit constexpr zview(Args &&...args) : std::string_view(std::forward(args)...) { invariant(); } // NOLINTEND( // cppcoreguidelines-pro-bounds-array-to-pointer-decay, // hicpp-no-array-decay // ) // NOLINTBEGIN(google-explicit-constructor,hicpp-explicit-conversions) /// @warning There's an implicit conversion from `std::string`. constexpr zview(std::string const &str) noexcept : std::string_view{str.c_str(), str.size()} { invariant(); } /// Construct a `zview` from a C-style string. /** @warning This scans the string to discover its length. So if you need to * do it many times, it's probably better to create the `zview` once and * re-use it. */ PQXX_ZARGS constexpr zview(char const str[]) noexcept( noexcept(std::string_view{str})) : std::string_view{str} { invariant(); } zview(std::nullptr_t) = delete; /// Construct a `zview` from a string literal. /** A C++ string literal ("foo") normally looks a lot like a pointer to * char const, but that's not really true. It's actually an array of char, * which _devolves_ to a pointer when you pass it. * * For the purpose of creating a `zview` there is one big difference: if we * know the array's size, we don't need to scan through the string in order * to find out its length. */ template PQXX_ZARGS constexpr zview(char const (&literal)[size]) : zview(literal, size - 1) {} // NOLINTEND(google-explicit-constructor,hicpp-explicit-conversions) /// Return as C string. [[nodiscard]] constexpr char const *c_str() const & noexcept { return data(); } // NOLINTBEGIN(google-explicit-constructor,hicpp-explicit-conversions) /// Return as C string. constexpr operator char const *() const noexcept { return data(); } // NOLINTEND(google-explicit-constructor,hicpp-explicit-conversions) /// Disambiguating comparison operator: leave it to `std::string_view`. constexpr bool operator==(zview const &rhs) const noexcept { return std::string_view{*this} == std::string_view{rhs}; } /// Disambiguating comparison operator: leave it to `std::string_view`. constexpr bool operator!=(zview const &rhs) const noexcept { return std::string_view{*this} != std::string_view{rhs}; } private: /// Check invariant: `data()` must be non-null and zero-terminated. [[maybe_unused]] constexpr void invariant() const noexcept { assert(std::data(*this) != nullptr); assert(std::data(*this)[std::size(*this)] == '\0'); } }; template<> inline constexpr std::string_view name_type() noexcept { return "pqxx::zview"; } /// Support @ref zview literals. /** You can "import" this selectively into your namespace, without pulling in * all of the @ref pqxx namespace: * * ```cxx * using pqxx::operator"" _zv; * ``` */ PQXX_ZARGS constexpr zview operator""_zv(char const str[], std::size_t len) noexcept { return zview{str, len}; } /// Disambiguating comparison operator: leave it to `std::string_view`. constexpr inline bool operator==(char const lhs[], pqxx::zview rhs) noexcept { return std::string_view{lhs} == std::string_view{rhs}; } /// Disambiguating comparison operator: leave it to `std::string_view`. constexpr inline bool operator!=(char const lhs[], pqxx::zview rhs) noexcept { return std::string_view{lhs} != std::string_view{rhs}; } } // namespace pqxx /// A zview is a view. template<> inline constexpr bool std::ranges::enable_view{true}; /// A zview is a borrowed range. template<> inline constexpr bool std::ranges::enable_borrowed_range{true}; #endif libpqxx-8.0.1/libpqxx.pc.in000066400000000000000000000004101516427024100156240ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libpqxx Description: C++ client API for the PostgreSQL database management system. Version: @VERSION@ Requires.private: libpq Libs: -L${libdir} -lpqxx Cflags: -I${includedir} libpqxx-8.0.1/pqxx_cxx_feature_checks.ac000066400000000000000000000102241516427024100204320ustar00rootroot00000000000000# Configuration for feature checks. Generated by generate_check_config.py. AC_MSG_CHECKING([PQXX_HAVE_ASSUME]) PQXX_HAVE_ASSUME=yes AC_COMPILE_IFELSE( [read_test(PQXX_HAVE_ASSUME.cxx)], AC_DEFINE( [PQXX_HAVE_ASSUME], 1, [Define if this feature is available.]), PQXX_HAVE_ASSUME=no) AC_MSG_RESULT($PQXX_HAVE_ASSUME) AC_MSG_CHECKING([PQXX_HAVE_CHARCONV_FLOAT]) PQXX_HAVE_CHARCONV_FLOAT=yes AC_COMPILE_IFELSE( [read_test(PQXX_HAVE_CHARCONV_FLOAT.cxx)], AC_DEFINE( [PQXX_HAVE_CHARCONV_FLOAT], 1, [Define if this feature is available.]), PQXX_HAVE_CHARCONV_FLOAT=no) AC_MSG_RESULT($PQXX_HAVE_CHARCONV_FLOAT) AC_MSG_CHECKING([PQXX_HAVE_CXA_DEMANGLE]) PQXX_HAVE_CXA_DEMANGLE=yes AC_COMPILE_IFELSE( [read_test(PQXX_HAVE_CXA_DEMANGLE.cxx)], AC_DEFINE( [PQXX_HAVE_CXA_DEMANGLE], 1, [Define if this feature is available.]), PQXX_HAVE_CXA_DEMANGLE=no) AC_MSG_RESULT($PQXX_HAVE_CXA_DEMANGLE) AC_MSG_CHECKING([PQXX_HAVE_GCC_PURE]) PQXX_HAVE_GCC_PURE=yes AC_COMPILE_IFELSE( [read_test(PQXX_HAVE_GCC_PURE.cxx)], AC_DEFINE( [PQXX_HAVE_GCC_PURE], 1, [Define if this feature is available.]), PQXX_HAVE_GCC_PURE=no) AC_MSG_RESULT($PQXX_HAVE_GCC_PURE) AC_MSG_CHECKING([PQXX_HAVE_GCC_VISIBILITY]) PQXX_HAVE_GCC_VISIBILITY=yes AC_COMPILE_IFELSE( [read_test(PQXX_HAVE_GCC_VISIBILITY.cxx)], AC_DEFINE( [PQXX_HAVE_GCC_VISIBILITY], 1, [Define if this feature is available.]), PQXX_HAVE_GCC_VISIBILITY=no) AC_MSG_RESULT($PQXX_HAVE_GCC_VISIBILITY) AC_MSG_CHECKING([PQXX_HAVE_MULTIDIM]) PQXX_HAVE_MULTIDIM=yes AC_COMPILE_IFELSE( [read_test(PQXX_HAVE_MULTIDIM.cxx)], AC_DEFINE( [PQXX_HAVE_MULTIDIM], 1, [Define if this feature is available.]), PQXX_HAVE_MULTIDIM=no) AC_MSG_RESULT($PQXX_HAVE_MULTIDIM) AC_MSG_CHECKING([PQXX_HAVE_POLL]) PQXX_HAVE_POLL=yes AC_COMPILE_IFELSE( [read_test(PQXX_HAVE_POLL.cxx)], AC_DEFINE( [PQXX_HAVE_POLL], 1, [Define if this feature is available.]), PQXX_HAVE_POLL=no) AC_MSG_RESULT($PQXX_HAVE_POLL) AC_MSG_CHECKING([PQXX_HAVE_RANGES]) PQXX_HAVE_RANGES=yes AC_COMPILE_IFELSE( [read_test(PQXX_HAVE_RANGES.cxx)], AC_DEFINE( [PQXX_HAVE_RANGES], 1, [Define if this feature is available.]), PQXX_HAVE_RANGES=no) AC_MSG_RESULT($PQXX_HAVE_RANGES) AC_MSG_CHECKING([PQXX_HAVE_SLEEP_FOR]) PQXX_HAVE_SLEEP_FOR=yes AC_COMPILE_IFELSE( [read_test(PQXX_HAVE_SLEEP_FOR.cxx)], AC_DEFINE( [PQXX_HAVE_SLEEP_FOR], 1, [Define if this feature is available.]), PQXX_HAVE_SLEEP_FOR=no) AC_MSG_RESULT($PQXX_HAVE_SLEEP_FOR) AC_MSG_CHECKING([PQXX_HAVE_STRERROR_R]) PQXX_HAVE_STRERROR_R=yes AC_COMPILE_IFELSE( [read_test(PQXX_HAVE_STRERROR_R.cxx)], AC_DEFINE( [PQXX_HAVE_STRERROR_R], 1, [Define if this feature is available.]), PQXX_HAVE_STRERROR_R=no) AC_MSG_RESULT($PQXX_HAVE_STRERROR_R) AC_MSG_CHECKING([PQXX_HAVE_STRERROR_S]) PQXX_HAVE_STRERROR_S=yes AC_COMPILE_IFELSE( [read_test(PQXX_HAVE_STRERROR_S.cxx)], AC_DEFINE( [PQXX_HAVE_STRERROR_S], 1, [Define if this feature is available.]), PQXX_HAVE_STRERROR_S=no) AC_MSG_RESULT($PQXX_HAVE_STRERROR_S) AC_MSG_CHECKING([PQXX_HAVE_TYPE_DISPLAY]) PQXX_HAVE_TYPE_DISPLAY=yes AC_COMPILE_IFELSE( [read_test(PQXX_HAVE_TYPE_DISPLAY.cxx)], AC_DEFINE( [PQXX_HAVE_TYPE_DISPLAY], 1, [Define if this feature is available.]), PQXX_HAVE_TYPE_DISPLAY=no) AC_MSG_RESULT($PQXX_HAVE_TYPE_DISPLAY) AC_MSG_CHECKING([PQXX_HAVE_YEAR_MONTH_DAY]) PQXX_HAVE_YEAR_MONTH_DAY=yes AC_COMPILE_IFELSE( [read_test(PQXX_HAVE_YEAR_MONTH_DAY.cxx)], AC_DEFINE( [PQXX_HAVE_YEAR_MONTH_DAY], 1, [Define if this feature is available.]), PQXX_HAVE_YEAR_MONTH_DAY=no) AC_MSG_RESULT($PQXX_HAVE_YEAR_MONTH_DAY) AC_MSG_CHECKING([PQXX_HAVE_ZARGS]) PQXX_HAVE_ZARGS=yes AC_COMPILE_IFELSE( [read_test(PQXX_HAVE_ZARGS.cxx)], AC_DEFINE( [PQXX_HAVE_ZARGS], 1, [Define if this feature is available.]), PQXX_HAVE_ZARGS=no) AC_MSG_RESULT($PQXX_HAVE_ZARGS) # End of config. libpqxx-8.0.1/requirements.json000066400000000000000000000003221516427024100166240ustar00rootroot00000000000000{ "description": "Minimum versions needed of various things.", "c++": "20", "libpq": "13.0", "postgresql": "13.0", "gcc": "13", "clang": "16", "msvc": "2022", "python": "3.11" } libpqxx-8.0.1/src/000077500000000000000000000000001516427024100140005ustar00rootroot00000000000000libpqxx-8.0.1/src/CMakeLists.txt000066400000000000000000000073201516427024100165420ustar00rootroot00000000000000if(NOT PostgreSQL_FOUND) if(POLICY CMP0074) cmake_policy(PUSH) # CMP0074 is `OLD` by `cmake_minimum_required(VERSION 3.7)`, # sets `NEW` to enable support CMake variable `PostgreSQL_ROOT`. cmake_policy(SET CMP0074 NEW) endif() find_package(PostgreSQL REQUIRED) if(POLICY CMP0074) cmake_policy(POP) endif() endif() # When setting up the include paths, mention the binary tree's include # directory *before* the source tree's include directory. If the source tree # happens to contain autoconf-generated config headers, we should still prefer # the ones in the binary tree. # cmake-lint: disable=C0301 macro(LIBRARY_TARGET_SETUP tgt) target_include_directories(${tgt} PUBLIC $ $ $ PRIVATE ${PostgreSQL_INCLUDE_DIRS} ) target_link_libraries(${tgt} PRIVATE PostgreSQL::PostgreSQL) if(WIN32) target_link_libraries(${tgt} PUBLIC wsock32 ws2_32) endif() install(TARGETS ${tgt} EXPORT libpqxx-targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) get_target_property(name ${tgt} NAME) get_target_property(output_name ${tgt} OUTPUT_NAME) if(NOT CMAKE_HOST_WIN32) # Create library symlink get_target_property(target_type ${tgt} TYPE) if(target_type STREQUAL "SHARED_LIBRARY") set(library_prefix ${CMAKE_SHARED_LIBRARY_PREFIX}) set(library_suffix ${CMAKE_SHARED_LIBRARY_SUFFIX}) elseif(target_type STREQUAL "STATIC_LIBRARY") set(library_prefix ${CMAKE_STATIC_LIBRARY_PREFIX}) set(library_suffix ${CMAKE_STATIC_LIBRARY_SUFFIX}) endif() list(APPEND noop_command "${CMAKE_COMMAND}" "-E" "true") list( APPEND create_symlink_command "${CMAKE_COMMAND}" "-E" "create_symlink" "${library_prefix}${output_name}${library_suffix}" "${library_prefix}${name}${library_suffix}") # `add_custom_command()` does nothing if the `OUTPUT_NAME` and `NAME` # properties are equal, otherwise it creates library symlink. add_custom_command(TARGET ${tgt} POST_BUILD COMMAND "$,${noop_command},${create_symlink_command}>" VERBATIM COMMAND_EXPAND_LISTS COMMENT "Ensure library symlink" ) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${library_prefix}${name}${library_suffix} DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() endmacro() file(GLOB CXX_SOURCES *.cxx) add_library(pqxx ${CXX_SOURCES}) add_library(libpqxx::pqxx ALIAS pqxx) get_target_property(pqxx_target_type pqxx TYPE) if(pqxx_target_type STREQUAL "SHARED_LIBRARY") target_compile_definitions(pqxx PUBLIC PQXX_SHARED) endif() # cmake-lint: disable=C0301 set_target_properties( pqxx PROPERTIES OUTPUT_NAME $,pqxx,pqxx-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}> ) LIBRARY_TARGET_SETUP(pqxx) # Install pkg-config file. # cmake-lint: disable=C0103 set(prefix ${CMAKE_INSTALL_PREFIX}) # cmake-lint: disable=C0103 set(exec_prefix \${prefix}) # cmake-lint: disable=C0103 set(libdir "\${prefix}/${CMAKE_INSTALL_LIBDIR}") # cmake-lint: disable=C0103 set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") set(VERSION ${PROJECT_VERSION}) configure_file( ${PROJECT_SOURCE_DIR}/libpqxx.pc.in ${PROJECT_BINARY_DIR}/libpqxx.pc) install(FILES ${PROJECT_BINARY_DIR}/libpqxx.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) libpqxx-8.0.1/src/array.cxx000066400000000000000000000116701516427024100156470ustar00rootroot00000000000000/** Handling of SQL arrays. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include #include "pqxx/internal/header-pre.hxx" #include "pqxx/array.hxx" #include "pqxx/except.hxx" #include "pqxx/internal/array-composite.hxx" #include "pqxx/strconv.hxx" #include "pqxx/util.hxx" #include "pqxx/internal/header-post.hxx" namespace pqxx { /// Find the end of a double-quoted SQL string in an SQL array. template std::size_t array_parser::scan_double_quoted_string(sl loc) const { return pqxx::internal::scan_double_quoted_string(m_input, m_pos, loc); } /// Parse a double-quoted SQL string: un-quote it and un-escape it. template std::string array_parser::parse_double_quoted_string(std::size_t end, sl loc) const { // The only reason why we still let this substring start at the beginning // of the input is so that error messages can still provide a meaningful // offset. return pqxx::internal::parse_double_quoted_string( m_input.substr(0, end), m_pos, loc); } /// Find the end of an unquoted string in an SQL array. /** Assumes UTF-8 or an ASCII-superset single-byte encoding. */ template std::size_t array_parser::scan_unquoted_string(sl loc) const { return pqxx::internal::scan_unquoted_string( m_input, m_pos, loc); } /// Parse an unquoted SQL string. /** Here, the special unquoted value NULL means a null value, not a string * that happens to spell "NULL". */ template std::string_view array_parser::parse_unquoted_string(std::size_t end, sl loc) const { return pqxx::internal::parse_unquoted_string( m_input.substr(0, end), m_pos, loc); } array_parser::array_parser(std::string_view input, encoding_group enc) : m_input{input}, m_impl{specialize_for_encoding(enc, sl::current())} {} template std::pair array_parser::parse_array_step(sl loc) { std::string value{}; if (m_pos >= std::size(m_input)) return std::make_pair(juncture::done, value); auto [found, end] = [this, &value, loc] { // We don't need to do any actual scanning yet, because we're looking for // specific ASCII characters and we're at the beginning of a character. // The first byte in a multibyte character will not be in the ASCII range. switch (m_input[m_pos]) { case '\0': throw failure{"Unexpected zero byte in array.", loc}; case '{': return std::tuple{juncture::row_start, m_pos + 1}; case '}': return std::tuple{juncture::row_end, m_pos + 1}; case '"': { // Double-quoted string. This needs proper scanning. auto const endpoint = scan_double_quoted_string(loc); value = parse_double_quoted_string(endpoint, loc); return std::tuple{juncture::string_value, endpoint}; } default: { // Unquoted string. Needs proper scanning; in fact even the byte we're // currently inspecting may be the first in a multibyte character. auto const endpoint = scan_unquoted_string(loc); value = parse_unquoted_string(endpoint, loc); if (value == "NULL") { // In this one situation, as a special case, NULL means a null // field, not a string that happens to spell "NULL". value.clear(); return std::tuple{juncture::null_value, endpoint}; } else { // The normal case: we just parsed an unquoted string. The value // is what we need. [[likely]] return std::tuple{juncture::string_value, endpoint}; } } } }(); // Skip a trailing field separator, if present. // No need to call the scanner here: if we're not at the end of the string, // we're at the beginning of a character. And if the first byte of a // character is in the ASCII range, it's going to be an ASCII character. if (end < std::size(m_input) and (m_input[end] == ',')) [[unlikely]] ++end; m_pos = end; return std::make_pair(found, value); } array_parser::implementation array_parser::specialize_for_encoding(encoding_group enc, sl loc) { #define PQXX_ENCODING_CASE(GROUP) \ case encoding_group::GROUP: \ return &array_parser::parse_array_step switch (enc) { case encoding_group::unknown: throw usage_error{ "Tried to parse array without knowing its encoding.", loc}; PQXX_ENCODING_CASE(ascii_safe); PQXX_ENCODING_CASE(two_tier); PQXX_ENCODING_CASE(gb18030); PQXX_ENCODING_CASE(sjis); } [[unlikely]] throw pqxx::internal_error{ std::format("Unsupported encoding code: {}.", to_string(enc)), loc}; #undef PQXX_ENCODING_CASE } } // namespace pqxx libpqxx-8.0.1/src/blob.cxx000066400000000000000000000223751516427024100154530ustar00rootroot00000000000000#include "pqxx-source.hxx" #include #include #include #include "pqxx/internal/header-pre.hxx" #include #include "pqxx/blob.hxx" #include "pqxx/except.hxx" #include "pqxx/internal/gates/connection-largeobject.hxx" #include "pqxx/internal/header-post.hxx" namespace { constexpr int INV_WRITE{0x00020000}, INV_READ{0x00040000}; /// Cast a @ref pqxx::internal::pq::PGconn pointer back to a `PGconn` pointer. /** There's really no such thing as a @ref pqxx::internal::pg::PGconn. It's * just a placeholder we use in our headers so we can talk about this type * without actually importing its definition. * * It's not a _forward declaration_ though: before we can use these pointers, * we have to cast them back to their exact original type. That's what this * function does. * * We can't define this centrally because we can't declare it in a header, * because we can't mention its return type in a header without exposing the * libpq type definition there, in the global namespace. */ PQXX_PURE PQXX_INLINE_ONLY inline ::PGconn * real_conn(pqxx::internal::pq::PGconn *ptr) noexcept { return static_cast<::PGconn *>(ptr); } } // namespace pqxx::internal::pq::PGconn *pqxx::blob::raw_conn(pqxx::connection *cx) noexcept { pqxx::internal::gate::connection_largeobject const gate{*cx}; return gate.raw_connection(); } pqxx::internal::pq::PGconn * pqxx::blob::raw_conn(pqxx::dbtransaction const &tx) noexcept { return raw_conn(&tx.conn()); } std::string pqxx::blob::errmsg(connection const *cx) { pqxx::internal::gate::const_connection_largeobject const gate{*cx}; return gate.error_message(); } pqxx::blob pqxx::blob::open_internal(dbtransaction &tx, oid id, int mode, sl loc) { auto &cx{tx.conn()}; int const fd{lo_open(real_conn(raw_conn(&cx)), id, mode)}; if (fd == -1) throw pqxx::failure{ std::format( "Could not open binary large object {}: {}", id, errmsg(&cx)), loc}; return {cx, fd}; } pqxx::oid pqxx::blob::create(dbtransaction &tx, oid id, sl loc) { oid const actual_id{lo_create(real_conn(raw_conn(tx)), id)}; if (actual_id == 0) throw failure{ std::format( "Could not create binary large object: {}", errmsg(&tx.conn())), loc}; return actual_id; } void pqxx::blob::remove(dbtransaction &tx, oid id, sl loc) { if (id == 0) throw usage_error{ "Trying to delete binary large object without an ID.", loc}; if (lo_unlink(real_conn(raw_conn(tx)), id) == -1) throw failure{ std::format( "Could not delete large object {}: {}", id, errmsg(&tx.conn())), loc}; } pqxx::blob pqxx::blob::open_r(dbtransaction &tx, oid id, sl loc) { return open_internal(tx, id, INV_READ, loc); } pqxx::blob pqxx::blob::open_w(dbtransaction &tx, oid id, sl loc) { return open_internal(tx, id, INV_WRITE, loc); } pqxx::blob pqxx::blob::open_rw(dbtransaction &tx, oid id, sl loc) { return open_internal(tx, id, INV_READ | INV_WRITE, loc); } pqxx::blob::blob(blob &&other) : m_conn{std::exchange(other.m_conn, nullptr)}, m_fd{std::exchange(other.m_fd, -1)} {} pqxx::blob &pqxx::blob::operator=(blob &&other) { if (m_fd != -1) lo_close(real_conn(raw_conn(m_conn)), m_fd); m_conn = std::exchange(other.m_conn, nullptr); m_fd = std::exchange(other.m_fd, -1); return *this; } pqxx::blob::~blob() { try { close(); } catch (std::exception const &e) { if (m_conn != nullptr) { m_conn->process_notice("Failure while closing binary large object:\n"); // TODO: Make at least an attempt to append a newline. m_conn->process_notice(e.what()); } } } void pqxx::blob::close() { if (m_fd != -1) { lo_close(real_conn(raw_conn(m_conn)), m_fd); m_fd = -1; m_conn = nullptr; } } std::size_t pqxx::blob::raw_read(std::byte buf[], std::size_t size, sl loc) { if (m_conn == nullptr) throw usage_error{ "Attempt to read from a closed binary large object.", loc}; if (size > chunk_limit) throw range_error{ "Reads from a binary large object must be less than 2 GB at once.", loc}; auto data{reinterpret_cast(buf)}; int const received{lo_read(real_conn(raw_conn(m_conn)), m_fd, data, size)}; if (received < 0) throw failure{ std::format("Could not read from binary large object: {}", errmsg()), loc}; return static_cast(received); } std::size_t pqxx::blob::read(bytes &buf, std::size_t size, sl loc) { buf.resize(size); auto const received{raw_read(std::data(buf), size, loc)}; buf.resize(received); return static_cast(received); } void pqxx::blob::raw_write(bytes_view data, sl loc) { if (m_conn == nullptr) throw usage_error{ "Attempt to write to a closed binary large object.", loc}; auto const sz{std::size(data)}; if (sz > chunk_limit) throw range_error{"Write to binary large object exceeds 2GB limit.", loc}; auto ptr{reinterpret_cast(std::data(data))}; int const written{lo_write(real_conn(raw_conn(m_conn)), m_fd, ptr, sz)}; if (written < 0) throw failure{ std::format("Write to binary large object failed: {}", errmsg()), loc}; } void pqxx::blob::resize(std::int64_t size, sl loc) { if (m_conn == nullptr) throw usage_error{"Attempt to resize a closed binary large object.", loc}; if (lo_truncate64(real_conn(raw_conn(m_conn)), m_fd, size) < 0) throw failure{ std::format("Binary large object truncation failed: {}", errmsg()), loc}; } std::int64_t pqxx::blob::tell(sl loc) const { if (m_conn == nullptr) throw usage_error{"Attempt to tell() a closed binary large object.", loc}; std::int64_t const offset{lo_tell64(real_conn(raw_conn(m_conn)), m_fd)}; if (offset < 0) throw failure{ std::format("Error reading binary large object position: {}", errmsg()), loc}; return offset; } std::int64_t pqxx::blob::seek(std::int64_t offset, int whence, sl loc) { if (m_conn == nullptr) throw usage_error{"Attempt to seek() a closed binary large object.", loc}; std::int64_t const seek_result{ lo_lseek64(real_conn(raw_conn(m_conn)), m_fd, offset, whence)}; if (seek_result < 0) throw failure{ std::format("Error during seek on binary large object: {}", errmsg()), loc}; return seek_result; } std::int64_t pqxx::blob::seek_abs(std::int64_t offset, sl loc) { return this->seek(offset, SEEK_SET, loc); } std::int64_t pqxx::blob::seek_rel(std::int64_t offset, sl loc) { return this->seek(offset, SEEK_CUR, loc); } std::int64_t pqxx::blob::seek_end(std::int64_t offset, sl loc) { return this->seek(offset, SEEK_END, loc); } pqxx::oid pqxx::blob::from_buf(dbtransaction &tx, bytes_view data, oid id, sl loc) { oid const actual_id{create(tx, id, loc)}; try { open_w(tx, actual_id, loc).write(data, loc); } catch (std::exception const &) { try { remove(tx, id, loc); } catch (std::exception const &e) { try { tx.conn().process_notice(std::format( "Could not clean up partially created large object {}: {}\n", id, e.what())); } catch (std::exception const &) {} } throw; } return actual_id; } void pqxx::blob::append_from_buf( dbtransaction &tx, bytes_view data, oid id, sl loc) { if (std::size(data) > chunk_limit) throw range_error{ "Writes to a binary large object must be less than 2 GB at once.", loc}; blob b{open_w(tx, id, loc)}; b.seek_end(0, loc); b.write(data, loc); } void pqxx::blob::to_buf( dbtransaction &tx, oid id, bytes &buf, std::size_t max_size, sl loc) { open_r(tx, id, loc).read(buf, max_size, loc); } std::size_t pqxx::blob::append_to_buf( dbtransaction &tx, oid id, std::int64_t offset, bytes &buf, std::size_t append_max, sl loc) { if (append_max > chunk_limit) throw range_error{ "Reads from a binary large object must be less than 2 GB at once.", loc}; auto b{open_r(tx, id, loc)}; b.seek_abs(offset, loc); auto const org_size{std::size(buf)}; buf.resize(org_size + append_max); try { auto here{reinterpret_cast(std::data(buf) + org_size)}; auto chunk{static_cast( lo_read(real_conn(raw_conn(b.m_conn)), b.m_fd, here, append_max))}; buf.resize(org_size + chunk); return chunk; } catch (std::exception const &) { buf.resize(org_size); throw; } } pqxx::oid pqxx::blob::from_file(dbtransaction &tx, zview path, sl loc) { auto id{lo_import(real_conn(raw_conn(tx)), path.c_str())}; if (id == 0) throw failure{ std::format( "Could not import '{}' as a binary large object: {}", to_string(path), errmsg(tx)), loc}; return id; } pqxx::oid pqxx::blob::from_file(dbtransaction &tx, zview path, oid id, sl loc) { auto actual_id{ lo_import_with_oid(real_conn(raw_conn(tx)), path.c_str(), id)}; if (actual_id == 0) throw failure{ std::format( "Could not import '{}' as binary large object {}: {}", to_string(path), id, errmsg(tx)), loc}; return actual_id; } void pqxx::blob::to_file(dbtransaction &tx, oid id, zview path, sl loc) { if (lo_export(real_conn(raw_conn(tx)), id, path.c_str()) < 0) throw failure{ std::format( "Could not export binary large object {} to file '{}': {}", id, to_string(path), errmsg(tx)), loc}; } libpqxx-8.0.1/src/connection.cxx000066400000000000000000001177751516427024100167050ustar00rootroot00000000000000/** Implementation of the pqxx::connection class. * * pqxx::connection encapsulates a connection to a database. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" // For ioctlsocket(). // We would normally include this after the standard headers, but MinGW warns // that we can't include windows.h before winsock2.h, and some of the standard // headers probably include windows.h. #if defined(_WIN32) && __has_include() # include #endif #include #include #include #include #include #include #include #include #include #include #include #include // For fcntl(). #if __has_include() # include #endif #if __has_include() # include #endif #include "pqxx/internal/header-pre.hxx" extern "C" { #include } #include "pqxx/internal/wait.hxx" #include "pqxx/nontransaction.hxx" #include "pqxx/notification.hxx" #include "pqxx/pipeline.hxx" #include "pqxx/result.hxx" #include "pqxx/strconv.hxx" #include "pqxx/transaction.hxx" #include "pqxx/internal/gates/errorhandler-connection.hxx" #include "pqxx/internal/gates/result-connection.hxx" #include "pqxx/internal/gates/result-creation.hxx" #include "pqxx/internal/header-post.hxx" namespace { void process_notice_raw( pqxx::internal::notice_waiters *waiters, pqxx::zview msg) noexcept { if ((waiters != nullptr) and not msg.empty()) { auto const rbegin = std::crbegin(waiters->errorhandlers), rend = std::crend(waiters->errorhandlers); for (auto i{rbegin}; (i != rend) and (**i)(msg.data()); ++i); if (waiters->notice_handler) waiters->notice_handler(msg); } } /// Cast a @ref pqxx::internal::pq::PGconn pointer back to a `PGconn` pointer. /** There's really no such thing as a @ref pqxx::internal::pq::PGconn. It's * just a placeholder we use in our headers so we can talk about this type * without actually importing its definition. * * It's not a _forward declaration_ though: before we can use these pointers, * we have to cast them back to their exact original type. That's what this * function does. * * We can't define this centrally because we can't declare it in a header, * because we can't mention its return type in a header without exposing the * libpq type definition there, in the global namespace. */ PQXX_PURE PQXX_INLINE_ONLY inline ::PGconn * real_conn(pqxx::internal::pq::PGconn *ptr) noexcept { return static_cast<::PGconn *>(ptr); } /// Cast a @ref pqxx::internal::pq::PGconn pointer back to a `PGconn` pointer. /** There's really no such thing as a @ref pqxx::internal::pq::PGconn. It's * just a placeholder we use in our headers so we can talk about this type * without actually importing its definition. * * It's not a _forward declaration_ though: before we can use these pointers, * we have to cast them back to their exact original type. That's what this * function does. * * We can't define this centrally because we can't declare it in a header, * because we can't mention its return type in a header without exposing the * libpq type definition there, in the global namespace. */ PQXX_PURE PQXX_INLINE_ONLY inline ::PGconn const * real_conn(pqxx::internal::pq::PGconn const *ptr) noexcept { return static_cast<::PGconn const *>(ptr); } /// Wrapper for `PQerrorMessage()` that takes our `PGconn` placeholder type. PQXX_INLINE_ONLY inline char const * pq_error_message(pqxx::internal::pq::PGconn *ptr) noexcept { return PQerrorMessage(real_conn(ptr)); } /// Wrapper for `PQfinish()` that takes our `PGconn` placeholder type. PQXX_INLINE_ONLY inline void pq_finish(pqxx::internal::pq::PGconn *ptr) noexcept { PQfinish(real_conn(ptr)); } /// Wrapper for `PQport()` that takes our `PGconn` placeholder type. PQXX_INLINE_ONLY inline char const * pq_port(pqxx::internal::pq::PGconn *ptr) noexcept { return PQport(real_conn(ptr)); } /// Wrapper for `PQgetResult()` that deals in our placeholder types. PQXX_INLINE_ONLY inline pqxx::internal::pq::PGresult * pq_get_result(pqxx::internal::pq::PGconn *ptr) noexcept { return PQgetResult(real_conn(ptr)); } /// Wrapper for `PQexec()` that deals in our placeholder types. PQXX_INLINE_ONLY inline pqxx::internal::pq::PGresult * pq_exec(pqxx::internal::pq::PGconn *ptr, char const *q) noexcept { return PQexec(real_conn(ptr), q); } /// Wrapper for `PQputCopyData()` that deals in our placeholder types. PQXX_INLINE_ONLY inline int pq_put_copy_data( pqxx::internal::pq::PGconn *ptr, char const q[], int n) noexcept { return PQputCopyData(real_conn(ptr), q, n); } } // namespace extern "C" { // The PQnoticeProcessor that receives an error or warning from libpq and // sends it to the appropriate connection for processing. PQXX_ZARGS void pqxx_notice_processor(void *data, char const *msg) noexcept { process_notice_raw( static_cast(data), pqxx::zview{msg}); } } // extern "C" using namespace std::literals; PQXX_COLD PQXX_LIBEXPORT void pqxx::internal::skip_init_ssl(int skips) noexcept { // We got "skip flags," but we pass to libpq which libraries we *do* want it // to initialise. PQinitOpenSSL( (skips & (1 << skip_init::openssl)) == 0, (skips & (1 << skip_init::crypto)) == 0); } pqxx::connection::connection(connection &&rhs, sl loc) : m_conn{rhs.m_conn}, m_notice_waiters{std::move(rhs.m_notice_waiters)}, m_notification_handlers{std::move(rhs.m_notification_handlers)}, m_created_loc{loc}, m_unique_id{rhs.m_unique_id} { rhs.check_movable(loc); rhs.m_conn = nullptr; } pqxx::connection::connection( connection::connect_mode, zview connection_string, sl loc) : m_conn{PQconnectStart(connection_string.c_str())}, m_created_loc{loc} { if (m_conn == nullptr) throw std::bad_alloc{}; set_up_notice_handlers(); if (status() == CONNECTION_BAD) { std::string const msg{pq_error_message(m_conn)}; pq_finish(m_conn); m_conn = nullptr; throw pqxx::broken_connection{msg, loc}; } } pqxx::connection::connection(internal::pq::PGconn *raw_conn, sl loc) : m_conn{raw_conn}, m_created_loc{loc} { set_up_notice_handlers(); } std::pair pqxx::connection::poll_connect(sl loc) { switch (PQconnectPoll(real_conn(m_conn))) { case PGRES_POLLING_FAILED: throw pqxx::broken_connection{pq_error_message(m_conn), loc}; case PGRES_POLLING_READING: return std::make_pair(true, false); case PGRES_POLLING_WRITING: return std::make_pair(false, true); case PGRES_POLLING_OK: if (not is_open()) throw pqxx::broken_connection{pq_error_message(m_conn), loc}; [[likely]] return std::make_pair(false, false); case PGRES_POLLING_ACTIVE: throw internal_error{ "Nonblocking connection poll returned obsolete 'active' state.", loc}; default: throw internal_error{ "Nonblocking connection poll returned unknown value.", loc}; } } void pqxx::connection::set_up_notice_handlers() { if (not m_notice_waiters) m_notice_waiters = std::make_shared(); // Our notice processor gets a pointer to our notice_waiters. We can't // just pass "this" to it, because it may get called at a time when the // pqxx::connection has already been destroyed and only a pqxx::result // remains. if (m_conn != nullptr) PQsetNoticeProcessor( real_conn(m_conn), pqxx_notice_processor, m_notice_waiters.get()); } void pqxx::connection::complete_connection(sl loc) { if (m_conn == nullptr) throw std::bad_alloc{}; try { if (not is_open()) throw broken_connection{pq_error_message(m_conn), loc}; constexpr int min_proto{3}; if (auto const proto_ver{protocol_version()}; proto_ver < min_proto) { if (proto_ver == 0) throw broken_connection{"No connection.", loc}; else throw version_mismatch{ std::format( "Unsupported frontend/backend protocol version; {} is the " "minimum.", min_proto), loc}; } constexpr int min_server{110'000}; if (server_version() < min_server) throw version_mismatch{ std::format( "Unsupported server version; the minimum is {}.{}.", min_server / 10'000, min_server % 10'000), loc}; } catch (std::exception const &) { pq_finish(m_conn); m_conn = nullptr; throw; } } namespace { /// Return value-terminated array of `PQconninfoOption` into a `std::range`. /** The termination condition is the `keyword` field being null. */ std::span span_options(PQconninfoOption const *opts) noexcept { PQconninfoOption const *here{opts}; while (here->keyword != nullptr) ++here; return {opts, static_cast(here - opts)}; } /// If `opts` is not null, free the options array to which it points. void delete_pg_conn_option(pqxx::internal::pq::PQconninfoOption *opts) noexcept { PQconninfoFree(static_cast(opts)); } } // namespace namespace pqxx::internal { connection_string_parser::connection_string_parser( char const connection_string[], sl loc) : m_options{nullptr, delete_pg_conn_option} { if ((connection_string != nullptr) and (connection_string[0] != '\0')) { char *errmsg{nullptr}; m_options = opts_pointer{ PQconninfoParse(connection_string, &errmsg), delete_pg_conn_option}; std::unique_ptr const errmsg_guard{errmsg, pqxx::internal::pq::pqfreemem}; if (not m_options) { if (errmsg) throw broken_connection{ std::format("Error in connection string: {}", errmsg), loc}; else throw broken_connection{"Could not parse connection string.", loc}; } } } connection_string_parser::~connection_string_parser() noexcept = default; std::array, 2u> connection_string_parser::parse() const { std::array, 2u> output{}; if (m_options) { // Was a value specified for this connection option? static constexpr auto has_value{ [](PQconninfoOption const &o) { return o.val != nullptr; }}; // A span across the parsed connection string options. auto const parsed{ span_options(static_cast(m_options.get()))}; // This will allocate room for all possible options, since the array of // PQconninfoOption we got from libpq includes options that were not // specified (though their "val" will be null and we won't include them in // our output). It also includes room for a terminating null. // // The generous allocation is probably no big deal though since there are // only so many different connection options. It also saves us having to // worry about reserving space when we add in any key/value parameters // later. std::get<0>(output).reserve(std::size(parsed)); std::get<1>(output).reserve(std::size(parsed)); for (auto const &o : parsed | std::ranges::views::filter(has_value)) { std::get<0>(output).push_back(o.keyword); std::get<1>(output).push_back(o.val); } } return output; } } // namespace pqxx::internal void pqxx::connection::init( std::vector const &keys, std::vector const &values, sl loc) { m_conn = PQconnectdbParams(keys.data(), values.data(), 0); set_up_notice_handlers(); complete_connection(loc); } void pqxx::connection::check_movable(sl loc) const { if (m_trans) throw pqxx::usage_error{ "Moving a connection with a transaction open.", loc}; if (not std::empty(m_receivers)) throw pqxx::usage_error{ "Moving a connection with notification receivers registered.", loc}; } void pqxx::connection::check_overwritable(sl loc) const { if (m_trans) throw pqxx::usage_error{ "Moving a connection onto one with a transaction open.", loc}; if (not std::empty(m_receivers)) throw usage_error{ "Moving a connection onto one " "with notification receivers registered.", loc}; } pqxx::connection &pqxx::connection::operator=(connection &&rhs) { check_overwritable(m_created_loc); rhs.check_movable(m_created_loc); // Close our old connection, if any. close(m_created_loc); m_conn = std::exchange(rhs.m_conn, nullptr); m_unique_id = rhs.m_unique_id; m_notice_waiters = std::move(rhs.m_notice_waiters); m_notification_handlers = std::move(rhs.m_notification_handlers); m_created_loc = rhs.m_created_loc; return *this; } pqxx::result pqxx::connection::make_result( internal::pq::PGresult *pgr, std::shared_ptr const &query, std::string_view desc, sl loc) { std::shared_ptr const smart{ pgr, internal::clear_result}; if (not smart) { if (is_open()) throw failure(err_msg()); else throw broken_connection{"Lost connection to the database server.", loc}; } auto const enc{get_encoding_group(loc)}; auto r{pqxx::internal::gate::result_creation::create( smart, query, m_notice_waiters, enc)}; pqxx::internal::gate::result_creation{r}.check_status(desc, loc); return r; } PQXX_COLD int pqxx::connection::backendpid() const & noexcept { return (m_conn == nullptr) ? 0 : PQbackendPID(real_conn(m_conn)); } namespace { PQXX_PURE int socket_of(::pqxx::internal::pq::PGconn const *c) noexcept { return (c == nullptr) ? -1 : PQsocket(real_conn(c)); } } // namespace int pqxx::connection::sock() const & noexcept { return socket_of(m_conn); } PQXX_COLD int pqxx::connection::protocol_version() const noexcept { return (m_conn == nullptr) ? 0 : PQprotocolVersion(real_conn(m_conn)); } PQXX_COLD int pqxx::connection::server_version() const noexcept { return PQserverVersion(real_conn(m_conn)); } void pqxx::connection::set_variable( std::string_view var, std::string_view value, sl loc) & { exec(std::format("SET {}={}", quote_name(var), value), loc); } std::string pqxx::connection::get_variable(std::string_view var, sl loc) { return exec(std::format("SHOW {}", quote_name(var)), loc) .at(0) .at(0) .as(std::string{}); } std::string pqxx::connection::get_var(std::string_view var, sl loc) { // (Variables can't be null, so far as I can make out.) return exec(std::format("SHOW {}", quote_name(var)), loc) .one_field_ref(loc) .as(loc); } bool pqxx::connection::is_open() const noexcept { return status() == CONNECTION_OK; } void pqxx::connection::process_notice(char const msg[]) noexcept { process_notice(zview{msg}); } void pqxx::connection::process_notice(zview msg) noexcept { if (not msg.empty()) process_notice_raw(m_notice_waiters.get(), msg); } PQXX_COLD void pqxx::connection::trace(FILE *out) noexcept { if (m_conn) { if (out) PQtrace(real_conn(m_conn), out); else PQuntrace(real_conn(m_conn)); } } PQXX_COLD void pqxx::connection::add_receiver(pqxx::notification_receiver *n, sl loc) { if (n == nullptr) throw argument_error{"Null receiver registered", loc}; // Add to receiver list and attempt to start listening. auto const p{m_receivers.find(n->channel())}; auto const new_value{receiver_list::value_type{n->channel(), n}}; if (p == std::end(m_receivers)) { // Not listening on this event yet, start doing so. auto const lq{std::make_shared( std::format("LISTEN {}", quote_name(n->channel())))}; make_result(pq_exec(m_conn, lq->c_str()), lq, *lq, loc); m_receivers.insert(new_value); } else { m_receivers.insert(p, new_value); } } void pqxx::connection::listen( std::string_view channel, notification_handler handler, sl loc) { if (m_trans != nullptr) throw usage_error{ std::format( "Attempting to listen for notifications on '{}' while transaction is " "active.", channel), loc}; std::string str_name{channel}; auto const pos{m_notification_handlers.lower_bound(str_name)}, handlers_end{std::end(m_notification_handlers)}; if (handler) { // Setting a handler. if ((pos != handlers_end) and (pos->first == channel)) { // Overwrite existing handler. m_notification_handlers.insert_or_assign( pos, std::move(str_name), std::move(handler)); } else { // We had no handler installed for this name. Start listening. exec(std::format("LISTEN {}", quote_name(channel)), loc).no_rows(loc); m_notification_handlers.emplace_hint(pos, channel, std::move(handler)); } } else { // Installing an empty handler. That's equivalent to removing whatever // handler may have been installed previously. if (pos != handlers_end) { // Yes, we had a handler for this name. Remove it. exec(std::format("UNLISTEN {}", quote_name(channel)), loc).no_rows(loc); m_notification_handlers.erase(pos); } } } PQXX_COLD void pqxx::connection::remove_receiver( pqxx::notification_receiver *T, sl loc) noexcept { if (T == nullptr) return; try { auto needle{ std::pair{T->channel(), T}}; auto R{m_receivers.equal_range(needle.first)}; auto i{find(R.first, R.second, needle)}; if (i == R.second) { [[unlikely]] process_notice(std::format( "Attempt to remove unknown receiver '{}'\n", needle.first)); } else { // Erase first; otherwise a notification for the same receiver may yet // come in and wreak havoc. Thanks Dragan Milenkovic. bool const gone{R.second == ++R.first}; m_receivers.erase(i); if (gone) exec(std::format("UNLISTEN {}", quote_name(needle.first)), loc); } } catch (std::exception const &e) { // TODO: Make at least an attempt to append a newline. process_notice(e.what()); } } bool pqxx::connection::consume_input() noexcept { return PQconsumeInput(real_conn(m_conn)) != 0; } bool pqxx::connection::is_busy() const noexcept { return PQisBusy(real_conn(m_conn)) != 0; } namespace { /// Wrapper for `PQfreeCancel`, with C++ linkage. void wrap_pgfreecancel(PGcancel *ptr) { PQfreeCancel(ptr); } /// A fairly arbitrary buffer size for error strings and such. constexpr int buf_size{500u}; } // namespace PQXX_COLD void pqxx::connection::cancel_query(sl loc) { std::unique_ptr const cancel{ PQgetCancel(real_conn(m_conn)), wrap_pgfreecancel}; if (cancel == nullptr) [[unlikely]] throw std::bad_alloc{}; std::array errbuf{}; auto const err{errbuf.data()}; auto const c{PQcancel(cancel.get(), err, buf_size)}; if (c == 0) [[unlikely]] throw pqxx::sql_error{ std::string{err, std::size(errbuf)}, "[cancel]", "", loc}; } #if defined(_WIN32) || __has_include() void pqxx::connection::set_blocking(bool block, sl loc) & { auto const fd{sock()}; # if defined _WIN32 unsigned long mode{not block}; if (std::cmp_not_equal( ::ioctlsocket(static_cast(fd), FIONBIO, &mode), 0)) { std::array errbuf{}; char const *err{pqxx::internal::error_string(WSAGetLastError(), errbuf)}; throw broken_connection{ std::format("Could not set socket's blocking mode: {}", err), loc}; } # else // _WIN32 std::array errbuf{}; auto flags{::fcntl(fd, F_GETFL, 0)}; if (flags == -1) { char const *const err{pqxx::internal::error_string(errno, errbuf)}; throw broken_connection{ std::format("Could not get socket state: {}", err), loc}; } if (block) flags &= ~O_NONBLOCK; else flags |= O_NONBLOCK; if (::fcntl(fd, F_SETFL, flags) == -1) { char const *const err{pqxx::internal::error_string(errno, errbuf)}; throw broken_connection{ std::format("Could not set socket's blocking mode: {}", err), loc}; } # endif // _WIN32 } #endif // defined(_WIN32) || __has_include() PQXX_COLD void pqxx::connection::set_verbosity(error_verbosity verbosity) & noexcept { PQsetErrorVerbosity(real_conn(m_conn), static_cast(verbosity)); } namespace { /// Unique pointer to PGnotify. using notify_ptr = std::unique_ptr; /// Get one notification from a connection, or null. notify_ptr get_notif(pqxx::internal::pq::PGconn *cx) { return {PQnotifies(real_conn(cx)), pqxx::internal::pq::pqfreemem}; } } // namespace int pqxx::connection::get_notifs(sl loc) { if (not consume_input()) throw broken_connection{"Connection lost.", loc}; // Even if somehow we receive notifications during our transaction, don't // deliver them. if (m_trans != nullptr) [[unlikely]] return 0; int notifs = 0; // Old mechanism. This is going away. for (auto N{get_notif(m_conn)}; N.get(); N = get_notif(m_conn)) { notifs++; std::string const channel{N->relname}; auto const Hit{m_receivers.equal_range(channel)}; if (Hit.second != Hit.first) { std::string const payload{N->extra}; for (auto i{Hit.first}; i != Hit.second; ++i) try { (*i->second)(payload, N->be_pid); } catch (std::exception const &e) { try { process_notice(std::format( "Exception in notification receiver '{}': {}\n", i->first, e.what())); } catch (std::bad_alloc const &) { // Out of memory. Try to get the message out in a more robust way. process_notice( "Exception in notification receiver, " "and also ran out of memory\n"); } catch (std::exception const &) { process_notice( "Exception in notification receiver " "(compounded by other error)\n"); } } } auto const handler{m_notification_handlers.find(N->relname)}; if (handler != std::end(m_notification_handlers)) (handler->second)(notification{ .conn = *this, .channel = channel, .payload = N->extra, .backend_pid = N->be_pid, }); N.reset(); } return notifs; } PQXX_COLD char const *pqxx::connection::dbname() const noexcept { return PQdb(real_conn(m_conn)); } PQXX_COLD char const *pqxx::connection::username() const noexcept { return PQuser(real_conn(m_conn)); } PQXX_COLD char const *pqxx::connection::hostname() const noexcept { return PQhost(real_conn(m_conn)); } PQXX_COLD char const *pqxx::connection::port() const noexcept { return pq_port(m_conn); } PQXX_COLD std::optional pqxx::connection::port_number(sl loc) const { char const *const ptr{pq_port(m_conn)}; if ((ptr == nullptr) or (*ptr == '\0')) return {}; else return from_string( ptr, conversion_context{encoding_group::ascii_safe, loc}); } char const *pqxx::connection::err_msg() const noexcept { return (m_conn == nullptr) ? "No connection to database" : pq_error_message(m_conn); } PQXX_COLD void pqxx::connection::register_errorhandler(errorhandler *handler) { m_notice_waiters->errorhandlers.push_back(handler); } PQXX_COLD void pqxx::connection::unregister_errorhandler(errorhandler *handler) noexcept { // The errorhandler itself will take care of nulling its pointer to this // connection. m_notice_waiters->errorhandlers.remove(handler); } PQXX_COLD std::vector pqxx::connection::get_errorhandlers() const { return { std::begin(m_notice_waiters->errorhandlers), std::end(m_notice_waiters->errorhandlers)}; } pqxx::result pqxx::connection::exec(std::string_view query, std::string_view desc, sl loc) { return exec(std::make_shared(query), desc, loc); } pqxx::result pqxx::connection::exec( std::shared_ptr const &query, std::string_view desc, sl loc) { auto res{make_result(pq_exec(m_conn, query->c_str()), query, desc, loc)}; get_notifs(loc); return res; } std::string pqxx::connection::encrypt_password( char const user[], char const password[], char const *algorithm) { auto const buf{ PQencryptPasswordConn(real_conn(m_conn), password, user, algorithm)}; std::unique_ptr const ptr{ buf, pqxx::internal::pq::pqfreemem}; return (ptr.get()); } void pqxx::connection::prepare( char const name[], char const definition[], sl loc) & { auto const q{ std::make_shared(std::format("[PREPARE {}]", name))}; auto const r{make_result( PQprepare(real_conn(m_conn), name, definition, 0, nullptr), q, *q, loc)}; } void pqxx::connection::prepare(char const definition[], sl loc) & { this->prepare("", definition, loc); } void pqxx::connection::unprepare(std::string_view name, sl loc) { exec(std::format("DEALLOCATE {}", quote_name(name)), loc); } pqxx::result pqxx::connection::exec_prepared( std::string_view statement, internal::c_params const &args, sl loc) { auto const q{std::make_shared(statement)}; auto const pq_result{PQexecPrepared( real_conn(m_conn), q->c_str(), check_cast(std::size(args.values), "exec_prepared"sv, loc), args.values.data(), args.lengths.data(), args.formats.data(), static_cast(format::text))}; auto r{make_result(pq_result, q, statement, loc)}; get_notifs(loc); return r; } void pqxx::connection::close(sl) { // Just in case PQfinish() doesn't handle nullptr nicely. if (m_conn == nullptr) return; try { if (m_trans) [[unlikely]] process_notice(std::format( "Closing connection while {} is still open.\n", internal::describe_object("transaction"sv, m_trans->name()))); if (not std::empty(m_receivers)) { [[unlikely]] process_notice( "Closing connection with outstanding receivers.\n"); m_receivers.clear(); } if (m_notice_waiters) { // It's a bit iffy to unregister these in this destructor. There may // still be result objects that want to process notices. But it's an // improvement over the 7.9-and-older situation where you'd simply get a // stale pointer. Better yet, this whole mechanism is going away. #include "pqxx/internal/ignore-deprecated-pre.hxx" auto old_handlers{get_errorhandlers()}; #include "pqxx/internal/ignore-deprecated-post.hxx" auto const rbegin{std::crbegin(old_handlers)}, rend{std::crend(old_handlers)}; for (auto i{rbegin}; i != rend; ++i) pqxx::internal::gate::errorhandler_connection{**i}.unregister(); } pq_finish(m_conn); m_conn = nullptr; } catch (std::exception const &) { m_conn = nullptr; throw; } } int pqxx::connection::status() const noexcept { return PQstatus(real_conn(m_conn)); } namespace { /// Return a name for t, if t is non-null and has a name; or empty string. std::string_view get_name(pqxx::transaction_base const *t) { return (t == nullptr) ? ""sv : t->name(); } } // namespace void pqxx::connection::register_transaction(transaction_base *t) { internal::check_unique_register( m_trans, "transaction", get_name(m_trans), t, "transaction", get_name(t)); m_trans = t; } void pqxx::connection::unregister_transaction(transaction_base *t) noexcept { try { internal::check_unique_unregister( m_trans, "transaction", get_name(m_trans), t, "transaction", get_name(t)); } catch (std::exception const &e) { // TODO: Make at least an attempt to append a newline. process_notice(e.what()); } m_trans = nullptr; } std::pair, std::size_t> pqxx::connection::read_copy_line(sl loc) { char *buf{nullptr}; // Allocate once, re-use across invocations. static auto const q{std::make_shared("[END COPY]")}; auto const line_len{PQgetCopyData(real_conn(m_conn), &buf, false)}; switch (line_len) { case -2: // Error. throw failure{ std::format("Reading of table data failed: {}", err_msg()), loc}; case -1: // End of COPY. make_result(pq_get_result(m_conn), q, *q, loc); return std::make_pair( std::unique_ptr{ nullptr, pqxx::internal::pq::pqfreemem}, 0u); case 0: // "Come back later." throw internal_error{"table read inexplicably went asynchronous", loc}; default: // Success, got buffer size. [[likely]] { // Line size includes a trailing zero, which we ignore. auto const text_len{static_cast(line_len) - 1}; return std::make_pair( std::unique_ptr{ buf, pqxx::internal::pq::pqfreemem}, text_len); } } } void pqxx::connection::write_copy_line(std::string_view line, sl loc) { static std::string const err_prefix{"Error writing to table: "}; auto const size{check_cast( std::ssize(line), "Line in stream_to is too long to process."sv, loc)}; if (pq_put_copy_data(m_conn, line.data(), size) <= 0) [[unlikely]] throw failure{err_prefix + err_msg(), loc}; if (pq_put_copy_data(m_conn, "\n", 1) <= 0) [[unlikely]] throw failure{err_prefix + err_msg(), loc}; } void pqxx::connection::end_copy_write(sl loc) { int const res{PQputCopyEnd(real_conn(m_conn), nullptr)}; switch (res) { case -1: throw failure{std::format("Write to table failed: {}", err_msg()), loc}; case 0: throw internal_error{"table write is inexplicably asynchronous", loc}; case 1: // Normal termination. Retrieve result object. break; default: throw internal_error{ std::format("unexpected result {} from PQputCopyEnd()", res), loc}; } static auto const q{std::make_shared("[END COPY]")}; make_result(pq_get_result(m_conn), q, *q, loc); } void pqxx::connection::start_exec(char const query[]) { if (PQsendQuery(real_conn(m_conn), query) == 0) [[unlikely]] throw failure{err_msg()}; } pqxx::internal::pq::PGresult *pqxx::connection::get_result() { return pq_get_result(m_conn); } std::size_t pqxx::connection::esc_to_buf( std::string_view text, std::span buf, sl loc) const { int err{0}; auto const copied{PQescapeStringConn( real_conn(m_conn), std::data(buf), std::data(text), std::size(text), &err)}; if (err) [[unlikely]] throw argument_error{err_msg(), loc}; return copied; } std::string pqxx::connection::esc(std::string_view text, sl loc) const { std::string buf; buf.resize(2 * std::size(text) + 1); auto const copied{esc_to_buf(text, buf, loc)}; buf.resize(copied); return buf; } std::string pqxx::connection::esc_raw(bytes_view bin) const { return pqxx::internal::esc_bin(bin); } std::string pqxx::connection::quote_raw(bytes_view bytes) const { return std::format("'{}'::bytea", esc_raw(bytes)); } std::string pqxx::connection::quote_name(std::string_view identifier) const { std::unique_ptr const buf{ PQescapeIdentifier( real_conn(m_conn), identifier.data(), std::size(identifier)), pqxx::internal::pq::pqfreemem}; if (buf == nullptr) [[unlikely]] throw failure{err_msg()}; return std::string{buf.get()}; } std::string pqxx::connection::quote_table(std::string_view table_name) const { return this->quote_name(table_name); } std::string pqxx::connection::quote_table(table_path path) const { return separated_list( ".", std::begin(path), std::end(path), [this](auto name) { return this->quote_name(*name); }); } std::string pqxx::connection::esc_like( std::string_view text, char escape_char, sl loc) const { auto const sz{std::size(text)}; if (sz == 0u) return ""; auto const data{std::data(text)}; auto const finder{ pqxx::internal::get_char_finder<'_', '%'>(get_encoding_group(loc), loc)}; // We're going to loop in a counterintuitive order. First we look for the // end of the leading sequence of unremarkable characters. auto next{finder(text, 0, loc)}; if (next >= sz) // No special characters at all. Copy the entire input. return std::string{text}; // Still here? Then we'll need to do some actual escaping. Start a buffer. // // In the worst case we'll need 2 * sz bytes. So why not just reserve those? // Because if the string is short, reserving too much space may lose us the // Short String Optimization and cost us an unnecessary memory allocation. // // For large inputs, std::string will have an efficient growth algorithm so // it's not like we'll be re-allocating for every byte. std::string out; // Append any leading unremarkable characters that we just scanned. out.append(data, data + next); // Now we loop. This is the counterintuitive part. We'll be dealing in // chunks of text, each _starting_ with a special character with zero or more // unremarkable ones after. for (std::size_t here{next}; here < sz; here = next) { // So we found a special character. It's exactly 1 byte long. assert((data[here] == '%') or (data[here] == '_')); // Look for the next stopping point after that, whether another special // character or the end of the input. (This search may even start at the // end of the input, and find nothing at all.) next = finder(text, here + 1, loc); // Now we start appending: an escape character, followed by the special // character (so that it gets escaped) and its tail of unremarkable // characters after that. This way we copy the special character and the // unremarkable ones all in one go. out.push_back(escape_char); out.append(data + here, data + next); } return out; } int pqxx::connection::await_notification(sl loc) { return await_notification(10, 0, loc); } int pqxx::connection::await_notification( std::time_t seconds, long microseconds, sl loc) { int const notifs = get_notifs(loc); if (notifs == 0) { [[likely]] internal::wait_fd( socket_of(m_conn), true, false, check_cast(seconds, "Seconds out of range.", loc), check_cast(microseconds, "Microseconds out of range.", loc)); return get_notifs(loc); } return notifs; } std::string pqxx::connection::adorn_name(std::string_view n) { auto const id{to_string(++m_unique_id)}; if (std::empty(n)) return std::format("x{}", id); else return std::format("{}_{}", n, id); } std::string pqxx::connection::get_client_encoding(sl loc) const { return internal::name_encoding(encoding_id(loc)); } PQXX_ZARGS PQXX_COLD void pqxx::connection::set_client_encoding(char const encoding[], sl loc) & { if ((encoding == nullptr) or (encoding[0] == '\0')) throw pqxx::argument_error{ "No encoding string passed to set_client_encoding.", loc}; // TODO: Remove this check once JOHAB is gone from all supported versions. if ( ((encoding[0] == 'J') or (encoding[0] == 'j')) and ((encoding[1] == 'O') or (encoding[1] == 'o')) and ((encoding[2] == 'H') or (encoding[2] == 'h')) and ((encoding[3] == 'A') or (encoding[3] == 'a')) and ((encoding[4] == 'B') or (encoding[4] == 'b')) and (encoding[5] == '\0')) { throw pqxx::argument_error{"JOHAB encoding is not supported.", loc}; } switch (auto const retval{PQsetClientEncoding(real_conn(m_conn), encoding)}; retval) { case 0: // OK. [[likely]] break; case -1: if (is_open()) throw failure{ std::format("Setting client encoding failed ('{}').", encoding), loc}; else throw broken_connection{"Lost connection to the database server.", loc}; default: throw internal_error{ std::format("Unexpected result from PQsetClientEncoding: {}", retval), loc}; } } int pqxx::connection::encoding_id(sl loc) const { int const enc{PQclientEncoding(real_conn(m_conn))}; if (enc == -1) { // PQclientEncoding does not query the database, but it does check for // broken connections. And unfortunately, we check the encoding right // *before* checking a query result for failure. So, we need to handle // connection failure here and it will apply in lots of places. // TODO: Make pqxx::result::result(...) do all the checking. [[unlikely]] if (is_open()) throw failure{"Could not obtain client encoding.", loc}; else throw broken_connection{"Lost connection to the database server.", loc}; } [[likely]] return enc; } pqxx::result pqxx::connection::exec_params( std::string_view query, internal::c_params const &args, sl loc) { auto const q{std::make_shared(query)}; auto const pq_result{PQexecParams( real_conn(m_conn), q->c_str(), check_cast(std::size(args.values), "exec_params"sv, loc), nullptr, args.values.data(), args.lengths.data(), args.formats.data(), static_cast(format::text))}; auto r{make_result(pq_result, q, loc)}; get_notifs(loc); return r; } namespace { /// Get the prevailing default value for a connection parameter. char const *get_default(PQconninfoOption const &opt) noexcept { if (opt.envvar == nullptr) { // There's no environment variable for this setting. The only default is // the one that was compiled in. return opt.compiled; } // As of C++11, std::getenv() uses thread-local storage, so it should be // thread-safe. MSVC still warns about it though. #if defined(_MSC_VER) # pragma warning(push) # pragma warning(disable : 4996) #endif char const *var{std::getenv(opt.envvar)}; #if defined(_MSC_VER) # pragma warning(pop) #endif if (var == nullptr) { // There's an environment variable for this setting, but it's not set. return opt.compiled; } // The environment variable is the prevailing default. return var; } /// Wrapper for `PQconninfoFree()`, with C++ linkage. void pqconninfofree(PQconninfoOption *ptr) { PQconninfoFree(ptr); } /// Quote and escape a connection string parameter as needed. /** There's no encoding support here because all of that is based on client * encodings. And there's no such thing when we're not connected yet */ std::string quote_connect_param(std::string_view val) { std::string buf; buf.reserve(2 * std::size(val) + 2); bool const quote{ pqxx::str_contains(val, ' ') or pqxx::str_contains(val, '\'')}; if (quote) buf += '\''; for (auto c : val) { if ((c == '\\') or (c == '\'')) buf += '\\'; buf += c; } if (quote) buf += '\''; return buf; } } // namespace std::string pqxx::connection::connection_string() const { if (m_conn == nullptr) [[unlikely]] throw usage_error{"Can't get connection string: connection is not open."}; std::unique_ptr const parms{PQconninfo(real_conn(m_conn)), pqconninfofree}; if (parms == nullptr) throw std::bad_alloc{}; std::string buf; for (std::size_t i{0}; parms.get()[i].keyword != nullptr; ++i) { auto const param{parms.get()[i]}; if (param.val != nullptr) { auto const default_val{get_default(param)}; // Skip over parameters that have the default value. if ( (default_val == nullptr) or (std::strcmp(param.val, default_val) != 0)) { if (not std::empty(buf)) buf.push_back(' '); buf += param.keyword; buf.push_back('='); // There is no particular encoding support for connection strings in // libpq, not even percent-encoding. They just have to be in ASCII or // some ASCII-safe encoding. buf += quote_connect_param(param.val); } } } return buf; } #if defined(_WIN32) || __has_include() pqxx::connecting::connecting(zview connection_string, sl loc) : m_conn{connection::connect_nonblocking, connection_string, loc} {} #endif // defined(_WIN32) || __has_include( #if defined(_WIN32) || __has_include() void pqxx::connecting::process(sl loc) & { auto const [reading, writing]{m_conn.poll_connect(loc)}; m_reading = reading; m_writing = writing; } #endif // defined(_WIN32) || __has_include( #if defined(_WIN32) || __has_include() pqxx::connection pqxx::connecting::produce(sl loc) && { if (!done()) throw usage_error{ "Tried to produce a nonblocking connection before it was done.", loc}; m_conn.complete_connection(loc); return {std::move(m_conn), loc}; } #endif // defined(_WIN32) || __has_include() libpqxx-8.0.1/src/cursor.cxx000066400000000000000000000203641516427024100160460ustar00rootroot00000000000000/** Implementation of libpqxx STL-style cursor classes. * * These classes wrap SQL cursors in STL-like interfaces. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include "pqxx/internal/header-pre.hxx" #include "pqxx/cursor.hxx" #include "pqxx/internal/gates/icursor_iterator-icursorstream.hxx" #include "pqxx/internal/gates/icursorstream-icursor_iterator.hxx" #include "pqxx/result.hxx" #include "pqxx/strconv.hxx" #include "pqxx/transaction.hxx" #include "pqxx/internal/header-post.hxx" #include "pqxx/internal/ignore-deprecated-pre.hxx" pqxx::cursor_base::cursor_base( connection &context, std::string_view Name, bool embellish_name, sl loc) : m_name{embellish_name ? context.adorn_name(Name) : Name}, m_created_loc{loc} {} #include "pqxx/internal/ignore-deprecated-post.hxx" pqxx::result::size_type pqxx::internal::obtain_stateless_cursor_size(sql_cursor &cur, sl loc) { if (cur.endpos() == -1) cur.move(cursor_base::all(), loc); return result::size_type(cur.endpos() - 1); } pqxx::result pqxx::internal::stateless_cursor_retrieve( sql_cursor &cur, result::difference_type size, result::difference_type begin_pos, result::difference_type end_pos, sl loc) { if (begin_pos < 0 or begin_pos > size) throw range_error{"Starting position out of range", loc}; if (end_pos < -1) end_pos = -1; else if (end_pos > size) end_pos = size; if (begin_pos == end_pos) return cur.empty_result(); int const direction{((begin_pos < end_pos) ? 1 : -1)}; cur.move((begin_pos - direction) - (cur.pos() - 1), loc); return cur.fetch(end_pos - begin_pos, loc); } pqxx::icursorstream::icursorstream( transaction_base &context, std::string_view query, std::string_view basename, difference_type sstride, sl loc) : m_cur{ context, query, basename, cursor_base::forward_only, cursor_base::read_only, cursor_base::owned, false, loc}, m_stride{sstride}, m_realpos{0}, m_reqpos{0} { set_stride(sstride, loc); } pqxx::icursorstream::icursorstream( transaction_base &context, field const &cname, difference_type sstride, cursor_base::ownership_policy op, sl loc) : m_cur{context, cname.c_str(), op}, m_stride{sstride}, m_realpos{0}, m_reqpos{0} { set_stride(sstride, loc); } void pqxx::icursorstream::set_stride(difference_type stride, sl loc) & { if (stride < 1) throw argument_error{ std::format("Attempt to set cursor stride to {}.", stride), loc}; m_stride = stride; } pqxx::result pqxx::icursorstream::fetchblock(sl loc) { result r{m_cur.fetch(m_stride, loc)}; m_realpos += std::size(r); if (std::empty(r)) m_done = true; return r; } pqxx::icursorstream &pqxx::icursorstream::ignore(std::streamsize n, sl loc) & { auto offset{m_cur.move(difference_type(n), loc)}; m_realpos += offset; if (offset < n) m_done = true; return *this; } pqxx::icursorstream::size_type pqxx::icursorstream::forward(size_type n) { m_reqpos += difference_type(n) * m_stride; return icursorstream::size_type(m_reqpos); } void pqxx::icursorstream::insert_iterator(icursor_iterator *i) noexcept { pqxx::internal::gate::icursor_iterator_icursorstream{*i}.set_next( m_iterators); if (m_iterators != nullptr) pqxx::internal::gate::icursor_iterator_icursorstream{*m_iterators} .set_prev(i); m_iterators = i; } void pqxx::icursorstream::remove_iterator(icursor_iterator *i) const noexcept { pqxx::internal::gate::icursor_iterator_icursorstream igate{*i}; if (i == m_iterators) { m_iterators = igate.get_next(); if (m_iterators != nullptr) pqxx::internal::gate::icursor_iterator_icursorstream{*m_iterators} .set_prev(nullptr); } else { auto prev{igate.get_prev()}, next{igate.get_next()}; pqxx::internal::gate::icursor_iterator_icursorstream{*prev}.set_next(next); if (next != nullptr) pqxx::internal::gate::icursor_iterator_icursorstream{*next}.set_prev( prev); } igate.set_prev(nullptr); igate.set_next(nullptr); } void pqxx::icursorstream::service_iterators(difference_type topos, sl loc) { if (topos < m_realpos) return; using todolist = std::multimap; todolist todo; for (icursor_iterator *i{m_iterators}, *next{}; i != nullptr; i = next) { pqxx::internal::gate::icursor_iterator_icursorstream const gate{*i}; auto const ipos{gate.pos()}; if (ipos >= m_realpos and ipos <= topos) todo.insert(todolist::value_type(ipos, i)); next = gate.get_next(); } auto const todo_end = std::end(todo); for (auto i{std::begin(todo)}; i != todo_end;) { auto const readpos{i->first}; if (readpos > m_realpos) ignore(readpos - m_realpos); result const r{fetchblock(loc)}; for (; i != todo_end and i->first == readpos; ++i) pqxx::internal::gate::icursor_iterator_icursorstream{*i->second}.fill(r); } } pqxx::icursor_iterator::icursor_iterator() noexcept : m_pos{0} {} pqxx::icursor_iterator::icursor_iterator(istream_type &s) noexcept : m_stream{&s}, m_pos{difference_type( pqxx::internal::gate::icursorstream_icursor_iterator(s).forward(0))} { pqxx::internal::gate::icursorstream_icursor_iterator{*m_stream} .insert_iterator(this); } pqxx::icursor_iterator::icursor_iterator(icursor_iterator const &rhs) noexcept : m_stream{rhs.m_stream}, m_here{rhs.m_here}, m_pos{rhs.m_pos} { if (m_stream != nullptr) pqxx::internal::gate::icursorstream_icursor_iterator{*m_stream} .insert_iterator(this); } pqxx::icursor_iterator::~icursor_iterator() noexcept { if (m_stream != nullptr) pqxx::internal::gate::icursorstream_icursor_iterator{*m_stream} .remove_iterator(this); } pqxx::icursor_iterator pqxx::icursor_iterator::operator++(int) & { icursor_iterator const old{*this}; m_pos = difference_type( pqxx::internal::gate::icursorstream_icursor_iterator{*m_stream}.forward()); m_here.clear(); return old; } pqxx::icursor_iterator &pqxx::icursor_iterator::operator++() { m_pos = difference_type( pqxx::internal::gate::icursorstream_icursor_iterator{*m_stream}.forward()); m_here.clear(); return *this; } pqxx::icursor_iterator &pqxx::icursor_iterator::operator+=(difference_type n) { if (n <= 0) [[unlikely]] { if (n == 0) return *this; throw argument_error{"Advancing icursor_iterator by negative offset."}; } [[likely]] m_pos = difference_type( pqxx::internal::gate::icursorstream_icursor_iterator{*m_stream}.forward( icursorstream::size_type(n))); m_here.clear(); return *this; } pqxx::icursor_iterator & pqxx::icursor_iterator::operator=(icursor_iterator const &rhs) noexcept { if (&rhs == this) {} else if (rhs.m_stream == m_stream) { [[unlikely]] m_here = rhs.m_here; m_pos = rhs.m_pos; } else { [[likely]] if (m_stream != nullptr) pqxx::internal::gate::icursorstream_icursor_iterator{*m_stream} .remove_iterator(this); m_here = rhs.m_here; m_pos = rhs.m_pos; m_stream = rhs.m_stream; if (m_stream != nullptr) pqxx::internal::gate::icursorstream_icursor_iterator{*m_stream} .insert_iterator(this); } return *this; } bool pqxx::icursor_iterator::operator==(icursor_iterator const &rhs) const { auto loc{best_location(rhs)}; if (m_stream == rhs.m_stream) return pos() == rhs.pos(); if (m_stream != nullptr and rhs.m_stream != nullptr) return false; refresh(loc); rhs.refresh(loc); return std::empty(m_here) and std::empty(rhs.m_here); } bool pqxx::icursor_iterator::operator<(icursor_iterator const &rhs) const { if (m_stream == rhs.m_stream) return pos() < rhs.pos(); auto loc{best_location(rhs)}; refresh(loc); rhs.refresh(loc); return not std::empty(m_here); } void pqxx::icursor_iterator::refresh(sl loc) const { if (m_stream != nullptr) pqxx::internal::gate::icursorstream_icursor_iterator{*m_stream} .service_iterators(pos(), loc); } void pqxx::icursor_iterator::fill(result const &r) { m_here = r; } libpqxx-8.0.1/src/encodings.cxx000066400000000000000000000223351516427024100165020ustar00rootroot00000000000000/** Implementation of string encodings support * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include #include #include "pqxx/internal/header-pre.hxx" extern "C" { #include } #include "pqxx/internal/encodings.hxx" #include "pqxx/strconv.hxx" #include "pqxx/internal/header-post.hxx" using namespace std::literals; namespace { /// Do these two string_views contain the same text? constexpr bool same(std::string_view a, std::string_view b) noexcept { // Clang-tidy check "readability-string-compare" prefers '==' over compare(). return a == b; } /// Subtypes of Windows encoding. const std::array windows_subtypes{ "866"sv, "874"sv, "1250"sv, "1251"sv, "1252"sv, "1253"sv, "1254"sv, "1255"sv, "1256"sv, "1257"sv, "1258"sv, }; } // namespace namespace pqxx::internal { // LCOV_EXCL_START // C++23: Reduce to const std::flat_map on top of constexpr array? /// Look up encoding group for an encoding by name. /** @throw argument_error if the encoding name is not an accepted one. */ constexpr encoding_group enc_group(std::string_view encoding_name, sl loc) { auto const sz{std::size(encoding_name)}; if (sz > 0u) switch (encoding_name[0]) { case 'B': if (same(encoding_name, "BIG5"sv)) return encoding_group::two_tier; break; case 'E': // All the EUC encodings are ASCII-safe. if (encoding_name.starts_with("EUC_"sv)) return encoding_group::ascii_safe; break; case 'G': if (same(encoding_name, "GB18030"sv)) return encoding_group::gb18030; else if (same(encoding_name, "GBK"sv)) // GBK is an older subset of GB18030. return encoding_group::gb18030; break; case 'I': // We know iso-8859-X, where 5 <= X < 9. They're all single-byte // encodings, and therefore ASCII-safe. if ( (std::size(encoding_name) == 10) and encoding_name.starts_with("ISO_8859_"sv)) { char const subtype{encoding_name[9]}; if (('5' <= subtype) and (subtype < '9')) return encoding_group::ascii_safe; } break; case 'K': if (same(encoding_name, "KOI8R"sv) or same(encoding_name, "KOI8U"sv)) return encoding_group::ascii_safe; break; case 'L': // We know LATIN1 through LATIN10. if (encoding_name.starts_with("LATIN"sv)) { auto const subtype{encoding_name.substr(5)}; if (subtype.size() == 1) { char const n{subtype[0]}; if (('1' <= n) and (n <= '9')) return encoding_group::ascii_safe; } else if (same(subtype, "10"sv)) { return encoding_group::ascii_safe; } } break; case 'M': if (same(encoding_name, "MULE_INTERNAL"sv)) return encoding_group::ascii_safe; break; case 'S': if (same(encoding_name, "SHIFT_JIS_2004"sv)) return encoding_group::sjis; else if (same(encoding_name, "SJIS"sv)) return encoding_group::sjis; else if (same(encoding_name, "SQL_ASCII"sv)) return encoding_group::ascii_safe; break; case 'U': [[likely]] if (same(encoding_name, "UHC"sv)) { // Not actually ASCII-safe, but close enough for our purposes. The // trail bytes can be in the ASCII range, but only with values A-Z and // a-z. We never need to search for those, so we can treat this group // as ASCII-safe. return encoding_group::ascii_safe; } else if (same(encoding_name, "UTF8"sv)) [[likely]] { return encoding_group::ascii_safe; } break; case 'W': if (same(encoding_name.substr(0, 3), "WIN"sv)) { auto const subtype{encoding_name.substr(3)}; for (auto const n : windows_subtypes) if (same(n, subtype)) return encoding_group::ascii_safe; } break; default: break; } throw argument_error{ std::format("Unrecognized encoding: '{}'.", encoding_name), loc}; } // Compile-time tests. (Conditional so as not to slow down production builds.) #if defined(DEBUG) static_assert(enc_group("BIG5", sl::current()) == encoding_group::two_tier); static_assert( enc_group("EUC_CN", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("EUC_JIS_2004", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("EUC_JP", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("EUC_KR", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("EUC_TW", sl::current()) == encoding_group::ascii_safe); static_assert(enc_group("GB18030", sl::current()) == encoding_group::gb18030); static_assert(enc_group("GBK", sl::current()) == encoding_group::gb18030); static_assert( enc_group("ISO_8859_1", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("ISO_8859_2", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("ISO_8859_3", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("ISO_8859_4", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("ISO_8859_5", sl::current()) == encoding_group::ascii_safe); static_assert(enc_group("KOI8R", sl::current()) == encoding_group::ascii_safe); static_assert(enc_group("KOI8U", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("LATIN1", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("LATIN2", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("LATIN3", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("LATIN4", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("LATIN5", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("LATIN6", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("LATIN7", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("LATIN8", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("LATIN9", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("LATIN10", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("MULE_INTERNAL", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("SHIFT_JIS_2004", sl::current()) == encoding_group::sjis); static_assert(enc_group("SJIS", sl::current()) == encoding_group::sjis); static_assert( enc_group("SQL_ASCII", sl::current()) == encoding_group::ascii_safe); static_assert(enc_group("UHC", sl::current()) == encoding_group::two_tier); static_assert(enc_group("UTF8", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("WIN866", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("WIN874", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("WIN1250", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("WIN1251", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("WIN1252", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("WIN1253", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("WIN1254", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("WIN1255", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("WIN1256", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("WIN1257", sl::current()) == encoding_group::ascii_safe); static_assert( enc_group("WIN1258", sl::current()) == encoding_group::ascii_safe); #endif // DEBUG // LCOV_EXCL_STOP PQXX_PURE char const *name_encoding(int encoding_id) noexcept { return pg_encoding_to_char(encoding_id); } PQXX_PURE encoding_group enc_group(int libpq_enc_id, sl loc) { // TODO: Is there a safe, faster way without the string representation? return enc_group(name_encoding(libpq_enc_id), loc); } /// Represent a short stretch of binary data (at most 3) for human readers. PQXX_PURE std::string list_bytes(std::string_view data) { assert(not std::empty(data)); // C++23: Use std::ranges::views::join_with(), std::format()? std::stringstream s; s << std::hex << std::setfill('0'); for (char const c : data) s << std::setw(2) << "0x" << static_cast(c) << ' '; std::string const out{s.str()}; return out.substr(0u, std::size(out) - 1); } PQXX_ZARGS void throw_for_encoding_error( char const *encoding, std::string_view buffer, std::size_t start, std::size_t count, sl loc) { throw pqxx::argument_error{ std::format( "Text is not correctly encoded in {} at byte {}: {}.", encoding, start, list_bytes(buffer.substr(start, count))), loc}; } PQXX_ZARGS void throw_for_truncated_character( char const *encoding, std::string_view buffer, std::size_t start, sl loc) { throw pqxx::argument_error{ std::format( "Text encoded in {} is truncated in mid-character at byte {}: {}.", encoding, start, list_bytes(buffer.substr(start))), loc}; } } // namespace pqxx::internal libpqxx-8.0.1/src/errorhandler.cxx000066400000000000000000000020401516427024100172070ustar00rootroot00000000000000/** Implementation of pqxx::errorhandler and helpers. * * pqxx::errorhandler allows programs to receive errors and warnings. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include "pqxx/internal/header-pre.hxx" #include "pqxx/connection.hxx" #include "pqxx/errorhandler.hxx" #include "pqxx/internal/gates/connection-errorhandler.hxx" #include "pqxx/internal/header-post.hxx" pqxx::errorhandler::errorhandler(connection &cx) : m_home{&cx} { pqxx::internal::gate::connection_errorhandler{*m_home}.register_errorhandler( this); } pqxx::errorhandler::~errorhandler() { unregister(); } void pqxx::errorhandler::unregister() noexcept { if (m_home != nullptr) { pqxx::internal::gate::connection_errorhandler connection_gate{*m_home}; m_home = nullptr; connection_gate.unregister_errorhandler(this); } } libpqxx-8.0.1/src/except.cxx000066400000000000000000000126521516427024100160220ustar00rootroot00000000000000/** Implementation of libpqxx exception classes. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include "pqxx/internal/header-pre.hxx" #include "pqxx/except.hxx" #include "pqxx/internal/header-post.hxx" // Define virtual functions here so compilers will output vtables here, once. // // When compiling a class with virtual functions, compilers generally emit the // vtable in the translation unit(s) where they find the definition of its // first non-pure-virtual, non-inline virtual member function. Or perhaps the // destructor. // // Either way it's easy to end up with lots of redundant definitions of the // same vtable across many object files, which is a waste of space and time. // Therefore, we try to define exception classes' first virtual member // functions here. namespace pqxx { failure::~failure() noexcept = default; std::string_view failure::name() const noexcept { return "failure"; } std::string_view broken_connection::name() const noexcept { return "broken_connection"; } std::string_view version_mismatch::name() const noexcept { return "version_mismatch"; } std::string_view variable_set_to_null::name() const noexcept { return "variable_set_to_null"; } std::string_view sql_error::name() const noexcept { return "sql_error"; } std::string_view protocol_violation::name() const noexcept { return "protocol_violation"; } std::string_view in_doubt_error::name() const noexcept { return "in_doubt_error"; } std::string_view transaction_rollback::name() const noexcept { return "transaction_rollback"; } std::string_view serialization_failure::name() const noexcept { return "serialization_failure"; } std::string_view statement_completion_unknown::name() const noexcept { return "statement_completion_unknown"; } std::string_view deadlock_detected::name() const noexcept { return "deadlock_detected"; } std::string_view internal_error::name() const noexcept { return "internal_error"; } // Special case: We add a prefix to the message. internal_error::internal_error(std::string const &whatarg, sl loc, st &&tr) : failure{ std::format("LIBPQXX INTERNAL ERROR: {}", whatarg), loc, // When there's no support, clang-tidy complains that our placeholder // is trivially copyable and therefore the std::move() is pointless. // // NOLINTNEXTLINE(performance-move-const-arg) std::move(tr)} {} std::string_view usage_error::name() const noexcept { return "usage_error"; } std::string_view argument_error::name() const noexcept { return "argument_error"; } std::string_view conversion_error::name() const noexcept { return "conversion_error"; } std::string_view unexpected_null::name() const noexcept { return "unexpected_null"; } std::string_view conversion_overrun::name() const noexcept { return "conversion_overrun"; } std::string_view range_error::name() const noexcept { return "range_error"; } std::string_view unexpected_rows::name() const noexcept { return "unexpected_rows"; } std::string_view feature_not_supported::name() const noexcept { return "feature_not_supported"; } std::string_view data_exception::name() const noexcept { return "data_exception"; } std::string_view integrity_constraint_violation::name() const noexcept { return "integrity_constraint_violation"; } std::string_view restrict_violation::name() const noexcept { return "restrict_violation"; } std::string_view not_null_violation::name() const noexcept { return "not_null_violation"; } std::string_view foreign_key_violation::name() const noexcept { return "foreign_key_violation"; } std::string_view unique_violation::name() const noexcept { return "unique_violation"; } std::string_view check_violation::name() const noexcept { return "check_violation"; } std::string_view invalid_cursor_state::name() const noexcept { return "invalid_cursor_state"; } std::string_view invalid_sql_statement_name::name() const noexcept { return "invalid_sql_statement_name"; } std::string_view invalid_cursor_name::name() const noexcept { return "invalid_cursor_name"; } std::string_view syntax_error::name() const noexcept { return "syntax_error"; } std::string_view undefined_column::name() const noexcept { return "undefined_column"; } std::string_view undefined_function::name() const noexcept { return "undefined_function"; } std::string_view undefined_table::name() const noexcept { return "undefined_table"; } std::string_view insufficient_privilege::name() const noexcept { return "insufficient_privilege"; } std::string_view insufficient_resources::name() const noexcept { return "insufficient_resources"; } std::string_view disk_full::name() const noexcept { return "disk_full"; } std::string_view server_out_of_memory::name() const noexcept { return "server_out_of_memory"; } std::string_view too_many_connections::name() const noexcept { return "too_many_connections"; } std::string_view plpgsql_error::name() const noexcept { return "plpgsql_error"; } std::string_view plpgsql_raise::name() const noexcept { return "plpgsql_raise"; } std::string_view plpgsql_no_data_found::name() const noexcept { return "plpgsql_no_data_found"; } std::string_view plpgsql_too_many_rows::name() const noexcept { return "plpgsql_too_many_rows"; } } // namespace pqxx libpqxx-8.0.1/src/field.cxx000066400000000000000000000022501516427024100156060ustar00rootroot00000000000000/** Implementation of the pqxx::field class. * * pqxx::field refers to a field in a query result. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include "pqxx/internal/header-pre.hxx" #include "pqxx/field.hxx" #include "pqxx/result.hxx" #include "pqxx/row.hxx" #include "pqxx/internal/header-post.hxx" pqxx::field::field(pqxx::row const &r, pqxx::row::size_type c) noexcept : m_home{r.m_result}, m_row{r.m_index}, m_col{c} {} PQXX_COLD bool pqxx::field::operator==(field const &rhs) const noexcept { if (is_null() and rhs.is_null()) return true; if (is_null() != rhs.is_null()) return false; auto const s{size()}; return (s == std::size(rhs)) and (std::memcmp(c_str(), rhs.c_str(), s) == 0); } char const *pqxx::field::name(sl loc) const & { return home().column_name(column_number(), loc); } pqxx::row::size_type pqxx::field::table_column(sl loc) const { return home().table_column(column_number(), loc); } libpqxx-8.0.1/src/largeobject.cxx000066400000000000000000000211601516427024100170050ustar00rootroot00000000000000/** Implementation of the Large Objects interface. * * Allows direct access to large objects, as well as though I/O streams. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include #include #include "pqxx/internal/header-pre.hxx" extern "C" { #include } #include "pqxx/connection.hxx" #include "pqxx/internal/gates/connection-largeobject.hxx" #include "pqxx/largeobject.hxx" #include "pqxx/internal/header-post.hxx" #include "pqxx/internal/ignore-deprecated-pre.hxx" // This code is deprecated. // LCOV_EXCL_START namespace { /// Cast a @ref pqxx::internal::pq::PGconn pointer back to a `PGconn` pointer. /** There's really no such thing as a @ref pqxx::internal::pq::PGconn. It's * just a placeholder we use in our headers so we can talk about this type * without actually importing its definition. * * It's not a _forward declaration_ though: before we can use these pointers, * we have to cast them back to their exact original type. That's what this * function does. * * We can't define this centrally because we can't declare it in a header, * because we can't mention its return type in a header without exposing the * libpq type definition there, in the global namespace. */ PQXX_PURE PQXX_INLINE_ONLY inline ::PGconn * real_conn(pqxx::internal::pq::PGconn *ptr) noexcept { return static_cast<::PGconn *>(ptr); } PQXX_COLD constexpr inline int std_mode_to_pq_mode(std::ios::openmode mode) { /// Mode bits, copied from libpq-fs.h so that we no longer need that header. constexpr int INV_WRITE{0x00020000}, INV_READ{0x00040000}; return ((mode & std::ios::in) ? INV_READ : 0) | ((mode & std::ios::out) ? INV_WRITE : 0); } PQXX_COLD constexpr int std_dir_to_pq_dir(std::ios::seekdir dir) noexcept { if constexpr ( static_cast(std::ios::beg) == int(SEEK_SET) and static_cast(std::ios::cur) == int(SEEK_CUR) and static_cast(std::ios::end) == int(SEEK_END)) { // Easy optimisation: they're the same constants. This is actually the // case for the gcc I'm using. return dir; } else switch (dir) { case std::ios::beg: return SEEK_SET; break; case std::ios::cur: return SEEK_CUR; break; case std::ios::end: return SEEK_END; break; // Shouldn't happen, but may silence compiler warning. default: return dir; break; } } } // namespace PQXX_COLD pqxx::largeobject::largeobject(dbtransaction &t) : m_id{lo_creat(real_conn(raw_connection(t)), 0)} { // (Mode is ignored as of postgres 8.1.) if (m_id == oid_none) { int const err{errno}; if (err == ENOMEM) throw std::bad_alloc{}; throw failure{ std::format("Could not create large object: {}", reason(t.conn(), err))}; } } PQXX_COLD pqxx::largeobject::largeobject(dbtransaction &t, std::string_view file) : m_id{lo_import(real_conn(raw_connection(t)), std::data(file))} { if (m_id == oid_none) { int const err{errno}; if (err == ENOMEM) throw std::bad_alloc{}; throw failure{std::format( "Could not import file '{}' to large object: {}", file, reason(t.conn(), err))}; } } PQXX_COLD pqxx::largeobject::largeobject(largeobjectaccess const &o) noexcept : m_id{o.id()} {} PQXX_COLD void pqxx::largeobject::to_file(dbtransaction &t, std::string_view file) const { if (id() == oid_none) throw usage_error{"No object selected."}; if (lo_export(real_conn(raw_connection(t)), id(), std::data(file)) == -1) { int const err{errno}; if (err == ENOMEM) throw std::bad_alloc{}; throw failure{std::format( "Could not export large object {} to file '{}': {}", m_id, file, reason(t.conn(), err))}; } } PQXX_COLD void pqxx::largeobject::remove(dbtransaction &t) const { if (id() == oid_none) throw usage_error{"No object selected."}; if (lo_unlink(real_conn(raw_connection(t)), id()) == -1) { int const err{errno}; if (err == ENOMEM) throw std::bad_alloc{}; throw failure{std::format( "Could not delete large object {}: {}", m_id, reason(t.conn(), err))}; } } PQXX_COLD pqxx::internal::pq::PGconn * pqxx::largeobject::raw_connection(dbtransaction const &t) { return pqxx::internal::gate::connection_largeobject{t.conn()} .raw_connection(); } PQXX_COLD std::string pqxx::largeobject::reason(connection const &cx, int err) const { if (err == ENOMEM) return "Out of memory"; return pqxx::internal::gate::const_connection_largeobject{cx} .error_message(); } PQXX_COLD pqxx::largeobjectaccess::largeobjectaccess(dbtransaction &t, openmode mode) : largeobject{t}, m_trans{t} { open(mode); } PQXX_COLD pqxx::largeobjectaccess::largeobjectaccess( dbtransaction &t, oid o, openmode mode) : largeobject{o}, m_trans{t} { open(mode); } PQXX_COLD pqxx::largeobjectaccess::largeobjectaccess( dbtransaction &t, largeobject o, openmode mode) : largeobject{o}, m_trans{t} { open(mode); } PQXX_COLD pqxx::largeobjectaccess::largeobjectaccess( dbtransaction &t, std::string_view file, openmode mode) : largeobject{t, file}, m_trans{t} { open(mode); } PQXX_COLD pqxx::largeobjectaccess::size_type pqxx::largeobjectaccess::seek(size_type dest, seekdir dir) { auto const res{cseek(dest, dir)}; if (res == -1) { int const err{errno}; if (err == ENOMEM) throw std::bad_alloc{}; if (id() == oid_none) throw usage_error{"No object selected."}; throw failure{ std::format("Error seeking in large object: {}", reason(err))}; } return res; } PQXX_COLD pqxx::largeobjectaccess::pos_type pqxx::largeobjectaccess::cseek(off_type dest, seekdir dir) noexcept { return lo_lseek64( real_conn(raw_connection()), m_fd, dest, std_dir_to_pq_dir(dir)); } PQXX_COLD pqxx::largeobjectaccess::pos_type pqxx::largeobjectaccess::cwrite(char const buf[], std::size_t len) noexcept { return std::max(lo_write(real_conn(raw_connection()), m_fd, buf, len), -1); } PQXX_COLD pqxx::largeobjectaccess::pos_type pqxx::largeobjectaccess::cread(char buf[], std::size_t len) noexcept { return std::max(lo_read(real_conn(raw_connection()), m_fd, buf, len), -1); } PQXX_COLD pqxx::largeobjectaccess::pos_type pqxx::largeobjectaccess::ctell() const noexcept { return lo_tell64(real_conn(raw_connection()), m_fd); } PQXX_COLD void pqxx::largeobjectaccess::write(char const buf[], std::size_t len) { if (id() == oid_none) throw usage_error{"No object selected."}; if (auto const bytes{cwrite(buf, len)}; std::cmp_less(bytes, len)) { int const err{errno}; if (err == ENOMEM) throw std::bad_alloc{}; if (bytes < 0) throw failure{std::format( "Error writing to large object #{}: {}", id(), reason(err))}; if (bytes == 0) throw failure{std::format( "Could not write to large object #{}: {}", id(), reason(err))}; throw failure{std::format( "Wanted to write {} bytes to large object #{}; could only write {}.", len, id(), bytes)}; } } PQXX_COLD pqxx::largeobjectaccess::size_type pqxx::largeobjectaccess::read(char buf[], std::size_t len) { if (id() == oid_none) throw usage_error{"No object selected."}; auto const bytes{cread(buf, len)}; if (bytes < 0) { int const err{errno}; if (err == ENOMEM) throw std::bad_alloc{}; throw failure{std::format( "Error reading from large object #{}: {}", id(), reason(err))}; } return bytes; } PQXX_COLD void pqxx::largeobjectaccess::open(openmode mode) { if (id() == oid_none) throw usage_error{"No object selected."}; m_fd = lo_open(real_conn(raw_connection()), id(), std_mode_to_pq_mode(mode)); if (m_fd < 0) { int const err{errno}; if (err == ENOMEM) throw std::bad_alloc{}; throw failure{ std::format("Could not open large object {}: {}", id(), reason(err))}; } } PQXX_COLD void pqxx::largeobjectaccess::close() noexcept { if (m_fd >= 0) lo_close(real_conn(raw_connection()), m_fd); } PQXX_COLD pqxx::largeobjectaccess::size_type pqxx::largeobjectaccess::tell() const { auto const res{ctell()}; if (res == -1) throw failure{reason(errno)}; return res; } PQXX_COLD std::string pqxx::largeobjectaccess::reason(int err) const { if (m_fd == -1) return "No object opened."; return largeobject::reason(m_trans.conn(), err); } PQXX_COLD void pqxx::largeobjectaccess::process_notice(zview s) noexcept { m_trans.process_notice(s); } // LCOV_EXCL_STOP #include "pqxx/internal/ignore-deprecated-post.hxx" libpqxx-8.0.1/src/notification.cxx000066400000000000000000000020031516427024100172050ustar00rootroot00000000000000/** Implementation of the pqxx::notification_receiever class. * * pqxx::notification_receiver processes notifications. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include "pqxx/internal/header-pre.hxx" #include "pqxx/internal/gates/connection-notification_receiver.hxx" #include "pqxx/notification.hxx" #include "pqxx/internal/header-post.hxx" pqxx::notification_receiver::notification_receiver( connection &cx, std::string_view channel, sl loc) : m_conn{cx}, m_channel{channel} { pqxx::internal::gate::connection_notification_receiver{cx}.add_receiver( this, loc); } pqxx::notification_receiver::~notification_receiver() { auto loc{sl::current()}; pqxx::internal::gate::connection_notification_receiver{this->conn()} .remove_receiver(this, loc); } libpqxx-8.0.1/src/params.cxx000066400000000000000000000054051516427024100160130ustar00rootroot00000000000000/* Implementations related to prepared and parameterised statements. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include "pqxx/internal/header-pre.hxx" #include "pqxx/connection.hxx" #include "pqxx/params.hxx" #include "pqxx/transaction_base.hxx" #include "pqxx/internal/header-post.hxx" pqxx::encoding_group pqxx::internal::get_encoding_group(pqxx::connection const &cx, sl loc) { return cx.get_encoding_group(loc); } pqxx::encoding_group pqxx::internal::get_encoding_group(pqxx::transaction_base const &tx, sl loc) { return get_encoding_group(tx.conn(), loc); } void pqxx::internal::c_params::reserve(std::size_t n) & { values.reserve(n); lengths.reserve(n); formats.reserve(n); } void pqxx::params::reserve(std::size_t n) & { m_params.reserve(n); } void pqxx::params::append(sl) & { m_params.emplace_back(nullptr); } void pqxx::params::append(zview value, sl) & { m_params.emplace_back(value); } void pqxx::params::append(std::string const &value, sl) & { m_params.emplace_back(value); } void pqxx::params::append(std::string &&value, sl) & { m_params.emplace_back(std::move(value)); } void pqxx::params::append(params const &value, sl) & { this->reserve(std::size(value.m_params) + std::size(this->m_params)); for (auto const ¶m : value.m_params) m_params.emplace_back(param); } void pqxx::params::append(bytes_view value, sl) & { m_params.emplace_back(value); } void pqxx::params::append(bytes &&value, sl) & { m_params.emplace_back(std::move(value)); } void pqxx::params::append(params &&value, sl) & { // TODO: If currently empty, just "steal" value's m_params wholesale. // C++23: Use append_range()? this->reserve(std::size(value.m_params) + std::size(this->m_params)); for (auto const ¶m : value.m_params) m_params.emplace_back(param); value.m_params.clear(); } pqxx::internal::c_params pqxx::params::make_c_params(sl loc) const { pqxx::internal::c_params p; p.reserve(std::size(m_params)); for (auto const ¶m : m_params) std::visit( [&p, &loc](auto const &value) { using T = std::remove_cvref_t; if constexpr (std::is_same_v) { p.values.push_back(nullptr); p.lengths.push_back(0); } else { p.values.push_back(reinterpret_cast(std::data(value))); p.lengths.push_back( check_cast(std::ssize(value), s_overflow, loc)); } p.formats.push_back(static_cast(param_format(value))); }, param); return p; } libpqxx-8.0.1/src/pipeline.cxx000066400000000000000000000274021516427024100163360ustar00rootroot00000000000000/** Implementation of the pqxx::pipeline class. * * Throughput-optimized query interface. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include "pqxx/internal/header-pre.hxx" #include "pqxx/dbtransaction.hxx" #include "pqxx/internal/gates/connection-pipeline.hxx" #include "pqxx/internal/gates/result-creation.hxx" #include "pqxx/internal/gates/result-pipeline.hxx" #include "pqxx/pipeline.hxx" #include "pqxx/separated_list.hxx" #include "pqxx/internal/header-post.hxx" using namespace std::literals::string_view_literals; namespace { constexpr std::string_view theSeparator{"; "sv}, theDummyValue{"1"sv}, theDummyQuery{"SELECT 1; "sv}; } // namespace void pqxx::pipeline::init(sl loc) { m_encoding = trans().conn().get_encoding_group(loc); m_issuedrange = make_pair(std::end(m_queries), std::end(m_queries)); attach(); } pqxx::pipeline::~pipeline() noexcept { sl const loc{m_created_loc}; try { cancel(loc); } catch (std::exception const &) {} detach(); } void pqxx::pipeline::attach() { if (not registered()) register_me(); } void pqxx::pipeline::detach() { if (registered()) unregister_me(); } pqxx::pipeline::query_id pqxx::pipeline::insert(std::string_view q, sl loc) & { attach(); query_id const qid{generate_id()}; auto const i{m_queries.insert(std::make_pair(qid, Query(q))).first}; if (m_issuedrange.second == std::end(m_queries)) { m_issuedrange.second = i; if (m_issuedrange.first == std::end(m_queries)) m_issuedrange.first = i; } m_num_waiting++; if (m_num_waiting > m_retain) { if (have_pending()) receive_if_available(loc); if (not have_pending()) issue(loc); } return qid; } void pqxx::pipeline::complete(sl loc) { if (have_pending()) receive(m_issuedrange.second, loc); if (m_num_waiting and (m_error == qid_limit())) { issue(loc); receive(std::end(m_queries), loc); } detach(); } void pqxx::pipeline::flush(sl loc) { if (not std::empty(m_queries)) { if (have_pending()) receive(m_issuedrange.second, loc); m_issuedrange.first = m_issuedrange.second = std::end(m_queries); m_num_waiting = 0; m_dummy_pending = false; m_queries.clear(); } detach(); } PQXX_COLD void pqxx::pipeline::cancel(sl loc) { while (have_pending()) { pqxx::internal::gate::connection_pipeline(trans().conn()) .cancel_query(loc); auto canceled_query{m_issuedrange.first}; ++m_issuedrange.first; m_queries.erase(canceled_query); } } bool pqxx::pipeline::is_finished(pipeline::query_id q) const { if (not m_queries.contains(q)) throw std::logic_error{ std::format("Requested status for unknown query '{}'.", q)}; return (QueryMap::const_iterator(m_issuedrange.first) == std::end(m_queries)) or (q < m_issuedrange.first->first and q < m_error); } std::pair pqxx::pipeline::retrieve(sl loc) { if (std::empty(m_queries)) throw std::logic_error{"Attempt to retrieve result from empty pipeline."}; return retrieve(std::begin(m_queries), loc); } int pqxx::pipeline::retain(int retain_max) & { if (retain_max < 0) throw range_error{ std::format("Attempt to make pipeline retain {} queries.", retain_max)}; int const oldvalue{m_retain}; m_retain = retain_max; if (m_num_waiting >= m_retain) resume(); return oldvalue; } void pqxx::pipeline::resume(sl loc) & { if (have_pending()) receive_if_available(loc); if (not have_pending() and m_num_waiting) { issue(loc); receive_if_available(loc); } } pqxx::pipeline::query_id pqxx::pipeline::generate_id() { if (m_q_id == qid_limit()) throw std::overflow_error{"Too many queries went through pipeline."}; ++m_q_id; return m_q_id; } void pqxx::pipeline::issue(sl loc) { // Retrieve that null result for the last query, if needed. obtain_result(false, loc); // Don't issue anything if we've encountered an error. if (m_error < qid_limit()) return; // Start with oldest query (lowest id) not in previous issue range. auto oldest{m_issuedrange.second}; // Construct cumulative query string for entire batch. auto cum{separated_list( theSeparator, oldest, std::end(m_queries), [](QueryMap::const_iterator i) { return *i->second.query; })}; auto const num_issued{ QueryMap::size_type(std::distance(oldest, std::end(m_queries)))}; bool const prepend_dummy{num_issued > 1}; if (prepend_dummy) cum = std::format("{}{}", theDummyQuery, cum); pqxx::internal::gate::connection_pipeline{trans().conn()}.start_exec( cum.c_str()); // Since we managed to send out these queries, update state to reflect this. m_dummy_pending = prepend_dummy; m_issuedrange.first = oldest; m_issuedrange.second = std::end(m_queries); m_num_waiting -= check_cast(num_issued, "pipeline issue()"sv, loc); } PQXX_COLD void pqxx::pipeline::internal_error(std::string const &err, sl loc) { set_error_at(0); throw pqxx::internal_error{err, loc}; } bool pqxx::pipeline::obtain_result(bool expect_none, sl loc) { pqxx::internal::gate::connection_pipeline gate{trans().conn()}; std::shared_ptr const r{ gate.get_result(), pqxx::internal::clear_result}; if (not r) { if (have_pending() and not expect_none) [[unlikely]] { set_error_at(m_issuedrange.first->first); m_issuedrange.second = m_issuedrange.first; } return false; } pqxx::internal::gate::connection_pipeline const pgate{trans().conn()}; auto handler{pgate.get_notice_waiters()}; result const res{pqxx::internal::gate::result_creation::create( r, std::begin(m_queries)->second.query, handler, m_encoding)}; if (not have_pending()) [[unlikely]] { set_error_at(std::begin(m_queries)->first); throw std::logic_error{ "Got more results from pipeline than there were queries."}; } // Must be the result for the oldest pending query. if (not std::empty(m_issuedrange.first->second.res)) [[unlikely]] internal_error("Multiple results for one query.", loc); m_issuedrange.first->second.res = res; ++m_issuedrange.first; return true; } void pqxx::pipeline::obtain_dummy(sl loc) { conversion_context const c{{}, loc}; // Allocate once, re-use across invocations. static auto const text{ std::make_shared("[DUMMY PIPELINE QUERY]")}; pqxx::internal::gate::connection_pipeline gate{trans().conn()}; std::shared_ptr const r{ gate.get_result(), pqxx::internal::clear_result}; m_dummy_pending = false; if (not r) [[unlikely]] internal_error( "Pipeline got no result from backend when it expected one.", loc); pqxx::internal::gate::connection_pipeline const pgate{trans().conn()}; auto handler{pgate.get_notice_waiters()}; result const R{pqxx::internal::gate::result_creation::create( r, text, handler, m_encoding)}; bool OK{false}; try { pqxx::internal::gate::result_creation{R}.check_status(loc); OK = true; } catch (sql_error const &) {} if (OK) [[likely]] { if (std::size(R) > 1) [[unlikely]] internal_error("Unexpected result for dummy query in pipeline.", loc); if (R.at(0).at(0).view() != theDummyValue) [[unlikely]] internal_error( "Dummy query in pipeline returned unexpected value.", loc); return; } // TODO: Can we actually re-issue statements after a failure? /* Execution of this batch failed. * * When we send multiple statements in one go, the backend treats them as a * single transaction. So the entire batch was effectively rolled back. * * Since none of the queries in the batch were actually executed, we can * afford to replay them one by one until we find the exact query that * caused the error. This gives us not only a more specific error message * to report, but also tells us which query to report it for. */ // First, give the whole batch the same syntax error message, in case all // else is going to fail. for (auto i{m_issuedrange.first}; i != m_issuedrange.second; ++i) i->second.res = R; // Remember where the end of this batch was auto const stop{m_issuedrange.second}; // Retrieve that null result for the last query, if needed obtain_result(true, loc); // Reset internal state to forget botched batch attempt m_num_waiting += check_cast( std::distance(m_issuedrange.first, stop), "pipeline obtain_dummy()"sv, loc); m_issuedrange.second = m_issuedrange.first; // Issue queries in failed batch one at a time. unregister_me(); try { do { m_num_waiting--; auto const query{*m_issuedrange.first->second.query}; auto &holder{m_issuedrange.first->second}; holder.res = trans().exec(query, loc); pqxx::internal::gate::result_creation{holder.res}.check_status(loc); ++m_issuedrange.first; } while (m_issuedrange.first != stop); } catch (std::exception const &) { auto const thud{m_issuedrange.first->first}; ++m_issuedrange.first; m_issuedrange.second = m_issuedrange.first; auto q{m_issuedrange.first}; set_error_at((q == std::end(m_queries)) ? thud + 1 : q->first); } } std::pair pqxx::pipeline::retrieve(pipeline::QueryMap::iterator q, sl loc) { if (q == std::end(m_queries)) throw std::logic_error{"Attempt to retrieve result for unknown query."}; if (q->first >= m_error) throw std::runtime_error{ "Could not complete query in pipeline due to error in earlier query."}; // If query hasn't issued yet, do it now. if ( m_issuedrange.second != std::end(m_queries) and (q->first >= m_issuedrange.second->first)) { if (have_pending()) receive(m_issuedrange.second, loc); if (m_error == qid_limit()) issue(loc); } // If result not in yet, get it; else get at least whatever's convenient. if (have_pending()) { if (q->first >= m_issuedrange.first->first) { auto suc{q}; ++suc; receive(suc, loc); } else { receive_if_available(loc); } } if (q->first >= m_error) throw std::runtime_error{ "Could not complete query in pipeline due to error in earlier query."}; // Don't leave the backend idle if there are queries waiting to be issued. if (m_num_waiting and not have_pending() and (m_error == qid_limit())) issue(loc); // We do a strange dance with the first argument, just so we get the "move" // version of std::make_pair(). auto p{ std::make_pair(query_id{q->first}, std::move(std::move(q->second.res)))}; m_queries.erase(q); pqxx::internal::gate::result_creation{p.second}.check_status(loc); return p; } void pqxx::pipeline::get_further_available_results(sl loc) { pqxx::internal::gate::connection_pipeline gate{trans().conn()}; while (not gate.is_busy() and obtain_result(false, loc)) if (not gate.consume_input()) throw broken_connection{loc}; } void pqxx::pipeline::receive_if_available(sl loc) { pqxx::internal::gate::connection_pipeline gate{trans().conn()}; if (not gate.consume_input()) throw broken_connection{loc}; if (gate.is_busy()) return; if (m_dummy_pending) obtain_dummy(loc); if (have_pending()) get_further_available_results(loc); } void pqxx::pipeline::receive(pipeline::QueryMap::const_iterator stop, sl loc) { if (m_dummy_pending) obtain_dummy(loc); while (obtain_result(false, loc) and QueryMap::const_iterator{m_issuedrange.first} != stop); // Also haul in any remaining "targets of opportunity". if (QueryMap::const_iterator{m_issuedrange.first} == stop) get_further_available_results(loc); } libpqxx-8.0.1/src/pqxx-source.hxx000066400000000000000000000016571516427024100170400ustar00rootroot00000000000000/* Compiler settings for compiling libpqxx itself. * * Include this header in every source file that goes into the libpqxx library * binary, and nowhere else. * * To ensure this, include this file once, as the very first header, in each * compilation unit for the library. * * DO NOT INCLUDE THIS FILE when building client programs. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ // NOLINTBEGIN(llvm-header-guard) #ifndef PQXX_SOURCE_HXX #define PQXX_SOURCE_HXX // NOLINTEND(llvm-header-guard) #ifdef _WIN32 # ifdef PQXX_SHARED // We're building libpqxx as a shared library. # undef PQXX_LIBEXPORT # define PQXX_LIBEXPORT __declspec(dllexport) # define PQXX_PRIVATE __declspec() # endif // PQXX_SHARED #endif // _WIN32 #endif libpqxx-8.0.1/src/result.cxx000066400000000000000000000444711516427024100160540ustar00rootroot00000000000000/** Implementation of the pqxx::result class and support classes. * * pqxx::result represents the set of result rows from a database query * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include #include #include "pqxx/internal/header-pre.hxx" extern "C" { #include } #include "pqxx/except.hxx" #include "pqxx/internal/result_iterator.hxx" #include "pqxx/result.hxx" #include "pqxx/row.hxx" #include "pqxx/internal/header-post.hxx" namespace pqxx { PQXX_DECLARE_ENUM_CONVERSION(ExecStatusType); /// Cast a @ref pqxx::internal::pq::PGresult pointer back to its real type. /** There's really no such thing as a @ref pqxx::internal::pq::PGresult. It's * just a placeholder we use in our headers so we can talk about this type * without actually importing its definition. * * It's not a _forward declaration_ though: before we can use these pointers, * we have to cast them back to their original type. This does that. */ PQXX_PURE PQXX_INLINE_ONLY inline ::PGresult * real_res(pqxx::internal::pq::PGresult *ptr) noexcept { return static_cast<::PGresult *>(ptr); } /// Cast a @ref pqxx::internal::pq::PGresult pointer back to its real type. /** There's really no such thing as a @ref pqxx::internal::pq::PGresult. It's * just a placeholder we use in our headers so we can talk about this type * without actually importing its definition. * * It's not a _forward declaration_ though: before we can use these pointers, * we have to cast them back to their original type. This does that. */ PQXX_PURE PQXX_INLINE_ONLY inline ::PGresult const * real_res(pqxx::internal::pq::PGresult const *ptr) noexcept { return static_cast<::PGresult const *>(ptr); } /// Wrapper for `PQntuples()` that deals in our placeholder types. PQXX_INLINE_ONLY inline int pq_n_tuples(pqxx::internal::pq::PGresult const *ptr) noexcept { return PQntuples(real_res(ptr)); } } // namespace pqxx std::string const pqxx::result::s_empty_string; /// C++ wrapper for libpq's PQclear. void pqxx::internal::clear_result(pq::PGresult const *data) noexcept { // This acts as a destructor, though implemented as a regular function so we // can pass it into a smart pointer. That's why I think it's kind of fair // to treat the PGresult as const. // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast) PQclear(const_cast<::PGresult *>(real_res(data))); } pqxx::result::result( std::shared_ptr const &rhs, std::shared_ptr const &query, std::shared_ptr const ¬ice_waiters, encoding_group enc) : m_data{rhs}, m_query{query}, m_notice_waiters{notice_waiters}, m_encoding(enc) {} pqxx::result::const_reverse_iterator pqxx::result::rbegin() const noexcept { return const_reverse_iterator{end()}; } pqxx::result::const_reverse_iterator pqxx::result::crbegin() const noexcept { return rbegin(); } pqxx::result::const_reverse_iterator pqxx::result::rend() const noexcept { return const_reverse_iterator{begin()}; } pqxx::result::const_reverse_iterator pqxx::result::crend() const noexcept { return rend(); } pqxx::result::const_iterator pqxx::result::begin() const noexcept { return {*this, 0}; } pqxx::result::const_iterator pqxx::result::cbegin() const noexcept { return begin(); } pqxx::result::size_type pqxx::result::size() const noexcept { return (m_data.get() == nullptr) ? 0 : static_cast(pq_n_tuples(m_data.get())); } bool pqxx::result::empty() const noexcept { return (m_data.get() == nullptr) or (pq_n_tuples(m_data.get()) == 0); } pqxx::row_ref pqxx::result::front() const noexcept { return {*this, 0}; } pqxx::row_ref pqxx::result::back() const noexcept { return {*this, size() - 1}; } void pqxx::result::swap(result &rhs) noexcept { m_data.swap(rhs.m_data); m_query.swap(rhs.m_query); } pqxx::row_ref pqxx::result::operator[](result_size_type i) const noexcept { return {*this, i}; } #if defined(PQXX_HAVE_MULTIDIM) pqxx::field_ref pqxx::result::operator[]( result_size_type row_num, row_size_type col_num) const noexcept { return {*this, row_num, col_num}; } #endif // PQXX_HAVE_MULTIDIM pqxx::row_ref pqxx::result::at(pqxx::result::size_type i, sl loc) const { if (std::cmp_less(i, 0) or std::cmp_greater_equal(i, size())) throw range_error{"Row number out of range.", loc}; return operator[](i); } pqxx::field_ref pqxx::result::at( pqxx::result_size_type row_num, pqxx::row_size_type col_num, sl loc) const { if (std::cmp_less(row_num, 0) or std::cmp_greater_equal(row_num, size())) throw range_error{"Row number out of range.", loc}; if (std::cmp_less(col_num, 0) or std::cmp_greater_equal(col_num, columns())) throw range_error{"Column out of range.", loc}; return {*this, row_num, col_num}; } namespace { /// C string comparison. PQXX_ZARGS PQXX_PURE inline bool equal(char const lhs[], char const rhs[]) { return strcmp(lhs, rhs) == 0; } } // namespace PQXX_COLD void pqxx::result::throw_sql_error( std::string const &Err, std::string const &Query, sl loc) const { // Try to establish more precise error type, and throw corresponding // type of exception. char const *const code{ PQresultErrorField(real_res(m_data.get()), PG_DIAG_SQLSTATE)}; if (code == nullptr) { // No SQLSTATE at all. Can this even happen? // Let's assume the connection is no longer usable. throw broken_connection{Err, loc}; } switch (code[0]) { case '\0': // SQLSTATE is empty. We may have seen this happen in one // circumstance: a client-side socket timeout (while using the // tcp_user_timeout connection option). Unfortunately in that case the // connection was just fine, so we had no real way of detecting the // problem. (Trying to continue to use the connection does break // though, so I feel justified in panicking.) throw broken_connection{Err, loc}; case '0': switch (code[1]) { case 'A': throw feature_not_supported{Err, Query, code, loc}; case '8': if (equal(code, "08P01")) throw protocol_violation{Err, Query, code, loc}; throw broken_connection{Err, loc}; case 'L': case 'P': throw insufficient_privilege{Err, Query, code, loc}; } break; case '2': switch (code[1]) { case '2': throw data_exception{Err, Query, code, loc}; case '3': if (equal(code, "23001")) throw restrict_violation{Err, Query, code, loc}; if (equal(code, "23502")) throw not_null_violation{Err, Query, code, loc}; if (equal(code, "23503")) throw foreign_key_violation{Err, Query, code, loc}; if (equal(code, "23505")) throw unique_violation{Err, Query, code, loc}; if (equal(code, "23514")) throw check_violation{Err, Query, code, loc}; throw integrity_constraint_violation{Err, Query, code, loc}; case '4': throw invalid_cursor_state{Err, Query, code, loc}; case '6': throw invalid_sql_statement_name{Err, Query, code, loc}; } break; case '3': switch (code[1]) { case '4': throw invalid_cursor_name{Err, Query, code, loc}; } break; case '4': switch (code[1]) { case '0': if (equal(code, "40000")) throw transaction_rollback{Err, Query, code, loc}; if (equal(code, "40001")) throw serialization_failure{Err, Query, code, loc}; if (equal(code, "40003")) throw statement_completion_unknown{Err, Query, code, loc}; if (equal(code, "40P01")) throw deadlock_detected{Err, Query, code, loc}; break; case '2': if (equal(code, "42501")) throw insufficient_privilege{Err, Query, code, loc}; if (equal(code, "42601")) throw syntax_error{Err, Query, code, errorposition(), loc}; if (equal(code, "42703")) throw undefined_column{Err, Query, code, loc}; if (equal(code, "42883")) throw undefined_function{Err, Query, code, loc}; if (equal(code, "42P01")) throw undefined_table{Err, Query, code, loc}; } break; case '5': switch (code[1]) { case '3': if (equal(code, "53100")) throw disk_full{Err, Query, code, loc}; if (equal(code, "53200")) throw server_out_of_memory{Err, Query, code, loc}; if (equal(code, "53300")) throw too_many_connections{Err, loc}; throw insufficient_resources{Err, Query, code, loc}; } break; case 'P': if (equal(code, "P0001")) throw plpgsql_raise{Err, Query, code, loc}; if (equal(code, "P0002")) throw plpgsql_no_data_found{Err, Query, code, loc}; if (equal(code, "P0003")) throw plpgsql_too_many_rows{Err, Query, code, loc}; throw plpgsql_error{Err, Query, code}; } // Unknown error code. throw sql_error{Err, Query, code, loc}; } void pqxx::result::check_status(std::string_view desc, sl loc) const { if (auto err{status_error(loc)}; not std::empty(err)) [[unlikely]] { if (not std::empty(desc)) err = std::format("Failure during '{}': {}", desc, err); throw_sql_error(err, query(), loc); } } std::string pqxx::result::status_error(sl loc) const { if (m_data.get() == nullptr) throw failure{"No result set given.", loc}; std::string err; auto const status{PQresultStatus(real_res(m_data.get()))}; switch (status) { case PGRES_EMPTY_QUERY: // The string sent to the backend was empty. case PGRES_COMMAND_OK: // Successful completion, no result data. case PGRES_TUPLES_OK: // The query successfully executed. case PGRES_COPY_OUT: // Copy Out (from server) data transfer started. case PGRES_COPY_IN: // Copy In (to server) data transfer started. case PGRES_COPY_BOTH: // Copy In/Out. Used for streaming replication. break; #if defined(LIBPQ_HAS_PIPELINING) case PGRES_PIPELINE_SYNC: // Pipeline mode synchronisation point. case PGRES_PIPELINE_ABORTED: // Previous command in pipeline failed. throw feature_not_supported{ "Not supported yet: libpq pipelines.", "", "", loc}; #endif case PGRES_BAD_RESPONSE: // The server's response was not understood. case PGRES_NONFATAL_ERROR: case PGRES_FATAL_ERROR: [[unlikely]] err = PQresultErrorMessage(real_res(m_data.get())); break; case PGRES_SINGLE_TUPLE: throw feature_not_supported{ "Not supported: single-row mode.", "", "", loc}; default: throw internal_error{ std::format( "pqxx::result: Unrecognized result status code {}", to_string(status)), loc}; } return err; } char const *pqxx::result::cmd_status() const noexcept { // PQcmdStatus() can't take a PGresult const * because it returns a non-const // pointer into the PGresult's data, and that can't be changed without // breaking compatibility. // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast) return PQcmdStatus(const_cast<::PGresult *>(real_res(m_data.get()))); } std::string const &pqxx::result::query() const & noexcept { return (m_query == nullptr) ? s_empty_string : *m_query; } pqxx::oid pqxx::result::inserted_oid(sl loc) const { if (m_data.get() == nullptr) throw usage_error{ "Attempt to read oid of inserted row without an INSERT result", loc}; return PQoidValue(real_res(m_data.get())); } pqxx::result::size_type pqxx::result::affected_rows() const { // PQcmdTuples() can't take a "PGresult const *" because it returns a // non-const pointer into the PGresult's data, and that can't be changed // without breaking compatibility. // // But as far as libpqxx is concerned, it's totally const. std::string_view const rows_str{ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast) PQcmdTuples(const_cast<::PGresult *>(real_res(m_data.get())))}; // rows_str may be empty in case the query executed was a `SET = // ''` return rows_str.empty() ? 0 : from_string(rows_str); } char const *pqxx::result::get_value( pqxx::result::size_type row, pqxx::row::size_type col) const noexcept { return PQgetvalue(real_res(m_data.get()), row, col); } bool pqxx::result::get_is_null( pqxx::result::size_type row, pqxx::row::size_type col) const noexcept { return PQgetisnull(real_res(m_data.get()), row, col) != 0; } pqxx::field::size_type pqxx::result::get_length( pqxx::result::size_type row, pqxx::row::size_type col) const noexcept { return static_cast( PQgetlength(real_res(m_data.get()), row, col)); } pqxx::oid pqxx::result::column_type(row::size_type col_num, sl loc) const { oid const t{PQftype(real_res(m_data.get()), col_num)}; if (t == oid_none) throw argument_error{ std::format( "Attempt to retrieve type of nonexistent column {} of query result.", col_num), loc}; return t; } pqxx::row::size_type pqxx::result::column_number(zview col_name, sl loc) const { auto const n{PQfnumber(real_res(m_data.get()), col_name.c_str())}; if (n == -1) throw argument_error{ std::format("Unknown column name: '{}'.", to_string(col_name)), loc}; return static_cast(n); } pqxx::oid pqxx::result::column_table(row::size_type col_num, sl loc) const { oid const t{PQftable(real_res(m_data.get()), col_num)}; /* If we get oid_none, it may be because the column is computed, or because * we got an invalid row number. */ if (t == oid_none and col_num >= columns()) throw argument_error{ std::format( "Attempt to retrieve table ID for column {} out of {}.", col_num, columns()), loc}; return t; } pqxx::row::size_type pqxx::result::table_column(row::size_type col_num, sl loc) const { auto const n{row::size_type(PQftablecol(real_res(m_data.get()), col_num))}; if (n != 0) [[likely]] return n - 1; // Failed. Now find out why, so we can throw a sensible exception. auto const col_str{to_string(col_num)}; if (col_num > columns()) throw range_error{ std::format("Invalid column index in table_column(): {}.", col_str), loc}; if (m_data.get() == nullptr) throw usage_error{ std::format( "Can't query origin of column {}: result is not initialized.", col_str), loc}; throw usage_error{ std::format( "Can't query origin of column {}: not derived from table column.", col_str), loc}; } int pqxx::result::errorposition() const { int pos{-1}; if (m_data.get()) { auto const p{ PQresultErrorField(real_res(m_data.get()), PG_DIAG_STATEMENT_POSITION)}; if (p) pos = from_string(p); } return pos; } char const * pqxx::result::column_name(pqxx::row::size_type number, sl loc) const & { auto const n{PQfname(real_res(m_data.get()), number)}; if (n == nullptr) [[unlikely]] { if (m_data.get() == nullptr) throw usage_error{"Queried column name on null result.", loc}; throw range_error{ std::format( "Invalid column number: {} (maximum is {}).", number, (columns() - 1)), loc}; } return n; } pqxx::row::size_type pqxx::result::columns() const noexcept { return m_data ? row::size_type(PQnfields(real_res(m_data.get()))) : 0; } int pqxx::result::column_storage(pqxx::row::size_type number, sl loc) const { int const out{PQfsize(real_res(m_data.get()), number)}; if (out == 0) { auto const sz{this->size()}; if (std::cmp_less(number, 0) or std::cmp_greater_equal(number, sz)) throw argument_error{ std::format( "Column number out of range: {} (have 0 - {})", number, sz), loc}; throw failure{ std::format("Error getting column_storage for column {}.", number), loc}; } return out; } int pqxx::result::column_type_modifier( pqxx::row::size_type number) const noexcept { return PQfmod(real_res(m_data.get()), number); } pqxx::row pqxx::result::one_row(sl loc) const { check_one_row(loc); return row{front()}; } pqxx::row_ref pqxx::result::one_row_ref(sl loc) const { check_one_row(loc); return front(); } pqxx::field pqxx::result::one_field(sl loc) const { expect_columns(1, loc); return field{one_row(loc)[0]}; } pqxx::field_ref pqxx::result::one_field_ref(sl loc) const { expect_columns(1, loc); return one_row_ref(loc)[0]; } std::optional pqxx::result::opt_row(sl loc) const { auto const sz{size()}; if (sz > 1) { // TODO: See whether result contains a generated statement. if (not m_query or m_query->empty()) throw unexpected_rows{ std::format("Expected at most 1 row from query, got {}.", sz), loc}; else throw unexpected_rows{ std::format( "Expected at most 1 row from query '{}', got {}.", *m_query, sz), loc}; } else if (sz == 1) { return row{front()}; } else { return {}; } } std::optional pqxx::result::opt_row_ref(sl loc) const { // TODO: Reduce duplication with opt_row(). auto const sz{size()}; if (sz > 1) { // TODO: See whether result contains a generated statement. if (not m_query or m_query->empty()) throw unexpected_rows{ std::format("Expected at most 1 row from query, got {}.", sz), loc}; else throw unexpected_rows{ std::format( "Expected at most 1 row from query '{}', got {}.", *m_query, sz), loc}; } else if (sz == 1) { return {front()}; } else { return {}; } } // const_result_iterator pqxx::const_result_iterator pqxx::const_result_iterator::operator++(int) & { const_result_iterator old{*this}; pqxx::internal::gate::row_ref_const_result_iterator{m_row}.offset(1); return old; } pqxx::const_result_iterator pqxx::const_result_iterator::operator--(int) & { const_result_iterator old{*this}; pqxx::internal::gate::row_ref_const_result_iterator{m_row}.offset(-1); return old; } pqxx::result::const_iterator pqxx::result::const_reverse_iterator::base() const noexcept { iterator_type tmp{*this}; return ++tmp; } pqxx::const_reverse_result_iterator pqxx::const_reverse_result_iterator::operator++(int) & { const_reverse_result_iterator const tmp{*this}; iterator_type::operator--(); return tmp; } pqxx::const_reverse_result_iterator pqxx::const_reverse_result_iterator::operator--(int) & { const_reverse_result_iterator const tmp{*this}; iterator_type::operator++(); return tmp; } libpqxx-8.0.1/src/robusttransaction.cxx000066400000000000000000000151511516427024100203130ustar00rootroot00000000000000/** Implementation of the pqxx::robusttransaction class. * * pqxx::robusttransaction is a slower but safer transaction class. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include #include #include #include "pqxx/internal/header-pre.hxx" #include "pqxx/connection.hxx" #include "pqxx/internal/wait.hxx" #include "pqxx/nontransaction.hxx" #include "pqxx/result.hxx" #include "pqxx/robusttransaction.hxx" #include "pqxx/internal/header-post.hxx" using namespace std::literals; namespace { using pqxx::operator""_zv; /// Statuses in which we may find our transaction. /** There's also "in the future," but it manifests as an error, not as an * actual status. */ enum tx_stat { tx_unknown, tx_committed, tx_aborted, tx_in_progress, }; constexpr auto committed{"committed"_zv}, aborted{"aborted"_zv}, in_progress{"in progress"_zv}; // LCOV_EXCL_START /// Parse a nonempty transaction status string. constexpr tx_stat parse_status(std::string_view text) noexcept { switch (text[0]) { case 'a': if (text == aborted) [[likely]] return tx_aborted; break; case 'c': if (text == committed) [[likely]] return tx_committed; break; case 'i': if (text == in_progress) [[likely]] return tx_in_progress; break; } return tx_unknown; } #if !defined(NDEBUG) static_assert(parse_status("aborted") == tx_aborted); static_assert(parse_status("committed") == tx_committed); static_assert(parse_status("in progress") == tx_in_progress); static_assert(parse_status("ABORTED") == tx_unknown); static_assert(parse_status("Aborted") == tx_unknown); static_assert(parse_status("COMMITTED") == tx_unknown); static_assert(parse_status("Committed") == tx_unknown); static_assert(parse_status("IN PROGRESS") == tx_unknown); static_assert(parse_status("In Progress") == tx_unknown); static_assert(parse_status("unknown") == tx_unknown); static_assert(parse_status("something") == tx_unknown); #endif // LCOV_EXCL_STOP tx_stat query_status( std::string const &xid, std::string const &conn_str, pqxx::sl loc = pqxx::sl::current()) { static std::string_view const name{"robusttxck"sv}; auto const query{std::format("SELECT txid_status({})", xid)}; pqxx::connection cx{conn_str, loc}; pqxx::nontransaction tx{cx, name}; auto const status_row{tx.exec(query, loc).one_row(loc)}; auto const status_field{status_row[0]}; if (std::size(status_field) == 0) throw pqxx::internal_error{"Transaction status string is empty.", loc}; auto const status{parse_status(status_field.view())}; if (status == tx_unknown) throw pqxx::internal_error{ std::format( "Unknown transaction status string: {}", static_cast(status_field.view())), loc}; return status; } } // namespace void pqxx::internal::basic_robusttransaction::init(zview begin_command, sl loc) { static auto const txid_q{ std::make_shared("SELECT txid_current()"sv)}; m_backendpid = conn().backendpid(); direct_exec(begin_command, loc); m_xid = direct_exec(txid_q, loc).one_field_ref(loc).as(loc); } pqxx::internal::basic_robusttransaction::basic_robusttransaction( connection &cx, zview begin_command, sl loc) : dbtransaction(cx, loc), m_conn_string{cx.connection_string()} { init(begin_command, loc); } pqxx::internal::basic_robusttransaction::~basic_robusttransaction() = default; void pqxx::internal::basic_robusttransaction::do_commit(sl loc) { static auto const check_constraints_q{ std::make_shared("SET CONSTRAINTS ALL IMMEDIATE"sv)}, commit_q{std::make_shared("COMMIT"sv)}; // Check constraints before sending the COMMIT to the database, so as to // minimise our in-doubt window. try { direct_exec(check_constraints_q, loc); } catch (std::exception const &) { do_abort(loc); throw; } // Here comes the in-doubt window. If we lose our connection here, we'll be // left clueless as to what happened on the backend. It may have received // the commit command and completed the transaction, and ended up with a // success it could not report back to us. Or it may have noticed the broken // connection and aborted the transaction. It may even still be executing // the commit, only to fail later. // // All this uncertainty requires some special handling, and that's what makes // robusttransaction what it is. try { direct_exec(commit_q, loc); // If we make it here, great. Normal, successful commit. return; } catch (broken_connection const &) { // Oops, lost connection at the crucial moment. Fall through to in-doubt // handling below. } catch (std::exception const &) { if (conn().is_open()) { // Commit failed, for some other reason. do_abort(loc); throw; } // Otherwise, fall through to in-doubt handling. } // If we get here, we're in doubt. Figure out what happened. constexpr int max_attempts{500}; constexpr unsigned int wait_micros{300u}; static_assert(max_attempts > 0); for (int attempts{0}; attempts < max_attempts; ++attempts, pqxx::internal::wait_for(wait_micros)) { try { switch (query_status(m_xid, m_conn_string, loc)) { case tx_unknown: // We were unable to reconnect and query transaction status. // Stay in it for another attempt. return; case tx_committed: // Success! We're done. return; case tx_aborted: // Aborted. We're done. do_abort(loc); return; case tx_in_progress: // The transaction is still running. Stick around until we know what // transpires. break; default: PQXX_UNREACHABLE; } } catch (pqxx::broken_connection const &) { // We can expect this to happen before we can get a working // connection. Swallow the error and retry. } } // Okay, this has taken too long. Give up, report in-doubt state. throw in_doubt_error{ std::format( "Transaction {} (with transaction ID {}) lost connection while " "committing. It's impossible to tell whether it committed, or aborted, " "or is still running. Attempts to find out its outcome have failed. " "The backend process on the server had process ID {}. " "You may be able to check what happened to that process.", name(), m_xid, m_backendpid), loc}; } libpqxx-8.0.1/src/row.cxx000066400000000000000000000053451516427024100153420ustar00rootroot00000000000000/** Implementation of the pqxx::result class and support classes. * * pqxx::result represents the set of result rows from a database query. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include #include "pqxx/internal/header-pre.hxx" extern "C" { #include } #include "pqxx/except.hxx" #include "pqxx/result.hxx" #include "pqxx/row.hxx" #include "pqxx/internal/header-post.hxx" pqxx::row::row(result r, result::size_type index, size_type cols) noexcept : m_result{std::move(r)}, m_index{index}, m_end{cols} {} pqxx::field_ref pqxx::row::front() const noexcept { return {m_result, m_index, 0}; } pqxx::field_ref pqxx::row::back() const noexcept { return {m_result, m_index, m_end - 1}; } pqxx::field_ref pqxx::row::operator[](size_type i) const noexcept { return {m_result, m_index, i}; } #if defined(PQXX_HAVE_MULTIDIM) pqxx::field_ref pqxx::row_ref::operator[](zview col_name, sl loc) const { return at(col_name, loc); } #endif // PQXX_HAVE_MULTIDIM pqxx::field_ref pqxx::row_ref::operator[](zview col_name) const { return at(col_name, sl::current()); } void pqxx::row::swap(row &rhs) noexcept { auto const i{m_index}; auto const e{m_end}; m_result.swap(rhs.m_result); m_index = rhs.m_index; m_end = rhs.m_end; rhs.m_index = i; rhs.m_end = e; } pqxx::field_ref pqxx::row::at(zview col_name, sl loc) const { return {m_result, m_index, column_number(col_name, loc)}; } pqxx::field_ref pqxx::row::at(pqxx::row::size_type i, sl loc) const { auto const sz{this->size()}; if (std::cmp_greater_equal(i, sz)) throw range_error{ std::format( "Column index out of range: {} in a result of {} column(s).", i, sz), loc}; return operator[](i); } pqxx::const_row_iterator pqxx::const_row_iterator::operator++(int) & noexcept { auto old{*this}; pqxx::internal::gate::field_ref_const_row_iterator(m_field).offset(1); return old; } pqxx::const_row_iterator pqxx::const_row_iterator::operator--(int) & noexcept { auto old{*this}; pqxx::internal::gate::field_ref_const_row_iterator(m_field).offset(-1); return old; } pqxx::const_row_iterator pqxx::const_reverse_row_iterator::base() const noexcept { iterator_type tmp{*this}; return ++tmp; } pqxx::const_reverse_row_iterator pqxx::const_reverse_row_iterator::operator++(int) & noexcept { auto tmp{*this}; operator++(); return tmp; } pqxx::const_reverse_row_iterator pqxx::const_reverse_row_iterator::operator--(int) & { auto tmp{*this}; operator--(); return tmp; } libpqxx-8.0.1/src/sql_cursor.cxx000066400000000000000000000246051516427024100167270ustar00rootroot00000000000000/** Implementation of libpqxx STL-style cursor classes. * * These classes wrap SQL cursors in STL-like interfaces. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include #include "pqxx/internal/header-pre.hxx" #include "pqxx/cursor.hxx" #include "pqxx/internal/encodings.hxx" #include "pqxx/internal/gates/connection-sql_cursor.hxx" #include "pqxx/internal/header-post.hxx" using namespace std::literals; namespace { /// Is this character a "useless trailing character" in a query? /** A character is "useless" at the end of a query if it is either whitespace * or a semicolon. */ PQXX_PURE inline constexpr bool useless_trail(char c) noexcept { return (c == ' ') or (c == '\t') or (c == '\n') or (c == '\r') or (c == ';'); } // LCOV_EXCL_START /// Find end of nonempty query, stripping off any trailing semicolon. /** When executing a normal query, a trailing semicolon is meaningless but * won't hurt. That's why we can't rule out that some code may include one. * * But for cursor queries, a trailing semicolon is a problem. The query gets * embedded in a larger statement, which a semicolon would break into two. * We'll have to remove it if present. * * A trailing semicolon may not actually be at the end. It could be masked by * subsequent whitespace. If there's also a comment though, that's the * caller's own lookout. We can't guard against every possible mistake, and * text processing is actually remarkably sensitive to mistakes in a * multi-encoding world. * * If there is a trailing semicolon, this function returns its offset. If * there are more than one, it returns the offset of the first one. If there * is no trailing semicolon, it returns the length of the query string. * * The query must be nonempty. */ constexpr std::string::size_type find_query_end(std::string_view query, pqxx::encoding_group enc, pqxx::sl loc) { auto const size{std::size(query)}; // Marker for the end of the last "useful" character in the query. std::size_t end{}; if (enc == pqxx::encoding_group::ascii_safe) { // This is an encoding where we can just scan backwards from the end. for (end = size; end > 0 and useless_trail(query[end - 1]); --end); } else { // Complex encoding. We only know how to iterate forwards, so start from // the beginning. end = 0; // Look for ASCII whitespace & semicolons. Really we're looking for // anything that's _not_ one of those. auto const finder{ pqxx::internal::get_char_finder<' ', '\t', '\n', '\r', ';'>(enc, loc)}; for (std::size_t here{0}, next{}; here < size; here = next + 1) { next = finder(query, here, loc); if ((next - here) > 0) // Found something that's not whitespace or semicolon. Move the "end" // marker to the location right after it. end = next; } } return end; } #if !defined(NDEBUG) /// Convenience shorthand: Invoke @ref find_query_end for compile-time testing. consteval auto check_query_end( pqxx::encoding_group enc, std::string_view query, pqxx::sl loc = pqxx::sl::current()) { return find_query_end(query, enc, loc); } static_assert(check_query_end(pqxx::encoding_group::ascii_safe, "") == 0); static_assert(check_query_end(pqxx::encoding_group::ascii_safe, "; ") == 0); static_assert(check_query_end(pqxx::encoding_group::ascii_safe, "ABC") == 3); static_assert(check_query_end(pqxx::encoding_group::ascii_safe, "X Y") == 3); static_assert(check_query_end(pqxx::encoding_group::ascii_safe, "n ") == 1); static_assert(check_query_end(pqxx::encoding_group::ascii_safe, " n ") == 2); static_assert(check_query_end(pqxx::encoding_group::ascii_safe, "? ; ") == 1); static_assert( check_query_end(pqxx::encoding_group::ascii_safe, " ( ; ) ") == 6); static_assert(check_query_end(pqxx::encoding_group::two_tier, "") == 0); static_assert(check_query_end(pqxx::encoding_group::two_tier, "; ") == 0); static_assert(check_query_end(pqxx::encoding_group::two_tier, "ABC") == 3); static_assert(check_query_end(pqxx::encoding_group::two_tier, "X Y") == 3); static_assert(check_query_end(pqxx::encoding_group::two_tier, "n ") == 1); static_assert(check_query_end(pqxx::encoding_group::two_tier, " n ") == 2); static_assert(check_query_end(pqxx::encoding_group::two_tier, "? ; ") == 1); static_assert(check_query_end(pqxx::encoding_group::two_tier, " ( ; ) ") == 6); #endif // NDEBUG // LCOV_EXCL_STOP } // namespace pqxx::internal::sql_cursor::sql_cursor( transaction_base &t, std::string_view query, std::string_view cname, cursor_base::access_policy ap, cursor_base::update_policy up, cursor_base::ownership_policy op, bool hold, sl loc) : cursor_base{t.conn(), cname}, m_home{t.conn()}, m_at_end{-1}, m_pos{0}, m_created_loc{loc} { if (&t.conn() != &m_home) throw internal_error{"Using cursor in the wrong connection.", loc}; if (std::empty(query)) throw usage_error{"Cursor has empty query.", loc}; auto const enc{t.conn().get_encoding_group(loc)}; auto const qend{find_query_end(query, enc, loc)}; if (qend == 0) throw usage_error{"Cursor has effectively empty query.", loc}; query.remove_suffix(std::size(query) - qend); std::string const cq{std::format( "DECLARE {} {} SCROLL CURSOR {} FOR {} {}", t.quote_name(name()), ((ap == cursor_base::forward_only) ? "NO" : ""), (hold ? "WITH HOLD" : ""), query, ((up == cursor_base::update) ? "FOR UPDATE "sv : "FOR READ ONLY"))}; t.exec(cq, loc); // Now that we're here in the starting position, keep a copy of an empty // result. That may come in handy later, because we may not be able to // construct an empty result with all the right metadata due to the weird // meaning of "FETCH 0." init_empty_result(t, loc); m_ownership = op; } pqxx::internal::sql_cursor::sql_cursor( transaction_base &t, std::string_view cname, cursor_base::ownership_policy op, sl loc) : cursor_base{t.conn(), cname, false}, m_home{t.conn()}, m_ownership{op}, m_at_end{0}, m_pos{-1}, m_created_loc{loc} {} pqxx::internal::sql_cursor::~sql_cursor() noexcept { try { close(m_created_loc); } catch (std::exception const &e) { m_home.process_notice( std::format("Error closing cursor {}: {}", name(), e.what())); // Not much more we can do! } } void pqxx::internal::sql_cursor::close(sl loc) { if (m_ownership == cursor_base::owned) { gate::connection_sql_cursor{m_home}.exec( std::format("CLOSE {}", m_home.quote_name(name())).c_str(), loc); m_ownership = cursor_base::loose; } } void pqxx::internal::sql_cursor::init_empty_result(transaction_base &t, sl loc) { if (pos() != 0) throw internal_error{"init_empty_result() from bad pos().", loc}; m_empty_result = t.exec(std::format("FETCH 0 IN {}", m_home.quote_name(name())), loc); } /// Compute actual displacement based on requested and reported displacements. pqxx::internal::sql_cursor::difference_type pqxx::internal::sql_cursor::adjust( difference_type hoped, difference_type actual) { if (actual < 0) throw internal_error{"Negative rows in cursor movement."}; if (hoped == 0) return 0; int const direction{((hoped < 0) ? -1 : 1)}; bool hit_end{false}; if (actual != labs(hoped)) { if (actual > labs(hoped)) throw internal_error{"Cursor displacement larger than requested."}; // If we see fewer rows than requested, then we've hit an end (on either // side) of the result set. Wether we make an extra step to a one-past-end // position or whether we're already there depends on where we were // previously: if our last move was in the same direction and also fell // short, we're already at a one-past-end row. if (m_at_end != direction) ++actual; // If we hit the beginning, make sure our position calculation ends up // at zero (even if we didn't previously know where we were!), and if we // hit the other end, register the fact that we now know where the end // of the result set is. if (direction > 0) hit_end = true; else if (m_pos == -1) m_pos = actual; else if (m_pos != actual) throw internal_error{std::format( "Moved back to beginning, but wrong position: hoped={}, " "actual={}, m_pos={}, direction={}.", hoped, actual, m_pos, direction)}; m_at_end = direction; } else { m_at_end = 0; } if (m_pos >= 0) m_pos += direction * actual; if (hit_end) { if (m_endpos >= 0 and m_pos != m_endpos) throw internal_error{"Inconsistent cursor end positions."}; m_endpos = m_pos; } return direction * actual; } pqxx::result pqxx::internal::sql_cursor::fetch( difference_type rows, difference_type &displacement, sl loc) { if (rows == 0) { displacement = 0; return m_empty_result; } auto const query{std::format( "FETCH {} IN {}", stridestring(rows), m_home.quote_name(name()))}; auto r{gate::connection_sql_cursor{m_home}.exec(query.c_str(), loc)}; displacement = adjust(rows, difference_type(std::size(r))); return r; } pqxx::cursor_base::difference_type pqxx::internal::sql_cursor::move( difference_type rows, difference_type &displacement, sl loc) { if (rows == 0) { displacement = 0; return 0; } auto const query{std::format( "MOVE {} IN {}", stridestring(rows), m_home.quote_name(name()))}; auto const r{gate::connection_sql_cursor{m_home}.exec(query.c_str(), loc)}; auto d{static_cast(r.affected_rows())}; displacement = adjust(rows, d); return d; } std::string pqxx::internal::sql_cursor::stridestring(difference_type n) { /* Some special-casing for ALL and BACKWARD ALL here. We used to use numeric * "infinities" for difference_type for this (the highest and lowest possible * values for "long"), but for PostgreSQL 8.0 at least, the backend appears * to expect a 32-bit number and fails to parse large 64-bit numbers. We * could change the alias to match this behaviour, but that would break * if/when Postgres is changed to accept 64-bit displacements. */ static std::string const All{"ALL"}, BackAll{"BACKWARD ALL"}; if (n >= cursor_base::all()) return All; else if (n <= cursor_base::backward_all()) return BackAll; return to_string(n); } libpqxx-8.0.1/src/strconv.cxx000066400000000000000000000331401516427024100162230ustar00rootroot00000000000000/** Implementation of string conversions. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include #include #include #include #include #include #include #include #include #include "pqxx/internal/header-pre.hxx" #include "pqxx/except.hxx" #include "pqxx/strconv.hxx" #include "pqxx/internal/header-post.hxx" using namespace std::literals; namespace { /// The lowest possible value of integral type T. template constexpr T bottom{std::numeric_limits::min()}; /// The highest possible value of integral type T. template constexpr T top{std::numeric_limits::max()}; /// Write nonnegative integral value at end of buffer. Return start. /** Assumes a sufficiently large buffer. * * Includes a single trailing null byte, right before @c *end. */ template constexpr inline char *nonneg_to_buf(char *end, T value) { assert(std::cmp_greater_equal(value, 0)); constexpr int ten{10}; // Seeming bug in clang-tidy rule: it thinks we can make pos a "char const *" // instead of a plain "char *". I don't see how. // NOLINTNEXTLINE(misc-const-correctness) char *pos = end; do { *--pos = pqxx::internal::number_to_digit(int(value % ten)); value = T(value / ten); } while (value > 0); return pos; } /// Write negative version of value at end of buffer. Return start. /** Like @c nonneg_to_buf, but prefixes a minus sign. */ template constexpr inline char *neg_to_buf(char *end, T value) { assert(std::cmp_greater_equal(value, 0)); // Seeming bug in clang-tidy rule: it thinks we can make pos a "char const *" // instead of a plain "char *". I don't see how. // NOLINTNEXTLINE(misc-const-correctness) char *pos{nonneg_to_buf(end, value)}; *--pos = '-'; return pos; } /// Write lowest possible negative value at end of buffer. /** Like @c neg_to_buf, but for the special case of the bottom value. */ template constexpr inline char *bottom_to_buf(char *end) { static_assert(std::is_signed_v); // This is the hard case. In two's-complement systems, which includes // any modern-day system I can think of, a signed type's bottom value // has no positive equivalent. Luckily the C++ standards committee can't // think of any exceptions either, so it's the required representation as // of C++20. static_assert(-(bottom + 1) == top); // The unsigned version of T does have the unsigned version of bottom. using unsigned_t = std::make_unsigned_t; // Careful though. If we tried to negate value in order to promote to // unsigned_t, the value will overflow, which means behaviour is // undefined. Promotion of a negative value to an unsigned type is // well-defined, given a representation, so let's do that: constexpr auto positive{static_cast(bottom)}; // As luck would have it, in two's complement, this gives us exactly the // value we want. static_assert(positive == top / 2 + 1); // So the only thing we need to do differently from the regular negative // case is to skip that overflowing negation and promote to an unsigned type! return neg_to_buf(end, positive); } template concept arith = pqxx::internal::integer or std::floating_point; /// Call to_chars, report errors as exceptions, add zero, return pointer. template inline char *wrap_to_chars(std::span buf, T const &value, pqxx::sl loc) { auto const begin{std::data(buf)}, end{begin + std::size(buf)}; auto res{std::to_chars(begin, end, value)}; if (res.ec == std::errc()) [[likely]] return res.ptr; else if (res.ec == std::errc::value_too_large) throw pqxx::conversion_overrun{ std::format( "Could not convert {} to string: buffer too small ({} bytes).", pqxx::name_type(), std::size(buf)), loc}; else throw pqxx::conversion_error{ std::format("Could not convert {} to string.", pqxx::name_type()), loc}; } } // namespace namespace pqxx::internal { // TODO: Equivalents for converting a null in the other direction. PQXX_COLD void throw_null_conversion(std::string const &type, sl loc) { throw conversion_error{ std::format("Attempted to convert SQL null to {}.", type), loc}; } PQXX_COLD void throw_null_conversion(std::string_view type, sl loc) { throw conversion_error{ std::format("Attempted to convert SQL null to {}.", type), loc}; } PQXX_COLD std::string state_buffer_overrun(int have_bytes, int need_bytes) { // We convert these in standard library terms, to avoid "error cycles," if // these values in turn should fail to get enough buffer space. return std::format("Have {} bytes, need {}.", have_bytes, need_bytes); } } // namespace pqxx::internal namespace { template inline TYPE from_string_arithmetic(std::string_view in, pqxx::ctx c) { char const *here{std::data(in)}; auto const end{std::data(in) + std::size(in)}; // Skip whitespace. This is not the proper way to do it, but I see no way // that any of the supported encodings could ever produce a valid character // whose byte sequence would confuse this code. while (here < end and (*here == ' ' or *here == '\t')) ++here; TYPE out{}; auto const res{std::from_chars(here, end, out)}; if (res.ec == std::errc() and res.ptr == end) [[likely]] return out; std::string msg; if (res.ec == std::errc()) { msg = "Could not parse full string."; } else { switch (res.ec) { case std::errc::result_out_of_range: msg = "Value out of range."; break; case std::errc::invalid_argument: msg = "Invalid argument."; break; default: break; } } auto const base{std::format( "Could not convert '{}' to {}", std::string(in), pqxx::name_type())}; if (std::empty(msg)) throw pqxx::conversion_error{std::format("{}.", base), c.loc}; else throw pqxx::conversion_error{std::format("{}: {}", base, msg), c.loc}; } // TODO: Remove this workaround once compilers have float charconv. #if !defined(PQXX_HAVE_CHARCONV_FLOAT) constexpr bool valid_infinity_string(std::string_view text) noexcept { return text == "inf" or text == "infinity" or text == "INFINITY" or text == "Infinity"; } /// Wrapper for std::stringstream with C locale. /** We use this to work around missing std::to_chars for floating-point types. * * Initialising the stream (including locale and tweaked precision) seems to * be expensive. So, create thread-local instances which we re-use. It's a * lockless way of keeping global variables thread-safe, basically. * * The stream initialisation happens once per thread, in the constructor. * And that's why we need to wrap this in a class. We can't just do it at the * call site, or we'd still be doing it for every call. */ template class dumb_stringstream : public std::stringstream { public: // Do not initialise the base-class object using "stringstream{}" (with curly // braces): that breaks on Visual C++. The classic "stringstream()" syntax // (with parentheses) does work. PQXX_COLD dumb_stringstream() { this->imbue(std::locale::classic()); this->precision(std::numeric_limits::max_digits10); } }; template PQXX_COLD inline bool from_dumb_stringstream( dumb_stringstream &s, F &result, std::string_view text) { s.str(std::string{text}); return static_cast(s >> result); } // These are hard, and some popular compilers still lack std::from_chars. template PQXX_COLD inline T from_string_awful_float(std::string_view text, pqxx::ctx c) { if (std::empty(text)) throw pqxx::conversion_error{ std::format( "Trying to convert empty string to {}.", pqxx::name_type()), c.loc}; bool ok{false}; T result; switch (text[0]) { case 'N': case 'n': // Accept "NaN," "nan," etc. ok = (std::size(text) == 3 and (text[1] == 'A' or text[1] == 'a') and (text[2] == 'N' or text[2] == 'n')); result = std::numeric_limits::quiet_NaN(); break; case 'I': case 'i': ok = valid_infinity_string(text); result = std::numeric_limits::infinity(); break; default: if (text[0] == '-' and valid_infinity_string(text.substr(1))) { ok = true; result = -std::numeric_limits::infinity(); } else [[likely]] { thread_local dumb_stringstream S; // Visual Studio 2017 seems to fail on repeated conversions if the // clear() is done before the seekg(). Still don't know why! See #124 // and #125. S.seekg(0); S.clear(); ok = from_dumb_stringstream(S, result, text); } break; } if (not ok) throw pqxx::conversion_error{ std::format( "Could not convert string to numeric value: '{}'.", std::string(text)), c.loc}; return result; } #endif // !PQXX_HAVE_CHARCONV_FLOAT #if !defined(PQXX_HAVE_CHARCONV_FLOAT) template PQXX_COLD inline std::string to_dumb_stringstream(dumb_stringstream &s, F value) { s.str(""); s << value; return s.str(); } #endif } // namespace namespace pqxx::internal { /// Floating-point implementations for @c pqxx::to_string(). template std::string to_string_float(T value, [[maybe_unused]] ctx c) { #if defined(PQXX_HAVE_CHARCONV_FLOAT) { static constexpr auto space{pqxx::size_buffer(value)}; std::string buf; buf.resize(space); std::string_view const view{to_buf(buf, value, c)}; buf.resize(static_cast(std::size(view))); return buf; } #else return std::format("{}", value); #endif } template T float_string_traits::from_string(std::string_view text, pqxx::ctx c) { #if defined(PQXX_HAVE_CHARCONV_FLOAT) return from_string_arithmetic(text, c); #else return from_string_awful_float(text, c); #endif } template std::string_view float_string_traits::to_buf(std::span buf, T const &value, ctx c) { auto const begin{std::data(buf)}; #if defined(PQXX_HAVE_CHARCONV_FLOAT) { // Definitely prefer to let the standard library handle this! auto const ptr{wrap_to_chars(buf, value, c.loc)}; return {begin, std::size_t(ptr - begin)}; } #else { auto const end{begin + std::size(buf)}; auto const res{std::format_to_n(begin, end - begin, "{}", value)}; if (std::cmp_greater_equal(res.size, end - begin)) throw conversion_overrun{ std::format( "Buffer too small for converting {} to string.", name_type()), c.loc}; return {begin, static_cast(res.size)}; } #endif } template struct float_string_traits; template struct float_string_traits; template struct float_string_traits; } // namespace pqxx::internal namespace pqxx::internal { template TYPE integer_string_traits::from_string(std::string_view text, ctx c) { return from_string_arithmetic(text, c); } template inline std::string_view // NOLINTNEXTLINE(readability-non-const-parameter) integer_string_traits::to_buf( std::span buf, TYPE const &value, ctx c) { static_assert(std::is_integral_v); auto const space{std::size(buf)}, need{size_buffer(value)}; if (std::cmp_less(space, need)) throw conversion_overrun{ std::format( "Could not convert {} to string: buffer too small. {}", name_type(), pqxx::internal::state_buffer_overrun(space, need)), c.loc}; auto const end{std::data(buf) + std::size(buf)}; char const *const pos{[end, &value]() { if constexpr (std::is_unsigned_v) return nonneg_to_buf(end, value); else if (value >= 0) return nonneg_to_buf(end, value); else if (value > bottom) return neg_to_buf(end, -value); else return bottom_to_buf(end); }()}; return {pos, static_cast(end - pos)}; } template struct integer_string_traits; template struct integer_string_traits; template struct integer_string_traits; template struct integer_string_traits; template struct integer_string_traits; template struct integer_string_traits; template struct integer_string_traits; template struct integer_string_traits; } // namespace pqxx::internal namespace pqxx::internal { template std::string to_string_float(float, ctx); template std::string to_string_float(double, ctx); template std::string to_string_float(long double, ctx); } // namespace pqxx::internal bool pqxx::string_traits::from_string(std::string_view text, ctx c) { std::optional result; // TODO: Don't really need to handle all these formats. switch (std::size(text)) { case 0: result = false; break; case 1: switch (text[0]) { case 'f': case 'F': case '0': result = false; break; case 't': case 'T': case '1': result = true; break; default: break; } break; case std::size("true"sv): if (text == "true" or text == "TRUE") result = true; break; case std::size("false"sv): if (text == "false" or text == "FALSE") result = false; break; default: break; } if (result) return *result; else throw conversion_error{std::format( "Failed conversion to bool ({}): '{}'.", pqxx::source_loc(c.loc), std::string{text})}; } libpqxx-8.0.1/src/stream_from.cxx000066400000000000000000000167341516427024100170550ustar00rootroot00000000000000/** Implementation of the pqxx::stream_from class. * * pqxx::stream_from enables optimized batch reads from a database table. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include #include #include "pqxx/internal/header-pre.hxx" #include "pqxx/internal/encodings.hxx" #include "pqxx/internal/gates/connection-stream_from.hxx" #include "pqxx/stream_from.hxx" #include "pqxx/transaction_base.hxx" #include "pqxx/internal/header-post.hxx" namespace { pqxx::internal::char_finder_func *get_finder(pqxx::transaction_base const &tx) { pqxx::sl const loc{pqxx::sl::current()}; auto const group{tx.conn().get_encoding_group(loc)}; return pqxx::internal::get_char_finder<'\t', '\\'>(group, loc); } constexpr std::string_view stream_from_name{"stream_from"}; } // namespace pqxx::stream_from::stream_from( transaction_base &tx, from_query_t, std::string_view query) : transaction_focus{tx, stream_from_name}, m_char_finder{get_finder(tx)} { sl const loc{sl::current()}; tx.exec(std::format("COPY ({}) TO STDOUT", query), loc).no_rows(loc); register_me(); } pqxx::stream_from::stream_from( transaction_base &tx, from_table_t, std::string_view table) : transaction_focus{tx, stream_from_name, table}, m_char_finder{get_finder(tx)} { sl const loc{sl::current()}; tx.exec(std::format("COPY {} TO STDOUT", tx.quote_name(table)), loc) .no_rows(loc); register_me(); } pqxx::stream_from::stream_from( transaction_base &tx, std::string_view table, std::string_view columns, from_table_t) : transaction_focus{tx, stream_from_name, table}, m_char_finder{get_finder(tx)} { sl const loc{sl::current()}; if (std::empty(columns)) [[unlikely]] tx.exec(std::format("COPY {} TO STDOUT", table), loc).no_rows(loc); else [[likely]] tx.exec(std::format("COPY {}({}) TO STDOUT", table, columns), loc) .no_rows(loc); register_me(); } pqxx::stream_from::stream_from( transaction_base &tx, std::string_view unquoted_table, std::string_view columns, from_table_t, int) : stream_from{ tx, tx.conn().quote_table(unquoted_table), columns, from_table} {} pqxx::stream_from pqxx::stream_from::raw_table( transaction_base &tx, std::string_view path, std::string_view columns) { return {tx, path, columns, from_table}; } pqxx::stream_from pqxx::stream_from::table( transaction_base &tx, table_path path, std::initializer_list columns) { auto const &cx{tx.conn()}; #include "pqxx/internal/ignore-deprecated-pre.hxx" return raw_table(tx, cx.quote_table(path), cx.quote_columns(columns)); #include "pqxx/internal/ignore-deprecated-post.hxx" } pqxx::stream_from::~stream_from() noexcept { try { close(); } catch (std::exception const &e) { reg_pending_error(e.what(), sl::current()); } } pqxx::stream_from::raw_line pqxx::stream_from::get_raw_line(sl loc) { if (*this) { internal::gate::connection_stream_from gate{trans().conn()}; try { raw_line line{gate.read_copy_line(loc)}; if (line.first == nullptr) close(); return line; } catch (std::exception const &) { close(); throw; } } else { return std::make_pair( std::unique_ptr{nullptr, nullptr}, 0u); } } void pqxx::stream_from::close() { if (not m_finished) [[unlikely]] { m_finished = true; unregister_me(); } } void pqxx::stream_from::complete(sl loc) { if (m_finished) return; try { // Flush any remaining lines - libpq will automatically close the stream // when it hits the end. bool done{false}; while (not done) { [[maybe_unused]] auto [line, size] = get_raw_line(loc); done = not line.get(); } } catch (broken_connection const &) { close(); throw; } catch (std::exception const &e) { reg_pending_error(e.what(), loc); } close(); } void pqxx::stream_from::parse_line(sl loc) { if (m_finished) [[unlikely]] return; // TODO: Any way to keep current size in a local var, for speed? m_fields.clear(); auto const [line, line_size] = get_raw_line(loc); if (line.get() == nullptr) { m_finished = true; return; } if (line_size >= (std::numeric_limits::max() / 2)) throw range_error{"Stream produced a ridiculously long line.", loc}; // Make room for unescaping the line. It's a pessimistic size. // // This is the only place where we modify m_row. MAKE SURE THE BUFFER DOES // NOT GET RESIZED while we're working, because we're working with views into // its buffer. m_row.resize(line_size); char const *const line_begin{line.get()}; std::string_view const line_view{line_begin, line_size}; // Output iterator for unescaped text. char *write{m_row.data()}; // The pointer cannot be null at this point. But we initialise field_begin // with this value, and carry it around the loop, and it can later become // null. Static analysis in clang-tidy then likes to assume a case where // field_begin is null, and deduces from this that "write" must have been // null -- and so it marks "*write" as a null pointer dereference. // // This assertion tells clang-tidy just what it needs in order to deduce // that *write never dereferences a null pointer. assert(write != nullptr); // Beginning of current field in m_row, or nullptr for null fields. char const *field_begin{write}; std::size_t offset{0}; while (offset < line_size) { auto const stop_char{m_char_finder(line_view, offset, loc)}; assert(stop_char <= line_size); // Copy the text we have so far. It's got no special characters in it. std::memcpy(write, &line_begin[offset], stop_char - offset); write += (stop_char - offset); if (stop_char >= line_size) break; offset = stop_char; char const special{line_begin[stop_char]}; ++offset; if (special == '\t') { // Field separator. End the field. // End the field. if (field_begin == nullptr) m_fields.emplace_back(); else m_fields.emplace_back(field_begin, write - field_begin); // Set up for the next field. field_begin = write; } else { // Escape sequence. assert(special == '\\'); if ((offset) >= line_size) throw failure{"Row ends in backslash", loc}; // The database will only escape ASCII characters, so no need to use // the glyph scanner. char const escaped{line_begin[offset++]}; if (escaped == 'N') { // Null value. if (write != field_begin) throw failure{"Null sequence found in nonempty field", loc}; field_begin = nullptr; // (If there's any characters _after_ the null we'll just crash.) } *write++ = pqxx::internal::unescape_char(escaped); } } // End the last field here. if (field_begin == nullptr) { m_fields.emplace_back(); } else { m_fields.emplace_back(field_begin, write - field_begin); } // DO NOT shrink m_row to fit. We're carrying string_views pointing into // the buffer. (Also, how useful would shrinking really be?) } std::vector const *pqxx::stream_from::read_row(sl loc) & { parse_line(loc); return m_finished ? nullptr : &m_fields; } libpqxx-8.0.1/src/stream_to.cxx000066400000000000000000000071251516427024100165260ustar00rootroot00000000000000/** Implementation of the pqxx::stream_to class. * * pqxx::stream_to enables optimized batch updates to a database table. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include "pqxx/internal/header-pre.hxx" #include "pqxx/internal/gates/connection-stream_to.hxx" #include "pqxx/stream_from.hxx" #include "pqxx/stream_to.hxx" #include "pqxx/internal/header-post.hxx" namespace { using namespace std::literals; void begin_copy( pqxx::transaction_base &tx, std::string_view table, std::string_view columns, pqxx::sl loc) { pqxx::result res; if (std::empty(columns)) res = tx.exec(std::format("COPY {} FROM STDIN", table)); else res = tx.exec(std::format("COPY {} ({}) FROM STDIN", table, columns)); res.no_rows(loc); } /// Return the escape character for escaping the given special character. char escape_char(char special, pqxx::sl loc) { switch (special) { case '\b': return 'b'; case '\f': return 'f'; case '\n': return 'n'; case '\r': return 'r'; case '\t': return 't'; case '\v': return 'v'; case '\\': return '\\'; default: break; } throw pqxx::internal_error{ std::format( "Stream escaping unexpectedly stopped at '{}'.", static_cast(static_cast(special))), loc}; } } // namespace pqxx::stream_to::~stream_to() noexcept { try { complete(m_created_loc); } catch (std::exception const &e) { reg_pending_error(e.what(), m_created_loc); } } void pqxx::stream_to::write_raw_line(std::string_view text, sl loc) { internal::gate::connection_stream_to{trans().conn()}.write_copy_line( text, loc); } void pqxx::stream_to::write_buffer(sl loc) { if (not std::empty(m_buffer)) { // In append_to_buffer() we write a tab after each field. We only want a // tab _between_ fields. Remove that last one. assert(m_buffer[std::size(m_buffer) - 1] == '\t'); m_buffer.resize(std::size(m_buffer) - 1); } write_raw_line(m_buffer, loc); m_buffer.clear(); } pqxx::stream_to &pqxx::stream_to::operator<<(stream_from &tr) { while (tr) { const auto [line, size] = tr.get_raw_line(m_created_loc); if (line.get() == nullptr) break; write_raw_line(std::string_view{line.get(), size}, m_created_loc); } return *this; } pqxx::stream_to::stream_to( transaction_base &tx, std::string_view path, std::string_view columns, sl loc) : transaction_focus{tx, s_classname, path}, m_finder{pqxx::internal::get_char_finder< '\b', '\f', '\n', '\r', '\t', '\v', '\\'>( tx.conn().get_encoding_group(loc), loc)}, m_created_loc{loc} { begin_copy(tx, path, columns, loc); register_me(); } void pqxx::stream_to::complete(sl loc) { if (!m_finished) { m_finished = true; unregister_me(); internal::gate::connection_stream_to{trans().conn()}.end_copy_write(loc); } } void pqxx::stream_to::escape_field_to_buffer(std::string_view data, sl loc) { std::size_t const end{std::size(data)}; std::size_t here{0}; while (here < end) { auto const stop_char{m_finder(data, here, loc)}; // Append any unremarkable characters we just skipped over. m_buffer.append(std::data(data) + here, stop_char - here); if (stop_char < end) { m_buffer.push_back('\\'); m_buffer.push_back(escape_char(data[stop_char], loc)); } here = stop_char + 1; } // Terminate the field. m_buffer.push_back('\t'); } libpqxx-8.0.1/src/subtransaction.cxx000066400000000000000000000032601516427024100175640ustar00rootroot00000000000000/** Implementation of the pqxx::subtransaction class. * * pqxx::transaction is a nested transaction, i.e. one within a transaction * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include #include "pqxx/internal/header-pre.hxx" #include "pqxx/connection.hxx" #include "pqxx/subtransaction.hxx" #include "pqxx/internal/header-post.hxx" using namespace std::literals; pqxx::subtransaction::subtransaction( dbtransaction &t, std::string_view tname, sl loc) : transaction_focus{t, "subtransaction"sv, t.conn().adorn_name(tname)}, // We can't initialise the rollback command here, because we don't yet // have a full object to implement quoted_name(). dbtransaction{t.conn(), tname, std::shared_ptr{}, loc} { set_rollback_cmd(std::make_shared( std::format("ROLLBACK TO SAVEPOINT {}", quoted_name()))); direct_exec( std::make_shared(std::format("SAVEPOINT {}", quoted_name())), loc); } namespace { using dbtransaction_ref = pqxx::dbtransaction &; } // namespace pqxx::subtransaction::subtransaction( subtransaction &t, std::string_view tname, sl loc) : subtransaction(dbtransaction_ref(t), tname, loc) {} pqxx::subtransaction::~subtransaction() noexcept { close(created_loc()); } void pqxx::subtransaction::do_commit(sl loc) { direct_exec( std::make_shared( std::format("RELEASE SAVEPOINT {}", quoted_name())), loc); } libpqxx-8.0.1/src/time.cxx000066400000000000000000000161651516427024100154730ustar00rootroot00000000000000/** Implementation of date/time support. */ #include "pqxx-source.hxx" #include #include "pqxx/internal/header-pre.hxx" #include "pqxx/time.hxx" #include "pqxx/internal/header-post.hxx" #if defined(PQXX_HAVE_YEAR_MONTH_DAY) namespace { using namespace std::literals; /// Because the C++ Core Guidelines don't like numeric constants... constexpr int ten{10}; /// Render the numeric part of a year value into a buffer. /** Converts the year from "common era" (with a Year Zero) to "anno domini" * (without a Year Zero). * * Doesn't render the sign. When you're rendering a date, you indicate a * negative year by suffixing "BC" at the very end. * * @return A pointer to the character right after the last digit. */ inline char * year_into_buf(char *begin, std::chrono::year const &value, pqxx::ctx c = {}) { int const y{value}; if (y == int{(std::chrono::year::min)()}) [[unlikely]] { // This is an evil special case: C++ year -32767 translates to 32768 BC, // which is a number we can't fit into a short. At the moment postgres // doesn't handle years before 4713 BC, but who knows, right? constexpr int oldest{-32767}; static_assert(int{(std::chrono::year::min)()} == oldest); constexpr auto hardcoded{"32768"sv}; begin += hardcoded.copy(begin, std::size(hardcoded)); } else { // C++ std::chrono::year has a year zero. PostgreSQL does not. So, C++ // year zero is 1 BC in the postgres calendar; C++ 1 BC is postgres 2 BC, // and so on. auto const absy{static_cast(std::abs(y) + int{y <= 0})}; // Keep C++ Code Guidelines happy. constexpr int hundred{100}, thousand{1000}; // PostgreSQL requires year input to be at least 3 digits long, or it // won't be able to deduce the date format correctly. However on output // it always writes years as at least 4 digits, and we'll do the same. // Dates and times are a dirty, dirty business. if (absy < thousand) [[unlikely]] { *begin++ = '0'; if (absy < hundred) *begin++ = '0'; if (absy < ten) *begin++ = '0'; } // Maximum text length for a year. static constexpr int max_year{std::chrono::year::max()}; // This isn't the actual buffer size, but it's a conservative // approximation so should be fine. begin += pqxx::into_buf({begin, begin + pqxx::size_buffer(max_year)}, absy, c); } return begin; } /// Parse the numeric part of a year value. inline int year_from_buf(std::string_view text, pqxx::sl loc) { if (std::size(text) < 4) throw pqxx::conversion_error{ std::format("Year field is too small: '{}'.", text), loc}; // Parse as int, so we can accommodate 32768 BC which won't fit in a short // as-is, but equates to 32767 BCE which will. int const year{pqxx::from_string(text)}; if (year <= 0) throw pqxx::conversion_error{std::format("Bad year: '{}'.", text), loc}; return year; } /// Render a valid 1-based month number into a buffer. /* @return A pointer to the byte right after the last digit. */ inline char *month_into_buf(char *begin, std::chrono::month const &value) { unsigned const m{value}; if (m >= ten) *begin = '1'; else *begin = '0'; ++begin; *begin++ = pqxx::internal::number_to_digit(static_cast(m % ten)); return begin; } /// Parse a 1-based month value. inline std::chrono::month month_from_string(std::string_view text, pqxx::sl loc) { if ( not pqxx::internal::is_digit(text[0]) or not pqxx::internal::is_digit(text[1])) throw pqxx::conversion_error{ std::format("Invalid month: '{}'.", text), loc}; return std::chrono::month{unsigned( (ten * pqxx::internal::digit_to_number(text[0])) + pqxx::internal::digit_to_number(text[1]))}; } /// Render a valid 1-based day-of-month value into a buffer. inline char *day_into_buf(char *begin, std::chrono::day const &value) { unsigned const d{value}; *begin++ = pqxx::internal::number_to_digit(static_cast(d / ten)); *begin++ = pqxx::internal::number_to_digit(static_cast(d % ten)); return begin; } /// Parse a 1-based day-of-month value. inline std::chrono::day day_from_string(std::string_view text, pqxx::sl loc) { if ( not pqxx::internal::is_digit(text[0]) or not pqxx::internal::is_digit(text[1])) throw pqxx::conversion_error{ std::format("Bad day in date: '{}'.", text), loc}; std::chrono::day const d{unsigned( (ten * pqxx::internal::digit_to_number(text[0])) + pqxx::internal::digit_to_number(text[1]))}; if (not d.ok()) throw pqxx::conversion_error{ std::format("Bad day in date: '{}'.", text), loc}; return d; } /// Look for the dash separating year and month. /** Assumes that @c text is nonempty. */ inline std::size_t find_year_month_separator(std::string_view text) noexcept { // We're looking for a dash. PostgreSQL won't output a negative year, so // no worries about a leading dash. We could start searching at offset 4, // but starting at the beginning produces more helpful error messages for // malformed years. std::size_t here{0}; while (here < std::size(text) and text[here] != '-') ++here; return here; } /// Componse generic "invalid date" message for given (invalid) date text. std::string make_parse_error(std::string_view text) { return std::format("Invalid date: '{}'.", text); } } // namespace namespace pqxx { std::string_view string_traits::to_buf( std::span buf, std::chrono::year_month_day const &value, ctx c) { if (std::size(buf) < size_buffer(value)) throw conversion_overrun{"Not enough room in buffer for date.", c.loc}; auto here{std::data(buf)}; here = year_into_buf(here, value.year()); *here++ = '-'; here = month_into_buf(here, value.month()); *here++ = '-'; here = day_into_buf(here, value.day()); if (int{value.year()} <= 0) [[unlikely]] here += s_bc.copy(here, std::size(s_bc)); return {std::data(buf), static_cast(here - std::data(buf))}; } std::chrono::year_month_day string_traits::from_string( std::string_view text, sl loc) { // We can't just re-use the std::chrono::year conversions, because the "BC" // suffix comes at the very end. if (std::size(text) < 9) throw conversion_error{make_parse_error(text), loc}; bool const is_bc{text.ends_with(s_bc)}; if (is_bc) [[unlikely]] text = text.substr(0, std::size(text) - std::size(s_bc)); auto const ymsep{find_year_month_separator(text)}; if ((std::size(text) - ymsep) != 6) throw conversion_error{make_parse_error(text), loc}; auto const base_year{ year_from_buf(std::string_view{std::data(text), ymsep}, loc)}; if (base_year == 0) throw conversion_error{"Year zero conversion.", loc}; std::chrono::year const y{is_bc ? (-base_year + 1) : base_year}; auto const m{month_from_string(text.substr(ymsep + 1, 2), loc)}; if (text[ymsep + 3] != '-') throw conversion_error{make_parse_error(text), loc}; auto const d{day_from_string(text.substr(ymsep + 4, 2), loc)}; std::chrono::year_month_day const date{y, m, d}; if (not date.ok()) throw conversion_error{make_parse_error(text), loc}; return date; } } // namespace pqxx #endif libpqxx-8.0.1/src/transaction.cxx000066400000000000000000000065141516427024100170570ustar00rootroot00000000000000/** Implementation of the pqxx::transaction class. * * pqxx::transaction represents a regular database transaction. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include "pqxx/internal/header-pre.hxx" #include "pqxx/connection.hxx" #include "pqxx/result.hxx" #include "pqxx/transaction.hxx" #include "pqxx/internal/header-post.hxx" pqxx::internal::basic_transaction::basic_transaction( connection &cx, zview begin_command, std::string_view tname, sl loc) : dbtransaction(cx, tname, loc) { register_transaction(); direct_exec(begin_command, loc); } pqxx::internal::basic_transaction::basic_transaction( connection &cx, zview begin_command, std::string &&tname, sl loc) : dbtransaction(cx, std::move(tname), loc) { register_transaction(); direct_exec(begin_command, loc); } pqxx::internal::basic_transaction::basic_transaction( connection &cx, zview begin_command, sl loc) : dbtransaction(cx, loc) { register_transaction(); direct_exec(begin_command, loc); } // This should stop the compiler from generating the same vtables and // destructor in multiple translation units. More importantly, if we don't do // this, the sanitisers in g++ 7 and clang++ 6 complain about pointers to // dbtransaction actually pointing to basic_transaction. Which is odd, in that // any basic_transaction pointer should also be a dbtransaction pointer. But, // apparently the vtable isn't the right one. pqxx::internal::basic_transaction::~basic_transaction() noexcept = default; void pqxx::internal::basic_transaction::do_commit(sl loc) { static auto const commit_q{std::make_shared("COMMIT"sv)}; try { direct_exec(commit_q, loc); } catch (statement_completion_unknown const &e) { // Outcome of "commit" is unknown. This is a disaster: we don't know the // resulting state of the database. process_notice(std::format("{}\n", e.what())); std::string msg{std::format( "WARNING: {}: Commit status of transaction '{}' is unknown. " "There is no way to tell whether the transaction succeeded " "or was aborted except to check manually.\n", pqxx::source_loc(loc), name())}; process_notice(msg); // Strip newline. It was only needed for process_notice(). msg.pop_back(); throw in_doubt_error{msg, e.location()}; } catch (std::exception const &e) { if (not conn().is_open()) { // We've lost the connection while committing. There is just no way of // telling what happened on the other end. >8-O process_notice(std::format("{}\n", e.what())); auto msg{std::format( "WARNING: {}: Connection lost while committing transaction '{}'. " "There is no way to tell whether the transaction succeeded or was " "aborted except to check manually.\n", pqxx::source_loc(loc), name())}; process_notice(msg); // Strip newline. It was only needed for process_notice(). msg.pop_back(); throw in_doubt_error{msg, loc}; } else { // Commit failed--probably due to a constraint violation or something // similar. throw; } } } libpqxx-8.0.1/src/transaction_base.cxx000066400000000000000000000343211516427024100200460ustar00rootroot00000000000000/** Common code and definitions for the transaction classes. * * pqxx::transaction_base defines the interface for any abstract class that * represents a database transaction. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include #include #include "pqxx/internal/header-pre.hxx" #include "pqxx/connection.hxx" #include "pqxx/internal/encodings.hxx" #include "pqxx/internal/gates/connection-transaction.hxx" #include "pqxx/internal/gates/transaction-transaction_focus.hxx" #include "pqxx/result.hxx" #include "pqxx/transaction_base.hxx" #include "pqxx/transaction_focus.hxx" #include "pqxx/internal/header-post.hxx" using namespace std::literals; namespace { /// Return a query pointer for the command "ROLLBACK". /** Concentrates constructions so as to minimise the number of allocations. * This way, the string gets allocated once and then all subsequent invocations * copy shared_ptr instances to the same string. */ std::shared_ptr make_rollback_cmd() { static auto const cmd{std::make_shared("ROLLBACK")}; return cmd; } } // namespace pqxx::transaction_base::transaction_base(connection &cx, sl loc) : m_conn{cx}, m_rollback_cmd{make_rollback_cmd()}, m_created_loc{loc} {} pqxx::transaction_base::transaction_base( connection &cx, std::string_view tname, sl loc) : m_conn{cx}, m_name{tname}, m_rollback_cmd{make_rollback_cmd()}, m_created_loc{loc} {} pqxx::transaction_base::transaction_base( connection &cx, std::string_view tname, std::shared_ptr rollback_cmd, sl loc) : m_conn{cx}, m_name{tname}, m_rollback_cmd{std::move(rollback_cmd)}, m_created_loc{loc} {} pqxx::transaction_base::~transaction_base() { try { if (not std::empty(m_pending_error)) [[unlikely]] process_notice(std::format("UNPROCESSED ERROR: {}\n", m_pending_error)); if (m_registered) { m_conn.process_notice( std::format("{} was never closed properly!\n", description())); pqxx::internal::gate::connection_transaction{conn()} .unregister_transaction(this); } } catch (std::exception const &e) { try { process_notice(std::format("{}\n", e.what())); } catch (std::exception const &) { // TODO: Make at least an attempt to append a newline. process_notice(e.what()); } } } void pqxx::transaction_base::register_transaction() { pqxx::internal::gate::connection_transaction{conn()}.register_transaction( this); m_registered = true; } pqxx::conversion_context pqxx::transaction_base::make_context(sl loc) const { return conversion_context{m_conn.get_encoding_group(loc), loc}; } void pqxx::transaction_base::commit(sl loc) { check_pending_error(); // Check previous status code. Caller should only call this function if // we're in "implicit" state, but multiple commits are silently accepted. switch (m_status) { case status::active: // Just fine. This is what we expect. break; case status::aborted: throw usage_error{ std::format("Attempt to commit previously aborted {}", description()), loc}; case status::committed: // Transaction has been committed already. This is not exactly proper // behaviour, but throwing an exception here would only give the impression // that an abort is needed--which would only confuse things further at this // stage. // Therefore, multiple commits are accepted, though under protest. m_conn.process_notice( std::format("{} committed more than once.\n", description())); return; case status::in_doubt: // Transaction may or may not have been committed. The only thing we can // really do is keep telling the caller that the transaction is in doubt. throw in_doubt_error{std::format( "{} committed again while in an indeterminate state.", description())}; default: PQXX_UNREACHABLE; } // Tricky one. If stream is nested in transaction but inside the same scope, // the commit() will come before the stream is closed. Which means the // commit is premature. Punish this swiftly and without fail to discourage // the habit from forming. if (m_focus != nullptr) throw failure{ std::format( "Attempt to commit {} with {} still open.", description(), m_focus->description()), loc}; // Check that we're still connected (as far as we know--this is not an // absolute thing!) before trying to commit. If the connection was broken // already, the commit would fail anyway but this way at least we don't // remain in-doubt as to whether the backend got the commit order at all. if (not m_conn.is_open()) throw broken_connection{ "Broken connection to backend; cannot complete transaction.", loc}; try { do_commit(loc); m_status = status::committed; } catch (in_doubt_error const &) { m_status = status::in_doubt; throw; } catch (std::exception const &) { m_status = status::aborted; throw; } close(loc); } void pqxx::transaction_base::do_abort(sl loc) { if (m_rollback_cmd) direct_exec(m_rollback_cmd, loc); } void pqxx::transaction_base::abort(sl loc) { // Check previous status code. Quietly accept multiple aborts to // simplify emergency bailout code. switch (m_status) { case status::active: try { do_abort(loc); } catch (std::exception const &e) { m_conn.process_notice(std::format("{}\n", e.what())); } break; case status::aborted: return; case status::committed: throw usage_error{ std::format("Attempt to abort previously committed {}.", description()), loc}; case status::in_doubt: // Aborting an in-doubt transaction is probably a reasonably sane response // to an insane situation. Log it, but do not fail. m_conn.process_notice(std::format( "Warning: {} aborted after going into indeterminate state; " "it may have been executed anyway.\n", description())); return; default: PQXX_UNREACHABLE; } m_status = status::aborted; close(loc); } namespace { /// Guard command execution against clashes with pipelines and such. /** A transaction can have only one focus at a time. Command execution is the * most basic example of a transaction focus. */ class PQXX_PRIVATE command : pqxx::transaction_focus { public: command(pqxx::transaction_base &tx, std::string_view oname) : transaction_focus{tx, "command"sv, oname} { register_me(); } ~command() noexcept { unregister_me(); } command() = delete; command(command const &) = delete; command(command &&) = delete; command &operator=(command const &) = delete; command &operator=(command &&) = delete; }; } // namespace pqxx::result pqxx::transaction_base::exec(std::string_view query, sl loc) { check_pending_error(); command const cmd{*this, {}}; switch (m_status) { case status::active: break; case status::committed: case status::aborted: case status::in_doubt: // TODO: Pass query. throw usage_error{ "Could not execute command: transaction is already closed.", loc}; default: PQXX_UNREACHABLE; } return direct_exec(query, loc); } pqxx::result pqxx::transaction_base::exec( std::string_view query, std::string_view desc, sl loc) { check_pending_error(); command const cmd{*this, desc}; switch (m_status) { case status::active: break; case status::committed: case status::aborted: case status::in_doubt: { std::string const n{std::empty(desc) ? "" : std::format("'{}' ", desc)}; throw usage_error{ std::format( "Could not execute command {}: transaction is already closed.", n), loc}; } default: PQXX_UNREACHABLE; } return direct_exec(query, desc, loc); } pqxx::result pqxx::transaction_base::exec_n( result::size_type rows, std::string_view query, std::string_view desc) { #include "pqxx/internal/ignore-deprecated-pre.hxx" result r{exec(query, desc)}; #include "pqxx/internal/ignore-deprecated-post.hxx" r.expect_rows(rows); return r; } pqxx::result pqxx::transaction_base::internal_exec_prepared( std::string_view statement, internal::c_params const &args, sl loc) { command const cmd{*this, statement}; return pqxx::internal::gate::connection_transaction{conn()}.exec_prepared( statement, args, loc); } pqxx::result pqxx::transaction_base::internal_exec_params( std::string_view query, internal::c_params const &args, sl loc) { command const cmd{*this, query}; return pqxx::internal::gate::connection_transaction{conn()}.exec_params( query, args, loc); } void pqxx::transaction_base::notify( std::string_view channel, std::string_view payload, sl loc) { // For some reason, NOTIFY does not work as a parameterised statement, // even just for the payload (which is supposed to be a normal string). // Luckily, pg_notify() does. exec("SELECT pg_notify($1, $2)", params{*this, channel, payload}, loc) .one_row(loc); } void pqxx::transaction_base::set_variable( std::string_view var, std::string_view value) { #include "pqxx/internal/ignore-deprecated-pre.hxx" conn().set_variable(var, value); #include "pqxx/internal/ignore-deprecated-post.hxx" } std::string pqxx::transaction_base::get_variable(std::string_view var) { #include "pqxx/internal/ignore-deprecated-pre.hxx" return conn().get_variable(var); #include "pqxx/internal/ignore-deprecated-post.hxx" } void pqxx::transaction_base::close(sl loc) noexcept { try { try { check_pending_error(); } catch (std::exception const &e) { // TODO: Make at least an attempt to append a newline. m_conn.process_notice(e.what()); } if (m_registered) { m_registered = false; pqxx::internal::gate::connection_transaction{conn()} .unregister_transaction(this); } if (m_status != status::active) return; if (m_focus != nullptr) [[unlikely]] m_conn.process_notice(std::format( "Closing {} with {} still open.\n", description(), m_focus->description())); try { abort(loc); } catch (std::exception const &e) { // TODO: Make at least an attempt to append a newline. m_conn.process_notice(e.what()); } } catch (std::exception const &e) { try { // TODO: Make at least an attempt to append a newline. m_conn.process_notice(e.what()); } catch (std::exception const &) {} } } namespace { [[nodiscard]] std::string_view get_classname(pqxx::transaction_focus const *focus) { return (focus == nullptr) ? ""sv : focus->classname(); } [[nodiscard]] std::string_view get_obj_name(pqxx::transaction_focus const *focus) { return (focus == nullptr) ? ""sv : focus->name(); } } // namespace void pqxx::transaction_base::register_focus(transaction_focus *new_focus) { internal::check_unique_register( m_focus, get_classname(m_focus), get_obj_name(m_focus), new_focus, get_classname(new_focus), get_obj_name(new_focus)); m_focus = new_focus; } void pqxx::transaction_base::unregister_focus( transaction_focus *new_focus) noexcept { try { pqxx::internal::check_unique_unregister( m_focus, get_classname(m_focus), get_obj_name(m_focus), new_focus, get_classname(new_focus), get_obj_name(new_focus)); m_focus = nullptr; } catch (std::exception const &e) { // TODO: Make at least an attempt to append a newline. m_conn.process_notice(e.what()); } } pqxx::result pqxx::transaction_base::direct_exec( std::string_view cmd, std::string_view desc, sl loc) { check_pending_error(); return pqxx::internal::gate::connection_transaction{conn()}.exec( cmd, desc, loc); } // TODO: Pass cmd as a const reference. // NOLINTBEGIN(performance-unnecessary-value-param) pqxx::result pqxx::transaction_base::direct_exec( std::shared_ptr cmd, std::string_view desc, sl loc) { check_pending_error(); return pqxx::internal::gate::connection_transaction{conn()}.exec( cmd, desc, loc); } // NOLINTEND(performance-unnecessary-value-param) void pqxx::transaction_base::register_pending_error(zview err, sl loc) noexcept { if (std::empty(m_pending_error) and not std::empty(err)) { try { m_pending_error = err; } catch (std::exception const &e) { try { [[unlikely]] process_notice( std::format("{} UNABLE TO PROCESS ERROR\n", pqxx::source_loc(loc))); // TODO: Make at least an attempt to append a newline. process_notice(e.what()); process_notice("ERROR WAS:\n"); process_notice(err); } catch (...) {} } } } void pqxx::transaction_base::register_pending_error( std::string &&err, sl loc) noexcept { if (std::empty(m_pending_error) and not std::empty(err)) { try { m_pending_error = std::move(err); } catch (std::exception const &e) { try { process_notice( std::format("{} UNABLE TO PROCESS ERROR\n", pqxx::source_loc(loc))); // TODO: Make at least an attempt to append a newline. process_notice(e.what()); process_notice("ERROR WAS:\n"); process_notice(err); } catch (...) {} } } } void pqxx::transaction_base::check_pending_error() { if (not std::empty(m_pending_error)) { // TODO: Store exceptions, or message + source_location. std::string err; err.swap(m_pending_error); throw failure{err}; } } std::string pqxx::transaction_base::description() const { return internal::describe_object("transaction", name()); } void pqxx::transaction_focus::register_me() { pqxx::internal::gate::transaction_transaction_focus{trans()}.register_focus( this); m_registered = true; } void pqxx::transaction_focus::unregister_me() noexcept { pqxx::internal::gate::transaction_transaction_focus{trans()} .unregister_focus(this); m_registered = false; } void pqxx::transaction_focus::reg_pending_error( std::string const &err, sl loc) noexcept { pqxx::internal::gate::transaction_transaction_focus{trans()} .register_pending_error(err, loc); } libpqxx-8.0.1/src/types.cxx000066400000000000000000000025641516427024100156770ustar00rootroot00000000000000/** Implementation of types-related helpers. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include #if __has_include() # include #endif #include "pqxx/internal/header-pre.hxx" #include "pqxx/types.hxx" #include "pqxx/internal/header-post.hxx" // C++26: Drop this. #if !defined(PQXX_HAVE_TYPE_DISPLAY) PQXX_ZARGS std::string pqxx::internal::demangle_type_name(char const raw[]) noexcept { # if defined(PQXX_HAVE_CXA_DEMANGLE) // We've got __cxa_demangle. Use it to get a friendlier type name. int status{0}; // We've seen this fail on FreeBSD 11.3 (see #361). Trying to throw a // meaningful exception only made things worse. So in case of error, just // fall back to the raw name. // // When __cxa_demangle fails, it's guaranteed to return null. // // Oh, and don't bother trying to pass in a "length" argument. That's only // for the length of the buffer, not the length of the string. std::unique_ptr const str{ abi::__cxa_demangle(raw, nullptr, nullptr, &status), std::free}; if (str) return std::string{str.get()}; # endif return raw; } #endif libpqxx-8.0.1/src/util.cxx000066400000000000000000000211621516427024100155030ustar00rootroot00000000000000/** Various utility functions. * * Copyright (c) 2000-2026, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #include "pqxx-source.hxx" #include #include #include #include #include #include #include #include "pqxx/internal/header-pre.hxx" extern "C" { #include } #include "pqxx/except.hxx" #include "pqxx/util.hxx" #include "pqxx/version.hxx" #include "pqxx/internal/header-post.hxx" using namespace std::literals; PQXX_COLD pqxx::thread_safety_model pqxx::describe_thread_safety() { auto const libpq_ok{PQisthreadsafe() != 0}, kerb_ok{false}; return { .description = std::format( "{}{}", (libpq_ok ? "" : "Using a libpq build that is not thread-safe.\n"), (kerb_ok ? "" : "Kerberos is not thread-safe. If your application uses Kerberos, " "protect all calls to Kerberos or libpqxx using a global lock.\n")), .safe_libpq = libpq_ok, // Sadly I'm not aware of any way to avoid this just yet. .safe_kerberos = kerb_ok}; } std::string pqxx::internal::describe_object( std::string_view class_name, std::string_view obj_name) { if (std::empty(obj_name)) return std::string{class_name}; else return std::format("{} '{}'", class_name, obj_name); } void pqxx::internal::check_unique_register( void const *old_guest, std::string_view old_class, std::string_view old_name, void const *new_guest, std::string_view new_class, std::string_view new_name) { if (new_guest == nullptr) throw internal_error{"Null pointer registered."}; if (old_guest != nullptr) throw usage_error{ (old_guest == new_guest) ? std::format( "Started twice: {}.", describe_object(old_class, old_name)) : std::format( "Started new {} while {} was still active.", describe_object(new_class, new_name), describe_object(old_class, old_name))}; } void pqxx::internal::check_unique_unregister( void const *old_guest, std::string_view old_class, std::string_view old_name, void const *new_guest, std::string_view new_class, std::string_view new_name) { if (new_guest != old_guest) [[unlikely]] { if (new_guest == nullptr) throw usage_error{std::format( "Expected to close, but got null pointer instead.", describe_object(old_class, old_name))}; if (old_guest == nullptr) throw usage_error{std::format( "Closed while not open: {}", describe_object(new_class, new_name))}; else throw usage_error{std::format( "Closed {}; expected to close ", describe_object(new_class, new_name), describe_object(old_class, old_name))}; } } namespace { constexpr std::array hex_digits{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', }; // LCOV_EXCL_START /// Translate a number (must be between 0 and 16 exclusive) to a hex digit. constexpr char hex_digit(int c) noexcept { PQXX_ASSUME(c >= 0); return hex_digits.at(static_cast(c)); } #if !defined(NDEBUG) static_assert(hex_digit(0) == '0'); static_assert(hex_digit(9) == '9'); static_assert(hex_digit(10) == 'a'); static_assert(hex_digit(15) == 'f'); #endif // LCOV_EXCL_STOP constexpr int ten{10}; // LCOV_EXCL_START /// Translate a hex digit to a nibble. Return -1 if it's not a valid digit. constexpr int nibble(int c) noexcept { if (c >= '0' and c <= '9') [[likely]] return c - '0'; else if (c >= 'a' and c <= 'f') return ten + (c - 'a'); else [[unlikely]] if (c >= 'A' and c <= 'F') return ten + (c - 'A'); else [[unlikely]] return -1; } #if !defined(NDEBUG) static_assert(nibble('0') == 0); static_assert(nibble('9') == 9); static_assert(nibble('a') == 10); static_assert(nibble('f') == 15); #endif // LCOV_EXCL_STOP } // namespace namespace pqxx::internal { void esc_bin(bytes_view binary_data, std::span buffer) noexcept { assert(std::size(buffer) >= size_esc_bin(std::size(binary_data))); std::size_t here{0u}; // C++26: Use at(). buffer[here++] = '\\'; buffer[here++] = 'x'; constexpr int nibble_bits{4}; constexpr int nibble_mask{0x0f}; for (auto const byte : binary_data) { auto uc{static_cast(byte)}; buffer[here++] = hex_digit(uc >> nibble_bits); buffer[here++] = hex_digit(uc & nibble_mask); } // (No need to increment further. Facebook's "infer" complains if we do.) buffer[here] = '\0'; } std::string esc_bin(bytes_view binary_data) { auto const bytes{size_esc_bin(std::size(binary_data))}; std::string buf; buf.resize(bytes); esc_bin(binary_data, buf); // Strip off the trailing zero. buf.resize(bytes - 1); return buf; } void unesc_bin( std::string_view escaped_data, std::span buffer, sl loc) { auto const in_size{std::size(escaped_data)}; if (in_size < 2) throw pqxx::failure{"Binary data appears truncated.", loc}; if ((in_size % 2) != 0) throw pqxx::failure{"Invalid escaped binary length.", loc}; std::size_t in{0u}; if (escaped_data[in++] != '\\' or escaped_data[in++] != 'x') throw pqxx::failure( "Escaped binary data did not start with '\\x'`. Is the server or libpq " "too old?", loc); std::size_t out{0u}; while (in < in_size) { int const hi{nibble(escaped_data[in++])}; if (hi < 0) throw pqxx::failure{"Invalid hex-escaped data.", loc}; int const lo{nibble(escaped_data[in++])}; if (lo < 0) throw pqxx::failure{"Invalid hex-escaped data.", loc}; buffer[out++] = static_cast((hi << 4) | lo); } assert(out <= std::size(buffer)); } pqxx::bytes unesc_bin(std::string_view escaped_data, sl loc) { auto const bytes{size_unesc_bin(std::size(escaped_data))}; pqxx::bytes buf; buf.resize(bytes); unesc_bin(escaped_data, buf, loc); return buf; } /// Persistent copies of libpqxx version information. /** These are not efficient. They are stored here for one reason only: to * ensure that the libpqxx library binary contains its own version inforamtion, * even if the application code that calls libpqxx is compiled against a * different version. (We allow some slight differences.) That way we can * compare the binary version against the version that was in the headers. * * The `volatile` is probably overkill. I just want this to have linkage as * far as compilation is concerned. */ volatile int const binary_major{version_major}, binary_minor{version_minor}, binary_patch{version_patch}; /// Peristent copy of libpqxx version string. /** I'd like to make this `volatile`, but there are just too many complications * along the way. Which is probably for the best. * * Let's just hope that this declaration is enough to prevent the compiler from * optimising this away completely. (I wouldn't particularly mind if the * linker did so though.) */ std::string_view const binary_version{version}; int check_libpqxx_version( int apps_major, int apps_minor, int apps_patch, std::string_view apps_version) { if ((apps_major == binary_major) and (apps_minor == binary_minor)) { // Major and minor versions match. Without that, the odds of even getting // to this point in the code are pretty slim anyway. if (0 <= apps_patch) { // Application was compiled against a "regular" libpqxx version. We're // cool so long as the libpqxx binary is also regular, and the binary's // patch level is no less than the one used in the application build. // // (If 0 <= apps_patch <= version_patch, then it follows that // 0 <= version_patch. No need to check that.) if (apps_patch <= binary_patch) return 1; } else { // Compiled against a "special" libpqxx version, such as a release // candidate. We don't try to get clever about tolerating mismatches in // such cases; there's just too much that can go wrong. Demand an exact // string match. if (apps_version == binary_version) return 2; } } throw version_mismatch{std::format( "Mismatch in libpqxx versions: Compiled against libpqxx {} headers, " "but libpqxx binary is {}.", apps_version, binary_version)}; } } // namespace pqxx::internal namespace pqxx::internal::pq { void pqfreemem(void const *ptr) noexcept { // Why is it OK to const_cast here? Because this is the C equivalent to a // destructor. Those apply to const objects as well as non-const ones. // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast) PQfreemem(const_cast(ptr)); } } // namespace pqxx::internal::pq libpqxx-8.0.1/src/wait.cxx000066400000000000000000000101131516427024100154640ustar00rootroot00000000000000/** Functions that wait. */ #include "pqxx-source.hxx" #include "pqxx/config-compiler.h" #include // For WSAPoll(). // Normally we'd do this *after* including , but MinGW complains: it // issues a warning telling us to include winsock2.h before windows.h. // We don't actually include windows.h ourselves, but it looks as if MinGW's // does. #if __has_include() # include # define PQXX_HAVE_SELECT #endif // The header is still broken on MinGW. :-( #if defined(PQXX_HAVE_SLEEP_FOR) # include #endif #if __has_include() # include #endif #if __has_include() # include #endif // For poll(): #if __has_include() # include #endif // For select() on recent POSIX systems. #if __has_include() # include # define PQXX_HAVE_SELECT #endif // For select() on some older POSIX systems. #if __has_include() # include # define PQXX_HAVE_SELECT #endif #if __has_include() # include #endif #if __has_include() # include #endif #include "pqxx/internal/header-pre.hxx" #include "pqxx/internal/wait.hxx" #include "pqxx/util.hxx" #include "pqxx/internal/header-post.hxx" namespace { template T to_milli(unsigned seconds, unsigned microseconds, pqxx::sl loc) { return pqxx::check_cast( (seconds * 1000) + (microseconds / 1000), "Wait timeout value out of bounds.", loc); } #if !defined(PQXX_HAVE_POLL) && defined(PQXX_HAVE_SELECT) /// Set a bit on an fd_set. [[maybe_unused]] void set_fdbit(fd_set &bits, auto fd) { # ifdef _MSC_VER // Suppress pointless, unfixable warnings in Visual Studio. # pragma warning(push) # pragma warning(disable : 4389) // Signed/unsigned mismatch. # pragma warning(disable : 4127) // Conditional expression is constant. # endif FD_SET(fd, &bits); # ifdef _MSV_VER // Restore prevalent warning settings. # pragma warning(pop) # endif } #endif } // namespace void pqxx::internal::wait_fd( int fd, bool for_read, bool for_write, unsigned seconds, unsigned microseconds, [[maybe_unused]] sl loc) { // WSAPoll is available in winsock2.h only for versions of Windows >= 0x0600 #if defined(_WIN32) && (_WIN32_WINNT >= 0x0600) static_assert(SOCKET_ERROR == -1); short const events{static_cast( (for_read ? POLLRDNORM : 0) | (for_write ? POLLWRNORM : 0))}; WSAPOLLFD fdarray{SOCKET(fd), events, 0}; int const code{WSAPoll( &fdarray, 1u, check_cast( to_milli(seconds, microseconds, loc), "Timeout too large."))}; #elif defined(PQXX_HAVE_POLL) auto const events{static_cast( POLLERR | POLLHUP | POLLNVAL | (for_read ? POLLIN : 0) | (for_write ? POLLOUT : 0))}; pollfd pfd{fd, events, 0}; int const code{poll(&pfd, 1, to_milli(seconds, microseconds, loc))}; #else // No poll()? Our last option is select(). fd_set read_fds; FD_ZERO(&read_fds); if (for_read) set_fdbit(read_fds, fd); fd_set write_fds; FD_ZERO(&write_fds); if (for_write) set_fdbit(write_fds, fd); fd_set except_fds; FD_ZERO(&except_fds); set_fdbit(except_fds, fd); timeval tv = {seconds, microseconds}; int const code{select(fd + 1, &read_fds, &write_fds, &except_fds, &tv)}; #endif if (code == -1) { constexpr std::size_t buf_size{200u}; std::array errbuf{}; int const err_code{ #if defined(_WIN32) && (_WIN32_WINNT >= 0x0600) WSAGetLastError() #else errno #endif }; throw std::runtime_error{pqxx::internal::error_string(err_code, errbuf)}; } } PQXX_COLD void pqxx::internal::wait_for(unsigned int microseconds) { #if defined(PQXX_HAVE_SLEEP_FOR) std::this_thread::sleep_for(std::chrono::microseconds{microseconds}); #else // MinGW still does not have a functioning header. Work around this // using select(). // Not worth optimising for though -- they'll have to fix it at some point. timeval tv{microseconds / 1'000'000u, microseconds % 1'000'000u}; select(0, nullptr, nullptr, nullptr, &tv); #endif } libpqxx-8.0.1/test/000077500000000000000000000000001516427024100141705ustar00rootroot00000000000000libpqxx-8.0.1/test/CMakeLists.txt000066400000000000000000000007541516427024100167360ustar00rootroot00000000000000enable_testing() if(NOT PostgreSQL_FOUND) find_package(PostgreSQL REQUIRED) endif() file(GLOB TEST_SOURCES *.cxx) add_executable(runner ${TEST_SOURCES}) target_link_libraries(runner PUBLIC pqxx) target_include_directories(runner PRIVATE ${PostgreSQL_INCLUDE_DIRS}) add_test( NAME runner WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} COMMAND runner ) if(INSTALL_TEST) install( PROGRAMS runner TYPE BIN RENAME libpqxx-test-runner ) endif() libpqxx-8.0.1/test/helpers.hxx000066400000000000000000000467541516427024100164030ustar00rootroot00000000000000// NOLINTBEGIN(llvm-header-guard) #ifndef PQXX_TEST_HELPERS_HXX #define PQXX_TEST_HELPERS_HXX // NOLINTEND(llvm-header-guard) #include #include #include #include #include #include namespace pqxx::test { /// Random engine, for generating random values in tests. using randomizer = std::mt19937; /// Context for running a test. /** Defines various utilities that can help tests: randomisers, a temporary * filesystem directory. */ struct context final { // NOLINTBEGIN(cert-msc32-c,cert-msc51-cpp) /// Create a context for one thread to run tests. /** Seeds the randommiser with a highly predictable 0 initially. Call the * @ref seed() function before consuming random values. */ explicit context(std::size_t random_seed) : rnd{0}, rnd_seed{random_seed} {} // NOLINTEND(cert-msc32-c,cert-msc51-cpp) context() = delete; context(context const &) = delete; context(context &&) = delete; ~context() = default; context &operator=(context const &) = delete; context &operator=(context &&) = delete; /// Seed the randomiser using the original seed. /** Do this before every individual test to get reproducible test sequences. */ void seed(std::string_view test_name) { auto const seed{static_cast( rnd_seed ^ string_hasher(test_name))}; rnd.seed(seed); } /// Return an arbitrary nonnegative integer. int make_num() { return static_cast(rnd() >> 1); } /// Return an arbitrary nonnegative integer below `ceiling`. int make_num(int ceiling) { return make_num() % ceiling; } /// Return an arbitrary nonzero `char` value from the full 8-bit range. char random_char() { return static_cast(static_cast(make_num(255) + 1)); } /// Return an arbitrary numeric floating-point value. (No NaN or infinity.) template T make_float_num() { auto const x{make_num()}, z{make_num()}; auto y{make_num()}; while (y == x) y = make_num(); return static_cast(x - y) / static_cast(z); } /// Generate a name with a given prefix and a randomised suffix. std::string make_name(std::string_view prefix = {}) { int const num{make_num()}; // TODO: Use wider character set than just those digits. if (std::empty(prefix)) return std::format("{}", num); else return std::format("{}_{}", prefix, num); } private: /// A random engine. randomizer rnd; /// The random seed std::size_t rnd_seed; /// A factory of hash values for strings. std::hash string_hasher; }; /// Exception: A test does not satisfy expected condition. class test_failure : public std::logic_error { public: explicit test_failure(std::string const &desc, sl loc = sl::current()); test_failure(test_failure const &) = default; test_failure(test_failure &&) = default; ~test_failure() noexcept override; [[nodiscard]] sl const &location() const noexcept { return m_loc; } [[nodiscard]] std::string_view name() const noexcept { return "Failure"; } test_failure &operator=(test_failure const &) = delete; test_failure &operator=(test_failure &&) = delete; private: sl m_loc; }; /// For use by tests that need to simulate an exception. struct deliberate_error : std::exception {}; /// Drop a table, if it exists. void drop_table( transaction_base &, std::string const &table, sl loc = sl::current()); using testfunc = void (*)(pqxx::test::context &); /// Maximum number of tests in the test suite. /** If this should prove insufficient, increase it. */ constexpr inline std::size_t max_tests{1000}; /// The test suite. /** This is where the tests get registered at initialisation time. * * This gets a bit hacky. It relies on an internal counter being * zero-initialised before the test registrations get constructed. */ class suite { public: /// Register a test function. static void register_test(std::string_view name, testfunc func) noexcept; /// Collect all tests into a map: test name to test function. static std::map gather(); private: /// Number of registered tests. static constinit std::size_t s_num_tests; static constinit std::array s_names; static constinit std::array s_funcs; }; // Register a test function, so the runner will run it. #define PQXX_REGISTER_TEST(func) \ [[maybe_unused]] pqxx::test::registrar const tst_##func \ { \ #func, func \ } /// Register a test while not inside a function. struct registrar final { registrar(char const name[], testfunc func) noexcept { pqxx::test::suite::register_test(name, func); } }; // Unconditional test failure. [[noreturn]] void check_notreached( std::string const &desc = "Execution was never supposed to reach this point.", sl loc = sl::current()); // Verify that a condition is met, similar to assert(). // Takes an optional failure description as a second argument. #if defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL // Work around Visual Studio lacking support for __VA_OPT__. # define PQXX_CHECK(condition, ...) \ pqxx::test::check((condition), #condition, ##__VA_ARGS__) #else # define PQXX_CHECK(condition, ...) \ pqxx::test::check((condition), #condition __VA_OPT__(, ) __VA_ARGS__) #endif void check( bool condition, char const text[], std::string const &desc = "Condition check failed,", sl loc = sl::current()); // Verify that variable has the expected value. // Takes an optional failure description as a third argument. #if defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL // Work around Visual Studio lacking support for __VA_OPT__. # define PQXX_CHECK_EQUAL(actual, expected, ...) \ pqxx::test::check_equal( \ (actual), #actual, (expected), #expected, ##__VA_ARGS__) #else # define PQXX_CHECK_EQUAL(actual, expected, ...) \ pqxx::test::check_equal( \ (actual), #actual, (expected), #expected __VA_OPT__(, ) __VA_ARGS__) #endif template inline void check_equal( ACTUAL const &actual, char const *actual_text, EXPECTED const &expected, char const *expected_text, std::string const &desc = "Equality check failed.", sl loc = sl::current()) { // clang-tidy rule bug: // NOLINTBEGIN( // cppcoreguidelines-pro-bounds-array-to-pointer-decay, // hicpp-no-array-decay // ) if (expected == actual) return; // NOLINTEND( // cppcoreguidelines-pro-bounds-array-to-pointer-decay, // hicpp-no-array-decay // ) std::string const fulldesc = desc + " (" + actual_text + " <> " + expected_text + ": " "actual=" + to_string(actual) + ", " "expected=" + to_string(expected) + ")"; throw test_failure{ std::format( "{}\n{} <> {}.\nExpected: {}\nActual: {}", desc, actual_text, expected_text, to_string(expected), to_string(actual)), loc}; } // clang-tidy rule bug: // NOLINTBEGIN( // cppcoreguidelines-pro-bounds-array-to-pointer-decay, // hicpp-no-array-decay // ) // Verify that two values are not equal. // Takes an optional failure description as a third argument. #if defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL // Work around Visual Studio lacking support for __VA_OPT__. # define PQXX_CHECK_NOT_EQUAL(value1, value2, ...) \ pqxx::test::check_not_equal( \ (value1), #value1, (value2), #value2, ##__VA_ARGS__) #else # define PQXX_CHECK_NOT_EQUAL(value1, value2, ...) \ pqxx::test::check_not_equal( \ (value1), #value1, (value2), #value2 __VA_OPT__(, ) __VA_ARGS__) #endif template inline void check_not_equal( VALUE1 const &value1, char const text1[], VALUE2 const &value2, char const text2[], std::string const &desc = "Inequality check failed.", sl loc = sl::current()) { if (value1 != value2) return; std::string const fulldesc = desc + " (" + text1 + " == " + text2 + ": " "both are " + to_string(value2) + ")"; throw test_failure{fulldesc, loc}; } // NOLINTEND( // cppcoreguidelines-pro-bounds-array-to-pointer-decay, // hicpp-no-array-decay // ) // Verify that value1 is less/greater than value2. // Takes an optional failure description as a third argument. #if defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL // Work around Visual Studio lacking support for __VA_OPT__. # define PQXX_CHECK_LESS(value1, value2, ...) \ pqxx::test::check_less((value1), #value1, (value2), #value2, ##__VA_ARGS__) # define PQXX_CHECK_GREATER(value2, value1, ...) \ pqxx::test::check_less((value1), #value1, (value2), #value2, ##__VA_ARGS__) #else # define PQXX_CHECK_LESS(value1, value2, ...) \ pqxx::test::check_less( \ (value1), #value1, (value2), #value2 __VA_OPT__(, ) __VA_ARGS__) # define PQXX_CHECK_GREATER(value2, value1, ...) \ pqxx::test::check_less( \ (value1), #value1, (value2), #value2 __VA_OPT__(, ) __VA_ARGS__) #endif template inline void check_less( VALUE1 const &value1, char const text1[], VALUE2 const &value2, char const text2[], std::string const &desc = "Less/greater check failed.", sl loc = sl::current()) { if (value1 < value2) return; std::string const fulldesc = desc + " (" + text1 + " >= " + text2 + ": " "\"lower\"=" + to_string(value1) + ", " "\"upper\"=" + to_string(value2) + ")"; throw test_failure{fulldesc, loc}; } // Verify that value1 is less/greater than or equal to value2. // Takes an optional failure description as a third argument. #if defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL // Work around Visual Studio lacking support for __VA_OPT__. # define PQXX_CHECK_LESS_EQUAL(value1, value2, ...) \ pqxx::test::check_less_equal( \ (value1), #value1, (value2), #value2, ##__VA_ARGS__) # define PQXX_CHECK_GREATER_EQUAL(value2, value1, ...) \ pqxx::test::check_less_equal( \ (value1), #value1, (value2), #value2, ##__VA_ARGS__) #else # define PQXX_CHECK_LESS_EQUAL(value1, value2, ...) \ pqxx::test::check_less_equal( \ (value1), #value1, (value2), #value2 __VA_OPT__(, ) __VA_ARGS__) # define PQXX_CHECK_GREATER_EQUAL(value2, value1, ...) \ pqxx::test::check_less_equal( \ (value1), #value1, (value2), #value2 __VA_OPT__(, ) __VA_ARGS__) #endif template inline void check_less_equal( VALUE1 const &value1, char const text1[], VALUE2 const &value2, char const text2[], std::string const &desc = "Less/greater check failed.", sl loc = sl::current()) { if (value1 <= value2) return; std::string const fulldesc{std::format( R"-({} ({} > {}: "lower"={}, "upper"={}))-", desc, text1, text2, value1, value2)}; throw test_failure{fulldesc, loc}; } /// A special exception type not derived from `std::exception`. struct failure_to_fail final {}; namespace internal { /// Syntactic placeholder: require (and accept) semicolon after block. inline void end_of_statement() {} } // namespace internal // Verify that "action" does not throw an exception. // Takes an optional failure description as a second argument. #if defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL // Work around Visual Studio lacking support for __VA_OPT__. # define PQXX_CHECK_SUCCEEDS(action, ...) \ pqxx::test::check_succeeds(([&]() { action; }), #action, ##__VA_ARGS__) #else # define PQXX_CHECK_SUCCEEDS(action, ...) \ pqxx::test::check_succeeds( \ ([&]() { action; }), #action __VA_OPT__(, ) __VA_ARGS__) #endif template inline void check_succeeds( F &&f, char const text[], std::string desc = "Expected this to succeed.", sl loc = sl::current()) { try { f(); } catch (std::exception const &e) { pqxx::test::check_notreached( std::format("{} - \"{}\" threw exception: {}", desc, text, e.what()), loc); } catch (...) { pqxx::test::check_notreached( std::format("{} - \"{}\" threw a non-exception!", desc, text), loc); } } template inline void check_throws( F &&f, char const text[], std::string desc = "This code did not thow the expected exception.", pqxx::sl loc = sl::current()) { try { f(); // NOLINTNEXTLINE(hicpp-exception-baseclass) throw failure_to_fail{}; } catch (failure_to_fail const &) { check_notreached( std::format("{} (\"{}\" did not throw).", desc, text), loc); } catch (EXC const &) { // OK, that's the exception we wanted. return; } catch (std::exception const &e) { auto const fail{dynamic_cast(&e)}; if (fail == nullptr) { check_notreached( std::format( "{} (\"{}\" threw the wrong exception type: {}).", desc, text, e.what()), loc); } else { check_notreached( std::format( "{} (\"{}\" threw the wrong exception type: [{}] {}).", desc, text, fail->name(), e.what()), loc); } } catch (...) { check_notreached( std::format("{} (\"{}\" threw a non-exception type!)", desc, text), loc); } } template inline void check_throws_exception( F &&f, char const text[], std::string desc = "This code did not thow a std::exception.", pqxx::sl loc = sl::current()) { try { f(); // NOLINTNEXTLINE(hicpp-exception-baseclass) throw failure_to_fail{}; } catch (failure_to_fail const &) { check_notreached( std::format("{} (\"{}\" did not throw)", desc, text), loc); } catch (std::exception const &) {} catch (...) { check_notreached( std::format("{} (\"{}\" threw a non-exception type).", desc, text), loc); } } #if defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL // Work around Visual Studio lacking support for __VA_OPT__. // Verify that "action" throws an exception, of any std::exception-based type. // Takes an optional failure description as an 2nd argument. # define PQXX_CHECK_THROWS_EXCEPTION(action, ...) \ pqxx::test::check_throws_exception( \ ([&]() { return action, 0; }), #action, ##__VA_ARGS__) // Verify that "action" throws "exception_type" (which is not std::exception). // Takes an optional failure description as an 2nd argument. # define PQXX_CHECK_THROWS(action, exception_type, ...) \ pqxx::test::check_throws( \ ([&] { return action, 0; }), #action, ##__VA_ARGS__) // Verify that "value" is between "lower" (inclusive) and "upper" (exclusive). // Takes an optional failure description as a 4th argument. # define PQXX_CHECK_BOUNDS(value, lower, upper, ...) \ pqxx::test::check_bounds( \ (value), #value, (lower), #lower, (upper), #upper, ##__VA_ARGS__) #else // Verify that "action" throws an exception, of any std::exception-based type. // Takes an optional failure description as an 2nd argument. # define PQXX_CHECK_THROWS_EXCEPTION(action, ...) \ pqxx::test::check_throws_exception( \ ([&]() { return action, 0; }), #action __VA_OPT__(, ) __VA_ARGS__) // Verify that "action" throws "exception_type" (which is not std::exception). // Takes an optional failure description as an 2nd argument. # define PQXX_CHECK_THROWS(action, exception_type, ...) \ pqxx::test::check_throws( \ ([&] { return action, 0; }), #action __VA_OPT__(, ) __VA_ARGS__) // Verify that "value" is between "lower" (inclusive) and "upper" (exclusive). // Takes an optional failure description as a 4th argument. # define PQXX_CHECK_BOUNDS(value, lower, upper, ...) \ pqxx::test::check_bounds( \ (value), #value, (lower), #lower, (upper), \ #upper __VA_OPT__(, ) __VA_ARGS__) #endif template inline void check_bounds( VALUE const &value, char const text[], LOWER const &lower, char const lower_text[], UPPER const &upper, char const upper_text[], std::string const &desc = "Bounds check failed.", sl loc = sl::current()) { std::string const range_check = std::string{lower_text} + " < " + upper_text, lower_check = std::string{"!("} + text + " < " + lower_text + ")", upper_check = std::string{text} + " < " + upper_text; pqxx::test::check( lower < upper, range_check.c_str(), desc + " (acceptable range is empty; value was " + text + ")", loc); pqxx::test::check( not(value < lower), lower_check.c_str(), std::format( "{} ({} is below lower bound {}: {} < {})", desc, text, lower_text, value, lower), loc); pqxx::test::check( value < upper, upper_check.c_str(), std::format( "{} ({} is not below upper bound {}: {} > {})", desc, text, upper_text, value, upper), loc); } // Report expected exception void expected_exception(std::string const &); // Represent result row as string. std::string list_row(row); // Represent result row as string. std::string list_row(row_ref); // Represent result as string. std::string list_result(result); // Represent result iterator as string. std::string list_result_iterator(result::const_iterator const &); // @deprecated Set up test data for legacy tests. void create_pqxxevents(transaction_base &); } // namespace pqxx::test namespace pqxx { template<> inline std::string to_string(row const &value, ctx) { return pqxx::test::list_row(value); } // clang-tidy rule bug: // NOLINTNEXTLINE(misc-unused-parameters) template<> inline std::string to_string(result const &value, ctx) { return pqxx::test::list_result(value); } // clang-tidy rule bug: // NOLINTBEGIN(misc-unused-parameters) template<> inline std::string to_string(result::const_iterator const &value, ctx) { return pqxx::test::list_result_iterator(value); } // NOLINTEND(misc-unused-parameters) } // namespace pqxx #endif libpqxx-8.0.1/test/runner.cxx000066400000000000000000000357021516427024100162340ustar00rootroot00000000000000/// Libpqxx test runner. /** This is the main program responsible for running libpqxx's test suite. * It is only really needed for developing libpqxx itself, though when you * build libpqxx it's definitely a good idea to build the test suite and run * this program to verify that everything works well in your specific * environment. * * Usage: * runner [-j|--jobs=] * [-s|--seed=] * [test function...] * * The -j option dictates the number of parallel threads that will run the * tests. I get most of the performance benefits from the parallelism by * setting this to 4; anything beyond that is probably overkill. * * The -s option sets an initial random seed, for reproducible or randomised * test runs. If set to zero (the default), will randomise the seed. Random * values in tests will differ for almost any two runs with this setting. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "helpers.hxx" namespace pqxx::test { test_failure::test_failure(std::string const &desc, sl loc) : std::logic_error{desc}, m_loc{loc} {} test_failure::~test_failure() noexcept = default; /// Drop table, if it exists. inline void drop_table(transaction_base &t, std::string const &table, sl loc) { t.exec("DROP TABLE IF EXISTS " + table, loc); } [[noreturn]] void check_notreached(std::string const &desc, sl loc) { throw test_failure{desc, loc}; } void check(bool condition, char const text[], std::string const &desc, sl loc) { if (not condition) throw test_failure{ std::format("{} (failed expression: '{}')", desc, text), loc}; } void expected_exception(std::string const &message) { std::cout << "(Expected) " << message << std::endl; } std::string list_row(row_ref Obj) { return separated_list( ", ", std::begin(Obj), std::end(Obj), [](pqxx::row_ref::iterator f) { return f->view(); }); } std::string list_row(row Obj) { return separated_list( ", ", std::begin(Obj), std::end(Obj), [](pqxx::row_ref::iterator f) { return f->view(); }); } std::string list_result(result Obj) { if (std::empty(Obj)) return ""; return "{" + separated_list( "}\n{", std::begin(Obj), std::end(Obj), [](pqxx::result::iterator r) { return list_row(*r); }) + "}"; } std::string list_result_iterator(result::const_iterator const &Obj) { return "row_number()) + ">"; } void create_pqxxevents(transaction_base &t) { t.exec( "CREATE TEMP TABLE pqxxevents(year integer, event varchar) " "ON COMMIT PRESERVE ROWS"); t.exec("INSERT INTO pqxxevents(year, event) VALUES (71, 'jtv')"); t.exec("INSERT INTO pqxxevents(year, event) VALUES (38, 'time_t overflow')"); t.exec( "INSERT INTO pqxxevents(year, event) VALUES (1, '''911'' WTC attack')"); t.exec("INSERT INTO pqxxevents(year, event) VALUES (81, 'C:\\>')"); t.exec( "INSERT INTO pqxxevents(year, event) VALUES (1978, 'bloody\t\tcold')"); t.exec("INSERT INTO pqxxevents(year, event) VALUES (99, '')"); t.exec("INSERT INTO pqxxevents(year, event) VALUES (2002, 'libpqxx')"); t.exec( "INSERT INTO pqxxevents(year, event) " "VALUES (1989, 'Ode an die Freiheit')"); t.exec( "INSERT INTO pqxxevents(year, event) VALUES (2001, 'New millennium')"); t.exec("INSERT INTO pqxxevents(year, event) VALUES (1974, '')"); t.exec("INSERT INTO pqxxevents(year, event) VALUES (97, 'Asian crisis')"); t.exec( "INSERT INTO pqxxevents(year, event) VALUES (2001, 'A Space Odyssey')"); } } // namespace pqxx::test namespace pqxx::test { void suite::register_test(std::string_view name, testfunc func) noexcept { assert(s_num_tests < max_tests); s_names.at(s_num_tests) = name; s_funcs.at(s_num_tests) = func; ++s_num_tests; } std::map suite::gather() { std::map all_tests; for (std::size_t idx{0}; idx < s_num_tests; ++idx) { auto const name{s_names.at(idx)}; assert(not all_tests.contains(name)); auto const func{s_funcs.at(idx)}; // This could happen if the internal arrays get constructed after we've // already written tests into them. assert(func != nullptr); all_tests.emplace(name, func); } return all_tests; } // This needs to get zero-initialised, not constructed in the usual way. // It's a hack, reliant on an implementation detail. But is there a better // way? To my knowledge there's no way in the standard to enforce an order on // the initialisation of this class' internal state on the one hand, and that // of the test registrations on the other. constinit std::size_t suite::s_num_tests{0}; // These need to get zero-initialised as well, not constructed. // Otherwise, construction will overwrite the values already written, which // most likely will crash the test suite (as test function pointers get // initialised as null pointers after function pointers had already been // written there). constinit std::array suite::s_names; constinit std::array suite::s_funcs{}; } // namespace pqxx::test namespace { /// Produce a human-readable string describing an exception from a test. /** A bunch of libpqxx exception types have a "location" field. Use that if * available. */ template std::string describe_failure(std::string_view test, EXCEPTION const &err) { std::string summary; char const *const msg{err.what()}; if constexpr (requires { err.location(); }) { std::string const loc{pqxx::source_loc(err.location())}; if ((msg != nullptr) and (msg[0] != '\0')) summary = std::format("[{}] ({}): {}", err.name(), loc, msg); else summary = std::format("{} ({})", err.name(), loc); } else { if ((msg != nullptr) and (msg[0] != '\0')) summary = msg; else summary = "unknown error"; } if constexpr (requires { err.query(); }) { if (not std::empty(err.query())) summary = std::format("{} -- {}\nQuery: {}", test, summary, err.query()); } else { summary = std::format("{} -- {}", test, summary); } #if defined(PQXX_HAVE_STACKTRACE) // TODO: Control this with command-line option, to avoid huge outputs. if constexpr (requires { err.trace(); }) if (err.trace()) summary = std::format("{}\nTraceback:\n{}", summary, *err.trace()); #endif return summary; } /// Produce a human-readable string describing an error from a test. /** This is for the case where we don't have a meaningful exception object. */ std::string describe_failure(std::string_view desc, std::string_view test) { return std::format("{} -- {}", test, desc); } /// Run one test. Return optional failure message. std::optional run_test( std::string_view name, pqxx::test::testfunc func, pqxx::test::context &tctx) { try { func(tctx); } catch (pqxx::test::test_failure const &e) { return describe_failure(name, e); } catch (pqxx::failure const &e) { return describe_failure(name, e); } catch (std::exception const &e) { return describe_failure(name, e); } catch (...) { // C++26: Can introspection give us more details? return describe_failure("Unknown exception", name); } return {}; } /// Maximum allowed number of concurrent tests. /** No particular reason, except anything higher isn't likely to give us much * in the way of speedup while still increasing peak memory usage etc. */ inline constexpr std::ptrdiff_t max_jobs{255}; /// Dispatcher of individual tests. /** Hands out the names of tests to be run to worker threads, on request, one * at a time. */ class dispatcher final { public: dispatcher(std::ptrdiff_t jobs, std::vector &&tests) : m_jobs{jobs}, m_tests{std::move(tests)}, m_here{m_tests.begin()}, m_capacity{jobs} { assert(m_jobs <= max_jobs); } ~dispatcher() = default; /// Start the worker threads. /** This class does not manage the pool of workers. But the workers can't * run any tests until this function is called. */ void start() & { // Our capacity semaphore starts out with all slots "taken." Release them // now to kick off the workers. for (auto i{m_jobs}; i > 0; --i) m_capacity.release(); } /// Obtain a test name to run, or empty string if there are no more. /** Will give out each test exactly once. */ [[nodiscard]] std::string_view next() & noexcept { std::string_view test{}; m_capacity.acquire(); std::lock_guard const progress_lock{m_progress}; if (m_here != m_tests.end()) test = *m_here++; m_capacity.release(); return test; } dispatcher(dispatcher const &) = delete; dispatcher &operator=(dispatcher const &) = delete; dispatcher(dispatcher &&) = delete; dispatcher &operator=(dispatcher &&) = delete; private: std::ptrdiff_t m_jobs; std::vector const m_tests; std::vector::const_iterator m_here; std::counting_semaphore m_capacity; std::mutex m_progress; }; /// Work through tests waiting to be executed. Runs in each worker thread. void execute( dispatcher &disp, std::map const &all_tests, std::mutex &fail_lock, std::vector &failures, std::size_t random_seed) { // Thread-local test context. pqxx::test::context tctx{random_seed}; // Execute tests while there are any left to do. for (std::string_view test{disp.next()}; not std::empty(test); test = disp.next()) { tctx.seed(test); auto const func{all_tests.at(test)}; auto const msg{run_test(test, func, tctx)}; if (msg.has_value()) { std::lock_guard const l{fail_lock}; std::cerr << *msg << '\n'; failures.emplace_back(*msg); } } } /// Exception class: user requested help output, exit cleanly. struct help_exit final : std::exception {}; /// Parsed command line. struct options final { /// Test functions to run. If empty, run all. std::vector tests; /// Number of parallel test threads. /** On my laptop with 8 physical cores, 4 workers give me about 95% of the * performance I get from 300 workers. That can change radically though: * right now there are just a few "negative tests" holding things up by * waiting for a few seconds to check that something doesn't happen. */ std::ptrdiff_t jobs{4}; /// Random seed for randomised values in tests. /** If seed is zero (the default), we'll use something variable. */ std::size_t seed{0}; }; options parse_command_line(int argc, char const *argv[]) { options opts; // Is the command-line parser in a state where it needs an argument to the // preceding "--jobs" option, or "--seed" option, respectively? bool want_jobs{false}, want_seed{false}; // TODO: Store jobs & seed as strings, parse afterwards, once. // Parse command line. for (int arg{1}; arg < argc; ++arg) { std::string_view const elt{argv[arg]}; if ((elt == "--help") or (elt == "-h")) { std::cout << "Test runner for libpqxx.\n" "Usage: " << argv[0] << " [ -j | --jobs= ] [ test_function ... ]\n"; throw help_exit{}; } else if (want_jobs) { // Expecting an argument to the "jobs" option. opts.jobs = pqxx::from_string(elt); want_jobs = false; } else if (want_seed) { opts.seed = pqxx::from_string(elt); want_seed = false; } else if ((elt == "-j") or (elt == "--jobs")) { // The "jobs" option, where the actual number is in the next element. want_jobs = true; } else if (elt.starts_with("-j")) { // Short-form "jobs" option, with a number attached. opts.jobs = pqxx::from_string(elt.substr(2)); } else if (elt.starts_with("--jobs=")) { // Long-form "jobs" option, with a number attached. opts.jobs = pqxx::from_string(elt.substr(7)); } else if ((elt == "-s") or (elt == "--seed")) { // The "seed" option, where the actual number is in the next element. want_seed = true; } else if (elt.starts_with("-s")) { opts.seed = pqxx::from_string(elt.substr(2)); } else if (elt.starts_with("--seed=")) { opts.seed = pqxx::from_string(elt.substr(7)); } else { // A test name. opts.tests.emplace_back(elt); } } if (want_jobs) throw std::runtime_error{"The jobs option needs a numeric argument."}; if (want_seed) throw std::runtime_error{"The seed option needs a numeric argument."}; if (opts.jobs <= 0) throw std::runtime_error{"Number of parallel jobs must be at least 1."}; return opts; } /// Choose a random seed: either the given one, or if zero, a random one. std::size_t get_random_seed(std::size_t seed_opt) { if (seed_opt == 0u) return std::random_device{}(); else return seed_opt; } } // namespace int main(int argc, char const *argv[]) { try { auto opts{parse_command_line(argc, argv)}; auto const seed{get_random_seed(opts.seed)}; std::cout << "Random seed: " << seed << '\n'; auto const all_tests{pqxx::test::suite::gather()}; if (std::empty(opts.tests)) { // Caller didn't pass any test names on the command line. Run all. for (auto const &[name, _] : all_tests) opts.tests.emplace_back(name); } else { for (auto const name : opts.tests) if (not all_tests.contains(name)) { std::cerr << "Unknown test: " << name << ".\n"; return 2; } } auto const test_count{std::size(opts.tests)}; std::mutex fail_lock; std::vector failures; dispatcher disp{opts.jobs, std::move(opts.tests)}; std::vector pool; pool.reserve(static_cast(opts.jobs)); for (std::ptrdiff_t j{0}; j < opts.jobs; ++j) pool.emplace_back( execute, std::ref(disp), std::cref(all_tests), std::ref(fail_lock), std::ref(failures), seed); disp.start(); for (auto &thread : pool) thread.join(); if (test_count == 1) std::cout << "Ran " << test_count << " test.\n"; else std::cout << "Ran " << test_count << " tests.\n"; if (std::empty(failures)) { std::cout << "Tests OK.\n"; return 0; } else { std::cerr << "\n*** " << std::size(failures) << " test(s) failed: ***\n"; // Lazy: each message starts with the test name, so mostly sorts by that. std::sort(failures.begin(), failures.end()); for (auto const &i : failures) std::cerr << "- " << i << '\n'; return 1; } } catch (help_exit const &) { return 0; } catch (std::exception const &e) { std::cerr << e.what() << '\n'; return 1; } } libpqxx-8.0.1/test/sample_types.hxx000066400000000000000000000132421516427024100174300ustar00rootroot00000000000000/* * Custom types for testing & libpqxx support those types */ #if !defined(PQXX_H_TEST_TYPES) # define PQXX_H_TEST_TYPES # include # include # include # include # include # include # include # include # include # include namespace pqxx { template<> struct nullness final : no_null {}; } // namespace pqxx class ipv4 { public: ipv4() : m_as_int{0u} {} ipv4(ipv4 const &) = default; ipv4(ipv4 &&) = default; explicit ipv4(uint32_t i) : m_as_int{i} {} ipv4( unsigned char b1, unsigned char b2, unsigned char b3, unsigned char b4) : ipv4() { set_byte(0, b1); set_byte(1, b2); set_byte(2, b3); set_byte(3, b4); } ~ipv4() = default; ipv4 &operator=(ipv4 const &) = default; ipv4 &operator=(ipv4 &&) = default; bool operator==(ipv4 const &o) const { return m_as_int == o.m_as_int; } /// Index bytes, from 0 to 3, in network (i.e. Big-Endian) byte order. unsigned int operator[](int byte) const { if (byte < 0 or byte > 3) throw pqxx::usage_error("Byte out of range."); auto const shift = compute_shift(byte); return static_cast((m_as_int >> shift) & 0xff); } /// Set individual byte, in network byte order. void set_byte(int byte, uint32_t value) { auto const shift = compute_shift(byte); auto const blanked = (m_as_int & ~uint32_t(0xff << shift)); m_as_int = (blanked | ((value & 0xff) << shift)); } private: static unsigned compute_shift(int byte) { if (byte < 0 or byte > 3) throw pqxx::usage_error("Byte out of range."); return static_cast((3 - byte) * 8); } uint32_t m_as_int; }; using bytea = std::vector; namespace pqxx { template<> struct nullness final : no_null {}; template<> struct string_traits final { static ipv4 from_string(std::string_view text, sl loc = sl::current()) { ipv4 ts; if (std::data(text) == nullptr) internal::throw_null_conversion(name_type(), loc); std::vector ends; for (std::size_t i{0}; i < std::size(text); ++i) if (text[i] == '.') ends.push_back(i); ends.push_back(std::size(text)); if (std::size(ends) != 4) throw conversion_error{std::format( "Can't parse '{}' as ipv4: expected 4 octets, found {}.", text, std::size(ends))}; std::size_t start{0}; for (int i{0}; i < 4; ++i) { auto idx{static_cast(i)}; std::string_view const digits{&text[start], ends.at(idx) - start}; auto value{pqxx::from_string(digits)}; ts.set_byte(i, value); start = ends.at(idx) + 1; } return ts; } static std::string_view to_buf(std::span buf, ipv4 const &value, ctx c = {}) { if (std::cmp_less(std::size(buf), size_buffer(value))) throw conversion_error{"Buffer too small for ipv4.", c.loc}; auto tmp{buf}; for (int i = 0; i < 4; ++i) { auto const octet{pqxx::into_buf(tmp, value[i], c)}; // C++26: Use at(). tmp[octet] = '.'; tmp = tmp.subspan(octet + 1); } // Return the composed string, but leave off the trailing dot. return { std::data(buf), static_cast(std::data(tmp) - std::data(buf)) - 1}; } static constexpr std::size_t size_buffer(ipv4 const &) noexcept { return 20; } }; } // namespace pqxx namespace pqxx::test::internal { inline char nibble_to_hex(unsigned nibble) { if (nibble < 10) return char('0' + nibble); else if (nibble < 16) return char('a' + (nibble - 10)); else throw std::runtime_error{"Invalid digit going into bytea."}; } inline unsigned hex_to_digit(char hex) { auto x = static_cast(hex); if (x >= '0' and x <= '9') return static_cast(x - '0'); else if (x >= 'a' and x <= 'f') return static_cast(10 + x - 'a'); else if (x >= 'A' and x <= 'F') return static_cast(10 + x - 'A'); else throw std::runtime_error{"Invalid hex in bytea."}; } } // namespace pqxx::test::internal namespace pqxx { template<> struct nullness final : no_null {}; template<> struct string_traits final { static bytea from_string(std::string_view text) { if ((std::size(text) & 1) != 0) throw std::runtime_error{"Odd hex size."}; bytea value; value.reserve((std::size(text) - 2) / 2); for (std::size_t i = 2; i < std::size(text); i += 2) { auto hi = pqxx::test::internal::hex_to_digit(text[i]), lo = pqxx::test::internal::hex_to_digit(text[i + 1]); value.push_back(static_cast((hi << 4) | lo)); } return value; } // NOLINTNEXTLINE(readability-non-const-parameter) static zview to_buf(char *begin, char *end, bytea const &value) { auto const need = size_buffer(value); auto const have = end - begin; if (std::size_t(have) < need) throw pqxx::conversion_overrun{"Not enough space in buffer for bytea."}; // clang-tidy rule bug: // NOLINTNEXTLINE(misc-const-correctness) char *pos = begin; *pos++ = '\\'; *pos++ = 'x'; for (unsigned char const u : value) { *pos++ = pqxx::test::internal::nibble_to_hex(unsigned(u) >> 4); *pos++ = pqxx::test::internal::nibble_to_hex(unsigned(u) & 0x0f); } *pos++ = '\0'; return {begin, pos - begin - 1}; } static char *into_buf(char *begin, char *end, bytea const &value) { return begin + std::size(to_buf(begin, end, value)) + 1; } static std::size_t size_buffer(bytea const &value) { return 2 + 2 * std::size(value) + 1; } }; } // namespace pqxx #endif libpqxx-8.0.1/test/test00.cxx000066400000000000000000000056721516427024100160450ustar00rootroot00000000000000#include #include #include #include "helpers.hxx" // Examples and tests for libpqxx: tests that do not require a connection to // a database. namespace { template concept converts_from_string = requires(T val, std::string_view v) { val = pqxx::string_traits::from_string(v); }; /// Convert an object to/from string, and check for expected results. template inline void strconv(std::string const &type, T const &obj, std::string const &expected) { std::string const objstr{pqxx::to_string(obj)}; PQXX_CHECK_EQUAL(objstr, expected, "String mismatch for " + type + "."); if constexpr (converts_from_string) { T newobj; pqxx::from_string(objstr, newobj); PQXX_CHECK_EQUAL( pqxx::to_string(newobj), expected, "String mismatch for recycled " + type + "."); } } constexpr double not_a_number{std::numeric_limits::quiet_NaN()}; void test_000(pqxx::test::context &) { PQXX_CHECK_EQUAL( pqxx::oid_none, 0u, "InvalidId is not zero as it used to be. This may conceivably " "cause problems in libpqxx."); PQXX_CHECK( pqxx::cursor_base::prior() < 0 and pqxx::cursor_base::backward_all() < 0, "cursor_base::difference_type appears to be unsigned."); constexpr char weird[]{"foo\t\n\0bar"}; std::string const weirdstr(std::data(weird), std::size(weird) - 1); // Test string conversions strconv("char const[]", "", ""); strconv("char const[]", "foo", "foo"); strconv("int", 0, "0"); strconv("int", 100, "100"); strconv("int", -1, "-1"); #if defined(_MSC_VER) long const long_min{LONG_MIN}, long_max{LONG_MAX}; #else long const long_min{std::numeric_limits::min()}, long_max{std::numeric_limits::max()}; #endif std::stringstream lminstr, lmaxstr, llminstr, llmaxstr, ullmaxstr; lminstr.imbue(std::locale("C")); lmaxstr.imbue(std::locale("C")); llminstr.imbue(std::locale("C")); llmaxstr.imbue(std::locale("C")); ullmaxstr.imbue(std::locale("C")); lminstr << long_min; lmaxstr << long_max; auto const ullong_max{std::numeric_limits::max()}; auto const llong_max{std::numeric_limits::max()}, llong_min{std::numeric_limits::min()}; llminstr << llong_min; llmaxstr << llong_max; ullmaxstr << ullong_max; strconv("long", 0, "0"); strconv("long", long_min, lminstr.str()); strconv("long", long_max, lmaxstr.str()); strconv("double", not_a_number, "nan"); strconv("string", std::string{}, ""); strconv("string", weirdstr, weirdstr); strconv("long long", 0LL, "0"); strconv("long long", llong_min, llminstr.str()); strconv("long long", llong_max, llmaxstr.str()); strconv("unsigned long long", 0ULL, "0"); strconv("unsigned long long", ullong_max, ullmaxstr.str()); std::stringstream ss; strconv("empty stringstream", ss, ""); ss << -3.1415; strconv("stringstream", ss, ss.str()); } PQXX_REGISTER_TEST(test_000); } // namespace libpqxx-8.0.1/test/test01.cxx000066400000000000000000000034471516427024100160440ustar00rootroot00000000000000#include #include "helpers.hxx" namespace { // Simple test program and example for libpqxx. Open a connection to the // database, start a transaction, and perform a query inside it. void test_001(pqxx::test::context &) { // Creating a pqxx::connection is the same thing as connecting to a database. // We can pass an optional connection string with connection options. Our // tests however rely on the database being accessible with the default // parameters. // // If the connection should fail, this will throw an exception. There's no // need to check whether the connection succeeded. pqxx::connection cx{""}; // Begin a transaction acting on our current connection. Give it a human- // readable name so that if there's an error, libpqxx can include that name // in the error message to help you debug. pqxx::work tx{cx, "test1"}; // Perform a query on the database, storing result rows in r. pqxx::result const r(tx.exec("SELECT 42, 84")); // We got the one row that we selected. The result object works a lot like a // normal C++ container. PQXX_CHECK(not std::empty(r)); PQXX_CHECK_EQUAL(std::size(r), 1); // A result is two-dimensional though: it's got rows and columns. PQXX_CHECK_EQUAL(r.columns(), 2); // Each row acts pretty much as a container of fields. (A field is the // intersection of one row and one column.) PQXX_CHECK_EQUAL(r[0][0].view(), "42"); // To make our transaction take effect, we need to commit it. If we don't // go through this, the transaction will roll back when the work object gets // destroyed. // // (Of course we made no changes to the database here, so in this case // there's nothing to commit and we might as well leave this out.) tx.commit(); } PQXX_REGISTER_TEST(test_001); } // namespace libpqxx-8.0.1/test/test02.cxx000066400000000000000000000045301516427024100160370ustar00rootroot00000000000000#include #include "helpers.hxx" // Example/test program for libpqxx. Perform a query and enumerate its output // using array indexing. namespace { /// Attempt to connect to a database, but fail. void bad_connect() { pqxx::connection const cx{"totally#invalid@connect$string!?"}; } void test_002(pqxx::test::context &) { // Before we really connect, test the expected behaviour of the default // connection type, where a failure to connect results in an immediate // exception rather than a silent retry. PQXX_CHECK_THROWS( bad_connect(), pqxx::broken_connection, "Invalid connection string did not cause exception."); // Actually connect to the database. If we're happy to use the defaults // (in these tests we are) then we don't need to pass a connection string. pqxx::connection cx; // Start a transaction within the context of our connection. pqxx::work tx{cx, "test2"}; // Perform a query within the transaction. pqxx::result const R(tx.exec("SELECT * FROM pg_tables")); // Let's keep the database waiting as briefly as possible: commit now, // before we start processing results. We could do this later, or since // we're not making any changes in the database that need to be committed, // we could in this case even omit it altogether. tx.commit(); // The result knows from which table each column originated. pqxx::oid const rtable{R.column_table(0)}; PQXX_CHECK_EQUAL( rtable, R.column_table(pqxx::row::size_type(0)), "Inconsistent answers from column_table()"); std::string const rcol{R.column_name(0)}; pqxx::oid const crtable{R.column_table(rcol)}; PQXX_CHECK_EQUAL( crtable, rtable, "Field looked up by name gives different origin."); // Now we've got all that settled, let's process our results. for (auto const &f : R) { pqxx::oid const ftable{f[0].table()}; PQXX_CHECK_EQUAL(ftable, rtable, "field::table() is broken."); pqxx::oid const ttable{f.column_table(0)}; PQXX_CHECK_EQUAL( ttable, f.column_table(pqxx::row::size_type(0)), "Inconsistent pqxx::row::column_table()."); PQXX_CHECK_EQUAL(ttable, rtable, "Inconsistent result::column_table()."); pqxx::oid const cttable{f.column_table(rcol)}; PQXX_CHECK_EQUAL(cttable, rtable, "pqxx::row::column_table() is broken."); } } PQXX_REGISTER_TEST(test_002); } // namespace libpqxx-8.0.1/test/test07.cxx000066400000000000000000000055101516427024100160430ustar00rootroot00000000000000#include #include #include #include "helpers.hxx" // Example program for libpqxx. Modify the database, retaining transactional // integrity using the transactor framework. // // This assumes the existence of a database table "pqxxevents" containing a // 2-digit "year" field, which is extended to a 4-digit format by assuming all // year numbers of 70 or higher are in the 20th century, and all others in the // 21st, and that no years before 1970 are possible. namespace { void test_007(pqxx::test::context &) { pqxx::connection cx; cx.set_client_encoding("SQL_ASCII"); { pqxx::work tx{cx}; pqxx::test::create_pqxxevents(tx); tx.commit(); } // Perform (an instantiation of) the UpdateYears transactor we've defined // in the code above. This is where the work gets done. std::map conversions; pqxx::perform([&conversions, &cx] { pqxx::work tx{cx}; // First select all different years occurring in the table. pqxx::result R(tx.exec("SELECT year FROM pqxxevents")); // See if we get reasonable type identifier for this column. pqxx::oid const rctype{R.column_type(0)}; PQXX_CHECK_EQUAL( R.column_type(pqxx::row::size_type(0)), rctype, "Inconsistent result::column_type()."); std::string const rct{pqxx::to_string(rctype)}; PQXX_CHECK(rctype > 0, "Got strange type ID for column: " + rct); std::string const rcol{R.column_name(0)}; PQXX_CHECK(not std::empty(rcol)); pqxx::oid const rcctype{R.column_type(rcol)}; PQXX_CHECK_EQUAL(rcctype, rctype); pqxx::oid const rawrcctype{R.column_type(rcol)}; PQXX_CHECK_EQUAL(rawrcctype, rctype); // Note all different years currently occurring in the table, writing // them and their correct mappings to conversions. for (auto const &r : R) { // See if type identifiers are consistent pqxx::oid const tctype{r.column_type(0)}; PQXX_CHECK_EQUAL(tctype, r.column_type(pqxx::row::size_type(0))); PQXX_CHECK_EQUAL(tctype, rctype, ); pqxx::oid const ctctype{r.column_type(rcol)}; PQXX_CHECK_EQUAL(ctctype, rctype); pqxx::oid const rawctctype{r.column_type(rcol)}; PQXX_CHECK_EQUAL(rawctctype, rctype); pqxx::oid const fctype{r[0].type()}; PQXX_CHECK_EQUAL(fctype, rctype); } // For each occurring year, write converted date back to whereever it may // occur in the table. Since we're in a transaction, any changes made by // others at the same time will not affect us. for (auto const &c : conversions) { auto const query{ "UPDATE pqxxevents " "SET year=" + pqxx::to_string(c.second) + " " "WHERE year=" + pqxx::to_string(c.first)}; R = tx.exec(query).no_rows(); } }); } PQXX_REGISTER_TEST(test_007); } // namespace libpqxx-8.0.1/test/test10.cxx000066400000000000000000000053011516427024100160330ustar00rootroot00000000000000#include #include "helpers.hxx" // Test program for libpqxx. Open connection to database, start a transaction, // abort it, and verify that it "never happened" (due to the rollback). namespace { // Let's take a boring year that is not going to be in the "pqxxevents" table constexpr int boring_year_10{1977}; std::string_view const table("pqxxevents"); // Count events, and boring events, in table std::pair count_events(pqxx::transaction_base &T) { std::string const events_query{ std::format("SELECT count(*) FROM {}", table)}; std::string const boring_query{ events_query + " WHERE year=" + pqxx::to_string(boring_year_10)}; return std::make_pair( T.query_value(events_query), T.query_value(boring_query)); } // Try adding a record, then aborting it, and check whether the abort was // performed correctly. void Test(pqxx::connection &C, bool ExplicitAbort) { std::pair event_counts; // First run our doomed transaction. This will refuse to run if an event // exists for our Boring Year. { // Begin a transaction acting on our current connection; we'll abort it // later though. pqxx::work doomed{C, "doomed"}; // Verify that our Boring Year was not yet in the events table event_counts = count_events(doomed); PQXX_CHECK_EQUAL( event_counts.second, 0, "Can't run, boring year is already in table."); // Now let's try to introduce a row for our Boring Year doomed .exec( std::format("INSERT INTO {} (year, event) ", table) + "VALUES (" + pqxx::to_string(boring_year_10) + ", 'yawn')") .no_rows(); auto const Recount{count_events(doomed)}; PQXX_CHECK_EQUAL(Recount.second, 1); PQXX_CHECK_EQUAL(Recount.first, event_counts.first + 1); // Okay, we've added an entry but we don't really want to. Abort it // explicitly if requested, or simply let the Transaction object "expire." if (ExplicitAbort) doomed.abort(); // The doomed transaction ends here because it goes out of scope, even if // there was no explicit commit or abort. } // Now check that we're back in the original state. Note that this may go // wrong if somebody managed to change the table between our two // transactions. pqxx::work checkup(C, "checkup"); auto const NewEvents{count_events(checkup)}; PQXX_CHECK_EQUAL(NewEvents.first, event_counts.first); PQXX_CHECK_EQUAL(NewEvents.second, 0); } void test_abort(pqxx::test::context &) { pqxx::connection cx; pqxx::nontransaction tx{cx}; pqxx::test::create_pqxxevents(tx); pqxx::connection &c(tx.conn()); tx.commit(); Test(c, true); Test(c, false); } PQXX_REGISTER_TEST(test_abort); } // namespace libpqxx-8.0.1/test/test11.cxx000066400000000000000000000033271516427024100160420ustar00rootroot00000000000000#include #include "helpers.hxx" // Test program for libpqxx. Query a table and report its metadata. namespace { void test_011(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; std::string const Table{"pg_tables"}; pqxx::result const r(tx.exec("SELECT * FROM " + Table)); // Print column names for (pqxx::row::size_type c{0}; c < r.columns(); ++c) { std::string const n{r.column_name(c)}; PQXX_CHECK_EQUAL(r.column_number(n), c); } // If there are rows in r, compare their metadata to r's. if (not std::empty(r)) { PQXX_CHECK_EQUAL(r[0].row_number(), 0); if (std::size(r) >= 2) PQXX_CHECK_EQUAL(r[1].row_number(), 1); // Test result::iterator::swap() pqxx::result::const_iterator const T1(r.begin() + 0), T2(r.begin() + 1); PQXX_CHECK_NOT_EQUAL(T1, T2, "Values are identical--can't test swap()."); pqxx::result::const_iterator T1s(T1), T2s(T2); PQXX_CHECK_EQUAL(T1s, T1, "Result iterator copy-construction is wrong."); PQXX_CHECK_EQUAL( T2s, T2, "Result iterator copy-construction is inconsistently wrong."); T1s.swap(T2s); PQXX_CHECK_NOT_EQUAL(T1s, T1, "Result iterator swap doesn't work."); PQXX_CHECK_NOT_EQUAL(T2s, T2); PQXX_CHECK_EQUAL(T2s, T1); PQXX_CHECK_EQUAL(T1s, T2); for (pqxx::row::size_type c{0}; c < std::size(r[0]); ++c) { std::string const n{r.column_name(c)}; PQXX_CHECK_EQUAL(std::string{r[0].at(c).c_str()}, r[0].at(n).c_str()); PQXX_CHECK_EQUAL(std::string{r[0][c].c_str()}, r[0][n].c_str()); PQXX_CHECK_EQUAL(r[0][c].name(), n); PQXX_CHECK_EQUAL(std::size(r[0][c]), strlen(r[0][c].c_str())); } } } PQXX_REGISTER_TEST(test_011); } // namespace libpqxx-8.0.1/test/test13.cxx000066400000000000000000000047201516427024100160420ustar00rootroot00000000000000#include #include #include "helpers.hxx" // Test program for libpqxx. Verify abort behaviour of transactor. // // The program will attempt to add an entry to a table called "pqxxevents", // with a key column called "year"--and then abort the change. // // Note for the superstitious: the numbering for this test program is pure // coincidence. namespace { // Let's take a boring year that is not going to be in the "pqxxevents" table constexpr int boring_year_13 = 1977; // Count events and specifically events occurring in Boring Year, leaving the // former count in the result pair's first member, and the latter in second. std::pair count_events_13(pqxx::connection &cx, std::string const &table) { pqxx::work tx{cx}; std::string const count_query{"SELECT count(*) FROM " + table}; return std::make_pair( tx.query_value(count_query), tx.query_value( count_query + " WHERE year=" + pqxx::to_string(boring_year_13))); } void failed_insert(pqxx::connection &cx, std::string const &table) { pqxx::work tx(cx); pqxx::result const R = tx.exec( "INSERT INTO " + table + " VALUES (" + pqxx::to_string(boring_year_13) + ", " "'yawn')") .no_rows(); PQXX_CHECK_EQUAL(R.affected_rows(), 1); throw pqxx::test::deliberate_error(); } void test_013(pqxx::test::context &) { pqxx::connection cx; { pqxx::work tx{cx}; pqxx::test::create_pqxxevents(tx); tx.commit(); } std::string const Table{"pqxxevents"}; auto const Before{ pqxx::perform([&cx, &Table] { return count_events_13(cx, Table); })}; PQXX_CHECK_EQUAL( Before.second, 0, "Already have event for " + pqxx::to_string(boring_year_13) + "--can't test."); #include "pqxx/internal/ignore-deprecated-pre.hxx" pqxx::quiet_errorhandler const d(cx); #include "pqxx/internal/ignore-deprecated-post.hxx" PQXX_CHECK_THROWS( pqxx::perform([&cx, &Table] { failed_insert(cx, Table); }), pqxx::test::deliberate_error); auto const After{ pqxx::perform([&cx, &Table] { return count_events_13(cx, Table); })}; PQXX_CHECK_EQUAL( After.first, Before.first, "abort() didn't reset event count."); PQXX_CHECK_EQUAL( After.second, Before.second, "abort() didn't reset event count for " + pqxx::to_string(boring_year_13)); } PQXX_REGISTER_TEST(test_013); } // namespace libpqxx-8.0.1/test/test18.cxx000066400000000000000000000041741516427024100160520ustar00rootroot00000000000000#include #include #include #include #include "helpers.hxx" // Test and example program for libpqxx. Verify abort behaviour of // robusttransaction. // // The program will attempt to add an entry to a table called "pqxxevents", // with a key column called "year"--and then abort the change to roll it back. namespace { // Let's take a boring year that is not going to be in the "pqxxevents" table constexpr int boring_year_18{1977}; // Count events and specifically events occurring in Boring Year, leaving the // former count in the result pair's first member, and the latter in second. std::pair count_events_18(pqxx::connection &cx, std::string const &table) { pqxx::nontransaction tx{cx}; std::string const count_query{"SELECT count(*) FROM " + table}; return std::make_pair( tx.query_value(count_query), tx.query_value( count_query + " WHERE year=" + pqxx::to_string(boring_year_18))); } void test_018(pqxx::test::context &) { pqxx::connection cx; { pqxx::work tx{cx}; pqxx::test::create_pqxxevents(tx); tx.commit(); } std::string const table{"pqxxevents"}; auto const before{ pqxx::perform([&cx, &table] { return count_events_18(cx, table); })}; PQXX_CHECK_EQUAL( before.second, 0, "Already have event for " + pqxx::to_string(boring_year_18) + ", cannot run."); { PQXX_CHECK_THROWS( pqxx::perform([&cx, table] { pqxx::robusttransaction tx{cx}; tx.exec( "INSERT INTO " + table + " VALUES (" + pqxx::to_string(boring_year_18) + ", '" + tx.esc("yawn") + "')") .no_rows(); throw pqxx::test::deliberate_error(); }), pqxx::test::deliberate_error); } auto const after{ pqxx::perform([&cx, &table] { return count_events_18(cx, table); })}; PQXX_CHECK_EQUAL(after.first, before.first, "Event count changed."); PQXX_CHECK_EQUAL( after.second, before.second, "Event count for " + pqxx::to_string(boring_year_18) + " changed."); } PQXX_REGISTER_TEST(test_018); } // namespace libpqxx-8.0.1/test/test20.cxx000066400000000000000000000037651516427024100160500ustar00rootroot00000000000000#include #include #include "helpers.hxx" // Test: nontransaction changes are not rolled back on abort. namespace { constexpr int boring_year_20{1977}; void test_020(pqxx::test::context &) { pqxx::connection cx; pqxx::nontransaction t1{cx}; pqxx::test::create_pqxxevents(t1); std::string const table{"pqxxevents"}; // Verify our start condition before beginning: there must not be a 1977 // record already. pqxx::result r{t1.exec( "SELECT * FROM " + table + " WHERE year=" + pqxx::to_string(boring_year_20))}; PQXX_CHECK_EQUAL( std::size(r), 0, "Already have a row for " + pqxx::to_string(boring_year_20) + ", cannot test."); // (Not needed, but verify that clear() works on empty containers) r.clear(); PQXX_CHECK(std::empty(r)); // OK. Having laid that worry to rest, add a record for 1977. t1.exec( "INSERT INTO " + table + " VALUES" "(" + pqxx::to_string(boring_year_20) + "," "'Yawn'" ")") .no_rows(); // Abort T1. Since T1 is a nontransaction, which provides only the // transaction class interface without providing any form of transactional // integrity, this is not going to undo our work. t1.abort(); // Verify that our record was added, despite the Abort() pqxx::nontransaction t2{cx, "t2"}; r = t2.exec( "SELECT * FROM " + table + " WHERE year=" + pqxx::to_string(boring_year_20)); PQXX_CHECK_EQUAL(std::size(r), 1); PQXX_CHECK_GREATER_EQUAL(r.capacity(), std::size(r)); r.clear(); PQXX_CHECK(std::empty(r)); // Now remove our record again t2.exec( "DELETE FROM " + table + " " "WHERE year=" + pqxx::to_string(boring_year_20)) .no_rows(); t2.commit(); // And again, verify results pqxx::nontransaction t3{cx, "t3"}; r = t3.exec( "SELECT * FROM " + table + " WHERE year=" + pqxx::to_string(boring_year_20)); PQXX_CHECK_EQUAL(std::size(r), 0); } PQXX_REGISTER_TEST(test_020); } // namespace libpqxx-8.0.1/test/test21.cxx000066400000000000000000000034151516427024100160410ustar00rootroot00000000000000#include #include #include "helpers.hxx" // Simple test program for libpqxx. Open a connection to the database, start a // transaction, and perform a query inside it. namespace { void test_021(pqxx::test::context &) { pqxx::connection cx; std::string const host{ ((cx.hostname() == nullptr) ? "" : cx.hostname())}; #include cx.process_notice( std::string{} + "database=" + cx.dbname() + ", " "username=" + cx.username() + ", " "hostname=" + host + ", " "port=" + pqxx::to_string(cx.port()) + ", " "backendpid=" + pqxx::to_string(cx.backendpid()) + "\n"); #include pqxx::work tx{cx, "test_021"}; // By now our connection should really have been created cx.process_notice("Printing details on actual connection\n"); #include cx.process_notice( std::string{} + "database=" + cx.dbname() + ", " "username=" + cx.username() + ", " "hostname=" + host + ", " "port=" + pqxx::to_string(cx.port()) + ", " "backendpid=" + pqxx::to_string(cx.backendpid()) + "\n"); #include std::string p; #include pqxx::from_string(cx.port(), p); PQXX_CHECK_EQUAL(p, pqxx::to_string(cx.port())); #include PQXX_CHECK_EQUAL(pqxx::to_string(p), p); pqxx::result const R(tx.exec("SELECT * FROM pg_tables")); tx.process_notice(std::format( "{} result row in transaction {}\n", pqxx::to_string(std::size(R)), tx.name())); tx.commit(); } PQXX_REGISTER_TEST(test_021); } // namespace libpqxx-8.0.1/test/test26.cxx000066400000000000000000000040211516427024100160400ustar00rootroot00000000000000#include #include #include #include #include "helpers.hxx" // Example program for libpqxx. Modify the database, retaining transactional // integrity using the transactor framework. namespace { // Convert year to 4-digit format. int to_4_digits(int y) { int Result{y}; PQXX_CHECK(y >= 0, "Negative year: " + pqxx::to_string(y)); if (y < 70) Result += 2000; else if (y < 100) Result += 1900; else PQXX_CHECK_GREATER_EQUAL(y, 1970); return Result; } // Transaction definition for year-field update. Returns conversions done. std::map update_years(pqxx::connection &cx) { std::map conversions; pqxx::work tx{cx}; // Note all different years currently occurring in the table, writing them // and their correct mappings to m_conversions for (auto const &[y] : tx.stream>("SELECT year FROM pqxxevents")) { // Read year, and if it is non-null, note its converted value if (bool(y)) conversions[y.value_or(1)] = to_4_digits(y.value_or(2)); } // For each occurring year, write converted date back to whereever it may // occur in the table. Since we're in a transaction, any changes made by // others at the same time will not affect us. for (auto const &c : conversions) tx.exec( "UPDATE pqxxevents " "SET year=" + pqxx::to_string(c.second) + " " "WHERE year=" + pqxx::to_string(c.first)) .no_rows(); tx.commit(); return conversions; } void test_026(pqxx::test::context &) { pqxx::connection cx; { pqxx::nontransaction tx{cx}; pqxx::test::create_pqxxevents(tx); tx.commit(); } // Perform (an instantiation of) the UpdateYears transactor we've defined // in the code above. This is where the work gets done. auto const conversions{pqxx::perform([&cx] { return update_years(cx); })}; PQXX_CHECK(not std::empty(conversions), "No conversions done!"); } PQXX_REGISTER_TEST(test_026); } // namespace libpqxx-8.0.1/test/test29.cxx000066400000000000000000000056241516427024100160550ustar00rootroot00000000000000#include #include #include #include "helpers.hxx" // Test program for libpqxx. Open connection to database, start a transaction, // abort it, and verify that it "never happened." // // The program will attempt to add an entry to a table called "pqxxevents", // with a key column called "year"--and then abort the change. namespace { // Let's take a boring year that is not going to be in the "pqxxevents" table constexpr int boring_year_29{1977}; std::string_view const table{"pqxxevents"}; // Count events, and boring events, in table std::pair count_events(pqxx::transaction_base &tx) { std::string const events_query{ std::format("SELECT count(*) FROM {}", table)}; std::string const boring_query{ events_query + " WHERE year=" + pqxx::to_string(boring_year_29)}; return std::make_pair( tx.query_value(events_query), tx.query_value(boring_query)); } // Try adding a record, then aborting it, and check whether the abort was // performed correctly. void check(pqxx::connection &cx, bool explicit_abort) { std::pair event_counts; // First run our doomed transaction. This will refuse to run if an event // exists for our Boring Year. { // Begin a transaction acting on our current connection; we'll abort it // later though. pqxx::work doomed{cx, "doomed"}; // Verify that our Boring Year was not yet in the events table event_counts = count_events(doomed); PQXX_CHECK_EQUAL( event_counts.second, 0, "Can't run; " + pqxx::to_string(boring_year_29) + " is already in the table."); // Now let's try to introduce a row for our Boring Year doomed .exec( std::format("INSERT INTO {}", table) + "(year, event) " "VALUES (" + pqxx::to_string(boring_year_29) + ", 'yawn')") .no_rows(); auto recount{count_events(doomed)}; PQXX_CHECK_EQUAL(recount.second, 1); PQXX_CHECK_EQUAL(recount.first, event_counts.first + 1); // Okay, we've added an entry but we don't really want to. Abort it // explicitly if requested, or simply let the Transaction object "expire." if (explicit_abort) doomed.abort(); // If now explicit abort requested, doomed Transaction still ends here } // Now check that we're back in the original state. Note that this may go // wrong if somebody managed to change the table between our two // transactions. pqxx::work checkup{cx, "checkup"}; auto new_events{count_events(checkup)}; PQXX_CHECK_EQUAL(new_events.first, event_counts.first); PQXX_CHECK_EQUAL(new_events.second, 0); } void test_029(pqxx::test::context &) { pqxx::connection cx; { pqxx::nontransaction tx{cx}; pqxx::test::create_pqxxevents(tx); } // Test abort semantics, both with explicit and implicit abort check(cx, true); check(cx, false); } PQXX_REGISTER_TEST(test_029); } // namespace libpqxx-8.0.1/test/test30.cxx000066400000000000000000000024631516427024100160430ustar00rootroot00000000000000#include #include "helpers.hxx" // Test program for libpqxx. Query a table and report its metadata. namespace { void test_030(pqxx::test::context &) { std::string const table{"pg_tables"}; pqxx::connection cx; pqxx::work tx{cx, "test30"}; pqxx::result const R{tx.exec("SELECT * FROM " + table)}; PQXX_CHECK(not std::empty(R), "Table " + table + " is empty, cannot test."); // Print column names for (pqxx::row::size_type c{0}; c < R.columns(); ++c) { std::string const N{R.column_name(c)}; PQXX_CHECK_EQUAL(R[0].column_number(N), R.column_number(N)); PQXX_CHECK_EQUAL(R[0].column_number(N), c); } // If there are rows in R, compare their metadata to R's. PQXX_CHECK_GREATER( std::size(R), 1, std::format("{} didn't have enough data for test.", table)); PQXX_CHECK_EQUAL(R[0].row_number(), 0); PQXX_CHECK_EQUAL(R[1].row_number(), 1); for (pqxx::row::size_type c{0}; c < std::size(R[0]); ++c) { std::string const N{R.column_name(c)}; PQXX_CHECK_EQUAL(std::string{R[0].at(c).c_str()}, R[0].at(N).c_str()); PQXX_CHECK_EQUAL(std::string{R[0][c].c_str()}, R[0][N].c_str()); PQXX_CHECK_EQUAL(R[0][c].name(), N); PQXX_CHECK_EQUAL(std::size(R[0][c]), std::strlen(R[0][c].c_str())); } } PQXX_REGISTER_TEST(test_030); } // namespace libpqxx-8.0.1/test/test32.cxx000066400000000000000000000040261516427024100160420ustar00rootroot00000000000000#include #include #include #include "helpers.hxx" // Test program for libpqxx. Verify abort behaviour of transactor. // // The program will attempt to add an entry to a table called "pqxxevents", // with a key column called "year"--and then abort the change. // // Note for the superstitious: the numbering for this test program is pure // coincidence. namespace { // Let's take a boring year that is not going to be in the "pqxxevents" table constexpr int boring_year_32{1977}; std::pair count_events_32(pqxx::connection &cx, std::string const &table) { std::string const count_query{"SELECT count(*) FROM " + table}; pqxx::work tx{cx}; return std::make_pair( tx.query_value(count_query), tx.query_value( count_query + " WHERE year=" + pqxx::to_string(boring_year_32))); } void test_032(pqxx::test::context &) { pqxx::connection cx; { pqxx::nontransaction tx{cx}; pqxx::test::create_pqxxevents(tx); } std::string const table{"pqxxevents"}; std::pair const before{ pqxx::perform([&cx, &table] { return count_events_32(cx, table); })}; PQXX_CHECK_EQUAL( before.second, 0, "Already have event for " + pqxx::to_string(boring_year_32) + ", cannot test."); { #include "pqxx/internal/ignore-deprecated-pre.hxx" pqxx::quiet_errorhandler const d(cx); #include "pqxx/internal/ignore-deprecated-post.hxx" PQXX_CHECK_THROWS( pqxx::perform([&cx, &table] { pqxx::work{cx} .exec( "INSERT INTO " + table + " VALUES (" + pqxx::to_string(boring_year_32) + ", " "'yawn')") .no_rows(); throw pqxx::test::deliberate_error(); }), pqxx::test::deliberate_error); } std::pair const after{ pqxx::perform([&cx, &table] { return count_events_32(cx, table); })}; PQXX_CHECK_EQUAL(after.first, before.first); PQXX_CHECK_EQUAL(after.second, before.second); } PQXX_REGISTER_TEST(test_032); } // namespace libpqxx-8.0.1/test/test37.cxx000066400000000000000000000041371516427024100160520ustar00rootroot00000000000000#include #include #include #include "helpers.hxx" // Test program for libpqxx. Verify abort behaviour of RobustTransaction. // // The program will attempt to add an entry to a table called "pqxxevents", // with a key column called "year"--and then abort the change. namespace { // Let's take a boring year that is not going to be in the "pqxxevents" table constexpr int boring_year_37{1977}; // Count events and specifically events occurring in Boring Year, leaving the // former count in the result pair's first member, and the latter in second. std::pair count_events_37(pqxx::connection &cx, std::string const &table) { std::string const count_query{"SELECT count(*) FROM " + table}; pqxx::nontransaction tx{cx}; return std::make_pair( tx.query_value(count_query), tx.query_value( count_query + " WHERE year=" + pqxx::to_string(boring_year_37))); } void test_037(pqxx::test::context &) { pqxx::connection cx; { pqxx::nontransaction tx{cx}; pqxx::test::create_pqxxevents(tx); } std::string const table{"pqxxevents"}; auto const Before{ pqxx::perform([&cx, &table] { return count_events_37(cx, table); })}; PQXX_CHECK_EQUAL( Before.second, 0, "Already have event for " + pqxx::to_string(boring_year_37) + ", cannot test."); { #include "pqxx/internal/ignore-deprecated-pre.hxx" pqxx::quiet_errorhandler const d(cx); #include "pqxx/internal/ignore-deprecated-post.hxx" PQXX_CHECK_THROWS( pqxx::perform([&cx, &table] { pqxx::robusttransaction<> tx{cx}; tx.exec( "INSERT INTO " + table + " VALUES (" + pqxx::to_string(boring_year_37) + ", " "'yawn')") .no_rows(); throw pqxx::test::deliberate_error(); }), pqxx::test::deliberate_error); } auto const After{ pqxx::perform([&cx, &table] { return count_events_37(cx, table); })}; PQXX_CHECK_EQUAL(After.first, Before.first); PQXX_CHECK_EQUAL(After.second, Before.second); } PQXX_REGISTER_TEST(test_037); } // namespace libpqxx-8.0.1/test/test39.cxx000066400000000000000000000040201516427024100160430ustar00rootroot00000000000000#include #include "helpers.hxx" // Test: nontransaction changes are committed immediately. namespace { constexpr int boring_year_39{1977}; void test_039(pqxx::test::context &) { pqxx::connection cx; pqxx::nontransaction tx1{cx}; pqxx::test::create_pqxxevents(tx1); std::string const table{"pqxxevents"}; // Verify our start condition before beginning: there must not be a 1977 // record already. pqxx::result r(tx1.exec( "SELECT * FROM " + table + " " "WHERE year=" + pqxx::to_string(boring_year_39))); PQXX_CHECK_EQUAL( std::size(r), 0, "Already have a row for " + pqxx::to_string(boring_year_39) + ", cannot test."); // (Not needed, but verify that clear() works on empty containers) r.clear(); PQXX_CHECK(std::empty(r)); // OK. Having laid that worry to rest, add a record for 1977. tx1 .exec( "INSERT INTO " + table + " VALUES" "(" + pqxx::to_string(boring_year_39) + "," "'Yawn'" ")") .no_rows(); // Abort tx1. Since tx1 is a nontransaction, which provides only the // transaction class interface without providing any form of transactional // integrity, this is not going to undo our work. tx1.abort(); // Verify that our record was added, despite the Abort() pqxx::nontransaction tx2(cx, "tx2"); r = tx2.exec( "SELECT * FROM " + table + " " "WHERE year=" + pqxx::to_string(boring_year_39)); PQXX_CHECK_EQUAL(std::size(r), 1); PQXX_CHECK_GREATER_EQUAL(r.capacity(), std::size(r)); r.clear(); PQXX_CHECK(std::empty(r)); // Now remove our record again tx2 .exec( "DELETE FROM " + table + " " "WHERE year=" + pqxx::to_string(boring_year_39)) .no_rows(); tx2.commit(); // And again, verify results pqxx::nontransaction tx3(cx, "tx3"); r = tx3.exec( "SELECT * FROM " + table + " " "WHERE year=" + pqxx::to_string(boring_year_39)); PQXX_CHECK_EQUAL(std::size(r), 0); } PQXX_REGISTER_TEST(test_039); } // namespace libpqxx-8.0.1/test/test46.cxx000066400000000000000000000032111516427024100160420ustar00rootroot00000000000000#include #include #include #include "helpers.hxx" // Streams test program for libpqxx. Insert a result field into various // types of streams. namespace { void test_046(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::field const r{tx.exec("SELECT count(*) FROM pg_tables").one_field()}; // Read the value into a stringstream. std::stringstream i; #include "pqxx/internal/ignore-deprecated-pre.hxx" i << r; #include "pqxx/internal/ignore-deprecated-post.hxx" // Now convert the stringstream into a numeric type long L{}, L2{}; i >> L; r.to(L2); PQXX_CHECK_EQUAL(L, L2, "Inconsistency between conversion methods."); float f{}, f2{}; std::stringstream I2; #include "pqxx/internal/ignore-deprecated-pre.hxx" I2 << r; #include "pqxx/internal/ignore-deprecated-post.hxx" I2 >> f; r.to(f2); PQXX_CHECK_BOUNDS(f2, f - 0.01, f + 0.01); auto F3{pqxx::from_string(r.c_str())}; PQXX_CHECK_BOUNDS(F3, f - 0.01, f + 0.01); auto D{pqxx::from_string(r.c_str())}; PQXX_CHECK_BOUNDS(D, f - 0.01, f + 0.01); // Valgrind doesn't support "long double." #if !defined(PQXX_VALGRIND) auto LD{pqxx::from_string(r.c_str())}; PQXX_CHECK_BOUNDS(LD, f - 0.01, f + 0.01); #endif auto S{pqxx::from_string(r.c_str())}, S2{pqxx::from_string(std::string{r.c_str()})}, S3{pqxx::from_string(r)}; PQXX_CHECK_EQUAL(S2, S); PQXX_CHECK_EQUAL(S3, S2); PQXX_CHECK(tx.query_value("SELECT 1=1")); PQXX_CHECK(not tx.query_value("SELECT 2+2=5")); } PQXX_REGISTER_TEST(test_046); } // namespace libpqxx-8.0.1/test/test56.cxx000066400000000000000000000005671516427024100160560ustar00rootroot00000000000000#include #include "helpers.hxx" // Simple test and sample code for libpqxx. Issue invalid query and handle // error. namespace { void test_056(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; PQXX_CHECK_THROWS( tx.exec("DELIBERATELY INVALID TEST QUERY..."), pqxx::sql_error); } PQXX_REGISTER_TEST(test_056); } // namespace libpqxx-8.0.1/test/test60.cxx000066400000000000000000000034151516427024100160440ustar00rootroot00000000000000#include #include #include #include "helpers.hxx" // Example program for libpqxx. Test session variable functionality. namespace { std::string get_datestyle(pqxx::connection &cx) { return cx.get_var("DATESTYLE"); } std::string set_datestyle(pqxx::connection &cx, std::string const &style) { cx.set_session_var("DATESTYLE", style); std::string const fullname{get_datestyle(cx)}; PQXX_CHECK( not std::empty(fullname), "Setting datestyle to " + style + " makes it an empty string."); return fullname; } void check_datestyle(pqxx::connection &cx, std::string const &expected) { PQXX_CHECK_EQUAL(get_datestyle(cx), expected); } void redo_datestyle( pqxx::connection &cx, std::string const &style, std::string const &expected) { PQXX_CHECK_EQUAL(set_datestyle(cx, style), expected); } void check_setting_datestyle( pqxx::connection &cx, std::string const &style, std::string const &expected) { redo_datestyle(cx, style, expected); check_datestyle(cx, expected); } void test_060(pqxx::test::context &) { pqxx::connection cx; PQXX_CHECK(not std::empty(get_datestyle(cx))); std::string const ISOname{set_datestyle(cx, "ISO")}; std::string const SQLname{set_datestyle(cx, "SQL")}; PQXX_CHECK_NOT_EQUAL(ISOname, SQLname); redo_datestyle(cx, "SQL", SQLname); check_setting_datestyle(cx, "ISO", ISOname); check_setting_datestyle(cx, "SQL", SQLname); PQXX_CHECK_THROWS( cx.set_session_var("bonjour_name", std::optional{}), pqxx::variable_set_to_null); // Prove that setting an unknown variable causes an error, as expected PQXX_CHECK_THROWS( cx.set_session_var("NONEXISTENT_VARIABLE_I_HOPE", 1), pqxx::sql_error); } PQXX_REGISTER_TEST(test_060); } // namespace libpqxx-8.0.1/test/test61.cxx000066400000000000000000000025721516427024100160500ustar00rootroot00000000000000#include #include "helpers.hxx" // Example program for libpqxx. Test local variable functionality. namespace { std::string GetDatestyle(pqxx::transaction_base &T) { return T.conn().get_var("DATESTYLE"); } std::string SetDatestyle(pqxx::transaction_base &T, std::string const &style) { T.conn().set_session_var("DATESTYLE", style); std::string const fullname{GetDatestyle(T)}; PQXX_CHECK( not std::empty(fullname), "Setting datestyle to " + style + " makes it an empty string."); return fullname; } void RedoDatestyle( pqxx::transaction_base &T, std::string const &style, std::string const &expected) { PQXX_CHECK_EQUAL(SetDatestyle(T, style), expected); } void test_061(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; PQXX_CHECK(not std::empty(GetDatestyle(tx))); std::string const ISOname{SetDatestyle(tx, "ISO")}; std::string const SQLname{SetDatestyle(tx, "SQL")}; PQXX_CHECK_NOT_EQUAL(ISOname, SQLname); RedoDatestyle(tx, "SQL", SQLname); // Prove that setting an unknown variable causes an error, as expected #include "pqxx/internal/ignore-deprecated-pre.hxx" pqxx::quiet_errorhandler const d(tx.conn()); #include "pqxx/internal/ignore-deprecated-post.hxx" PQXX_CHECK_THROWS( cx.set_session_var("NONEXISTENT_VARIABLE_I_HOPE", 1), pqxx::sql_error); } PQXX_REGISTER_TEST(test_061); } // namespace libpqxx-8.0.1/test/test62.cxx000066400000000000000000000030511516427024100160420ustar00rootroot00000000000000#include #include "helpers.hxx" // Example program for libpqxx. Test binary string functionality. namespace { void test_062(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; char const test_data[]{ "Nasty\n\030\0Test\n\t String with \200\277 weird bytes " "\r\0 and Trailer\\\\\0"}; static_assert(std::size(test_data) > 50); std::string const test_str{std::data(test_data), std::size(test_data)}; tx.exec("CREATE TEMP TABLE pqxxbin (binfield bytea)").no_rows(); // C++23: Initialise as data{std::from_range_t, test_str}? pqxx::bytes data; for (char c : test_str) data.push_back(static_cast(c)); PQXX_CHECK_EQUAL(std::size(data), std::size(test_data)); std::string const Esc{tx.esc(data)}; tx.exec("INSERT INTO pqxxbin VALUES ('" + Esc + "')").no_rows(); pqxx::result const R{tx.exec("SELECT * from pqxxbin")}; tx.exec("DELETE FROM pqxxbin").no_rows(); auto const B{R.at(0).at(0).as()}; PQXX_CHECK(not std::empty(B)); PQXX_CHECK_EQUAL(std::size(B), std::size(test_data)); pqxx::bytes::const_iterator c; pqxx::bytes::size_type i{}; for (i = 0, c = std::begin(B); i < std::size(B); ++i, ++c) { PQXX_CHECK(c != std::end(B)); char const x{test_str.at(i)}, y{char(B.at(i))}, z{char(std::data(B)[i])}; PQXX_CHECK_EQUAL(std::string(&x, 1), std::string(&y, 1)); PQXX_CHECK_EQUAL( std::string(&y, 1), std::string(&z, 1), "Inconsistent byte at offset " + pqxx::to_string(i) + "."); } } PQXX_REGISTER_TEST(test_062); } // namespace libpqxx-8.0.1/test/test70.cxx000066400000000000000000000042651516427024100160510ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { void TestPipeline(pqxx::pipeline &P, int numqueries) { std::string const Q{"SELECT * FROM generate_series(1, 10)"}; pqxx::result const Empty; PQXX_CHECK(std::empty(Empty)); PQXX_CHECK(std::empty(Empty.query())); P.retain(); for (int i{numqueries}; i > 0; --i) P.insert(Q); P.resume(); PQXX_CHECK((numqueries == 0) || not std::empty(P)); int res{0}; pqxx::result Prev; PQXX_CHECK_EQUAL(Prev, Empty); for (int i{numqueries}; i > 0; --i) { PQXX_CHECK(not std::empty(P)); auto R{P.retrieve()}; PQXX_CHECK_NOT_EQUAL(R.second, Empty); if (Prev != Empty) PQXX_CHECK_NOT_EQUAL(R.second, Prev); Prev = R.second; PQXX_CHECK_EQUAL(Prev, R.second); PQXX_CHECK_EQUAL(R.second.query(), Q); if (res != 0) PQXX_CHECK_EQUAL(Prev[0][0].as(), res); res = Prev[0][0].as(); } PQXX_CHECK(std::empty(P)); } // Test program for libpqxx. Issue a query repeatedly through a pipeline, and // compare results. Use retain() and resume() for performance. void test_070(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::pipeline P(tx); PQXX_CHECK(std::empty(P)); // Try to confuse the pipeline by feeding it a query and flushing P.retain(); std::string const Q{"SELECT * FROM pg_tables"}; P.insert(Q); P.flush(); PQXX_CHECK(std::empty(P)); // See if complete() breaks retain() as it should P.retain(); P.insert(Q); PQXX_CHECK(not std::empty(P)); P.complete(); PQXX_CHECK(not std::empty(P)); PQXX_CHECK_EQUAL(P.retrieve().second.query(), Q); PQXX_CHECK(std::empty(P)); // See if retrieve() breaks retain() when it needs to P.retain(); P.insert(Q); PQXX_CHECK_EQUAL(P.retrieve().second.query(), Q); // See if regular retain()/resume() works for (int i{0}; i < 5; ++i) TestPipeline(P, i); // See if retrieve() fails on an empty pipeline, as it should #include "pqxx/internal/ignore-deprecated-pre.hxx" pqxx::quiet_errorhandler const d(cx); #include "pqxx/internal/ignore-deprecated-post.hxx" PQXX_CHECK_THROWS_EXCEPTION(P.retrieve()); } } // namespace PQXX_REGISTER_TEST(test_070); libpqxx-8.0.1/test/test71.cxx000066400000000000000000000032651516427024100160510ustar00rootroot00000000000000#include #include #include #include "helpers.hxx" // Test program for libpqxx. Issue queries through a pipeline, and retrieve // results both in-order and out-of-order. namespace { using Exp = std::map; template void checkresult(pqxx::pipeline &P, PAIR c) { pqxx::result const r{P.retrieve(c.first)}; int const val{r.at(0).at(0).as(int(0))}; PQXX_CHECK_EQUAL(val, c.second); } void test_071(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::pipeline P(tx); // Keep expected result for every query we issue Exp values; // Insert queries returning various numbers. for (int i{1}; i < 10; ++i) values[P.insert("SELECT " + pqxx::to_string(i))] = i; // Retrieve results in query_id order, and compare to expected values for (auto &c : values) checkresult(P, c); PQXX_CHECK(std::empty(P)); values.clear(); // Insert more queries returning various numbers P.retain(20); for (int i{100}; i > 90; --i) values[P.insert("SELECT " + pqxx::to_string(i))] = i; P.resume(); // Retrieve results in reverse order for (auto c{std::rbegin(values)}; c != std::rend(values); ++c) checkresult(P, *c); values.clear(); P.retain(10); for (int i{1010}; i > 1000; --i) values[P.insert("SELECT " + pqxx::to_string(i))] = i; for (auto &c : values) { PQXX_CHECK( not P.is_finished(c.first), std::format("Query #{} completed despite retain().", c.first)); } // See that all results are retrieved by complete() P.complete(); for (auto &c : values) PQXX_CHECK(P.is_finished(c.first)); } } // namespace PQXX_REGISTER_TEST(test_071); libpqxx-8.0.1/test/test72.cxx000066400000000000000000000030541516427024100160460ustar00rootroot00000000000000#include #include #include "helpers.hxx" // Test program for libpqxx. Test error handling for pipeline. namespace { void test_072(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::pipeline P{tx}; // Ensure all queries are issued at once to make the test more interesting P.retain(); // The middle query should fail; the surrounding two should succeed auto const id_1{P.insert("SELECT 1")}; auto const id_f{P.insert("SELECT * FROM pg_nonexist")}; auto const id_2{P.insert("SELECT 2")}; // See that we can process the queries without stumbling over the error P.complete(); // We should be able to get the first result, which preceeds the error auto const res_1{P.retrieve(id_1).at(0).at(0).as()}; PQXX_CHECK_EQUAL(res_1, 1); // We should *not* get a result for the query behind the error { #include "pqxx/internal/ignore-deprecated-pre.hxx" pqxx::quiet_errorhandler const d{cx}; #include "pqxx/internal/ignore-deprecated-post.hxx" PQXX_CHECK_THROWS( std::ignore = P.retrieve(id_2).at(0).at(0).as(), std::runtime_error, "Pipeline wrongly resumed after SQL error."); } // Now see that we get an exception when we touch the failed result { #include "pqxx/internal/ignore-deprecated-pre.hxx" pqxx::quiet_errorhandler const d{cx}; #include "pqxx/internal/ignore-deprecated-post.hxx" PQXX_CHECK_THROWS( P.retrieve(id_f), pqxx::sql_error, "Pipeline failed to register SQL error."); } } } // namespace PQXX_REGISTER_TEST(test_072); libpqxx-8.0.1/test/test74.cxx000066400000000000000000000036211516427024100160500ustar00rootroot00000000000000#include #include #include "helpers.hxx" // Test program for libpqxx. Test fieldstream. namespace { void test_074(pqxx::test::context &) { #include "pqxx/internal/ignore-deprecated-pre.hxx" pqxx::connection cx; pqxx::work tx{cx}; pqxx::result R{tx.exec("SELECT * FROM pg_tables")}; std::string const sval{R.at(0).at(1).c_str()}; std::string sval2; pqxx::field const f1{R.front()[1]}; pqxx::fieldstream fs1{f1}; fs1 >> sval2; PQXX_CHECK_EQUAL(sval2, sval, "fieldstream returned wrong value."); R = tx.exec("SELECT count(*) FROM pg_tables"); int ival{}; pqxx::field const f2{pqxx::field{R.at(0).at(0)}}; pqxx::fieldstream fs2{f2}; fs2 >> ival; PQXX_CHECK_EQUAL(ival, R.front().front().as()); double dval{}; (pqxx::fieldstream{pqxx::field{R.at(0).at(0)}}) >> dval; PQXX_CHECK_BOUNDS( dval, R[0][0].as() - 0.1, R[0][0].as() + 0.1); auto const roughpi{static_cast(3.1415926435)}; R = tx.exec("SELECT " + pqxx::to_string(roughpi)); float pival{}; (pqxx::fieldstream{pqxx::field{R.at(0).at(0)}}) >> pival; PQXX_CHECK_BOUNDS(pival, roughpi - 0.001, roughpi + 0.001); PQXX_CHECK_EQUAL(pqxx::to_string(R[0][0]), R[0][0].c_str()); float float_pi{}; pqxx::from_string(pqxx::to_string(roughpi), float_pi); PQXX_CHECK_BOUNDS(float_pi, roughpi - 0.00001, roughpi + 0.00001); double double_pi{}; pqxx::from_string(pqxx::to_string(static_cast(roughpi)), double_pi); PQXX_CHECK_BOUNDS(double_pi, roughpi - 0.00001, roughpi + 0.00001); // Valgrind doesn't support "long double." #if !defined(PQXX_VALGRIND) long double const ld{roughpi}; long double long_double_pi{}; pqxx::from_string(pqxx::to_string(ld), long_double_pi); PQXX_CHECK_BOUNDS(long_double_pi, roughpi - 0.00001, roughpi + 0.00001); #endif #include "pqxx/internal/ignore-deprecated-post.hxx" } } // namespace PQXX_REGISTER_TEST(test_074); libpqxx-8.0.1/test/test75.cxx000066400000000000000000000046211516427024100160520ustar00rootroot00000000000000#include #include #include "helpers.hxx" // Test program for libpqxx. Compare const_reverse_iterator iteration of a // result to a regular, const_iterator iteration. namespace { void test_075(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::test::create_pqxxevents(tx); auto const R(tx.exec("SELECT year FROM pqxxevents")); PQXX_CHECK(not std::empty(R), "No events found, cannot test."); PQXX_CHECK(R[0] == R.at(0)); PQXX_CHECK(not(R[0] != R.at(0))); PQXX_CHECK(R[0][0] == R[0].at(0)); PQXX_CHECK(not(R[0][0] != R[0].at(0))); std::vector contents; for (auto const &i : R) contents.push_back(i.at(0).as()); PQXX_CHECK_EQUAL( std::size(contents), std::vector::size_type(std::size(R))); for (pqxx::result::size_type i{0}; i < std::size(R); ++i) PQXX_CHECK_EQUAL( contents[static_cast(i)], R.at(i).at(0).c_str()); // Thorough test for result::const_reverse_iterator pqxx::result::const_reverse_iterator const ri1(std::rbegin(R)); pqxx::result::const_reverse_iterator ri2(ri1), ri3(std::end(R)); ri2 = std::rbegin(R); PQXX_CHECK(ri2 == ri1); PQXX_CHECK(ri3 == ri2); PQXX_CHECK_EQUAL(ri2 - ri3, 0); PQXX_CHECK(ri2 == ri3 + 0); PQXX_CHECK(ri2 == ri3 - 0); PQXX_CHECK(not(ri3 < ri2)); PQXX_CHECK(ri2 <= ri3); PQXX_CHECK(ri3++ == ri2); PQXX_CHECK_EQUAL(ri3 - ri2, 1); PQXX_CHECK(ri3 > ri2); PQXX_CHECK(ri3 >= ri2); PQXX_CHECK(ri2 < ri3); PQXX_CHECK(ri2 <= ri3); PQXX_CHECK(ri3 == ri2 + 1); PQXX_CHECK(ri2 == ri3 - 1); PQXX_CHECK(ri3 == ++ri2); PQXX_CHECK(ri3 >= ri2); PQXX_CHECK(ri3 >= ri2); PQXX_CHECK_EQUAL(ri3.base()->front().view(), R.back()[0].view()); PQXX_CHECK_EQUAL( ri1->at(0).as(), (*ri1).at(0).as()); PQXX_CHECK(ri2-- == ri3); PQXX_CHECK(ri2 == --ri3); PQXX_CHECK(ri2 == std::rbegin(R)); ri2 += 1; ri3 -= -1; PQXX_CHECK(ri2 != std::rbegin(R)); PQXX_CHECK(ri3 == ri2); ri2 -= 1; PQXX_CHECK(ri2 == std::rbegin(R)); // Now verify that reverse iterator also sees the same results... auto l{std::rbegin(contents)}; for (auto i{std::rbegin(R)}; i != std::rend(R); ++i, ++l) PQXX_CHECK_EQUAL(*l, i->at(0).c_str()); PQXX_CHECK(l == std::rend(contents)); PQXX_CHECK(not std::empty(R), "No events found in table, cannot test."); } } // namespace PQXX_REGISTER_TEST(test_075); libpqxx-8.0.1/test/test76.cxx000066400000000000000000000027661516427024100160630ustar00rootroot00000000000000#include #include "helpers.hxx" // Simple test program for libpqxx. Test string conversion routines. namespace { void test_076(pqxx::test::context &) { pqxx::connection cx; pqxx::nontransaction tx{cx}; auto RFalse{tx.exec("SELECT 1=0").one_field()}, RTrue{tx.exec("SELECT 1=1").one_field()}; auto False{pqxx::from_string(RFalse)}, True{pqxx::from_string(RTrue)}; PQXX_CHECK(not False); PQXX_CHECK(True); RFalse = tx.exec("SELECT " + pqxx::to_string(False)).one_field(); RTrue = tx.exec("SELECT " + pqxx::to_string(True)).one_field(); False = pqxx::from_string(RFalse); True = pqxx::from_string(RTrue); PQXX_CHECK(not False); PQXX_CHECK(True); constexpr std::array svals{-1, 1, 999, -32767, -32768, 32767, 0}; for (short const v : svals) { auto s{pqxx::from_string(pqxx::to_string(v))}; PQXX_CHECK_EQUAL(s, v); s = pqxx::from_string( tx.exec("SELECT " + pqxx::to_string(v)).one_field().c_str()); PQXX_CHECK_EQUAL(s, v); } constexpr std::array uvals{1, 999, 32767, 32768, 65535, 0}; for (unsigned short const v : uvals) { auto u{pqxx::from_string(pqxx::to_string(v))}; PQXX_CHECK_EQUAL(u, v); u = pqxx::from_string( tx.exec("SELECT " + pqxx::to_string(v)).one_field().c_str()); PQXX_CHECK_EQUAL(u, v); } } } // namespace PQXX_REGISTER_TEST(test_076); libpqxx-8.0.1/test/test77.cxx000066400000000000000000000012201516427024100160440ustar00rootroot00000000000000#include #include "helpers.hxx" // Test program for libpqxx. Test result::swap() namespace { void test_077(pqxx::test::context &) { pqxx::connection cx; pqxx::nontransaction tx{cx}; auto RFalse{tx.exec("SELECT 1=0")}, RTrue{tx.exec("SELECT 1=1")}; auto f{pqxx::from_string(RFalse[0][0])}; auto t{pqxx::from_string(RTrue[0][0])}; PQXX_CHECK( not f and t, "Booleans converted incorrectly; can't trust this test."); RFalse.swap(RTrue); f = pqxx::from_string(RFalse[0][0]); t = pqxx::from_string(RTrue[0][0]); PQXX_CHECK(f and not t); } } // namespace PQXX_REGISTER_TEST(test_077); libpqxx-8.0.1/test/test82.cxx000066400000000000000000000054751516427024100160600ustar00rootroot00000000000000#include #include "helpers.hxx" // Test program for libpqxx. Read and print table using row iterators. namespace { void test_082(pqxx::test::context &) { pqxx::connection cx; pqxx::nontransaction tx{cx}; pqxx::test::create_pqxxevents(tx); std::string const Table{"pqxxevents"}; pqxx::result const R{tx.exec("SELECT * FROM " + Table)}; PQXX_CHECK(not std::empty(R)); std::string const nullstr("[null]"); for (auto const &r : R) { pqxx::row::const_iterator f2(r[0]); for (auto const &f : r) { PQXX_CHECK_EQUAL((*f2).as(nullstr), f.as(nullstr)); ++f2; } PQXX_CHECK( std::begin(r) + pqxx::row::difference_type(std::size(r)) == std::end(r)); PQXX_CHECK( pqxx::row::difference_type(std::size(r)) + std::begin(r) == std::end(r)); PQXX_CHECK_EQUAL(std::begin(r)->column_number(), 0); pqxx::row::const_iterator f3(r[std::size(r)]); PQXX_CHECK(f3 == std::end(r)); PQXX_CHECK(f3 > std::begin(r)); PQXX_CHECK(f3 >= std::end(r) and std::begin(r) < f3); PQXX_CHECK(f3 > std::begin(r)); pqxx::row::const_iterator f4{r, std::size(r)}; PQXX_CHECK(f4 == f3); --f3; f4 -= 1; PQXX_CHECK(f3 < std::end(r)); PQXX_CHECK(f3 >= std::begin(r)); PQXX_CHECK(f3 == std::end(r) - 1); PQXX_CHECK_EQUAL(std::end(r) - f3, 1); PQXX_CHECK(f4 == f3); f4 += 1; PQXX_CHECK(f4 == std::end(r)); for (auto fr = std::rbegin(r); fr != std::rend(r); ++fr, --f3) PQXX_CHECK_EQUAL(fr->as(), f3->as()); } // Thorough test for row::const_reverse_iterator pqxx::row::const_reverse_iterator const ri1(std::rbegin(R.front())); pqxx::row::const_reverse_iterator ri2(ri1), ri3(std::end(R.front())); ri2 = std::rbegin(R.front()); PQXX_CHECK(ri1 == ri2); PQXX_CHECK(ri2 == ri3); PQXX_CHECK_EQUAL(ri2 - ri3, 0); PQXX_CHECK(pqxx::row::const_reverse_iterator(ri1.base()) == ri1); PQXX_CHECK(ri2 == ri3 + 0); PQXX_CHECK(ri2 == ri3 - 0); PQXX_CHECK(not(ri3 < ri2)); PQXX_CHECK(ri2 <= ri3); PQXX_CHECK(ri3++ == ri2); PQXX_CHECK_EQUAL(ri3 - ri2, 1); PQXX_CHECK(ri3 > ri2); PQXX_CHECK(ri3 >= ri2); PQXX_CHECK(ri2 < ri3); PQXX_CHECK(ri2 <= ri3); PQXX_CHECK(ri3 == ri2 + 1); PQXX_CHECK(ri2 == ri3 - 1, ); PQXX_CHECK(ri3 == ++ri2); PQXX_CHECK(ri3 >= ri2); PQXX_CHECK(ri3 >= ri2); PQXX_CHECK_EQUAL( ri3.base()->as(), R.front().back().as()); PQXX_CHECK(ri1->c_str()[0] == (*ri1).c_str()[0]); PQXX_CHECK(ri2-- == ri3); PQXX_CHECK(ri2 == --ri3); PQXX_CHECK(ri2 == std::rbegin(R.front())); ri2 += 1; ri3 -= -1; PQXX_CHECK(ri2 != std::rbegin(R.front())); PQXX_CHECK(ri2 != std::rbegin(R.front())); PQXX_CHECK(ri3 == ri2); ri2 -= 1; PQXX_CHECK(ri2 == std::rbegin(R.front())); } } // namespace PQXX_REGISTER_TEST(test_082); libpqxx-8.0.1/test/test84.cxx000066400000000000000000000052661516427024100160600ustar00rootroot00000000000000#include #include #include #include "helpers.hxx" // "Adopted SQL Cursor" test program for libpqxx. Create SQL cursor, wrap it // in a cursor stream, then use it to fetch data and check for consistent // results. Compare results against an icursor_iterator so that is tested as // well. namespace { void test_084(pqxx::test::context &tctx) { pqxx::connection cx; pqxx::transaction tx{cx}; int const table_size{20}; // Create an SQL cursor and, for good measure, muddle up its state a bit. std::string const cur_name{tctx.make_name("pqxx-cur")}, query{std::format("SELECT * FROM generate_series(1, {})", table_size)}; constexpr int initial_skip{2}, get_rows{3}; tx.exec("DECLARE " + tx.quote_name(cur_name) + " CURSOR FOR " + query) .no_rows(); tx.exec( "MOVE " + pqxx::to_string(initial_skip * get_rows) + " " "IN " + tx.quote_name(cur_name)) .no_rows(); // Wrap cursor in cursor stream. Apply some trickery to get its name inside // a result field for this purpose. This isn't easy because it's not // supposed to be easy; normally we'd only construct streams around existing // SQL cursors if they were being returned by functions. pqxx::icursorstream C{ tx, tx.exec("SELECT $1", pqxx::params{cur_name}).one_field(), get_rows}; // Create parallel cursor to check results pqxx::icursorstream C2{tx, query, "CHECKCUR", get_rows}; pqxx::icursor_iterator i2{C2}; // Remember, our adopted cursor is at position (initial_skip*get_rows) pqxx::icursor_iterator i3(i2); PQXX_CHECK((i3 == i2) and not(i3 != i2)); PQXX_CHECK(not(i3 > i2) and not(i3 < i2) and (i3 <= i2) and (i3 >= i2)); i3 += initial_skip; PQXX_CHECK(not(i3 <= i2)); pqxx::icursor_iterator i4; pqxx::icursor_iterator const iend; PQXX_CHECK(i3 != iend); i4 = iend; PQXX_CHECK(i4 == iend); // Now start testing our new Cursor. pqxx::result res; C >> res; i2 = i3; pqxx::result res2(*i2++); PQXX_CHECK_EQUAL( std::size(res), static_cast(get_rows)); PQXX_CHECK_EQUAL(pqxx::to_string(res), pqxx::to_string(res2)); C.get(res); res2 = *i2; PQXX_CHECK_EQUAL(pqxx::to_string(res), pqxx::to_string(res2)); i2 += 1; C.ignore(get_rows); C.get(res); res2 = *++i2; PQXX_CHECK_EQUAL(pqxx::to_string(res), pqxx::to_string(res2)); ++i2; res2 = *i2++; for (int i{1}; C.get(res) and i2 != iend; res2 = *i2++, ++i) PQXX_CHECK_EQUAL( pqxx::to_string(res), pqxx::to_string(res2), "Unexpected result in iteration at " + pqxx::to_string(i)); PQXX_CHECK(i2 == iend); PQXX_CHECK(not(C >> res)); } } // namespace PQXX_REGISTER_TEST(test_084); libpqxx-8.0.1/test/test88.cxx000066400000000000000000000060411516427024100160540ustar00rootroot00000000000000#include #include #include "helpers.hxx" // Test program for libpqxx. Attempt to perform nested transactions. namespace { void test_088(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx0{cx}; pqxx::test::create_pqxxevents(tx0); // Trivial test: create subtransactions, and commit/abort PQXX_CHECK_EQUAL( tx0.query_value("SELECT 'tx0 starts'"), "tx0 starts"); pqxx::subtransaction T0a(static_cast(tx0), "T0a"); T0a.commit(); pqxx::subtransaction T0b(static_cast(tx0), "T0b"); T0b.abort(); PQXX_CHECK_EQUAL( tx0.query_value("SELECT 'tx0 ends'"), "tx0 ends"); tx0.commit(); // Basic functionality: perform query in subtransaction; abort, continue pqxx::work tx1{cx, "tx1"}; PQXX_CHECK_EQUAL( tx1.query_value("SELECT 'tx1 starts'"), "tx1 starts"); pqxx::subtransaction tx1a{tx1, "tx1a"}; PQXX_CHECK_EQUAL(tx1a.query_value("SELECT 'a'"), "a"); tx1a.commit(); pqxx::subtransaction tx1b{tx1, "tx1b"}; PQXX_CHECK_EQUAL(tx1b.query_value("SELECT 'b'"), "b"); tx1b.abort(); pqxx::subtransaction tx1c{tx1, "tx1c"}; PQXX_CHECK_EQUAL(tx1c.query_value("SELECT 'c'"), "c"); tx1c.commit(); PQXX_CHECK_EQUAL( tx1.query_value("SELECT 'tx1 ends'"), "tx1 ends"); tx1.commit(); // Commit/rollback functionality pqxx::work tx2{cx, "tx2"}; std::string const Table{"test088"}; tx2.exec("CREATE TEMP TABLE " + Table + "(no INTEGER, text VARCHAR)") .no_rows(); tx2.exec("INSERT INTO " + Table + " VALUES(1,'tx2')").no_rows(); pqxx::subtransaction tx2a{tx2, "tx2a"}; tx2a.exec("INSERT INTO " + Table + " VALUES(2,'tx2a')").no_rows(); tx2a.commit(); pqxx::subtransaction tx2b{tx2, "tx2b"}; tx2b.exec("INSERT INTO " + Table + " VALUES(3,'tx2b')").no_rows(); tx2b.abort(); pqxx::subtransaction tx2c{tx2, "tx2c"}; tx2c.exec("INSERT INTO " + Table + " VALUES(4,'tx2c')").no_rows(); tx2c.commit(); auto const R{tx2.exec("SELECT * FROM " + Table + " ORDER BY no")}; PQXX_CHECK_EQUAL(std::size(R), 3, "Wrong number of results."); for (auto const &i : R) PQXX_CHECK(i[1].view().starts_with("tx")); std::array const expected{1, 2, 4}; for (pqxx::result::size_type n{0}; n < std::size(R); ++n) PQXX_CHECK_EQUAL( R[n][0].as(), expected.at(static_cast(n)), "Hit unexpected row number."); tx2.abort(); // Auto-abort should only roll back the subtransaction. pqxx::work tx3{cx, "tx3"}; pqxx::subtransaction tx3a(tx3, "tx3a"); PQXX_CHECK_THROWS( tx3a.exec("SELECT * FROM nonexistent_table WHERE nonattribute=0"), pqxx::sql_error); // Subtransaction can only be aborted now, because there was an error. tx3a.abort(); // We're back in our top-level transaction. This did not abort. tx3.exec("SELECT count(*) FROM pqxxevents").one_row(); // Make sure we can commit exactly one more level of transaction. tx3.commit(); } } // namespace PQXX_REGISTER_TEST(test_088); libpqxx-8.0.1/test/test89.cxx000066400000000000000000000021401516427024100160510ustar00rootroot00000000000000#include #include #include "helpers.hxx" // Test program for libpqxx. Attempt to perform nested queries on various // types of connections. namespace { void test_089(pqxx::test::context &) { pqxx::connection cx; // Trivial test: create subtransactions, and commit/abort pqxx::work tx0(cx, "tx0"); tx0.exec("SELECT 'tx0 starts'").one_row(); pqxx::subtransaction tx0a(tx0, "tx0a"); tx0a.commit(); pqxx::subtransaction tx0b(tx0, "tx0b"); tx0b.abort(); tx0.exec("SELECT 'tx0 ends'").one_row(); tx0.commit(); // Basic functionality: perform query in subtransaction; abort, continue pqxx::work tx1(cx, "tx1"); tx1.exec("SELECT 'tx1 starts'").one_row(); pqxx::subtransaction tx1a(tx1, "tx1a"); tx1a.exec("SELECT ' a'").one_row(); tx1a.commit(); pqxx::subtransaction tx1b(tx1, "tx1b"); tx1b.exec("SELECT ' b'").one_row(); tx1b.abort(); pqxx::subtransaction tx1c(tx1, "tx1c"); tx1c.exec("SELECT ' c'").one_row(); tx1c.commit(); tx1.exec("SELECT 'tx1 ends'").one_row(); tx1.commit(); } } // namespace PQXX_REGISTER_TEST(test_089); libpqxx-8.0.1/test/test90.cxx000066400000000000000000000006211516427024100160430ustar00rootroot00000000000000#include #include "helpers.hxx" // Test program for libpqxx. Test adorn_name. namespace { void test_090(pqxx::test::context &) { pqxx::connection cx; // Test connection's adorn_name() function for uniqueness std::string const nametest{"basename"}; PQXX_CHECK_NOT_EQUAL(cx.adorn_name(nametest), cx.adorn_name(nametest)); } } // namespace PQXX_REGISTER_TEST(test_090); libpqxx-8.0.1/test/test_array.cxx000066400000000000000000000722341516427024100171010ustar00rootroot00000000000000#include #include "helpers.hxx" // Test program for libpqxx array parsing. using namespace std::literals; namespace pqxx { template<> struct nullness final : no_null {}; inline std::string to_string(pqxx::array_parser::juncture const &j) { #include "pqxx/internal/ignore-deprecated-pre.hxx" using junc = pqxx::array_parser::juncture; switch (j) { case junc::row_start: return "row_start"; case junc::row_end: return "row_end"; case junc::null_value: return "null_value"; case junc::string_value: return "string_value"; case junc::done: return "done"; default: return "UNKNOWN JUNCTURE: " + to_string(static_cast(j)); } #include "pqxx/internal/ignore-deprecated-post.hxx" } } // namespace pqxx namespace { void test_empty_arrays(pqxx::test::context &) { #include "pqxx/internal/ignore-deprecated-pre.hxx" std::pair output; // Parsing a null pointer just immediately returns "done". output = pqxx::array_parser(std::string_view()).get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::done); PQXX_CHECK_EQUAL(output.second, ""); // Parsing an empty array string immediately returns "done". output = pqxx::array_parser("").get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::done); PQXX_CHECK_EQUAL(output.second, ""); // Parsing an empty array returns "row_start", "row_end", "done". pqxx::array_parser empty_parser("{}"); output = empty_parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_start); PQXX_CHECK_EQUAL(output.second, ""); output = empty_parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_end); PQXX_CHECK_EQUAL(output.second, ""); output = empty_parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::done); PQXX_CHECK_EQUAL(output.second, ""); #include "pqxx/internal/ignore-deprecated-post.hxx" } void test_array_null_value(pqxx::test::context &) { #include "pqxx/internal/ignore-deprecated-pre.hxx" std::pair output; pqxx::array_parser containing_null("{NULL}"); output = containing_null.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_start); PQXX_CHECK_EQUAL(output.second, ""); output = containing_null.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::null_value); PQXX_CHECK_EQUAL(output.second, ""); output = containing_null.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_end); PQXX_CHECK_EQUAL(output.second, ""); output = containing_null.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::done); PQXX_CHECK_EQUAL(output.second, ""); #include "pqxx/internal/ignore-deprecated-post.hxx" } void test_array_double_quoted_string(pqxx::test::context &) { #include "pqxx/internal/ignore-deprecated-pre.hxx" std::pair output; pqxx::array_parser parser("{\"item\"}"); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_start); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::string_value); PQXX_CHECK_EQUAL(output.second, "item"); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_end); PQXX_CHECK_EQUAL(output.second, ""); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::done); PQXX_CHECK_EQUAL(output.second, ""); #include "pqxx/internal/ignore-deprecated-post.hxx" } void test_array_double_quoted_escaping(pqxx::test::context &) { #include "pqxx/internal/ignore-deprecated-pre.hxx" std::pair output; pqxx::array_parser parser(R"--({"don''t\\ care"})--"); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_start); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::string_value); PQXX_CHECK_EQUAL(output.second, "don''t\\ care"); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_end); PQXX_CHECK_EQUAL(output.second, ""); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::done); PQXX_CHECK_EQUAL(output.second, ""); #include "pqxx/internal/ignore-deprecated-post.hxx" } // A pair of double quotes in a double-quoted string is an escaped quote. void test_array_double_double_quoted_string(pqxx::test::context &) { #include "pqxx/internal/ignore-deprecated-pre.hxx" std::pair output; pqxx::array_parser parser{R"--({"3"" steel"})--"}; output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_start); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::string_value); PQXX_CHECK_EQUAL(output.second, "3\" steel"); #include "pqxx/internal/ignore-deprecated-post.hxx" } void test_array_unquoted_string(pqxx::test::context &) { #include "pqxx/internal/ignore-deprecated-pre.hxx" std::pair output; pqxx::array_parser parser("{item}"); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_start); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::string_value); PQXX_CHECK_EQUAL(output.second, "item"); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_end); PQXX_CHECK_EQUAL(output.second, ""); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::done); PQXX_CHECK_EQUAL(output.second, ""); #include "pqxx/internal/ignore-deprecated-post.hxx" } void test_array_multiple_values(pqxx::test::context &) { #include "pqxx/internal/ignore-deprecated-pre.hxx" std::pair output; pqxx::array_parser parser("{1,2}"); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_start); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::string_value); PQXX_CHECK_EQUAL(output.second, "1"); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::string_value); PQXX_CHECK_EQUAL(output.second, "2"); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_end); PQXX_CHECK_EQUAL(output.second, ""); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::done); PQXX_CHECK_EQUAL(output.second, ""); #include "pqxx/internal/ignore-deprecated-post.hxx" } void test_nested_array(pqxx::test::context &) { #include "pqxx/internal/ignore-deprecated-pre.hxx" std::pair output; pqxx::array_parser parser("{{item}}"); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_start); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_start); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::string_value); PQXX_CHECK_EQUAL(output.second, "item"); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_end); PQXX_CHECK_EQUAL(output.second, ""); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_end); PQXX_CHECK_EQUAL(output.second, ""); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::done); PQXX_CHECK_EQUAL(output.second, ""); #include "pqxx/internal/ignore-deprecated-post.hxx" } void test_nested_array_with_multiple_entries(pqxx::test::context &) { #include "pqxx/internal/ignore-deprecated-pre.hxx" std::pair output; pqxx::array_parser parser("{{1,2},{3,4}}"); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_start); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_start); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::string_value); PQXX_CHECK_EQUAL(output.second, "1"); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::string_value); PQXX_CHECK_EQUAL(output.second, "2"); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_end); PQXX_CHECK_EQUAL(output.second, ""); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_start); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::string_value); PQXX_CHECK_EQUAL(output.second, "3"); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::string_value); PQXX_CHECK_EQUAL(output.second, "4"); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_end); PQXX_CHECK_EQUAL(output.second, ""); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::row_end); PQXX_CHECK_EQUAL(output.second, ""); output = parser.get_next(); PQXX_CHECK_EQUAL(output.first, pqxx::array_parser::juncture::done); PQXX_CHECK_EQUAL(output.second, ""); #include "pqxx/internal/ignore-deprecated-post.hxx" } /// Create a `pqxx::conversion_context`. pqxx::conversion_context make_context( pqxx::encoding_group enc = pqxx::encoding_group::ascii_safe, std::source_location loc = std::source_location::current()) { return pqxx::conversion_context{enc, loc}; } void test_generate_empty_array(pqxx::test::context &) { PQXX_CHECK_EQUAL(pqxx::to_string(std::vector{}, make_context()), "{}"); PQXX_CHECK_EQUAL( pqxx::to_string(std::vector{}, make_context()), "{}"); } void test_generate_null_value(pqxx::test::context &) { PQXX_CHECK_EQUAL( pqxx::to_string(std::vector{nullptr}, make_context()), "{NULL}"); } void test_generate_single_item(pqxx::test::context &) { PQXX_CHECK_EQUAL( pqxx::to_string(std::vector{42}, make_context()), "{42}"); PQXX_CHECK_EQUAL( pqxx::to_string(std::vector{"foo"}, make_context()), "{\"foo\"}"); } void test_generate_multiple_items(pqxx::test::context &) { PQXX_CHECK_EQUAL( pqxx::to_string(std::vector{5, 4, 3, 2}, make_context()), "{5,4,3,2}"); PQXX_CHECK_EQUAL( pqxx::to_string(std::vector{"foo", "bar"}, make_context()), "{\"foo\",\"bar\"}"); } void test_generate_nested_array(pqxx::test::context &) { PQXX_CHECK_EQUAL( pqxx::to_string( std::vector>{{1, 2}, {3, 4}}, make_context()), "{{1,2},{3,4}}"); } void test_generate_escaped_strings(pqxx::test::context &) { PQXX_CHECK_EQUAL( pqxx::to_string(std::vector{"a\\b"}, make_context()), "{\"a\\\\b\"}", "Backslashes are not escaped properly."); PQXX_CHECK_EQUAL( pqxx::to_string(std::vector{"x\"y\""}, make_context()), "{\"x\\\"y\\\"\"}", "Double quotes are not escaped properly."); } void test_array_generate_empty_strings(pqxx::test::context &) { // Reproduce #816: Under-budgeted conversion of empty strings in arrays. PQXX_CHECK_EQUAL( pqxx::to_string(std::vector{{""}}, make_context()), "{\"\"}"); PQXX_CHECK_EQUAL( pqxx::to_string( std::vector({"", "", "", ""}), make_context()), "{\"\",\"\",\"\",\"\"}"); PQXX_CHECK_EQUAL( pqxx::to_string( std::vector( {"", "", "", "", "", "", "", "", "", "", "", ""}), make_context()), "{\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"}"); } void test_sparse_arrays(pqxx::test::context &) { // Reproduce #922 : NULL not paying for its separator in an array, causing // problems in sparse arrays. // If NULL didn't pay for its separator, the size allocated for an array-like // object filled with null-like values would be too small. auto arrayOfNulls = std::vector>(4, std::nullopt); std::string const arrayOfNullsStr = "{NULL,NULL,NULL,NULL}"; PQXX_CHECK_GREATER_EQUAL( pqxx::size_buffer(arrayOfNulls), arrayOfNullsStr.size(), "Buffer size allocated for an array of optional filled with nulls " "was too small."); PQXX_CHECK_EQUAL( pqxx::to_string(arrayOfNulls), arrayOfNullsStr, "Array of optional filled with std::nullopt came out wrong. "); // If the array-like object is instead sparsely-filled, the values contained // in non-null elements may leave behind excess unused size which hides the // problem better - it only becomes an error once the array contains enough // null-like values to outweigh this excess unused size. std::array, 14> sparseArray; sparseArray[sparseArray.size() - 1] = 42; std::string const sparseArrayStr = "{NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL," "42}"; PQXX_CHECK_GREATER_EQUAL( pqxx::size_buffer(sparseArray), sparseArrayStr.size(), "Buffer size allocated for a sparsely-filled array of optional was " "too small."); PQXX_CHECK_EQUAL(pqxx::to_string(sparseArray), sparseArrayStr); } void test_array_roundtrip(pqxx::test::context &) { #include "pqxx/internal/ignore-deprecated-pre.hxx" pqxx::connection cx; pqxx::work tx{cx}; std::vector const in{0, 1, 2, 3, 5}; auto const text{ tx.query_value("SELECT $1::integer[]", pqxx::params{in})}; pqxx::array_parser parser{text}; auto item{parser.get_next()}; PQXX_CHECK_EQUAL(item.first, pqxx::array_parser::juncture::row_start); std::vector out; for (item = parser.get_next(); item.first == pqxx::array_parser::juncture::string_value; item = parser.get_next()) { out.push_back(pqxx::from_string(item.second)); } PQXX_CHECK_EQUAL(item.first, pqxx::array_parser::juncture::row_end); PQXX_CHECK_EQUAL(std::size(out), std::size(in)); for (std::size_t i{0}; i < std::size(in); ++i) PQXX_CHECK_EQUAL(out[i], in[i]); item = parser.get_next(); PQXX_CHECK_EQUAL(item.first, pqxx::array_parser::juncture::done); #include "pqxx/internal/ignore-deprecated-post.hxx" } void test_array_strings(pqxx::test::context &) { #include "pqxx/internal/ignore-deprecated-pre.hxx" std::vector const inputs{ "", "null", "NULL", "\\N", "'", "''", "\\", "\n\t", "\\n", "\"", "\"\"", "a b", "a<>b", "{", "}", "{}", }; pqxx::connection cx; pqxx::work tx{cx}; for (auto const &input : inputs) { auto const f{tx.exec("SELECT ARRAY[$1]", pqxx::params{input}).one_field()}; pqxx::array_parser parser{f.as()}; [[maybe_unused]] auto [start_juncture, start_value]{parser.get_next()}; PQXX_CHECK_EQUAL(start_juncture, pqxx::array_parser::juncture::row_start); auto [value_juncture, value]{parser.get_next()}; PQXX_CHECK_EQUAL( value_juncture, pqxx::array_parser::juncture::string_value); PQXX_CHECK_EQUAL(value, input); } #include "pqxx/internal/ignore-deprecated-post.hxx" } void test_array_parses_real_arrays(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; PQXX_CHECK_THROWS( (std::ignore = pqxx::from_string>("{}")), pqxx::usage_error, "Array parser accepted text in an unknown encoding group."); auto const empty_s{tx.query_value("SELECT ARRAY[]::integer[]")}; pqxx::array const empty_a{ pqxx::from_string>(empty_s, make_context())}; PQXX_CHECK_EQUAL(empty_a.dimensions(), 1u); PQXX_CHECK_EQUAL(empty_a.sizes(), (std::array{0u})); auto const onedim_s{tx.query_value("SELECT ARRAY[0, 1, 2]")}; pqxx::array const onedim_a{ pqxx::from_string>(onedim_s, make_context())}; PQXX_CHECK_EQUAL(onedim_a.dimensions(), 1u); PQXX_CHECK_EQUAL(onedim_a.sizes(), (std::array{3u})); PQXX_CHECK_EQUAL(onedim_a.at(0), 0); PQXX_CHECK_EQUAL(onedim_a[0], 0); PQXX_CHECK_EQUAL(onedim_a.at(2), 2); PQXX_CHECK_EQUAL(onedim_a[2], 2); auto const null_s{ tx.query_value("SELECT ARRAY[NULL]::integer[]")}; PQXX_CHECK_THROWS((pqxx::array{null_s, cx}), pqxx::unexpected_null); auto const twodim_s{tx.query_value("SELECT ARRAY[[1], [2]]")}; pqxx::array const twodim_a{ pqxx::from_string>(twodim_s, make_context())}; PQXX_CHECK_EQUAL(twodim_a.dimensions(), 2u); PQXX_CHECK_EQUAL(twodim_a.sizes(), (std::array{2u, 1u})); auto const string_s{tx.query_value("SELECT ARRAY['Hello']")}; pqxx::array const string_a{string_s, cx}; PQXX_CHECK_EQUAL(string_a[0], "Hello"); auto const fake_null_s{tx.query_value("SELECT ARRAY['NULL']")}; pqxx::array const fake_null_a{string_s, cx}; PQXX_CHECK_EQUAL(fake_null_a[0], "Hello"); auto const nulls_s{ tx.query_value("SELECT ARRAY[NULL, 'NULL']")}; pqxx::array> const nulls_a{nulls_s, cx}; PQXX_CHECK(not nulls_a[0].has_value()); PQXX_CHECK(nulls_a[1].has_value()); PQXX_CHECK_EQUAL(nulls_a[1].value_or("(missing)"), "NULL"); } void test_array_rejects_malformed_simple_int_arrays(pqxx::test::context &) { pqxx::connection cx; std::string_view const bad_arrays[]{ ""sv, "null"sv, ","sv, "1"sv, "{"sv, "}"sv, "}{"sv, "{}{"sv, "{{}"sv, "{}}"sv, "{{}}"sv, "{1"sv, "{1,"sv, "{,}"sv, "{1,}"sv, "{,1}"sv, "{1,{}}"sv, "{x}"sv, "{1,{2,3}}"sv, }; for (auto bad : bad_arrays) PQXX_CHECK_THROWS( (pqxx::array{bad, cx}), pqxx::conversion_error, "No conversion_error for '" + std::string{bad} + "'."); } void test_array_rejects_malformed_simple_string_arrays(pqxx::test::context &) { pqxx::connection cx; std::string_view const bad_arrays[]{ ""sv, "null"sv, "1"sv, ","sv, "{"sv, "}"sv, "}{"sv, "{}{"sv, "{{}"sv, "{}}"sv, "{{}}"sv, "{1"sv, "{1,"sv, "{,}"sv, "{1,}"sv, "{,1}"sv, "{1,{}}"sv, }; for (auto bad : bad_arrays) PQXX_CHECK_THROWS( (pqxx::array{bad, cx}), pqxx::conversion_error, "No conversion_error for '" + std::string{bad} + "'."); } void test_array_rejects_malformed_twodimensional_arrays(pqxx::test::context &) { pqxx::connection cx; std::string_view const bad_arrays[]{ ""sv, "{}"sv, "{null}"sv, "{{1},{2,3}}"sv, }; for (auto bad : bad_arrays) PQXX_CHECK_THROWS( (pqxx::array{bad, cx}), pqxx::conversion_error, "No conversion_error for '" + std::string{bad} + "'."); } void test_array_parses_quoted_strings(pqxx::test::context &) { pqxx::connection const cx; pqxx::array const a{ R"x({"","n","nnn","\"'","""","\\","\"","a""","""z"})x", cx}; PQXX_CHECK_EQUAL(a.at(0), ""); PQXX_CHECK_EQUAL(a.at(1), "n"); PQXX_CHECK_EQUAL(a.at(2), "nnn"); PQXX_CHECK_EQUAL(a.at(3), R"x("')x"); PQXX_CHECK_EQUAL(a.at(4), R"x(")x"); PQXX_CHECK_EQUAL(a.at(5), "\\"); PQXX_CHECK_EQUAL(a.at(6), "\""); PQXX_CHECK_EQUAL(a.at(7), "a\""); PQXX_CHECK_EQUAL(a.at(8), "\"z"); // A byte value that looks like an ASCII backslash but inside a multibyte // character does not count as a backslash. pqxx::array const b{ "{\"\203\\\",\"\\\203\\\"}", pqxx::encoding_group::sjis}; PQXX_CHECK_EQUAL( b.at(0), "\203\\" ""); // If encoding support didn't work properly, puting a backslash in front // would probably only get applied to the first byte in the character, and // turn that embedded byte bcak into a backslash. PQXX_CHECK_EQUAL( b.at(1), "\203\\" ""); } void test_array_parses_multidim_arrays(pqxx::test::context &) { pqxx::connection const cx; pqxx::array const a{"{{0,1},{2,3}}", cx}; PQXX_CHECK_EQUAL(a.at(0u, 0u), 0); PQXX_CHECK_EQUAL(a.at(1u, 0u), 2); PQXX_CHECK_EQUAL(a.at(1u, 1u), 3); } void test_array_at_checks_bounds(pqxx::test::context &) { pqxx::connection const cx; // Simple, single-dimensional case: pqxx::array const simple{"{0, 1, 2}", cx}; PQXX_CHECK_EQUAL(simple.dimensions(), 1u); auto const size1d{simple.sizes()}; PQXX_CHECK_EQUAL(std::size(size1d), 1u); PQXX_CHECK_EQUAL(size1d[0], 3u); PQXX_CHECK_EQUAL(simple.at(1), 1); PQXX_CHECK_EQUAL(simple[1], 1); PQXX_CHECK_EQUAL(simple.at(2), 2); PQXX_CHECK_EQUAL(simple[2], 2); PQXX_CHECK_EQUAL(simple.at(0), 0); PQXX_CHECK_EQUAL(simple.at(2), 2); PQXX_CHECK_THROWS((std::ignore = simple.at(3)), pqxx::range_error); PQXX_CHECK_THROWS((std::ignore = simple.at(-1)), pqxx::range_error); // Two-dimensional case: pqxx::array const twodim{"{{0,1},{2,3},{4,5}}", cx}; PQXX_CHECK_EQUAL(twodim.dimensions(), 2u); auto const size2d{twodim.sizes()}; PQXX_CHECK_EQUAL(std::size(size2d), 2u); PQXX_CHECK_EQUAL(size2d[0], 3u); PQXX_CHECK_EQUAL(size2d[1], 2u); PQXX_CHECK_EQUAL(twodim.at(0, 0), 0); PQXX_CHECK_EQUAL(twodim.at(1, 1), 3); PQXX_CHECK_EQUAL(twodim.at(2, 1), 5); PQXX_CHECK_THROWS((std::ignore = twodim.at(3, 0)), pqxx::range_error); PQXX_CHECK_THROWS((std::ignore = twodim.at(0, 2)), pqxx::range_error); PQXX_CHECK_THROWS((std::ignore = twodim.at(0, -1)), pqxx::range_error); PQXX_CHECK_THROWS((std::ignore = twodim.at(-1, 0)), pqxx::range_error); // Three-dimensional: pqxx::array const threedim{ "{{{0,1,2},{3,4,5}},{{6,7,8},{9,10,11}}," "{{12,13,14},{15,16,17}},{{18,19,20},{21,22,23}}}", cx}; PQXX_CHECK_EQUAL(threedim.dimensions(), 3u); auto const size3d{threedim.sizes()}; PQXX_CHECK_EQUAL(std::size(size3d), 3u); PQXX_CHECK_EQUAL(size3d[0], 4u); PQXX_CHECK_EQUAL(size3d[1], 2u); PQXX_CHECK_EQUAL(size3d[2], 3u); PQXX_CHECK_EQUAL(threedim.at(3, 1, 2), 23); PQXX_CHECK_THROWS(std::ignore = threedim.at(4, 1, 2), pqxx::range_error); PQXX_CHECK_THROWS(std::ignore = threedim.at(3, 2, 2), pqxx::range_error); PQXX_CHECK_THROWS(std::ignore = threedim.at(3, 1, 3), pqxx::range_error); } void test_array_iterates_in_row_major_order(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; auto const array_s{tx.query_value( "SELECT ARRAY[[1, 2, 3], [4, 5, 6], [7, 8, 9]]")}; pqxx::array const array{array_s, cx}; auto it{array.begin()}; PQXX_CHECK_EQUAL(*it, 1); ++it; ++it; PQXX_CHECK_EQUAL(*it, 3); ++it; PQXX_CHECK_EQUAL(*it, 4); it += 6; PQXX_CHECK(it == array.end()); // Or just really quickly: our input happens to have the digits in // sequential order. int count{1}; for (auto elt : array) { PQXX_CHECK_EQUAL(elt, count); ++count; } PQXX_CHECK_EQUAL(*(array.end() - 1), 9); PQXX_CHECK_EQUAL(*array.rbegin(), 9); PQXX_CHECK_EQUAL(*(array.rend() - 1), 1); PQXX_CHECK_EQUAL(std::size(array), 9u); PQXX_CHECK_EQUAL(std::ssize(array), 9); PQXX_CHECK_EQUAL(array.front(), 1); PQXX_CHECK_EQUAL(array.back(), 9); } void test_result_parses_simple_array(pqxx::test::context &) { pqxx::connection cx; pqxx::row r; { pqxx::work tx{cx}; r = tx.exec("SELECT ARRAY [5, 4, 3, 2]").one_row(); // Connection closes, but we should still be able to parse the array. } #include auto const array{r[0].as_sql_array()}; #include PQXX_CHECK_EQUAL( array[1], 4, "Got wrong value out of array (via as_sql_array)."); auto const array2{r[0].as>()}; PQXX_CHECK_EQUAL(array2[3], 2, "Got wrong value out of array (via as)."); } // Shorthand for shorthand for std::source_location::current(). constexpr pqxx::sl here(pqxx::sl loc = pqxx::sl::current()) { return loc; } template void check_scan_double_quoted_ascii() { // TODO: Do this with static_assert() once Visual Studio handles it. PQXX_CHECK_EQUAL( pqxx::internal::scan_double_quoted_string(R"("")", 0u, here()), 2u); PQXX_CHECK_EQUAL( pqxx::internal::scan_double_quoted_string(R"(""z)", 0u, here()), 2u); PQXX_CHECK_EQUAL( pqxx::internal::scan_double_quoted_string(R"(x="")", 2u, here()), 4u); PQXX_CHECK_EQUAL( pqxx::internal::scan_double_quoted_string(R"(x=""z)", 2u, here()), 4u); PQXX_CHECK_EQUAL( pqxx::internal::scan_double_quoted_string(R"("x")", 0u, here()), 3u); PQXX_CHECK_EQUAL( pqxx::internal::scan_double_quoted_string(R"("x"z)", 0u, here()), 3u); PQXX_CHECK_THROWS( (pqxx::internal::scan_double_quoted_string(R"("foo)", 0u, here())), pqxx::argument_error, "Double-quoted string scan did not detect missing closing quote."); PQXX_CHECK_EQUAL( pqxx::internal::scan_double_quoted_string("\"x\\\"y\"", 0u, here()), 6u); PQXX_CHECK_EQUAL( pqxx::internal::scan_double_quoted_string( "\"x\\\"y\"z\"", 0u, here()), 6u); PQXX_CHECK_EQUAL( pqxx::internal::scan_double_quoted_string(R"("x\\y")", 0u, here()), 6u); PQXX_CHECK_EQUAL( pqxx::internal::scan_double_quoted_string(R"("x""y")", 0u, here()), 6u); PQXX_CHECK_EQUAL( pqxx::internal::scan_double_quoted_string(R"("x""y"z)", 0u, here()), 6u); PQXX_CHECK_EQUAL( pqxx::internal::scan_double_quoted_string( "\"\\\\\\\"\"\"\"", 0u, here()), 8u); PQXX_CHECK_EQUAL( pqxx::internal::scan_double_quoted_string( "a\"\\\\\\\"\"\"\"", 1u, here()), 9u); PQXX_CHECK_EQUAL( pqxx::internal::scan_double_quoted_string(R"("""")", 0u, here()), 4u); PQXX_CHECK_EQUAL( pqxx::internal::scan_double_quoted_string(R"(""""z)", 0u, here()), 4u); } void test_scan_double_quoted_string(pqxx::test::context &) { using enc = pqxx::encoding_group; check_scan_double_quoted_ascii(); check_scan_double_quoted_ascii(); check_scan_double_quoted_ascii(); check_scan_double_quoted_ascii(); // Now let's try a byte that _looks_ like an ASCII backslash escaping the // closing quote (which would be an obvious vector for an injection attack) // but is actually just one byte in a multibyte character. // (I believe these two SJIS bytes form the Katakana letter "so".) PQXX_CHECK_EQUAL( pqxx::internal::scan_double_quoted_string( "\"\203\\\"suffix", 0u, here()), 4u, "Fell for embedded ASCII-like byte in multibyte char."); } void test_sql_array_parses_to_container(pqxx::test::context &) { PQXX_CHECK_EQUAL( std::size(pqxx::from_string>("{}", make_context())), 0u); std::vector const ints_vec{ pqxx::from_string>("{6,5,4}", make_context())}; PQXX_CHECK_EQUAL(std::size(ints_vec), 3u); PQXX_CHECK_EQUAL(ints_vec.at(0), 6); PQXX_CHECK_EQUAL(ints_vec.at(1), 5); PQXX_CHECK_EQUAL(ints_vec.at(2), 4); std::vector const str_vec{ pqxx::from_string>("{7,6}", make_context())}; PQXX_CHECK_EQUAL(std::size(str_vec), 2u); PQXX_CHECK_EQUAL(str_vec.at(0), "7"); PQXX_CHECK_EQUAL(str_vec.at(1), "6"); std::list const ints_list{ pqxx::from_string>("{9,8,7}", make_context())}; PQXX_CHECK_EQUAL(std::size(ints_list), 3u); auto li{ints_list.cbegin()}; PQXX_CHECK(li != ints_list.cend()); PQXX_CHECK_EQUAL(*li, 9); ++li; PQXX_CHECK(li != ints_list.cend()); PQXX_CHECK_EQUAL(*li, 8); ++li; PQXX_CHECK(li != ints_list.cend()); PQXX_CHECK_EQUAL(*li, 7); // It doesn't work for multi-dimensional arrays. PQXX_CHECK_THROWS( (std::ignore = pqxx::from_string>("{{1}}", make_context())), pqxx::conversion_error); } PQXX_REGISTER_TEST(test_empty_arrays); PQXX_REGISTER_TEST(test_array_null_value); PQXX_REGISTER_TEST(test_array_double_quoted_string); PQXX_REGISTER_TEST(test_array_double_quoted_escaping); PQXX_REGISTER_TEST(test_array_double_double_quoted_string); PQXX_REGISTER_TEST(test_array_unquoted_string); PQXX_REGISTER_TEST(test_array_multiple_values); PQXX_REGISTER_TEST(test_nested_array); PQXX_REGISTER_TEST(test_nested_array_with_multiple_entries); PQXX_REGISTER_TEST(test_array_roundtrip); PQXX_REGISTER_TEST(test_array_strings); PQXX_REGISTER_TEST(test_array_parses_real_arrays); PQXX_REGISTER_TEST(test_array_rejects_malformed_simple_int_arrays); PQXX_REGISTER_TEST(test_array_rejects_malformed_simple_string_arrays); PQXX_REGISTER_TEST(test_array_rejects_malformed_twodimensional_arrays); PQXX_REGISTER_TEST(test_array_parses_quoted_strings); PQXX_REGISTER_TEST(test_array_parses_multidim_arrays); PQXX_REGISTER_TEST(test_array_at_checks_bounds); PQXX_REGISTER_TEST(test_array_iterates_in_row_major_order); PQXX_REGISTER_TEST(test_array_generate_empty_strings); PQXX_REGISTER_TEST(test_result_parses_simple_array); PQXX_REGISTER_TEST(test_scan_double_quoted_string); PQXX_REGISTER_TEST(test_generate_empty_array); PQXX_REGISTER_TEST(test_generate_null_value); PQXX_REGISTER_TEST(test_generate_single_item); PQXX_REGISTER_TEST(test_generate_multiple_items); PQXX_REGISTER_TEST(test_generate_nested_array); PQXX_REGISTER_TEST(test_generate_escaped_strings); PQXX_REGISTER_TEST(test_sparse_arrays); PQXX_REGISTER_TEST(test_sql_array_parses_to_container); } // namespace libpqxx-8.0.1/test/test_blob.cxx000066400000000000000000000431321516427024100166740ustar00rootroot00000000000000#include #include #include #include #include "helpers.hxx" #include "sample_types.hxx" namespace { void test_blob_is_useless_by_default(pqxx::test::context &) { pqxx::blob b{}; pqxx::bytes buf; PQXX_CHECK_THROWS(b.read(buf, 1), pqxx::usage_error); PQXX_CHECK_THROWS(b.write(buf), pqxx::usage_error); } void test_blob_create_makes_empty_blob(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::oid const id{pqxx::blob::create(tx)}; auto b{pqxx::blob::open_r(tx, id)}; b.seek_end(0); PQXX_CHECK_EQUAL(b.tell(), 0); } void test_blob_create_with_oid_requires_oid_be_free(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; auto id{pqxx::blob::create(tx)}; PQXX_CHECK_THROWS(std::ignore = pqxx::blob::create(tx, id), pqxx::failure); } void test_blob_create_with_oid_obeys_oid(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; auto id{pqxx::blob::create(tx)}; pqxx::blob::remove(tx, id); auto actual_id{pqxx::blob::create(tx, id)}; pqxx::blob::remove(tx, actual_id); PQXX_CHECK_EQUAL(actual_id, id); } void test_blobs_are_transactional(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::oid id{pqxx::blob::create(tx)}; tx.abort(); pqxx::work tx2{cx}; PQXX_CHECK_THROWS(std::ignore = pqxx::blob::open_r(tx2, id), pqxx::failure); } void test_blob_remove_removes_blob(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::oid id{pqxx::blob::create(tx)}; pqxx::blob::remove(tx, id); PQXX_CHECK_THROWS(std::ignore = pqxx::blob::open_r(tx, id), pqxx::failure); PQXX_CHECK_THROWS(pqxx::blob::remove(tx, 0), pqxx::usage_error); } void test_blob_remove_is_not_idempotent(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::oid id{pqxx::blob::create(tx)}; pqxx::blob::remove(tx, id); PQXX_CHECK_THROWS(pqxx::blob::remove(tx, id), pqxx::failure); } void test_blob_checks_open_mode(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::oid const id{pqxx::blob::create(tx)}; pqxx::blob b_r{pqxx::blob::open_r(tx, id)}; pqxx::blob b_w{pqxx::blob::open_w(tx, id)}; pqxx::blob b_rw{pqxx::blob::open_rw(tx, id)}; pqxx::bytes buf{std::byte{3}, std::byte{2}, std::byte{1}}; // These are all allowed: b_w.write(buf); b_r.read(buf, 3); b_rw.seek_end(0); b_rw.write(buf); b_rw.seek_abs(0); b_rw.read(buf, 6); // These are not: PQXX_CHECK_THROWS(b_r.write(buf), pqxx::failure); PQXX_CHECK_THROWS(b_w.read(buf, 10), pqxx::failure); } /// Convert a byte to an unsigned int. unsigned byte_as_num(std::byte b) { return static_cast(b); } void test_blob_supports_move(pqxx::test::context &) { pqxx::bytes buf; buf.push_back(std::byte{'x'}); pqxx::connection cx; pqxx::work tx{cx}; pqxx::oid const id{pqxx::blob::create(tx)}; pqxx::blob b1{pqxx::blob::open_rw(tx, id)}; b1.write(buf); pqxx::blob b2{std::move(b1)}; b2.seek_abs(0); b2.read(buf, 1u); PQXX_CHECK_THROWS(b1.read(buf, 1u), pqxx::usage_error); // NOLINT b1 = std::move(b2); b1.read(buf, 1u); PQXX_CHECK_THROWS(b2.read(buf, 1u), pqxx::usage_error); // NOLINT std::array const three{std::byte{0x03}}, four{std::byte{0x04}}; auto const id3{pqxx::blob::from_buf(tx, three)}, id4{pqxx::blob::from_buf(tx, four)}; auto b3{pqxx::blob::open_rw(tx, id3)}, b4{pqxx::blob::open_rw(tx, id4)}; b3 = std::move(b4); // The move invalidates b4. // NOLINTNEXTLINE PQXX_CHECK_THROWS(b4.seek_abs(0), pqxx::usage_error); b3.seek_abs(0); // Because of the assignment, b3 now refers to the blob with ID id4. std::array buf2{}; auto const out{b3.read(buf2)}; PQXX_CHECK_EQUAL(std::size(out), 1u); PQXX_CHECK_EQUAL(byte_as_num(out[0]), byte_as_num(std::byte{0x04})); } void test_blob_read_reads_data(pqxx::test::context &) { pqxx::bytes const data{std::byte{'a'}, std::byte{'b'}, std::byte{'c'}}; pqxx::connection cx; pqxx::work tx{cx}; pqxx::oid const id{pqxx::blob::from_buf(tx, data)}; pqxx::bytes buf; auto b{pqxx::blob::open_rw(tx, id)}; PQXX_CHECK_EQUAL(b.read(buf, 2), 2u); PQXX_CHECK_EQUAL(buf, (pqxx::bytes{std::byte{'a'}, std::byte{'b'}})); PQXX_CHECK_EQUAL(b.read(buf, 2), 1u); PQXX_CHECK_EQUAL(buf, (pqxx::bytes{std::byte{'c'}})); PQXX_CHECK_EQUAL(b.read(buf, 2), 0u); PQXX_CHECK_EQUAL(buf, (pqxx::bytes{})); } void test_blob_read_reads_generic_data(pqxx::test::context &) { std::array const data{ std::byte{'a'}, std::byte{'b'}, std::byte{'c'}}; pqxx::connection cx; pqxx::work tx{cx}; pqxx::oid const id{pqxx::blob::from_buf(tx, data)}; pqxx::bytes buf; auto b{pqxx::blob::open_rw(tx, id)}; PQXX_CHECK_EQUAL(b.read(buf, 2), 2u); PQXX_CHECK_EQUAL(buf, (pqxx::bytes{std::byte{'a'}, std::byte{'b'}})); PQXX_CHECK_EQUAL(b.read(buf, 2), 1u); PQXX_CHECK_EQUAL(buf, (pqxx::bytes{std::byte{'c'}})); PQXX_CHECK_EQUAL(b.read(buf, 2), 0u); PQXX_CHECK_EQUAL(buf, (pqxx::bytes{})); } /// Cast a `char` or `std::byte` to `unsigned int`. template inline unsigned byte_val(BYTE val) { return unsigned(static_cast(val)); } void test_blob_read_span(pqxx::test::context &) { pqxx::bytes const data{std::byte{'u'}, std::byte{'v'}, std::byte{'w'}, std::byte{'x'}, std::byte{'y'}, std::byte{'z'}}; pqxx::connection cx; pqxx::work tx{cx}; pqxx::oid const id{pqxx::blob::from_buf(tx, data)}; auto b{pqxx::blob::open_r(tx, id)}; pqxx::bytes string_buf; string_buf.resize(2); std::span output; output = b.read(std::span{}); PQXX_CHECK_EQUAL(std::size(output), 0u); output = b.read(string_buf); PQXX_CHECK_EQUAL(std::size(output), 2u); PQXX_CHECK_EQUAL(byte_val(output[0]), byte_val('u')); PQXX_CHECK_EQUAL(byte_val(output[1]), byte_val('v')); string_buf.resize(100); output = b.read(std::span{string_buf.data(), 1}); PQXX_CHECK_EQUAL(std::size(output), 1u); PQXX_CHECK_EQUAL(byte_val(output[0]), byte_val('w')); std::vector vec_buf; vec_buf.resize(2); auto output2{b.read(vec_buf)}; PQXX_CHECK_EQUAL(std::size(output2), 2u); PQXX_CHECK_EQUAL(byte_val(output2[0]), byte_val('x')); PQXX_CHECK_EQUAL(byte_val(output2[1]), byte_val('y')); vec_buf.resize(100); output2 = b.read(vec_buf); PQXX_CHECK_EQUAL(std::size(output2), 1u); PQXX_CHECK_EQUAL(byte_val(output2[0]), byte_val('z')); } void test_blob_reads_vector(pqxx::test::context &) { char const content[]{"abcd"}; pqxx::connection cx; pqxx::work tx{cx}; auto id{pqxx::blob::from_buf( tx, pqxx::bytes_view{ reinterpret_cast(content), std::size(content)})}; std::vector buf; buf.resize(10); auto out{pqxx::blob::open_r(tx, id).read(buf)}; PQXX_CHECK_EQUAL(std::size(out), std::size(content)); PQXX_CHECK_EQUAL(byte_val(out[0]), byte_val('a')); } void test_blob_write_appends_at_insertion_point(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; auto id{pqxx::blob::create(tx)}; auto b{pqxx::blob::open_rw(tx, id)}; b.write(pqxx::bytes{std::byte{'z'}}); b.write(pqxx::bytes{std::byte{'a'}}); pqxx::bytes buf; b.read(buf, 5); PQXX_CHECK_EQUAL(buf, (pqxx::bytes{}), "Found data at the end."); b.seek_abs(0); b.read(buf, 5); PQXX_CHECK_EQUAL( buf, (pqxx::bytes{std::byte{'z'}, std::byte{'a'}}), "Consecutive writes did not append correctly."); b.write(pqxx::bytes{std::byte{'x'}}); // Blob now contains "zax". That's not we wanted... Rewind and rewrite. b.seek_abs(1); b.write(pqxx::bytes{std::byte{'y'}}); b.seek_abs(0); b.read(buf, 5); PQXX_CHECK_EQUAL( buf, (pqxx::bytes{std::byte{'z'}, std::byte{'y'}, std::byte{'x'}}), "Rewriting in the middle did not work right."); } void test_blob_writes_span(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; constexpr char content[]{"gfbltk"}; // C++23: Initialise as data{std::from_range_t, content}? pqxx::bytes data; for (char c : content) data.push_back(static_cast(c)); auto id{pqxx::blob::create(tx)}; auto b{pqxx::blob::open_rw(tx, id)}; b.write(std::span{data.data() + 1, 3u}); b.seek_abs(0); std::vector buf; buf.resize(4); auto out{b.read(std::span{buf.data(), 4u})}; PQXX_CHECK_EQUAL(std::size(out), 3u); PQXX_CHECK_EQUAL(byte_val(out[0]), byte_val('f')); PQXX_CHECK_EQUAL(byte_val(out[2]), byte_val('l')); } void test_blob_resize_shortens_to_desired_length(pqxx::test::context &) { pqxx::bytes const data{ std::byte{'w'}, std::byte{'o'}, std::byte{'r'}, std::byte{'k'}}; pqxx::connection cx; pqxx::work tx{cx}; auto id{pqxx::blob::from_buf(tx, data)}; pqxx::blob::open_w(tx, id).resize(2); pqxx::bytes buf; pqxx::blob::to_buf(tx, id, buf, 10); PQXX_CHECK_EQUAL(buf, (pqxx::bytes{std::byte{'w'}, std::byte{'o'}})); } void test_blob_resize_extends_to_desired_length(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; auto id{pqxx::blob::from_buf(tx, pqxx::bytes{std::byte{100}})}; pqxx::blob::open_w(tx, id).resize(3); pqxx::bytes buf; pqxx::blob::to_buf(tx, id, buf, 10); PQXX_CHECK_EQUAL( buf, (pqxx::bytes{std::byte{100}, std::byte{0}, std::byte{0}}), "Resize did not zero-extend correctly."); } void test_blob_tell_tracks_position(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; auto id{pqxx::blob::create(tx)}; auto b{pqxx::blob::open_rw(tx, id)}; PQXX_CHECK_EQUAL(b.tell(), 0); b.write(pqxx::bytes{std::byte{'e'}, std::byte{'f'}}); PQXX_CHECK_EQUAL(b.tell(), 2); b.seek_abs(1); PQXX_CHECK_EQUAL(b.tell(), 1); b.close(); PQXX_CHECK_THROWS(b.seek_abs(0), pqxx::usage_error); PQXX_CHECK_THROWS(std::ignore = b.tell(), pqxx::usage_error); } void test_blob_seek_sets_positions(pqxx::test::context &) { pqxx::bytes const data{ std::byte{0}, std::byte{1}, std::byte{2}, std::byte{3}, std::byte{4}, std::byte{5}, std::byte{6}, std::byte{7}, std::byte{8}, std::byte{9}}; pqxx::connection cx; pqxx::work tx{cx}; auto id{pqxx::blob::from_buf(tx, data)}; auto b{pqxx::blob::open_r(tx, id)}; pqxx::bytes buf; b.seek_rel(3); b.read(buf, 1u); PQXX_CHECK_EQUAL(byte_val(buf.at(0)), byte_val(3)); b.seek_abs(2); b.read(buf, 1u); PQXX_CHECK_EQUAL(byte_val(buf.at(0)), byte_val(2)); b.seek_end(-2); b.read(buf, 1u); PQXX_CHECK_EQUAL(byte_val(buf.at(0)), byte_val(8)); } void test_blob_from_buf_interoperates_with_to_buf(pqxx::test::context &) { pqxx::bytes const data{std::byte{'h'}, std::byte{'i'}}; pqxx::bytes buf; pqxx::connection cx; pqxx::work tx{cx}; pqxx::blob::to_buf(tx, pqxx::blob::from_buf(tx, data), buf, 10); PQXX_CHECK_EQUAL(buf, data); } void test_blob_append_from_buf_appends(pqxx::test::context &) { pqxx::bytes const data{std::byte{'h'}, std::byte{'o'}}; pqxx::connection cx; pqxx::work tx{cx}; auto id{pqxx::blob::create(tx)}; pqxx::blob::append_from_buf(tx, data, id); pqxx::blob::append_from_buf(tx, data, id); pqxx::bytes buf; pqxx::blob::to_buf(tx, id, buf, 10); auto expect{data}; // Infer thinks the push_back() may invalidate e!? #if defined(__cpp_lib_containers_ranges) && __cpp_lib_containers_ranges expect.append_range(data); #else for (auto const &e : data) expect.push_back(e); #endif PQXX_CHECK_EQUAL(buf, expect); } void test_blob_generic_append_from_buf_appends(pqxx::test::context &) { std::array const data{std::byte{'h'}, std::byte{'o'}}; pqxx::connection cx; pqxx::work tx{cx}; auto id{pqxx::blob::create(tx)}; pqxx::blob::append_from_buf(tx, data, id); pqxx::blob::append_from_buf(tx, data, id); pqxx::bytes buf; pqxx::blob::to_buf(tx, id, buf, 10); PQXX_CHECK_EQUAL(std::size(buf), 2 * std::size(data)); } namespace { /// Wrap `std::fopen`. /** This is just here to stop Visual Studio from advertising its own * alternative. */ std::unique_ptr my_fopen(char const *path, char const *mode) { #if defined(_MSC_VER) # pragma warning(push) # pragma warning(disable : 4996) #endif std::array buffer{}; std::unique_ptr handle{ std::fopen(path, mode), std::fclose}; if (not handle) { std::string const message{pqxx::internal::error_string(errno, buffer)}; throw std::runtime_error{ std::format("Failed to open '{}' ({}): {}.", path, mode, message)}; } return handle; #if defined(_MSC_VER) # pragma warning(pop) #endif } void read_file(char const path[], std::size_t len, pqxx::bytes &buf) { buf.resize(len); auto f{my_fopen(path, "rb")}; PQXX_CHECK(f.get() != nullptr, std::format("Did not open file '{}'!", path)); auto bytes{ std::fread(reinterpret_cast(buf.data()), 1, len, f.get())}; if (bytes == 0) throw std::runtime_error{"Error reading test file."}; buf.resize(bytes); } void write_file(char const path[], pqxx::bytes_view data) { try { auto f{my_fopen(path, "wb")}; if ( std::fwrite( reinterpret_cast(data.data()), 1, std::size(data), f.get()) < std::size(data)) throw std::runtime_error{"File write failed."}; if (std::fflush(f.get()) != 0) throw std::runtime_error{"File flush failed."}; } catch (const std::exception &) { std::ignore = std::remove(path); throw; } } /// Temporary file. class TempFile { public: TempFile() = delete; TempFile(TempFile const &) = delete; TempFile(TempFile &&) = delete; TempFile &operator=(TempFile const &) = delete; TempFile &operator=(TempFile &&) = delete; /// Create (and later clean up) a file at path containing data. TempFile(char const path[], pqxx::bytes_view data) : m_path(path) { write_file(path, data); } ~TempFile() { std::ignore = std::remove(m_path.c_str()); } private: std::string m_path; }; } // namespace void test_blob_from_file_creates_blob_from_file_contents( pqxx::test::context &tctx) { std::string const temp_file = tctx.make_name("pqxx-blob"); pqxx::bytes const data{std::byte{'4'}, std::byte{'2'}}; pqxx::connection cx; pqxx::work tx{cx}; pqxx::bytes buf; pqxx::oid id{}; { TempFile const f{temp_file.c_str(), data}; id = pqxx::blob::from_file(tx, std::data(temp_file)); } pqxx::blob::to_buf(tx, id, buf, 10); PQXX_CHECK_EQUAL(buf, data); } void test_blob_from_file_with_oid_writes_blob(pqxx::test::context &tctx) { pqxx::bytes const data{std::byte{'6'}, std::byte{'9'}}; std::string const temp_file = tctx.make_name("pqxx-blob"); pqxx::bytes buf; pqxx::connection cx; pqxx::work tx{cx}; // Guarantee (more or less) that id is not in use. auto id{pqxx::blob::create(tx)}; pqxx::blob::remove(tx, id); { TempFile const f{temp_file.c_str(), data}; pqxx::blob::from_file(tx, std::data(temp_file), id); } pqxx::blob::to_buf(tx, id, buf, 10); PQXX_CHECK_EQUAL(buf, data); } void test_blob_append_to_buf_appends(pqxx::test::context &) { pqxx::bytes const data{ std::byte{'b'}, std::byte{'l'}, std::byte{'u'}, std::byte{'b'}}; pqxx::connection cx; pqxx::work tx{cx}; auto id{pqxx::blob::from_buf(tx, data)}; pqxx::bytes buf; PQXX_CHECK_EQUAL(pqxx::blob::append_to_buf(tx, id, 0u, buf, 1u), 1u); PQXX_CHECK_EQUAL(std::size(buf), 1u); PQXX_CHECK_EQUAL(pqxx::blob::append_to_buf(tx, id, 1u, buf, 5u), 3u); PQXX_CHECK_EQUAL(std::size(buf), 4u); PQXX_CHECK_EQUAL(buf, data); } void test_blob_to_file_writes_file(pqxx::test::context &tctx) { pqxx::bytes const data{std::byte{'C'}, std::byte{'+'}, std::byte{'+'}}; std::string const temp_file = tctx.make_name("blob-test"); pqxx::connection cx; pqxx::work tx{cx}; auto id{pqxx::blob::from_buf(tx, data)}; pqxx::bytes buf; try { pqxx::blob::to_file(tx, id, temp_file); read_file(temp_file.c_str(), 10u, buf); std::ignore = std::remove(temp_file.c_str()); } catch (std::exception const &) { std::ignore = std::remove(temp_file.c_str()); throw; } PQXX_CHECK_EQUAL(buf, data); } void test_blob_close_leaves_blob_unusable(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; auto id{pqxx::blob::from_buf(tx, pqxx::bytes{std::byte{1}})}; auto b{pqxx::blob::open_rw(tx, id)}; b.close(); pqxx::bytes buf; PQXX_CHECK_THROWS(b.read(buf, 1), pqxx::usage_error); } PQXX_REGISTER_TEST(test_blob_is_useless_by_default); PQXX_REGISTER_TEST(test_blob_create_makes_empty_blob); PQXX_REGISTER_TEST(test_blob_create_with_oid_requires_oid_be_free); PQXX_REGISTER_TEST(test_blob_create_with_oid_obeys_oid); PQXX_REGISTER_TEST(test_blobs_are_transactional); PQXX_REGISTER_TEST(test_blob_remove_removes_blob); PQXX_REGISTER_TEST(test_blob_remove_is_not_idempotent); PQXX_REGISTER_TEST(test_blob_checks_open_mode); PQXX_REGISTER_TEST(test_blob_supports_move); PQXX_REGISTER_TEST(test_blob_read_reads_data); PQXX_REGISTER_TEST(test_blob_read_reads_generic_data); PQXX_REGISTER_TEST(test_blob_reads_vector); PQXX_REGISTER_TEST(test_blob_read_span); PQXX_REGISTER_TEST(test_blob_write_appends_at_insertion_point); PQXX_REGISTER_TEST(test_blob_writes_span); PQXX_REGISTER_TEST(test_blob_resize_shortens_to_desired_length); PQXX_REGISTER_TEST(test_blob_resize_extends_to_desired_length); PQXX_REGISTER_TEST(test_blob_tell_tracks_position); PQXX_REGISTER_TEST(test_blob_seek_sets_positions); PQXX_REGISTER_TEST(test_blob_from_buf_interoperates_with_to_buf); PQXX_REGISTER_TEST(test_blob_append_from_buf_appends); PQXX_REGISTER_TEST(test_blob_generic_append_from_buf_appends); PQXX_REGISTER_TEST(test_blob_from_file_creates_blob_from_file_contents); PQXX_REGISTER_TEST(test_blob_from_file_with_oid_writes_blob); PQXX_REGISTER_TEST(test_blob_append_to_buf_appends); PQXX_REGISTER_TEST(test_blob_to_file_writes_file); PQXX_REGISTER_TEST(test_blob_close_leaves_blob_unusable); } // namespace libpqxx-8.0.1/test/test_cancel_query.cxx000066400000000000000000000010561516427024100204270ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { void test_cancel_query(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; // Calling cancel_query() while none is in progress has no effect. cx.cancel_query(); // Nothing much is guaranteed about cancel_query, except that it doesn't make // the process die in flames. pqxx::pipeline p{tx, "test_cancel_query"}; p.retain(0); p.insert("SELECT pg_sleep(1)"); cx.cancel_query(); } PQXX_REGISTER_TEST(test_cancel_query); } // namespace libpqxx-8.0.1/test/test_column.cxx000066400000000000000000000027561516427024100172620ustar00rootroot00000000000000#include #include "helpers.hxx" namespace { void test_table_column(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; tx.exec("CREATE TEMP TABLE pqxxfoo (x varchar, y integer, z integer)") .no_rows(); tx.exec("INSERT INTO pqxxfoo VALUES ('xx', 1, 2)").no_rows(); auto R{tx.exec("SELECT z,y,x FROM pqxxfoo")}; auto X{tx.exec("SELECT x,y,z,99 FROM pqxxfoo")}; pqxx::row::size_type x{R.table_column(2)}, y{R.table_column(1)}, z{R.table_column(static_cast(0))}; PQXX_CHECK_EQUAL(x, 0); PQXX_CHECK_EQUAL(y, 1); PQXX_CHECK_EQUAL(z, 2); x = R.table_column("x"); y = R.table_column("y"); z = R.table_column("z"); PQXX_CHECK_EQUAL(x, 0); PQXX_CHECK_EQUAL(y, 1); PQXX_CHECK_EQUAL(z, 2); pqxx::row::size_type const xx{X[0].table_column(static_cast(0))}, yx{X[0].table_column(pqxx::row::size_type(1))}, zx{X[0].table_column("z")}; PQXX_CHECK_EQUAL(xx, 0, "Bad result from table_column(int)."); PQXX_CHECK_EQUAL(yx, 1, "Bad result from table_column(size_type)."); PQXX_CHECK_EQUAL(zx, 2, "Bad result from table_column(string)."); for (pqxx::row::size_type i{0}; i < std::size(R[0]); ++i) PQXX_CHECK_EQUAL(R[0][i].table_column(), R.table_column(i)); [[maybe_unused]] int col{}; PQXX_CHECK_THROWS_EXCEPTION(col = R.table_column(3)); PQXX_CHECK_THROWS_EXCEPTION(col = R.table_column("nonexistent")); PQXX_CHECK_THROWS_EXCEPTION(col = X.table_column(3)); } } // namespace PQXX_REGISTER_TEST(test_table_column); libpqxx-8.0.1/test/test_composite.cxx000066400000000000000000000064701516427024100177640ustar00rootroot00000000000000#include "helpers.hxx" #include "pqxx/composite" #include "pqxx/transaction" namespace { pqxx::conversion_context make_context( pqxx::encoding_group enc = pqxx::encoding_group::ascii_safe, pqxx::sl loc = pqxx::sl::current()) { return pqxx::conversion_context{enc, loc}; } void test_composite(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; tx.exec("CREATE TYPE pqxxfoo AS (a integer, b text)").no_rows(); auto const f{tx.exec("SELECT '(5,hello)'::pqxxfoo").one_field()}; int a{}; std::string b; pqxx::parse_composite(make_context(), f.view(), a, b); PQXX_CHECK_EQUAL(a, 5); PQXX_CHECK_EQUAL(b, "hello"); } void test_composite_escapes(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; tx.exec("CREATE TYPE pqxxsingle AS (x text)").no_rows(); std::string s; pqxx::row r; r = tx.exec(R"--(SELECT '("a""b")'::pqxxsingle)--").one_row(); pqxx::parse_composite(make_context(), r[0].view(), s); PQXX_CHECK_EQUAL( s, "a\"b", "Double-double-quotes escaping did not parse correctly."); r = tx.exec(R"--(SELECT '("a\"b")'::pqxxsingle)--").one_row(); pqxx::parse_composite(make_context(), r[0].view(), s); PQXX_CHECK_EQUAL(s, "a\"b", "Backslash escaping did not parse correctly."); } void test_composite_handles_nulls(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::row r; tx.exec("CREATE TYPE pqxxnull AS (a integer)").no_rows(); int nonnull{}; r = tx.exec("SELECT '()'::pqxxnull").one_row(); PQXX_CHECK_THROWS( pqxx::parse_composite(make_context(), r[0].view(), nonnull), pqxx::conversion_error); std::optional nullable{5}; pqxx::parse_composite(make_context(), r[0].view(), nullable); PQXX_CHECK(not nullable.has_value()); tx.exec("CREATE TYPE pqxxnulls AS (a integer, b integer)").no_rows(); std::optional a{2}, b{4}; r = tx.exec("SELECT '(,)'::pqxxnulls").one_row(); pqxx::parse_composite(make_context(), r[0].view(), a, b); PQXX_CHECK(not a.has_value()); PQXX_CHECK(not b.has_value()); } void test_composite_renders_to_string(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; char buf[1000]; PQXX_CHECK_EQUAL( pqxx::composite_into_buf(make_context(), buf, 355, "foo", "b\na\\r"), "(355,\"foo\",\"b\na\\\\r\")"); tx.exec("CREATE TYPE pqxxcomp AS (a integer, b text, c text)").no_rows(); auto const f{ tx.exec("SELECT '" + std::string{std::data(buf)} + "'::pqxxcomp") .one_field()}; int a{}; std::string b, c; bool const nonnull{f.composite_to(a, b, c)}; PQXX_CHECK(nonnull); PQXX_CHECK_EQUAL(a, 355); PQXX_CHECK_EQUAL(b, "foo"); PQXX_CHECK_EQUAL(c, "b\na\\r"); PQXX_CHECK_EQUAL( nonnull, f.composite_to(pqxx::sl::current(), a, b, c), "field::composite_to() with source_location is different!?"); } void test_composite_can_contain_arrays(pqxx::test::context &) { std::array buf{}; std::vector const strings{"a", "b"}; auto const text{pqxx::composite_into_buf(make_context(), buf, 123, strings)}; PQXX_CHECK_EQUAL(text, ("(123,\"{\\\"a\\\",\\\"b\\\"}\")")); } PQXX_REGISTER_TEST(test_composite); PQXX_REGISTER_TEST(test_composite_escapes); PQXX_REGISTER_TEST(test_composite_handles_nulls); PQXX_REGISTER_TEST(test_composite_renders_to_string); PQXX_REGISTER_TEST(test_composite_can_contain_arrays); } // namespace libpqxx-8.0.1/test/test_connection.cxx000066400000000000000000000314611516427024100201170ustar00rootroot00000000000000#include #include #include #include "helpers.hxx" namespace { void test_connection_string_constructor(pqxx::test::context &) { pqxx::connection const c1{""}; PQXX_CHECK(c1.is_open()); pqxx::connection const c2{std::string{}}; PQXX_CHECK(c2.is_open()); pqxx::connection const c3{pqxx::zview{""}}; PQXX_CHECK(c3.is_open()); } void test_move_constructor(pqxx::test::context &) { pqxx::connection c1; PQXX_CHECK(c1.is_open()); pqxx::connection c2{std::move(c1)}; // Checking for predictable state of an object after its state has been // moved out... clang-tidy doesn't like this. PQXX_CHECK(not c1.is_open()); // NOLINT PQXX_CHECK(c2.is_open()); pqxx::work tx{c2}; PQXX_CHECK_EQUAL(tx.query_value("SELECT 5"), 5); PQXX_CHECK_THROWS(pqxx::connection{std::move(c2)}, pqxx::usage_error); } void test_move_assign(pqxx::test::context &) { pqxx::connection c1; pqxx::connection c2; c2.close(); c2 = std::move(c1); PQXX_CHECK(not c1.is_open()); // NOLINT PQXX_CHECK(c2.is_open()); { pqxx::work tx1{c2}; PQXX_CHECK_EQUAL(tx1.query_value("SELECT 8"), 8, "What!?"); pqxx::connection c3; PQXX_CHECK_THROWS(c1 = std::move(c2), pqxx::usage_error); PQXX_CHECK_THROWS(c2 = std::move(c3), pqxx::usage_error); } // After failed move attempts, the connection is still usable. pqxx::work tx2{c2}; PQXX_CHECK_EQUAL(tx2.query_value("SELECT 6"), 6, "Huh!?"); } void test_encrypt_password(pqxx::test::context &) { pqxx::connection c; auto pw{c.encrypt_password("user", "password")}; PQXX_CHECK(not std::empty(pw)); PQXX_CHECK_EQUAL( std::strlen(pw.c_str()), std::size(pw), "Encrypted password contains a null byte."); } void test_connection_string(pqxx::test::context &) { pqxx::connection const c; std::string const connstr{c.connection_string()}; #if defined(_MSC_VER) # pragma warning(push) # pragma warning(disable : 4996) #endif if (std::getenv("PGUSER") == nullptr) #if defined(_MSC_VER) # pragma warning(pop) #endif { PQXX_CHECK( pqxx::str_contains(connstr, "user=" + std::string{c.username()}), "Connection string did not specify user name: " + connstr); } else { PQXX_CHECK( not pqxx::str_contains(connstr, "user=" + std::string{c.username()}), "Connection string specified user name, even when using default: " + connstr); } } template std::size_t length(STR const &str) { return std::size(str); } template void test_params_type() { using item_t = std::remove_reference_t< decltype(*std::declval>())>; using key_t = decltype(std::get<0>(std::declval())); using value_t = decltype(std::get<1>(std::declval())); // Set some parameters that are relatively safe to change arbitrarily. MAP const params{{ {key_t{"application_name"}, value_t{"pqxx-test"}}, {key_t{"connect_timeout"}, value_t{"96"}}, {key_t{"keepalives_idle"}, value_t{"771"}}, }}; // Can we create a connection from these parameters? pqxx::connection const c{params}; // Check that the parameters came through in the connection string. // We don't know the exact format, but the parameters have to be in there. auto const connstr{c.connection_string()}; // for (auto const &[key, value] : params) for (auto it{params.cbegin()}; it != params.cend(); ++it) { // Normally we'd use structured binding for this, but Facebook Infer // reports an insane false positive error when we do. auto const &key{std::get<0>(*it)}; auto const value{std::get<1>(*it)}; PQXX_CHECK( pqxx::str_contains(connstr, key), std::format( "Could not find param name '{}' in connection string: {}", std::string{key}, connstr)); PQXX_CHECK( pqxx::str_contains(connstr, value), std::format( "Could not find value for '{}' in connection string: ", std::string{value}, connstr)); } } void test_connection_params(pqxx::test::context &) { // Connecting in this way supports a wide variety of formats for the // parameters. test_params_type>(); test_params_type>(); test_params_type>(); test_params_type>(); test_params_type>(); test_params_type>>(); test_params_type>>(); test_params_type>>(); test_params_type>>(); } void test_raw_connection(pqxx::test::context &) { pqxx::connection conn1; PQXX_CHECK(conn1.is_open()); pqxx::nontransaction tx1{conn1}; PQXX_CHECK_EQUAL(tx1.query_value("SELECT 8"), 8); // Checking for predictable bewhaviour of a dead object after move. // clang-tidy doesn't like this. pqxx::internal::pq::PGconn *raw{std::move(conn1).release_raw_connection()}; PQXX_CHECK(raw != nullptr); // NOLINT PQXX_CHECK(not conn1.is_open()); // NOLINT pqxx::connection conn2{pqxx::connection::seize_raw_connection(raw)}; PQXX_CHECK(conn2.is_open()); pqxx::nontransaction tx2{conn2}; PQXX_CHECK_EQUAL(tx2.query_value("SELECT 9"), 9); } void test_closed_connection(pqxx::test::context &) { pqxx::connection cx; cx.close(); PQXX_CHECK(not cx.dbname()); PQXX_CHECK(not cx.username()); PQXX_CHECK(not cx.hostname()); #include PQXX_CHECK(not cx.port()); #include PQXX_CHECK_EQUAL(cx.port_number(), (std::optional{})); } void test_skip_init_ssl(pqxx::test::context &) { pqxx::skip_init_ssl(); pqxx::skip_init_ssl(); } void test_connection_client_encoding(pqxx::test::context &tctx) { pqxx::connection cx; std::map const unsafe_encodings = { {"BIG5", pqxx::encoding_group::two_tier}, {"GBK", pqxx::encoding_group::gb18030}, {"GB18030", pqxx::encoding_group::gb18030}, {"SJIS", pqxx::encoding_group::sjis}, {"SHIFT_JIS_2004", pqxx::encoding_group::sjis}, // Not actually ASCII-safe, but just close enough for our purposes. {"UHC", pqxx::encoding_group::ascii_safe}, }; for (auto const &[name, enc] : unsafe_encodings) { cx.set_client_encoding(name); PQXX_CHECK_EQUAL(cx.get_encoding_group(), enc); } std::vector const safe_encodings{ "EUC_CN", "EUC_JIS_2004", "EUC_JP", "EUC_KR", "EUC_TW", "ISO_8859_5", "ISO_8859_6", "ISO_8859_7", "ISO_8859_8", "KOI8R", "KOI8U", "LATIN1", "LATIN2", "LATIN3", "LATIN4", "LATIN5", "LATIN6", "LATIN7", "LATIN8", "LATIN9", "LATIN10", // For some reason setting this fails. // "MULE_INTERNAL", "SQL_ASCII", "UTF8", "WIN866", "WIN874", "WIN1250", "WIN1251", "WIN1252", "WIN1253", "WIN1254", "WIN1255", "WIN1256", "WIN1257", "WIN1258", }; for (char const *const e : safe_encodings) { cx.set_client_encoding(e); PQXX_CHECK_EQUAL( cx.get_encoding_group(), pqxx::encoding_group::ascii_safe, std::format("Unexpected encoding group for '{}'.", e)); } // Covering lots of initial letters because it helps fill out test // coverage on an internal switch on that initial character. static std::vector const bogus_encodings{ "ABSENT", "BOGUS", "ELUSIVE", "GONE", "ILLUSORY", "JOCULAR", "KIBOSHED", "LOST", // Actually, MULE really is a mystery because the connection does not // seem to accept it. "MYSTERY", "SHREDDED", "UNAVAILABLE", "WANTING", }; for (char const *const e : bogus_encodings) PQXX_CHECK_THROWS(cx.set_client_encoding(e), pqxx::failure); for (int i{0}; i < 10; ++i) { std::string fake_encoding{tctx.random_char()}; PQXX_CHECK_THROWS(cx.set_client_encoding(fake_encoding), pqxx::failure); } for (char e{'A'}; e <= 'Z'; ++e) PQXX_CHECK_THROWS(cx.set_client_encoding(std::string{e}), pqxx::failure); // We no longer support this encoding. It turned out to be broken in // postgres itself. PQXX_CHECK_THROWS(cx.set_client_encoding("JOHAB"), pqxx::argument_error); } /// Simple check: does `cx` work? void check_connection_works(pqxx::connection &cx, pqxx::test::context &tctx) { pqxx::work tx{cx}; int const value{tctx.make_num()}; PQXX_CHECK_EQUAL(tx.query_value("SELECT $1", {value}), value); } void test_connection_takes_string_and_params(pqxx::test::context &tctx) { int const timeout{tctx.make_num(10) + 5}; std::string const appname{tctx.make_name()}; pqxx::connection cx{ std::format("connect_timeout={}", timeout), std::map{{"application_name", appname}}}; check_connection_works(cx, tctx); // The connection combines settings from both the connection string and the // parameters map. auto const connstr{cx.connection_string()}; PQXX_CHECK(pqxx::str_contains(connstr, "application_name")); PQXX_CHECK(pqxx::str_contains(connstr, appname)); PQXX_CHECK( pqxx::str_contains(connstr, std::format("connect_timeout={}", timeout))); } void test_connection_params_override_string(pqxx::test::context &tctx) { auto const first{tctx.make_name("1")}, second{tctx.make_name("2")}; pqxx::connection cx{ std::format("application_name={}", first), std::map{{"application_name", second}}}; check_connection_works(cx, tctx); auto const connstr{cx.connection_string()}; PQXX_CHECK(not pqxx::str_contains(connstr, first)); PQXX_CHECK(pqxx::str_contains(connstr, second)); } void test_connection_takes_string_and_empty_params(pqxx::test::context &tctx) { auto const appname{tctx.make_name()}; pqxx::connection cx{std::format("application_name={}", appname)}; check_connection_works(cx, tctx); PQXX_CHECK(pqxx::str_contains(cx.connection_string(), appname)); } void test_connection_takes_empty_string_and_params(pqxx::test::context &tctx) { auto const appname{tctx.make_name()}; pqxx::connection cx{ "", std::map{ {"application_name", appname}}}; check_connection_works(cx, tctx); PQXX_CHECK(pqxx::str_contains(cx.connection_string(), appname)); } void test_connection_takes_empty_string_and_empty_params( pqxx::test::context &tctx) { pqxx::connection cx{"", std::map{}}; check_connection_works(cx, tctx); } void test_connection_rejects_bad_string(pqxx::test::context &tctx) { PQXX_CHECK_THROWS( (pqxx::connection{tctx.make_name(), std::map{}}), pqxx::broken_connection); } void test_connection_duplicate_params_overwrite(pqxx::test::context &tctx) { auto const name1{tctx.make_name()}, name2{tctx.make_name()}; // Use a vector here, not a map, so that we're really passing multiple // parameters with identical keys to the connection. std::vector> const args{ {"application_name", name1}, {"connect_timeout", "1"}, {"application_name", name2}, }; pqxx::connection const cx{"", args}; auto const connstr{cx.connection_string()}; PQXX_CHECK(not pqxx::str_contains(connstr, name1)); PQXX_CHECK(pqxx::str_contains(connstr, name2)); } void test_quote_columns_quotes_and_escapes(pqxx::test::context &) { pqxx::connection const cx; PQXX_CHECK_EQUAL(cx.quote_columns(std::array{}), ""); PQXX_CHECK_EQUAL( cx.quote_columns(std::vector{"col"}), "\"col\""); std::string_view const doub[]{"aa", "bb"}; PQXX_CHECK_EQUAL(cx.quote_columns(doub), "\"aa\",\"bb\""); PQXX_CHECK_EQUAL( cx.quote_columns(std::vector{"a\"b"}), "\"a\"\"b\""); } PQXX_REGISTER_TEST(test_connection_string_constructor); PQXX_REGISTER_TEST(test_move_constructor); PQXX_REGISTER_TEST(test_move_assign); PQXX_REGISTER_TEST(test_encrypt_password); PQXX_REGISTER_TEST(test_connection_string); PQXX_REGISTER_TEST(test_connection_params); PQXX_REGISTER_TEST(test_raw_connection); PQXX_REGISTER_TEST(test_closed_connection); PQXX_REGISTER_TEST(test_skip_init_ssl); PQXX_REGISTER_TEST(test_connection_client_encoding); PQXX_REGISTER_TEST(test_quote_columns_quotes_and_escapes); PQXX_REGISTER_TEST(test_connection_takes_string_and_params); PQXX_REGISTER_TEST(test_connection_params_override_string); PQXX_REGISTER_TEST(test_connection_takes_string_and_empty_params); PQXX_REGISTER_TEST(test_connection_takes_empty_string_and_params); PQXX_REGISTER_TEST(test_connection_takes_empty_string_and_empty_params); PQXX_REGISTER_TEST(test_connection_rejects_bad_string); PQXX_REGISTER_TEST(test_connection_duplicate_params_overwrite); } // namespace libpqxx-8.0.1/test/test_connection_string.cxx000066400000000000000000000136071516427024100215070ustar00rootroot00000000000000#include #include "helpers.hxx" namespace { constexpr std::string_view const marker{"application_name="}; /// Connect to the database, passing `app_name` for its `application_name`. /** Does not do any quoting or escaping. The caller will have to do that. */ pqxx::connection connect(std::string const &app_name) { return pqxx::connection(std::string{marker} + app_name); } /// Extract the application name from a connection's connection string. /** Does not do any un-escaping, does not remove quotes. This is deliberate. * * Also does not handle much in the way of weird inputs. It just looks for * the first instance of "application_name=" and goes from there. This is * because I'm lazy and I see no substantial security risks in this. */ std::string app_name(pqxx::connection const &cx) { std::string const &all{cx.connection_string()}; auto const intro{all.find(marker)}; auto const start{intro + std::size(marker)}; if (start == std::string::npos or all.at(start) == ' ') return ""; std::size_t here{start}, end{}; if (all.at(here) == '\'') { // Quoted string. ++here; for (bool esc{false}; (here < std::size(all)) and ((all.at(here) != '\'') or esc); ++here) esc = (all.at(here) == '\\' and not esc); assert(here < std::size(all)); assert(all.at(here) == '\''); // Skip closing quote. end = here + 1; } else { // Simple string. Just stop at the next space, or end of string. // This find() can return npos, but that's fine here. end = all.find(' ', start); } return all.substr(start, end - start); } void check_connect_string(std::string const &in, std::string const &expected) { auto cx{connect(in)}; PQXX_CHECK_EQUAL(app_name(cx), expected); // Check that connection_string() produced a valid, more or less equivalent // connection string. pqxx::connection{cx.connection_string()}; } void test_connection_string_escapes(pqxx::test::context &) { check_connect_string("pqxxtest", "pqxxtest"); check_connect_string("'hello'", "hello"); check_connect_string("'a b c'", "'a b c'"); check_connect_string("'x \\\\y'", "'x \\\\y'"); // TODO: Use raw strings once Visual Studio copes with backslashes there. // NOLINTNEXTLINE(modernize-raw-string-literal) check_connect_string("\\\\r\\\\n", "\\\\r\\\\n"); // This does seem to get quoted, even though as I read the spec, that's not // actually required because there's no space in it. check_connect_string("don\\'t", "'don\\'t'"); } /// Convenience alias for a long, long name. using parser = pqxx::internal::connection_string_parser; void test_connection_string_parser_accepts_empty_string(pqxx::test::context &) { parser const p{""}; auto const [keys, values]{p.parse()}; PQXX_CHECK(keys.empty()); PQXX_CHECK(values.empty()); } void test_connection_string_parser_accepts_connection_string( pqxx::test::context &tctx) { int const timeout{tctx.make_num(10) + 5}; parser const p{std::format("connect_timeout={}", timeout).c_str()}; auto const [keys, values]{p.parse()}; PQXX_CHECK_EQUAL(std::size(keys), std::size(values)); PQXX_CHECK_EQUAL(std::size(keys), 1u); PQXX_CHECK_EQUAL(std::string{keys.at(0)}, "connect_timeout"); PQXX_CHECK_EQUAL(pqxx::from_string(values.at(0)), timeout); } void test_connection_string_parser_deduplicates(pqxx::test::context &tctx) { auto const name1{tctx.make_name()}, name2{tctx.make_name()}; parser const p{ std::format("application_name={} application_name={}", name1, name2) .c_str()}; auto const [keys, values]{p.parse()}; PQXX_CHECK_EQUAL(std::size(keys), std::size(values)); PQXX_CHECK_EQUAL(std::size(keys), 1u); PQXX_CHECK_EQUAL((std::string{keys.at(0)}), "application_name"); PQXX_CHECK_EQUAL((std::string{values.at(0)}), name2); } void test_connection_string_parser_unquotes(pqxx::test::context &) { parser const p1{"application_name='q u o t e d'"}; auto const [k1, v1]{p1.parse()}; PQXX_CHECK_EQUAL(std::size(k1), 1u); PQXX_CHECK_EQUAL(std::string{v1.at(0)}, "q u o t e d"); } void test_connection_string_parser_unescapes(pqxx::test::context &) { parser const p1{"application_name=can\\'t"}; auto const [k1, v1]{p1.parse()}; PQXX_CHECK_EQUAL(std::size(k1), 1u); PQXX_CHECK_EQUAL(std::string{v1.at(0)}, "can't"); } void test_connection_string_can_be_zview(pqxx::test::context &) { pqxx::connection const cx_without_params{pqxx::zview{}}; PQXX_CHECK(cx_without_params.is_open()); pqxx::connection const cx_with_params{ pqxx::zview{}, std::array, 1u>{ {{"connect_timeout", "5"}}}}; PQXX_CHECK(cx_with_params.is_open()); } void test_connection_string_can_be_c_string(pqxx::test::context &) { pqxx::connection const cx_without_params{""}; PQXX_CHECK(cx_without_params.is_open()); pqxx::connection const cx_with_params{ "", std::array, 1u>{ {{"connect_timeout", "5"}}}}; PQXX_CHECK(cx_with_params.is_open()); } void test_connection_string_can_be_string(pqxx::test::context &) { pqxx::connection const cx_without_params{std::string{}}; PQXX_CHECK(cx_without_params.is_open()); pqxx::connection const cx_with_params{ std::string{}, std::array, 1u>{ {{"connect_timeout", "5"}}}}; PQXX_CHECK(cx_with_params.is_open()); } PQXX_REGISTER_TEST(test_connection_string_escapes); PQXX_REGISTER_TEST(test_connection_string_parser_accepts_empty_string); PQXX_REGISTER_TEST(test_connection_string_parser_accepts_connection_string); PQXX_REGISTER_TEST(test_connection_string_parser_deduplicates); PQXX_REGISTER_TEST(test_connection_string_parser_unquotes); PQXX_REGISTER_TEST(test_connection_string_parser_unescapes); PQXX_REGISTER_TEST(test_connection_string_can_be_zview); PQXX_REGISTER_TEST(test_connection_string_can_be_c_string); PQXX_REGISTER_TEST(test_connection_string_can_be_string); } // namespace libpqxx-8.0.1/test/test_cursor.cxx000066400000000000000000000037551516427024100173020ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { void test_stateless_cursor_provides_random_access(pqxx::connection &cx) { pqxx::work tx{cx}; pqxx::stateless_cursor< pqxx::cursor_base::read_only, pqxx::cursor_base::owned> c{tx, "SELECT * FROM generate_series(0, 3)", "count", false}; auto r{c.retrieve(1, 2)}; PQXX_CHECK_EQUAL(std::size(r), 1); PQXX_CHECK_EQUAL(r[0][0].as(), 1); r = c.retrieve(3, 10); PQXX_CHECK_EQUAL(std::size(r), 1, "Expected 1 row retrieving past end."); PQXX_CHECK_EQUAL(r[0][0].as(), 3); r = c.retrieve(0, 1); PQXX_CHECK_EQUAL(std::size(r), 1); PQXX_CHECK_EQUAL(r[0][0].as(), 0); } void test_stateless_cursor_ignores_trailing_semicolon(pqxx::connection &cx) { pqxx::work tx{cx}; pqxx::stateless_cursor< pqxx::cursor_base::read_only, pqxx::cursor_base::owned> c{tx, "SELECT * FROM generate_series(0, 3) ;; ; \n \t ", "count", false}; auto r{c.retrieve(1, 2)}; PQXX_CHECK_EQUAL(std::size(r), 1, "Trailing semicolon confused retrieve()."); } void test_cursor(pqxx::test::context &) { pqxx::connection cx; test_stateless_cursor_provides_random_access(cx); test_stateless_cursor_ignores_trailing_semicolon(cx); } void test_cursor_constants(pqxx::test::context &tctx) { PQXX_CHECK_GREATER(pqxx::cursor_base::all(), tctx.make_num()); PQXX_CHECK_LESS(pqxx::cursor_base::backward_all(), -tctx.make_num()); } void test_icursorstream_tracks_creation_location(pqxx::test::context &) { std::source_location const loc{pqxx::sl::current()}; pqxx::connection cx; pqxx::work tx{cx}; pqxx::icursorstream const s{ tx, "SELECT * FROM generate_series(1, 3)", "mycur", 1, loc}; PQXX_CHECK_EQUAL( std::string{s.created_loc().file_name()}, std::string{loc.file_name()}); PQXX_CHECK_EQUAL(s.created_loc().line(), loc.line()); } PQXX_REGISTER_TEST(test_cursor); PQXX_REGISTER_TEST(test_cursor_constants); PQXX_REGISTER_TEST(test_icursorstream_tracks_creation_location); } // namespace libpqxx-8.0.1/test/test_encodings.cxx000066400000000000000000000156671516427024100177430ustar00rootroot00000000000000/** In this test module we'll be searching for the ASCII character '|' in * strings in various encodings. * * This gets interesting in the one scenario where we actually need to know * about the text's encoding: if a multibyte character contains a byte whose * numerical value happens to be the same as that of the ASCII character we're * trying to find. * * The '|' (pipe) character was chosen because it _can_ occur as a trail byte * in all of the supported non-ASCII-safe encodings, with the exception of * UHC, where letters are the only ASCII trail bytes allowed. We don't permit * searching for ASCII letters for exactly that reason: with a guarantee that * we won't be searching for ASCII letters, it's safe to treat UHC as if it * were ASCII-safe as well. */ #include "helpers.hxx" #include "pqxx/internal/encodings.hxx" namespace { using namespace std::literals; /// Convenience shorthand: `std::source_location::current()`. pqxx::sl loc(pqxx::sl l = pqxx::sl::current()) { return l; } /// A simple test text, no special tricks. /** The text is "My hovercraft is full of eels" translated to various * languages using Google Translate, and encoded in the respective encoding * groups. */ template std::string_view const eels; /// Big5: Traditional Chinese. template<> auto const eels{ "\xa7\xda\xaa\xba\xae\xf0\xb9\xd4\xb2\xee\xb8\xcc\xa5\xfe\xac\x4f\xc5\xc1" "\xb3\xbd"sv}; /// ASCII-safe: German. template<> auto const eels{ "Mein Luftkissenfahrzeug ist voll mit Aalen."sv}; /// GB18030: Simplified Chinese. template<> auto const eels{ "\xce\xd2\xb5\xc4\xc6\xf8\xb5\xe6\xb4\xac\xc0\xef\xd7\xb0\xc2\xfa\xc1\xcb" "\xf7\xa9\xd3\xe3\xa1\xa3"sv}; /// SJIS: Japanese. template<> auto const eels{ "\x8e\x84\x82\xcc\x83\x7a\x83\x6f\x81\x5b\x83\x4e\x83\x89\x83\x74\x83\x67" "\x82\xcd\x83\x45\x83\x69\x83\x4d\x82\xc5\x82\xa2\x82\xc1\x82\xcf\x82\xa2" "\x82\xc5\x82\xb7"sv}; /// A tricky test text. /** These represent multibyte characters in various encodings which happen to * contain a byte with the same numeric value as the ASCII pipe symbol, '|'. */ template std::string_view const tricky; template<> auto const tricky{"\xa1|"sv}; // (Yeah such a string is not possible here.) template<> auto const tricky{"\x81|"sv}; template<> auto const tricky{"\x81|"sv}; /// Test basic sanity of search in encoding group `ENC`. /** Searches test texts for first occurrence of '.' (a dot). * * Ensure that the text does not contain the ASCII _character_ '.'. However, * it may contain the _byte value_ for that character. In fact it makes the * test stronger and more useful. * * The texts are both `eels` and `tricky` for each of the encodings. */ template void test_search(std::string_view enc_name) { auto const finder{pqxx::internal::get_char_finder<'|'>(ENC, loc())}; // First, we do some generic tests on ASCII strings. All supported // encodings are ASCII supersets, so a plain ASCII string is valid and // correct in each of them. PQXX_CHECK_EQUAL( finder("", 0, loc()), 0u, std::format("Empty string search ({}) went out of bounds.", enc_name)); PQXX_CHECK_EQUAL( finder("|||", 0, loc()), 0u, std::format( "Search on ASCII string ({}) missed starting char.", enc_name)); PQXX_CHECK_EQUAL( finder("|||", 1, loc()), 1u, std::format( "Search ({}) at non-zero offset ended in the wrong place.", enc_name)); PQXX_CHECK_EQUAL( finder("abcd", 0, loc()), 4u, std::format( "Search ({}) for absent character in ASCII string went wrong.", enc_name)); // Now try searching a text that actually uses ENC. First a failing search, // since the text does not contain the character we're looking for: PQXX_CHECK_EQUAL( finder(eels, 0, loc()), std::size(eels), "Search for absent character did not hit end."); // Then, a successful search. PQXX_CHECK_EQUAL( finder(std::string{eels} + "|nn", 0, loc()), std::size(eels), "False negative on search."); // Finally, we perform similar searches but for the tricky strings which // contain a byte with value 0x7c ("|") inside a multibyte character. The // search should ignore that embedded byte. PQXX_CHECK_EQUAL( finder(tricky, 0, loc()), std::size(tricky), "Looks like we fell for an embedded '|' byte."); // Then, a successful search. PQXX_CHECK_EQUAL( finder(std::string{tricky} + "|nn", 0, loc()), std::size(tricky), "Did not find '|' after string with embedded '|' byte."); } void test_find_chars(pqxx::test::context &) { test_search("big5"); test_search("ascii_safe"); test_search("gb18030"); test_search("sjis"); } template void check_unfinished_character() { auto const finder{pqxx::internal::get_char_finder<'|'>(ENC, loc())}; // This happens to be an incomplete character in all supported non-ASCII-safe // encodings. PQXX_CHECK_THROWS(finder("\x81", 0, loc()), pqxx::argument_error); } void test_find_chars_fails_for_unfinished_character(pqxx::test::context &) { check_unfinished_character(); check_unfinished_character(); check_unfinished_character(); } template auto find_x(std::array const &data, pqxx::encoding_group enc) { auto const find{pqxx::internal::get_char_finder<'|'>(enc, loc())}; std::string_view const buf{std::data(data), N}; return find(buf, 0u, loc()); } void test_find_chars_reports_malencoded_text(pqxx::test::context &tctx) { // Set up an array containing random char values, but not '|'. // // We really need an amazingly large array here, since our encoding support // is only designed to detect structural problems, not invalid characters per // se. So even an array of 500 bytes will pass the SJIS checks far too // often. std::array data{}; for (std::size_t i{0}; i < std::size(data); ++i) { data.at(i) = tctx.random_char(); while (data.at(i) == '|') data.at(i) = tctx.random_char(); } // Bet that the random data isn't going to be fully valid text in these // encodings. (Not testing the "two-tier" encodings here, since the only way // to get those wrong is in the final byte.) PQXX_CHECK_THROWS( find_x(data, pqxx::encoding_group::gb18030), pqxx::argument_error); PQXX_CHECK_THROWS( find_x(data, pqxx::encoding_group::sjis), pqxx::argument_error); } PQXX_REGISTER_TEST(test_find_chars); PQXX_REGISTER_TEST(test_find_chars_fails_for_unfinished_character); PQXX_REGISTER_TEST(test_find_chars_reports_malencoded_text); } // namespace libpqxx-8.0.1/test/test_error_verbosity.cxx000066400000000000000000000017251516427024100212170ustar00rootroot00000000000000#include #include "helpers.hxx" #include extern "C" { #include } #include namespace { void test_error_verbosity(pqxx::test::context &) { // The error_verbosity enum matches the PGVerbosity one. We just don't // want to import the latter into our users' namespace. PQXX_CHECK_EQUAL( static_cast(pqxx::error_verbosity::terse), static_cast(PQERRORS_TERSE)); PQXX_CHECK_EQUAL( static_cast(pqxx::error_verbosity::normal), static_cast(PQERRORS_DEFAULT)); PQXX_CHECK_EQUAL( static_cast(pqxx::error_verbosity::verbose), static_cast(PQERRORS_VERBOSE)); pqxx::connection cx; pqxx::work tx{cx}; cx.set_verbosity(pqxx::error_verbosity::terse); tx.exec("SELECT 1").one_row(); cx.set_verbosity(pqxx::error_verbosity::verbose); tx.exec("SELECT 2").one_row(); } PQXX_REGISTER_TEST(test_error_verbosity); } // namespace libpqxx-8.0.1/test/test_errorhandler.cxx000066400000000000000000000165261516427024100204540ustar00rootroot00000000000000#include #include #include #include "helpers.hxx" namespace { class TestErrorHandler final : public pqxx::errorhandler { public: #include "pqxx/internal/ignore-deprecated-pre.hxx" TestErrorHandler( pqxx::connection &cx, std::vector &activated_handlers, bool retval = true) : pqxx::errorhandler(cx), m_handler_list(activated_handlers), m_return_value(retval) {} #include "pqxx/internal/ignore-deprecated-post.hxx" bool operator()(char const msg[]) noexcept override { m_message = std::string{msg}; m_handler_list.push_back(this); return m_return_value; } [[nodiscard]] std::string message() const { return m_message; } TestErrorHandler() = delete; TestErrorHandler(TestErrorHandler const &) = delete; TestErrorHandler &operator=(TestErrorHandler const &) = delete; TestErrorHandler(TestErrorHandler &&) = delete; TestErrorHandler &operator=(TestErrorHandler &&) = delete; ~TestErrorHandler() override = default; private: std::vector &m_handler_list; std::string m_message; bool m_return_value; }; } // namespace namespace pqxx { template<> struct nullness final { // clang warns about these being unused. And clang 6 won't accept a // [[maybe_unused]] attribute on them either! [[maybe_unused]] static inline constexpr bool has_null{true}; static inline constexpr bool always_null{false}; static constexpr bool is_null(TestErrorHandler *e) noexcept { return e == nullptr; } static constexpr TestErrorHandler *null() noexcept { return nullptr; } }; template<> struct string_traits final { static constexpr std::size_t size_buffer(TestErrorHandler *const &) noexcept { return 100; } static std::string_view to_buf(std::span buf, TestErrorHandler *const &value, ctx c = {}) { auto const sz{std::format_to_n( std::data(buf), std::ssize(buf), "TestErrorHandler at {}", std::size_t(value)) .size}; if (std::cmp_greater_equal(sz, std::size(buf))) throw conversion_overrun{ "Not enough buffer for TestErrorHandler.", c.loc}; return {std::data(buf), static_cast(sz)}; } }; } // namespace pqxx namespace { void test_process_notice_calls_errorhandler(pqxx::connection &cx) { std::vector dummy; TestErrorHandler const handler(cx, dummy); cx.process_notice("Error!\n"); PQXX_CHECK_EQUAL(handler.message(), "Error!\n"); } void test_error_handlers_get_called_newest_to_oldest(pqxx::connection &cx) { std::vector handlers; TestErrorHandler h1(cx, handlers); TestErrorHandler h2(cx, handlers); TestErrorHandler h3(cx, handlers); cx.process_notice("Warning.\n"); PQXX_CHECK_EQUAL(h3.message(), "Warning.\n"); PQXX_CHECK_EQUAL(h2.message(), "Warning.\n"); PQXX_CHECK_EQUAL(h1.message(), "Warning.\n"); PQXX_CHECK_EQUAL(std::size(handlers), 3u); PQXX_CHECK_EQUAL(&h3, handlers.at(0)); PQXX_CHECK_EQUAL(&h2, handlers.at(1)); PQXX_CHECK_EQUAL(&h1, handlers.at(2)); } void test_returning_false_stops_error_handling(pqxx::connection &cx) { std::vector handlers; TestErrorHandler const starved(cx, handlers); TestErrorHandler blocker(cx, handlers, false); cx.process_notice("Error output.\n"); PQXX_CHECK_EQUAL(std::size(handlers), 1u, "Handling chain was not stopped."); PQXX_CHECK_EQUAL(handlers.at(0), &blocker, "Wrong handler got message."); PQXX_CHECK_EQUAL(blocker.message(), "Error output.\n"); PQXX_CHECK_EQUAL( starved.message(), "", "Message received; it shouldn't be."); } void test_destroyed_error_handlers_are_not_called(pqxx::connection &cx) { std::vector handlers; { TestErrorHandler const doomed(cx, handlers); } cx.process_notice("Unheard output."); PQXX_CHECK( std::empty(handlers), "Message was received on dead errorhandler."); } class MinimalErrorHandler final : public pqxx::errorhandler { public: #include "pqxx/internal/ignore-deprecated-pre.hxx" explicit MinimalErrorHandler(pqxx::connection &cx) : pqxx::errorhandler(cx) {} #include "pqxx/internal/ignore-deprecated-post.hxx" bool operator()(char const[]) noexcept override { return true; } ~MinimalErrorHandler() override = default; MinimalErrorHandler(MinimalErrorHandler const &) = delete; MinimalErrorHandler &operator=(MinimalErrorHandler const &) = delete; MinimalErrorHandler(MinimalErrorHandler &&) = delete; MinimalErrorHandler &operator=(MinimalErrorHandler &&) = delete; }; void test_get_errorhandlers(pqxx::connection &cx) { std::unique_ptr eh3; #include "pqxx/internal/ignore-deprecated-pre.hxx" auto const handlers_before{cx.get_errorhandlers()}; #include "pqxx/internal/ignore-deprecated-post.hxx" std::size_t const base_handlers{std::size(handlers_before)}; { MinimalErrorHandler eh1(cx); #include "pqxx/internal/ignore-deprecated-pre.hxx" auto const handlers_with_eh1{cx.get_errorhandlers()}; #include "pqxx/internal/ignore-deprecated-post.hxx" PQXX_CHECK_EQUAL(std::size(handlers_with_eh1), base_handlers + 1); PQXX_CHECK_EQUAL( std::size_t(*std::rbegin(handlers_with_eh1)), std::size_t(&eh1)); { MinimalErrorHandler eh2(cx); #include "pqxx/internal/ignore-deprecated-pre.hxx" auto const handlers_with_eh2{cx.get_errorhandlers()}; #include "pqxx/internal/ignore-deprecated-post.hxx" PQXX_CHECK_EQUAL(std::size(handlers_with_eh2), base_handlers + 2); PQXX_CHECK_EQUAL( std::size_t(*(std::rbegin(handlers_with_eh2) + 1)), std::size_t(&eh1)); PQXX_CHECK_EQUAL( std::size_t(*std::rbegin(handlers_with_eh2)), std::size_t(&eh2)); } #include "pqxx/internal/ignore-deprecated-pre.hxx" auto const handlers_without_eh2{cx.get_errorhandlers()}; #include "pqxx/internal/ignore-deprecated-post.hxx" PQXX_CHECK_EQUAL(std::size(handlers_without_eh2), base_handlers + 1); PQXX_CHECK_EQUAL( std::size_t(*std::rbegin(handlers_without_eh2)), std::size_t(&eh1)); eh3 = std::make_unique(cx); #include "pqxx/internal/ignore-deprecated-pre.hxx" auto const handlers_with_eh3{cx.get_errorhandlers()}; #include "pqxx/internal/ignore-deprecated-post.hxx" PQXX_CHECK_EQUAL(std::size(handlers_with_eh3), base_handlers + 2); PQXX_CHECK_EQUAL( std::size_t(*std::rbegin(handlers_with_eh3)), std::size_t(eh3.get())); } #include "pqxx/internal/ignore-deprecated-pre.hxx" auto const handlers_without_eh1{cx.get_errorhandlers()}; #include "pqxx/internal/ignore-deprecated-post.hxx" PQXX_CHECK_EQUAL(std::size(handlers_without_eh1), base_handlers + 1); PQXX_CHECK_EQUAL( std::size_t(*std::rbegin(handlers_without_eh1)), std::size_t(eh3.get())); eh3.reset(); #include "pqxx/internal/ignore-deprecated-pre.hxx" auto const handlers_without_all{cx.get_errorhandlers()}; #include "pqxx/internal/ignore-deprecated-post.hxx" PQXX_CHECK_EQUAL(std::size(handlers_without_all), base_handlers); } void test_errorhandler(pqxx::test::context &) { pqxx::connection cx; test_process_notice_calls_errorhandler(cx); test_error_handlers_get_called_newest_to_oldest(cx); test_returning_false_stops_error_handling(cx); test_destroyed_error_handlers_are_not_called(cx); test_get_errorhandlers(cx); } PQXX_REGISTER_TEST(test_errorhandler); } // namespace libpqxx-8.0.1/test/test_escape.cxx000066400000000000000000000152131516427024100172150ustar00rootroot00000000000000#include #include "helpers.hxx" namespace { using namespace std::literals; using pqxx::operator""_zv; void compare_esc( pqxx::connection &cx, pqxx::transaction_base &t, char const text[]) { std::size_t const len{std::size(std::string{text})}; PQXX_CHECK_EQUAL( cx.esc(std::string_view{text, len}), t.esc(std::string_view{text, len})); PQXX_CHECK_EQUAL(t.esc(std::string_view{text, len}), t.esc(text)); PQXX_CHECK_EQUAL(t.esc(std::string{text}), t.esc(text)); PQXX_CHECK_EQUAL( text, t.query_value( "SELECT '" + t.esc(std::string_view{text, len}) + "'")); PQXX_CHECK_EQUAL(t.esc(std::string_view{text, len}), t.esc(text)); } void test_esc(pqxx::connection &cx, pqxx::transaction_base &t) { PQXX_CHECK_EQUAL(t.esc(""sv), ""); PQXX_CHECK_EQUAL(t.esc("'"sv), "''"); PQXX_CHECK_EQUAL(t.esc("hello"sv), "hello"); std::array const escstrings{"x", " ", "", nullptr}; for (std::size_t i{0}; escstrings.at(i) != nullptr; ++i) compare_esc(cx, t, escstrings.at(i)); } void test_quote(pqxx::connection &cx, pqxx::transaction_base &t) { PQXX_CHECK_EQUAL(t.quote("x"), "'x'"); PQXX_CHECK_EQUAL(t.quote(1), "'1'"); PQXX_CHECK_EQUAL(t.quote(0), "'0'"); char const *const null_ptr{nullptr}; PQXX_CHECK_EQUAL(t.quote(null_ptr), "NULL"); PQXX_CHECK_EQUAL(t.quote(nullptr), "NULL"); PQXX_CHECK_EQUAL(t.quote(std::string{"'"}), "''''"); PQXX_CHECK_EQUAL(t.quote("x"), cx.quote("x")); std::array const test_strings{ "", "x", "\\", "\\\\", "'", "''", "\\'", "\t", "\n", nullptr}; for (std::size_t i{0}; test_strings.at(i) != nullptr; ++i) { auto r{ t.query_value("SELECT " + t.quote(test_strings.at(i)))}; PQXX_CHECK_EQUAL(r, test_strings.at(i)); } std::vector const bin{std::byte{0x33}, std::byte{0x4a}}; PQXX_CHECK_EQUAL(t.quote(bin), "'\\x334a'::bytea"); PQXX_CHECK_EQUAL( t.quote(std::span{bin}), "'\\x334a'::bytea"); } void test_quote_name(pqxx::transaction_base &t) { PQXX_CHECK_EQUAL("\"A b\"", t.quote_name("A b")); PQXX_CHECK_EQUAL( std::string{"A b"}, t.exec("SELECT 1 AS " + t.quote_name("A b")).column_name(0)); } void test_esc_raw_unesc_raw(pqxx::transaction_base &t) { constexpr char binary[]{"1\002.3\\4x5"}; // C++23: Initialise as data{std::from_range_t, binary)? pqxx::bytes data; for (char c : binary) data.push_back(static_cast(c)); std::string const escaped{ t.esc(pqxx::bytes_view{std::data(data), std::size(binary)})}; for (auto const i : escaped) { PQXX_CHECK_GREATER( static_cast(static_cast(i)), 7u, "Non-ASCII character in escaped data: " + escaped); PQXX_CHECK_LESS( static_cast(static_cast(i)), 127u, "Non-ASCII character in escaped data: " + escaped); } for (auto const i : escaped) PQXX_CHECK( isprint(i), "Unprintable character in escaped data: " + escaped); PQXX_CHECK_EQUAL(escaped, "\\x31022e335c34783500"); PQXX_CHECK_EQUAL(std::size(t.unesc_bin(escaped)), std::size(data)); auto unescaped{t.unesc_bin(escaped)}; PQXX_CHECK_EQUAL(std::size(unescaped), std::size(data)); for (std::size_t i{0}; i < std::size(unescaped); ++i) PQXX_CHECK_EQUAL( int(unescaped[i]), int(data[i]), "Unescaping binary data did not restore byte #" + pqxx::to_string(i) + "."); PQXX_CHECK_THROWS(std::ignore = t.unesc_bin("\\"_zv), pqxx::failure); PQXX_CHECK_THROWS(std::ignore = t.unesc_bin("\\xa"_zv), pqxx::failure); PQXX_CHECK_THROWS(std::ignore = t.unesc_bin("\\xg0"_zv), pqxx::failure); PQXX_CHECK_THROWS(std::ignore = t.unesc_bin("\\x0g"_zv), pqxx::failure); PQXX_CHECK_THROWS( std::ignore = pqxx::internal::unesc_bin("\\a"sv, pqxx::sl::current()), pqxx::failure); PQXX_CHECK_THROWS( std::ignore = pqxx::internal::unesc_bin("\\"sv, pqxx::sl::current()), pqxx::failure); PQXX_CHECK_THROWS( std::ignore = pqxx::internal::unesc_bin("\\\xa"sv, pqxx::sl::current()), pqxx::failure); PQXX_CHECK_THROWS( std::ignore = pqxx::internal::unesc_bin("\\\a"sv, pqxx::sl::current()), pqxx::failure); } void test_esc_like(pqxx::transaction_base &tx) { PQXX_CHECK_EQUAL(tx.esc_like(""), ""); PQXX_CHECK_EQUAL(tx.esc_like("abc"), "abc"); PQXX_CHECK_EQUAL(tx.esc_like("_"), "\\_"); PQXX_CHECK_EQUAL(tx.esc_like("%"), "\\%"); PQXX_CHECK_EQUAL(tx.esc_like("a%b_c"), "a\\%b\\_c"); PQXX_CHECK_EQUAL(tx.esc_like("_", '+'), "+_"); PQXX_CHECK_EQUAL(tx.esc_like("%foo"), "\\%foo"); PQXX_CHECK_EQUAL(tx.esc_like("foo%"), "foo\\%"); PQXX_CHECK_EQUAL(tx.esc_like("f%o%o"), "f\\%o\\%o"); PQXX_CHECK_EQUAL(tx.esc_like("___"), "\\_\\_\\_"); PQXX_CHECK_EQUAL(tx.esc_like("_n_n__n_"), "\\_n\\_n\\_\\_n\\_"); } void test_escaping(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; test_esc(cx, tx); test_quote(cx, tx); test_quote_name(tx); test_esc_raw_unesc_raw(tx); test_esc_like(tx); } void test_esc_escapes_into_buffer(pqxx::test::context &) { pqxx::connection cx; pqxx::work const tx{cx}; std::string buffer; buffer.resize(20); auto const text{"Ain't"sv}; auto escaped_text{tx.esc(text, buffer)}; PQXX_CHECK_EQUAL(escaped_text, "Ain''t"); pqxx::bytes const data{std::byte{0x22}, std::byte{0x43}}; auto escaped_data(tx.esc(data, buffer)); PQXX_CHECK_EQUAL(escaped_data, "\\x2243"); } void test_esc_accepts_various_types(pqxx::test::context &) { pqxx::connection cx; pqxx::work const tx{cx}; std::string buffer; buffer.resize(20); std::string const text{"it's"}; auto escaped_text{tx.esc(text, buffer)}; PQXX_CHECK_EQUAL(escaped_text, "it''s"); std::vector const data{std::byte{0x23}, std::byte{0x44}}; auto escaped_data(tx.esc(data, buffer)); PQXX_CHECK_EQUAL(escaped_data, "\\x2344"); } void test_binary_esc_checks_buffer_length(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; std::string buf; pqxx::bytes bin{std::byte{'b'}, std::byte{'o'}, std::byte{'o'}}; buf.resize(2 * std::size(bin) + 3); std::ignore = tx.esc(bin, buf); PQXX_CHECK_EQUAL(int{buf[0]}, int{'\\'}, "Unexpected binary escape format."); PQXX_CHECK_NOT_EQUAL( int(buf[std::size(buf) - 2]), int('\0'), "Escaped binary ends too soon."); PQXX_CHECK_EQUAL( int(buf[std::size(buf) - 1]), int('\0'), "Terminating zero is missing."); buf.resize(2 * std::size(bin) + 2); PQXX_CHECK_THROWS(std::ignore = tx.esc(bin, buf), pqxx::range_error); } PQXX_REGISTER_TEST(test_escaping); PQXX_REGISTER_TEST(test_esc_escapes_into_buffer); PQXX_REGISTER_TEST(test_esc_accepts_various_types); PQXX_REGISTER_TEST(test_binary_esc_checks_buffer_length); } // namespace libpqxx-8.0.1/test/test_exceptions.cxx000066400000000000000000000014451516427024100201400ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { void test_exceptions(pqxx::test::context &) { std::string const broken_query{"SELECT HORRIBLE ERROR"}, err{"Error message"}; try { throw pqxx::sql_error{err, broken_query}; } catch (std::exception const &e) { PQXX_CHECK_EQUAL(e.what(), err); auto downcast{dynamic_cast(&e)}; PQXX_CHECK(downcast != nullptr); PQXX_CHECK_EQUAL(downcast->query(), broken_query); } pqxx::connection cx; pqxx::work tx{cx}; try { tx.exec("INVALID QUERY HERE"); } catch (pqxx::syntax_error const &e) { // SQL syntax error has sqlstate error 42601. PQXX_CHECK_EQUAL(e.sqlstate(), "42601"); } } PQXX_REGISTER_TEST(test_exceptions); } // namespace libpqxx-8.0.1/test/test_field.cxx000066400000000000000000000031661516427024100170440ustar00rootroot00000000000000#include #include "helpers.hxx" namespace { void test_field(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; auto const r1{tx.exec("SELECT 9").one_row()}; auto const &f1{r1[0]}; PQXX_CHECK_EQUAL(f1.as(), "9"); PQXX_CHECK_EQUAL(f1.as("z"), "9"); PQXX_CHECK_EQUAL(f1.as(), 9); PQXX_CHECK_EQUAL(f1.as(10), 9); std::string s; PQXX_CHECK(f1.to(s)); PQXX_CHECK_EQUAL(s, "9"); s = "x"; PQXX_CHECK(f1.to(s, std::string{"7"})); PQXX_CHECK_EQUAL(s, "9"); int i{}; PQXX_CHECK(f1.to(i)); PQXX_CHECK_EQUAL(i, 9); i = 8; PQXX_CHECK(f1.to(i, 12)); PQXX_CHECK_EQUAL(i, 9); auto const r2{tx.exec("SELECT NULL").one_row()}; auto const f2{r2[0]}; i = 100; PQXX_CHECK_THROWS(std::ignore = f2.as(), pqxx::conversion_error); PQXX_CHECK_EQUAL(i, 100); PQXX_CHECK_EQUAL(f2.as(66), 66); PQXX_CHECK(!(f2.to(i))); PQXX_CHECK(!(f2.to(i, 54))); PQXX_CHECK_EQUAL(i, 54); auto const r3{tx.exec("SELECT generate_series(1, 5)")}; PQXX_CHECK_EQUAL(r3.at(3, 0).as(), 4); // (Work around totally bogus MSVC warning: it thinks the comma in the C++23 // two-parameter indexing expression is a sequence operator. But only for // the purposes of issuing annoying warnings; it doesn't _actually_ believe // that.) #if defined(PQXX_HAVE_MULTIDIM) # if defined(_MSC_VER) # pragma warning(push) # pragma warning(disable : 4548) # endif PQXX_CHECK_EQUAL((r3[3, 0].as()), 4); # if defined(_MSC_VER) # pragma warning(pop) # endif #endif // PQXX_HAVE_MULTIDIM } PQXX_REGISTER_TEST(test_field); } // namespace libpqxx-8.0.1/test/test_float.cxx000066400000000000000000000135501516427024100170640ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { /// Test conversions for some floating-point type. template void infinity_test() { T const inf{std::numeric_limits::infinity()}; static constexpr auto big_num{static_cast(999999999)}; auto inf_string = pqxx::to_string(inf); T back_conversion; pqxx::from_string(inf_string, back_conversion); PQXX_CHECK_LESS(big_num, back_conversion); inf_string = pqxx::to_string(-inf); pqxx::from_string(inf_string, back_conversion); PQXX_CHECK_LESS(back_conversion, -big_num); } void test_infinities(pqxx::test::context &) { infinity_test(); infinity_test(); // Skip this test when building for a Valgrind run. The tool doesn't seem // to support long double. #if !defined(PQXX_VALGRIND) infinity_test(); #endif } /// Reproduce bug #262: repeated float conversions break without charconv. template void bug_262() { pqxx::connection cx; cx.prepare("stmt", "select cast($1 as float)"); pqxx::work tr{cx}; // We must use the same float type both for passing the value to the // statement and for retrieving result of the statement execution. This is // due to an internal stringstream being instantiated as a a parameterized // thread-local singleton. So, there are separate stream, // stream, stream, but every such instance is a // singleton. We should use only one of them for this test. pqxx::row row; // Nothing bad here, select a float value. // The stream is clear, so just fill it with the value and extract str(). row = tr.exec("SELECT 1.0").one_row(); // This works properly, but as we parse the value from the stream, the // seeking cursor moves towards the EOF. When the inevitable EOF happens // 'eof' flag is set in the stream and 'good' flag is unset. std::ignore = row[0].as(); // The second try. Select a float value again. The stream is not clean, so // we need to put an empty string into its buffer {stream.str("");}. This // resets the seeking cursor to 0. Then we will put the value using // operator<<(). // ... // ... // OOPS. stream.str("") does not reset 'eof' flag and 'good' flag! We are // trying to read from EOF! This is no good. // Throws on unpatched pqxx v6.4.5 row = tr.exec("SELECT 2.0").one_row(); // We won't get here without patch. The following statements are just for // demonstration of how are intended to work. If we // simply just reset the stream flags properly, this would work fine. // The most obvious patch is just explicitly stream.seekg(0). std::ignore = row[0].as(); row = tr.exec("SELECT 3.0").one_row(); std::ignore = row[0].as(); } /// Test for bug #262. void test_bug_262(pqxx::test::context &) { bug_262(); bug_262(); #if !defined(PQXX_VALGRIND) bug_262(); #endif } /// Test conversion of malformed floating-point values. void test_bad_float(pqxx::test::context &) { float x [[maybe_unused]]{}; PQXX_CHECK_THROWS(x = pqxx::from_string(""), pqxx::conversion_error); PQXX_CHECK_THROWS( x = pqxx::from_string("Infancy"), pqxx::conversion_error); PQXX_CHECK_THROWS( x = pqxx::from_string("-Infighting"), pqxx::conversion_error); PQXX_CHECK_THROWS( x = pqxx::from_string("Nanny"), pqxx::conversion_error); } template void test_float_length(T value) { auto const text{pqxx::to_string(value)}; PQXX_CHECK_GREATER_EQUAL( pqxx::size_buffer(value), std::size(text), std::format("Not enough buffer space for '{}'.", text)); } /// Test conversion of long float values to strings. void test_long_float(pqxx::test::context &) { test_float_length(0.1f); test_float_length(0.1); test_float_length(std::numeric_limits::denorm_min()); test_float_length(-std::numeric_limits::denorm_min()); test_float_length(std::numeric_limits::min()); test_float_length(-std::numeric_limits::min()); test_float_length(std::numeric_limits::max()); test_float_length(-std::numeric_limits::max()); test_float_length(-std::nextafter(1.0f, 2.0f)); test_float_length(std::numeric_limits::denorm_min()); test_float_length(-std::numeric_limits::denorm_min()); test_float_length(std::numeric_limits::min()); test_float_length(-std::numeric_limits::min()); test_float_length(std::numeric_limits::max()); test_float_length(-std::numeric_limits::max()); test_float_length(-std::nextafter(1.0, 2.0)); #if !defined(PQXX_VALGRIND) test_float_length(std::numeric_limits::denorm_min()); test_float_length(-std::numeric_limits::denorm_min()); test_float_length(std::numeric_limits::min()); test_float_length(-std::numeric_limits::min()); test_float_length(std::numeric_limits::max()); test_float_length(-std::numeric_limits::max()); test_float_length(-std::nextafter(1.0L, 2.0L)); #endif // Ahem. I'm not proud of this. We really can't assume much about the // floating-point types, but I'd really like to try a few things to see that // buffer sizes are in the right ballpark. So, if "double" is at least 64 // bits, check for some examples of long conversions. if constexpr (sizeof(double) >= 8) { auto constexpr awkward{-2.2250738585072014e-308}; auto const text{pqxx::to_string(awkward)}; PQXX_CHECK_LESS_EQUAL( std::size(text), 25u, text + " converted to too long a string."); } if constexpr (sizeof(double) <= 8) { auto const text{pqxx::to_string(0.99)}; PQXX_CHECK_LESS_EQUAL( pqxx::size_buffer(0.99), 25u, text + " converted to too long a string."); } } PQXX_REGISTER_TEST(test_infinities); PQXX_REGISTER_TEST(test_bug_262); PQXX_REGISTER_TEST(test_bad_float); PQXX_REGISTER_TEST(test_long_float); } // namespace libpqxx-8.0.1/test/test_helpers.cxx000066400000000000000000000145451516427024100174260ustar00rootroot00000000000000#include "helpers.hxx" namespace { void empty() {} // Test PQXX_CHECK. void test_check(pqxx::test::context &) { PQXX_CHECK(true, "PQXX_CHECK is broken."); bool failed{true}; try { PQXX_CHECK(false, "(expected)"); failed = false; } catch (pqxx::test::test_failure const &) {} if (not failed) pqxx::test::check_notreached("PQXX_CHECK failed to notice failure."); } // Test PQXX_CHECK_THROWS_EXCEPTION. void test_check_throws_exception(pqxx::test::context &) { // PQXX_CHECK_THROWS_EXCEPTION expects std::exception... PQXX_CHECK_THROWS_EXCEPTION( throw std::exception(), "PQXX_CHECK_THROWS_EXCEPTION did not catch std::exception."); // ...or any exception type derived from it. PQXX_CHECK_THROWS_EXCEPTION( throw pqxx::test::test_failure{"(expected)"}, "PQXX_CHECK_THROWS_EXCEPTION() failed to catch expected exception."); // Any other type is an error. bool failed{true}; try { // NOLINTBEGIN(hicpp-exception-baseclass) PQXX_CHECK_THROWS_EXCEPTION(throw 1, "(expected)"); // NOLINTEND(hicpp-exception-baseclass) failed = false; } catch (pqxx::test::test_failure const &) {} PQXX_CHECK( failed, "PQXX_CHECK_THROWS_EXCEPTION did not complain about non-exception."); // But there _must_ be an exception. failed = true; std::ignore = failed; try { // If the test fails to throw, this throws a failure. PQXX_CHECK_THROWS_EXCEPTION(empty(), "(expected)"); // So we shouldn't get to this point. failed = false; } catch (pqxx::test::test_failure const &) { // Instead, we go straight here. } PQXX_CHECK( failed, "PQXX_CHECK_THROWS_EXCEPTION did not notice missing exception."); // PQXX_CHECK_THROWS_EXCEPTION can test itself... PQXX_CHECK_THROWS_EXCEPTION( PQXX_CHECK_THROWS_EXCEPTION(empty(), "(expected)"), "PQXX_CHECK_THROWS_EXCEPTION failed to throw for missing exception."); // NOLINTBEGIN(hicpp-exception-baseclass) PQXX_CHECK_THROWS_EXCEPTION( PQXX_CHECK_THROWS_EXCEPTION(throw 1, "(expected)"), "PQXX_CHECK_THROWS_EXCEPTION ignored wrong exception type."); // NOLINTEND(hicpp-exception-baseclass) } // Test PQXX_CHECK_THROWS. void test_check_throws(pqxx::test::context &) { PQXX_CHECK_THROWS( throw pqxx::test::test_failure{"(expected)"}, pqxx::test::test_failure, "PQXX_CHECK_THROWS() failed to catch expected exception."); // Even if it's not std::exception-derived. // NOLINTBEGIN(hicpp-exception-baseclass) PQXX_CHECK_THROWS(throw 1, int, "(expected)"); // NOLINTEND(hicpp-exception-baseclass) // PQXX_CHECK_THROWS means there _must_ be an exception. bool failed{true}; try { // If the test fails to throw, PQXX_CHECK_THROWS throws a failure. PQXX_CHECK_THROWS(empty(), std::runtime_error, "(expected)"); // So we shouldn't get to this point. failed = false; } catch (pqxx::test::test_failure const &) { // Instead, we go straight here. } PQXX_CHECK(failed, "PQXX_CHECK_THROWS did not notice missing exception."); // The exception must be of the right type (or a subclass of the right type). failed = true; std::ignore = failed; try { // If the test throws the wrong type, PQXX_CHECK_THROWS throws a failure. PQXX_CHECK_THROWS( throw std::exception(), pqxx::test::test_failure, "(expected)"); failed = false; } catch (pqxx::test::test_failure const &) { // Instead, we go straight here. } PQXX_CHECK(failed, "PQXX_CHECK_THROWS did not notice wrong exception type."); // PQXX_CHECK_THROWS can test itself... PQXX_CHECK_THROWS( PQXX_CHECK_THROWS(empty(), pqxx::test::test_failure, "(expected)"), pqxx::test::test_failure, "PQXX_CHECK_THROWS failed to throw for missing exception."); // NOLINTBEGIN(hicpp-exception-baseclass) PQXX_CHECK_THROWS( PQXX_CHECK_THROWS(throw 1, std::runtime_error, "(expected)"), pqxx::test::test_failure, "PQXX_CHECK_THROWS failed to throw for wrong exception type."); // NOLINTEND(hicpp-exception-baseclass) } void test_helpers(pqxx::test::context &) { // Test other helpers against PQXX_CHECK_THROWS. PQXX_CHECK_THROWS( pqxx::test::check_notreached("(expected)"), pqxx::test::test_failure, "PQXX_CHECK_THROWS did not catch check_notreached()."); PQXX_CHECK_THROWS( PQXX_CHECK(false, "(expected)"), pqxx::test::test_failure, "PQXX_CHECK_THROWS did not catch failing PQXX_CHECK."); PQXX_CHECK_THROWS( PQXX_CHECK_THROWS( PQXX_CHECK(true, "(shouldn't happen)"), pqxx::test::test_failure, "(expected)"), pqxx::test::test_failure, "PQXX_CHECK_THROWS on successful PQXX_CHECK failed to throw."); // PQXX_CHECK_EQUAL tests for equality. Its arguments need not be of the // same type, as long as equality between them is defined. PQXX_CHECK_EQUAL(1, 1, "PQXX_CHECK_EQUAL is broken."); PQXX_CHECK_EQUAL(1, 1L, "PQXX_CHECK_EQUAL breaks on type mismatch."); PQXX_CHECK_THROWS( PQXX_CHECK_EQUAL(1, 2, "(expected)"), pqxx::test::test_failure, "PQXX_CHECK_EQUAL fails to spot inequality."); // PQXX_CHECK_NOT_EQUAL is like PQXX_CHECK_EQUAL, but tests for inequality. PQXX_CHECK_NOT_EQUAL(1, 2, "PQXX_CHECK_NOT_EQUAL is broken."); PQXX_CHECK_THROWS( PQXX_CHECK_NOT_EQUAL(1, 1, "(expected)"), pqxx::test::test_failure, "PQXX_CHECK_NOT_EQUAL fails to fail when arguments are equal."); PQXX_CHECK_THROWS( PQXX_CHECK_NOT_EQUAL(1, 1L, "(expected)"), pqxx::test::test_failure, "PQXX_CHECK_NOT_EQUAL breaks on type mismatch."); // PQXX_CHECK_BOUNDS checks a value against a range. PQXX_CHECK_BOUNDS(2, 1, 3, "PQXX_CHECK_BOUNDS wrongly finds fault."); PQXX_CHECK_THROWS( PQXX_CHECK_BOUNDS(1, 2, 3, "(Expected)"), pqxx::test::test_failure, "PQXX_CHECK_BOUNDS did not detect value below permitted range."); // PQXX_CHECK_BOUNDS tests against a half-open interval. PQXX_CHECK_BOUNDS(1, 1, 3, "PQXX_CHECK_BOUNDS goes wrong on lower bound."); PQXX_CHECK_THROWS( PQXX_CHECK_BOUNDS(3, 1, 3, "(Expected)"), pqxx::test::test_failure, "PQXX_CHECK_BOUNDS interval is not half-open."); // PQXX_CHECK_BOUNDS deals well with empty intervals. PQXX_CHECK_THROWS( PQXX_CHECK_BOUNDS(1, 2, 1, "(Expected)"), pqxx::test::test_failure, "PQXX_CHECK_BOUNDS did not detect empty interval."); } PQXX_REGISTER_TEST(test_helpers); PQXX_REGISTER_TEST(test_check); PQXX_REGISTER_TEST(test_check_throws_exception); PQXX_REGISTER_TEST(test_check_throws); } // namespace libpqxx-8.0.1/test/test_largeobject.cxx000066400000000000000000000032511516427024100202350ustar00rootroot00000000000000#include #include #include #include "helpers.hxx" namespace { void test_stream_large_object(pqxx::test::context &) { pqxx::connection cx; // Construct a really nasty string. (Don't just construct a std::string from // a char[] constant, because it'll terminate at the embedded zero.) // // The crucial thing is the "ff" byte at the beginning. It tests for // possible conflation between "eof" (-1) and a char which just happens to // have the same bit pattern as an 8-bit value of -1. This conflation can be // a problem when it occurs at buffer boundaries. constexpr char bytes[]{"\xff\0end"}; std::string const contents{std::data(bytes), std::size(bytes)}; pqxx::work tx{cx}; #include "pqxx/internal/ignore-deprecated-pre.hxx" pqxx::largeobject const new_obj{tx}; pqxx::olostream write{tx, new_obj}; write << contents; write.flush(); pqxx::largeobjectaccess check{tx, new_obj, std::ios::in | std::ios::binary}; std::array buf{}; std::size_t const len{ static_cast(check.read(std::data(buf), std::size(buf)))}; PQXX_CHECK_EQUAL(len, std::size(contents)); std::string const check_str{std::data(buf), len}; PQXX_CHECK_EQUAL(check_str, contents); pqxx::ilostream read{tx, new_obj}; std::string read_back; std::string chunk; while (read >> chunk) read_back += chunk; new_obj.remove(tx); PQXX_CHECK_EQUAL(read_back, contents); PQXX_CHECK_EQUAL(std::size(read_back), std::size(contents)); PQXX_CHECK_EQUAL(std::size(read_back), std::size(bytes)); #include "pqxx/internal/ignore-deprecated-post.hxx" } PQXX_REGISTER_TEST(test_stream_large_object); } // namespace libpqxx-8.0.1/test/test_nonblocking_connect.cxx000066400000000000000000000010031516427024100217610ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { void test_nonblocking_connect(pqxx::test::context &) { pqxx::connecting nbc; while (not nbc.done()) { pqxx::internal::wait_fd( nbc.sock(), nbc.wait_to_read(), nbc.wait_to_write()); nbc.process(); } pqxx::connection cx{std::move(nbc).produce()}; pqxx::work tx{cx}; PQXX_CHECK_EQUAL(tx.query_value("SELECT 10"), 10); } PQXX_REGISTER_TEST(test_nonblocking_connect); } // namespace libpqxx-8.0.1/test/test_notice_handler.cxx000066400000000000000000000111451516427024100207330ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { void test_notice_handler_receives_notice(pqxx::test::context &) { pqxx::connection cx; int notices{0}; cx.set_notice_handler([¬ices](pqxx::zview) noexcept { ++notices; }); pqxx::work tx{cx}; // Start a transaction while already in a transaction, to trigger a notice. tx.exec("BEGIN").no_rows(); PQXX_CHECK_EQUAL(notices, 1); } void test_notice_handler_works_after_connection_closes(pqxx::test::context &) { pqxx::result r; int notices{0}; { pqxx::connection cx; cx.set_notice_handler([¬ices](pqxx::zview) noexcept { ++notices; }); pqxx::work tx{cx}; r = tx.exec("SELECT 1"); } PQXX_CHECK_EQUAL(notices, 0); // Trigger a notice by asking libpq about a nonexistent column. PQXX_CHECK_THROWS_EXCEPTION(std::ignore = r.table_column(99)); PQXX_CHECK_EQUAL( notices, 1, "Did not get expected single post-connection notice."); } void test_process_notice_calls_notice_handler(pqxx::test::context &) { int calls{0}; std::string received; pqxx::connection cx; cx.set_notice_handler([&calls, &received](auto x) noexcept { ++calls; received = x; }); // The connection class has a process_notice() function which invokes the // handler. { std::string const msg{"Hello there\n"}; cx.process_notice(msg); PQXX_CHECK_EQUAL(calls, 1); PQXX_CHECK_EQUAL(received, msg); } // The transaction classes also have a process_notice() function. { std::string const msg{"work message\n"}; pqxx::work const tx{cx}; tx.process_notice(msg); PQXX_CHECK_EQUAL(calls, 2); PQXX_CHECK_EQUAL(received, msg); } // Even nontransaction has one; there's no difference. { std::string const msg{"work message\n"}; pqxx::nontransaction const tx{cx}; tx.process_notice(msg); PQXX_CHECK_EQUAL(calls, 3); PQXX_CHECK_EQUAL(received, msg); } } // Global counter so we can count calls to a global function. int notice_handler_test_func_counter{0}; // NOLINT void notice_handler_test_func(pqxx::zview) { ++notice_handler_test_func_counter; } void test_notice_handler_accepts_function(pqxx::test::context &) { pqxx::connection cx; cx.set_notice_handler(notice_handler_test_func); cx.process_notice("Hello"); PQXX_CHECK_EQUAL(notice_handler_test_func_counter, 1); } // Global counter so we can count calls to a captureless lambda. int notice_handler_test_lambda_counter{0}; // NOLINT void test_notice_handler_accepts_stateless_lambda(pqxx::test::context &) { pqxx::connection cx; cx.set_notice_handler( [](pqxx::zview) noexcept { ++notice_handler_test_lambda_counter; }); cx.process_notice("Hello"); PQXX_CHECK_EQUAL(notice_handler_test_lambda_counter, 1); } class notice_handler_test_functor { public: notice_handler_test_functor(int &c, std::string &r) : m_count{&c}, m_received{&r} {} void operator()(pqxx::zview msg) noexcept { ++*m_count; *m_received = msg; } private: int *m_count; std::string *m_received; }; void test_notice_handler_accepts_functor(pqxx::test::context &) { std::string const hello{"Hello world"}; // We're going to create a functor that stores its call count and message // her. We can't store it inside the functor, because that gets passed by // value to the connection as a std::function. int count{0}; std::string received; notice_handler_test_functor const f(count, received); pqxx::connection cx; cx.set_notice_handler(f); cx.process_notice(hello); PQXX_CHECK_EQUAL(count, 1); PQXX_CHECK_EQUAL(received, hello); } void test_notice_handler_works_after_moving_connection(pqxx::test::context &) { bool got_message{false}; pqxx::connection cx; cx.set_notice_handler( [&got_message](pqxx::zview) noexcept { got_message = true; }); auto cx2{std::move(cx)}; pqxx::connection cx3; cx3 = std::move(cx2); pqxx::work tx{cx3}; // Trigger a notice. Just calling process_notice() isn't hard enough for a // good strong test, because that function bypasses the libpq logic for // receiving a notice. tx.exec("BEGIN").no_rows(); PQXX_CHECK(got_message, "Did not receive notice after moving."); } PQXX_REGISTER_TEST(test_notice_handler_receives_notice); PQXX_REGISTER_TEST(test_notice_handler_works_after_connection_closes); PQXX_REGISTER_TEST(test_process_notice_calls_notice_handler); PQXX_REGISTER_TEST(test_notice_handler_accepts_function); PQXX_REGISTER_TEST(test_notice_handler_accepts_stateless_lambda); PQXX_REGISTER_TEST(test_notice_handler_accepts_functor); PQXX_REGISTER_TEST(test_notice_handler_works_after_moving_connection); } // namespace libpqxx-8.0.1/test/test_notification.cxx000066400000000000000000000312721516427024100204460ustar00rootroot00000000000000#include #include #include #include #include #include #include #include "helpers.hxx" namespace { #include struct TestReceiver final : public pqxx::notification_receiver { TestReceiver(pqxx::connection &cx, std::string const &channel_name) : pqxx::notification_receiver(cx, channel_name) {} ~TestReceiver() override = default; void operator()(std::string const &payload_string, int backend) override { m_payload = payload_string; m_backend_pid = backend; } [[nodiscard]] std::string const &payload() const noexcept { return m_payload; } [[nodiscard]] int backend_pid() const noexcept { return m_backend_pid; } TestReceiver(TestReceiver const &) = delete; TestReceiver &operator=(TestReceiver const &) = delete; TestReceiver(TestReceiver &&) = delete; TestReceiver &operator=(TestReceiver &&) = delete; private: std::string m_payload; int m_backend_pid = 0; }; void test_receive_classic( pqxx::transaction_base &tx, std::string const &channel, char const payload[] = nullptr) { pqxx::connection &cx(tx.conn()); std::string SQL{"NOTIFY " + tx.quote_name(channel)}; if (payload != nullptr) SQL += ", " + tx.quote(payload); TestReceiver const receiver{cx, channel}; // Clear out any previously pending notifications that might otherwise // confuse the test. cx.get_notifs(); // Notify, and receive. tx.exec(SQL); tx.commit(); int notifs{0}; for (int i{0}; (i < 100) and (notifs == 0); ++i, pqxx::internal::wait_for(100u)) notifs = cx.get_notifs(); PQXX_CHECK_EQUAL(notifs, 1); PQXX_CHECK_EQUAL(receiver.backend_pid(), cx.backendpid()); if (payload == nullptr) PQXX_CHECK(std::empty(receiver.payload())); else PQXX_CHECK_EQUAL(receiver.payload(), payload); } void test_notification_classic(pqxx::test::context &tctx) { pqxx::connection cx; std::string const chan0{tctx.make_name("pqxx-chan")}, chan1{tctx.make_name("pqxx-chan")}, chan2{tctx.make_name("pqxx-chan")}; TestReceiver const receiver(cx, chan0); PQXX_CHECK_EQUAL(receiver.channel(), chan0); pqxx::work tx{cx}; test_receive_classic(tx, chan1); pqxx::nontransaction u(cx); test_receive_classic(u, chan2, "payload"); } #include void test_notification_to_self_arrives_after_commit(pqxx::test::context &tctx) { pqxx::connection cx; auto const channel{tctx.make_name("pqxx-chan")}; int notifications{0}; pqxx::connection *conn{nullptr}; std::string incoming, payload; int pid{0}; cx.listen( channel, [¬ifications, &conn, &incoming, &payload, &pid](pqxx::notification n) { ++notifications; conn = &n.conn; incoming = n.channel; pid = n.backend_pid; payload = n.payload; }); cx.get_notifs(); // No notifications so far. PQXX_CHECK_EQUAL(notifications, 0); pqxx::work tx{cx}; tx.notify(channel); int received{cx.await_notification(0, 300)}; // Notification has not been delivered yet, since transaction has not yet // been committed. PQXX_CHECK_EQUAL(received, 0, "Notification went out before commit."); PQXX_CHECK_EQUAL(notifications, 0); tx.commit(); received = cx.await_notification(3); PQXX_CHECK_EQUAL(received, 1); PQXX_CHECK_EQUAL(notifications, 1); PQXX_CHECK(conn == &cx); PQXX_CHECK_EQUAL(pid, cx.backendpid()); PQXX_CHECK_EQUAL(incoming, channel); PQXX_CHECK_EQUAL(payload, ""); } void test_notification_has_payload(pqxx::test::context &tctx) { pqxx::connection cx; auto const channel{tctx.make_name("pqxx-chan")}; auto const payload{"two dozen eggs"}; int notifications{0}; std::string received; cx.listen(channel, [¬ifications, &received](pqxx::notification n) { ++notifications; received = n.payload; }); pqxx::work tx{cx}; tx.notify(channel, payload); tx.commit(); cx.await_notification(3); PQXX_CHECK_EQUAL(notifications, 1); PQXX_CHECK_EQUAL(received, payload); } // Functor-shaped notification handler. struct notify_test_listener final { explicit notify_test_listener(int &r) : m_received{&r} {} void operator()(pqxx::notification) { ++*m_received; } private: int *m_received; }; void test_listen_supports_different_types_of_callable( pqxx::test::context &tctx) { pqxx::connection cx; auto const chan{tctx.make_name("pqxx-chan")}; int received{}; // Using a functor as a handler. received = 0; notify_test_listener const l(received); cx.listen(chan, l); pqxx::work tx1{cx}; tx1.notify(chan); tx1.commit(); cx.await_notification(3); PQXX_CHECK_EQUAL(received, 1); // Using a handler that takes a const reference to the notification. received = 0; cx.listen(chan, [&received](pqxx::notification const &) { ++received; }); pqxx::work tx2{cx}; tx2.notify(chan); tx2.commit(); cx.await_notification(3); PQXX_CHECK_EQUAL(received, 1); // Using a handler that takes an rvalue reference. received = 0; cx.listen(chan, [&received](pqxx::notification &&) { ++received; }); pqxx::work tx3{cx}; tx3.notify(chan); tx3.commit(); cx.await_notification(3); PQXX_CHECK_EQUAL(received, 1); } void test_abort_cancels_notification(pqxx::test::context &tctx) { auto const chan{tctx.make_name("pqxx-chan")}; pqxx::connection cx; cx.listen(chan, [&chan](pqxx::notification const &n) { throw pqxx::test::test_failure{std::format( "Got unexpected notification on channel '{}' (payload '{}'). " "(Was waiting for '{}'.)", n.channel.c_str(), n.payload.c_str(), chan)}; }); pqxx::work tx{cx}; tx.notify(chan); tx.abort(); // This will throw a test failure if the notification should unexpectedly // still arrive. cx.await_notification(3); } void test_notification_channels_are_case_sensitive(pqxx::test::context &tctx) { pqxx::connection cx; std::string in; auto const base{tctx.make_name("pqxx-chan")}; cx.listen(base + "AbC", [&in](pqxx::notification n) { in = n.channel; }); pqxx::work tx{cx}; tx.notify(base + "AbC"); tx.notify(base + "ABC"); tx.notify(base + "abc"); tx.commit(); cx.await_notification(3); PQXX_CHECK_EQUAL(in, base + "AbC"); } void test_notification_channels_may_contain_weird_chars( pqxx::test::context &tctx) { auto const chan{tctx.make_name("pqxx-A_#&*!")}; pqxx::connection cx; std::string got; cx.listen(chan, [&got](pqxx::notification n) { got = n.channel; }); pqxx::work tx{cx}; tx.notify(chan); tx.commit(); cx.await_notification(3); PQXX_CHECK_EQUAL(got, chan); } /// In a nontransaction, a notification goes out even if you abort. void test_nontransaction_sends_notification(pqxx::test::context &tctx) { auto const chan{tctx.make_name("pqxx-chan")}; pqxx::connection cx; bool got{false}; cx.listen(chan, [&got](pqxx::notification) { got = true; }); pqxx::nontransaction tx{cx}; tx.notify(chan); tx.abort(); cx.await_notification(3); PQXX_CHECK(got); } void test_subtransaction_sends_notification(pqxx::test::context &tctx) { auto const chan{tctx.make_name("pqxx-chan")}; pqxx::connection cx; bool got{false}; cx.listen(chan, [&got](pqxx::notification) { got = true; }); pqxx::work tx{cx}; pqxx::subtransaction sx{tx}; sx.notify(chan); sx.commit(); tx.commit(); cx.await_notification(3); PQXX_CHECK(got); } void test_subtransaction_abort_cancels_notification(pqxx::test::context &tctx) { auto const chan{tctx.make_name("pqxx-chan")}; pqxx::connection cx; cx.listen(chan, [&chan](pqxx::notification const &n) { throw pqxx::test::test_failure{std::format( "Got unexpected notification on channel '{}' (payload '{}'). (Was " "waiting for '{}'.)", n.channel.c_str(), n.payload.c_str(), chan)}; }); pqxx::work tx{cx}; pqxx::subtransaction sx{tx}; sx.notify(chan); sx.abort(); tx.commit(); // This will throw if we unexpectedly got the notification. cx.await_notification(3); } void test_cannot_listen_during_transaction(pqxx::test::context &tctx) { pqxx::connection cx; // Listening while a transaction is active is an error, even when it's just // a nontransaction. pqxx::nontransaction const tx{cx}; PQXX_CHECK_THROWS( cx.listen(tctx.make_name("pqxx-chan"), [](pqxx::notification) {}), pqxx::usage_error); } void test_notifications_cross_connections(pqxx::test::context &tctx) { pqxx::connection cx_listen, cx_notify; auto const chan{tctx.make_name("pqxx-chan")}; int sender_pid{0}; cx_listen.listen( chan, [&sender_pid](pqxx::notification n) { sender_pid = n.backend_pid; }); pqxx::work tx{cx_notify}; tx.notify(chan); tx.commit(); cx_listen.await_notification(3); PQXX_CHECK_EQUAL(sender_pid, cx_notify.backendpid()); } void test_notification_goes_to_right_handler(pqxx::test::context &tctx) { pqxx::connection cx; std::string got; int count{0}; std::string const chanx{tctx.make_name("pqxx-chanX")}, chany{tctx.make_name("pqxx-chanY")}, chanz{tctx.make_name("pqxx-chanZ")}; cx.listen(chanx, [&got, &count](pqxx::notification) { got = "chanX"; ++count; }); cx.listen(chany, [&got, &count](pqxx::notification) { got = "chanY"; ++count; }); cx.listen(chanz, [&got, &count](pqxx::notification) { got = "chanZ"; ++count; }); pqxx::work tx{cx}; tx.notify(chany); tx.commit(); cx.await_notification(3); PQXX_CHECK_EQUAL(got, "chanY"); PQXX_CHECK_EQUAL(count, 1); } void test_listen_on_same_channel_overwrites(pqxx::test::context &tctx) { auto const chan{tctx.make_name("pqxx-chan")}; pqxx::connection cx; std::string got; int count{0}; cx.listen(chan, [&got, &count](pqxx::notification) { got = "first"; ++count; }); cx.listen(chan, [&got, &count](pqxx::notification) { got = "second"; ++count; }); cx.listen(chan, [&got, &count](pqxx::notification) { got = "third"; ++count; }); pqxx::work tx{cx}; tx.notify(chan); tx.commit(); cx.await_notification(3); PQXX_CHECK_EQUAL(count, 1, "Expected 1 notification despite overwrite."); PQXX_CHECK_EQUAL(got, "third"); } void test_empty_notification_handler_disables(pqxx::test::context &tctx) { auto const chan{tctx.make_name("pqxx-chan")}; pqxx::connection cx; bool got{false}; cx.listen(chan, [&got](pqxx::notification) { got = true; }); cx.listen(chan); pqxx::work tx{cx}; tx.notify(chan); tx.commit(); PQXX_CHECK(not got, "Disabling a notification handler did not work."); } void test_notifications_do_not_come_in_until_commit(pqxx::test::context &tctx) { auto const chan{tctx.make_name("pqxx-chan")}; pqxx::connection cx; bool got{false}; cx.listen(chan, [&got](pqxx::notification) { got = true; }); // This applies even during a nontransaction. Another test verifies that // a notification goes _out_ even if we abort the nontransaction, because // it goes out immediately, not at commit time. What we're establishing // here is that the notification does not come _in_ during a transaction, // even if it's a nontransaction. pqxx::nontransaction tx{cx}; tx.notify(chan); cx.await_notification(3); PQXX_CHECK(not got, "Notification came in during nontransaction."); } void test_notification_handlers_follow_connection_move( pqxx::test::context &tctx) { auto const chan{tctx.make_name("pqxx-chan")}; pqxx::connection cx1; pqxx::connection *got{nullptr}; cx1.listen(chan, [&got](pqxx::notification n) { got = &n.conn; }); pqxx::connection cx2{std::move(cx1)}; pqxx::connection cx3; cx3 = std::move(cx2); pqxx::work tx{cx3}; tx.notify(chan); tx.commit(); cx3.await_notification(3); PQXX_CHECK(got != nullptr); PQXX_CHECK(got == &cx3); } PQXX_REGISTER_TEST(test_notification_classic); PQXX_REGISTER_TEST(test_notification_to_self_arrives_after_commit); PQXX_REGISTER_TEST(test_notification_has_payload); PQXX_REGISTER_TEST(test_listen_supports_different_types_of_callable); PQXX_REGISTER_TEST(test_abort_cancels_notification); PQXX_REGISTER_TEST(test_notification_channels_are_case_sensitive); PQXX_REGISTER_TEST(test_notification_channels_may_contain_weird_chars); PQXX_REGISTER_TEST(test_nontransaction_sends_notification); PQXX_REGISTER_TEST(test_subtransaction_sends_notification); PQXX_REGISTER_TEST(test_subtransaction_abort_cancels_notification); PQXX_REGISTER_TEST(test_cannot_listen_during_transaction); PQXX_REGISTER_TEST(test_notifications_cross_connections); PQXX_REGISTER_TEST(test_notification_goes_to_right_handler); PQXX_REGISTER_TEST(test_listen_on_same_channel_overwrites); PQXX_REGISTER_TEST(test_empty_notification_handler_disables); PQXX_REGISTER_TEST(test_notifications_do_not_come_in_until_commit); PQXX_REGISTER_TEST(test_notification_handlers_follow_connection_move); } // namespace libpqxx-8.0.1/test/test_params.cxx000066400000000000000000000011341516427024100172350ustar00rootroot00000000000000#include #include "helpers.hxx" namespace { using pqxx::operator""_zv; void test_statement_params(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; std::array const bin{std::byte{'a'}, std::byte{'b'}}; pqxx::params p, q; p.append(); p.append("zview"_zv); q.append(bin); p.append(q); auto const res{tx.exec("SELECT $1, $2, $3", p)}; PQXX_CHECK(res.at(0).at(0).is_null()); PQXX_CHECK_EQUAL(res.at(0).at(1).view(), "zview"); PQXX_CHECK_EQUAL(res.at(0).at(2).view(), "ab"); } PQXX_REGISTER_TEST(test_statement_params); } // namespace libpqxx-8.0.1/test/test_pipeline.cxx000066400000000000000000000045461516427024100175710ustar00rootroot00000000000000#include #include #include #include "helpers.hxx" namespace { void test_pipeline_is_consistent(pqxx::test::context &tctx) { auto const num_queries = tctx.make_num(10) + 1; auto const value = tctx.make_num(); pqxx::connection cx; pqxx::work tx{cx}; pqxx::pipeline pipe{tx}; PQXX_CHECK(std::empty(pipe)); auto const query{std::format("SELECT {}", value)}; for (int i{0}; i < num_queries; ++i) pipe.insert(query); for (int i{0}; i < num_queries; ++i) { PQXX_CHECK(not std::empty(pipe)); auto res{pipe.retrieve()}; PQXX_CHECK_EQUAL(res.second.one_field().as(), value); } PQXX_CHECK(pipe.empty()); } void test_pipeline(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; // A pipeline grabs transaction focus, blocking regular queries and such. pqxx::pipeline pipe(tx, "test_pipeline_detach"); PQXX_CHECK_THROWS(tx.exec("SELECT 1"), pqxx::usage_error); // Flushing a pipeline relinquishes transaction focus. pipe.flush(); auto r{tx.exec("SELECT 2")}; PQXX_CHECK_EQUAL(std::size(r), 1); PQXX_CHECK_EQUAL(r.one_field().as(), 2); // Inserting a query makes the pipeline grab transaction focus back. auto q{pipe.insert("SELECT 2")}; PQXX_CHECK_THROWS( tx.exec("SELECT 3"), pqxx::usage_error, "Pipeline does not block regular queries"); // Invoking complete() also detaches the pipeline from the transaction. pipe.complete(); r = tx.exec("SELECT 4"); PQXX_CHECK_EQUAL(std::size(r), 1); PQXX_CHECK_EQUAL(r.one_field().as(), 4); // The complete() also received any pending query results from the backend. r = pipe.retrieve(q); PQXX_CHECK_EQUAL(std::size(r), 1); PQXX_CHECK_EQUAL(r.one_field().as(), 2); // We can cancel while the pipe is empty, and things will still work. pipe.cancel(); // Issue a query and cancel it. Measure time to see that we don't really // wait. using clock = std::chrono::steady_clock; auto const start{clock::now()}; pipe.retain(0); pipe.insert("pg_sleep(10)"); pipe.cancel(); auto const finish{clock::now()}; auto const seconds{ std::chrono::duration_cast(finish - start).count()}; PQXX_CHECK_LESS(seconds, 5, "Canceling a sleep took suspiciously long."); } } // namespace PQXX_REGISTER_TEST(test_pipeline_is_consistent); PQXX_REGISTER_TEST(test_pipeline); libpqxx-8.0.1/test/test_prepared_statement.cxx000066400000000000000000000301721516427024100216440ustar00rootroot00000000000000#include #include "helpers.hxx" // Test program for libpqxx. Define and use prepared statements. #define COMPARE_RESULTS(name, lhs, rhs) \ PQXX_CHECK_EQUAL( \ pqxx::to_string(rhs), pqxx::to_string(lhs), \ "Executing " name " as prepared statement yields different results."); namespace { using namespace std::literals; template std::string stringize(pqxx::transaction_base &t, T i) { return stringize(t, pqxx::to_string(i)); } // Substitute variables in raw query. This is not likely to be very robust, // but it should do for just this test. The main shortcomings are escaping, // and not knowing when to quote the variables. // Note we do the replacement backwards (meaning forward_only iterators won't // do!) to avoid substituting e.g. "$12" as "$1" first. template std::string subst(pqxx::transaction_base &t, std::string q, ITER patbegin, ITER patend) { ptrdiff_t i{distance(patbegin, patend)}; for (ITER arg{patend}; i > 0; --i) { --arg; std::string const marker{"$" + pqxx::to_string(i)}, var{stringize(t, *arg)}; std::string::size_type const msz{std::size(marker)}; while (pqxx::str_contains(q, marker)) q.replace(q.find(marker), msz, var); } return q; } template std::string subst(pqxx::transaction_base &t, std::string const &q, CNTNR const &patterns) { return subst(t, q, std::begin(patterns), std::end(patterns)); } void test_registration_and_invocation(pqxx::test::context &) { constexpr auto count_to_5{"SELECT * FROM generate_series(1, 5)"}; pqxx::connection cx; pqxx::work tx1{cx}; // Prepare a simple statement. tx1.conn().prepare("CountToFive", count_to_5); // The statement returns exactly what you'd expect. COMPARE_RESULTS( "CountToFive", tx1.exec(pqxx::prepped{"CountToFive"}), tx1.exec(count_to_5)); // Re-preparing it is an error. PQXX_CHECK_THROWS( tx1.conn().prepare("CountToFive", count_to_5), pqxx::sql_error); tx1.abort(); pqxx::work tx2{cx}; // Executing a nonexistent prepared statement is also an error. PQXX_CHECK_THROWS( tx2.exec(pqxx::prepped{"NonexistentStatement"}), pqxx::sql_error); } void test_basic_args(pqxx::test::context &) { pqxx::connection cx; cx.prepare("EchoNum", "SELECT $1::int"); pqxx::work tx{cx}; auto r{tx.exec(pqxx::prepped{"EchoNum"}, 7)}; PQXX_CHECK_EQUAL(std::size(r), 1); PQXX_CHECK_EQUAL(std::size(r.front()), 1); PQXX_CHECK_EQUAL(r.one_field().as(), 7); auto rw{tx.exec(pqxx::prepped{"EchoNum"}, 8).one_row()}; PQXX_CHECK_EQUAL(std::size(rw), 1); PQXX_CHECK_EQUAL(rw[0].as(), 8); } void test_multiple_params(pqxx::test::context &) { pqxx::connection cx; cx.prepare("CountSeries", "SELECT * FROM generate_series($1::int, $2::int)"); pqxx::work tx{cx}; auto r{tx.exec(pqxx::prepped{"CountSeries"}, pqxx::params{tx, 7, 10}) .expect_rows(4)}; PQXX_CHECK_EQUAL(std::size(r), 4); PQXX_CHECK_EQUAL(r.front().front().as(), 7); PQXX_CHECK_EQUAL(r.back().front().as(), 10); cx.prepare("Reversed", "SELECT * FROM generate_series($2::int, $1::int)"); r = tx.exec(pqxx::prepped{"Reversed"}, pqxx::params{tx, 8, 6}).expect_rows(3); PQXX_CHECK_EQUAL(r.front().front().as(), 6); PQXX_CHECK_EQUAL(r.back().front().as(), 8); } void test_nulls(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; cx.prepare("EchoStr", "SELECT $1::varchar"); auto rw{ tx.exec(pqxx::prepped{"EchoStr"}, pqxx::params{tx, nullptr}).one_row()}; PQXX_CHECK(rw.front().is_null()); char const *n{nullptr}; rw = tx.exec(pqxx::prepped{"EchoStr"}, pqxx::params{tx, n}).one_row(); PQXX_CHECK(rw.front().is_null()); } void test_strings(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; cx.prepare("EchoStr", "SELECT $1::varchar"); auto rw{ tx.exec(pqxx::prepped{"EchoStr"}, pqxx::params{tx, "foo"}).one_row()}; PQXX_CHECK_EQUAL(rw.front().as(), "foo"); char const nasty_string[]{R"--('\"\)--"}; rw = tx.exec(pqxx::prepped{"EchoStr"}, pqxx::params{tx, nasty_string}) .one_row(); PQXX_CHECK_EQUAL( rw.front().as(), std::string(std::data(nasty_string))); rw = tx.exec( pqxx::prepped{"EchoStr"}, pqxx::params{tx, std::string{std::data(nasty_string)}}) .one_row(); PQXX_CHECK_EQUAL( rw.front().as(), std::string(std::data(nasty_string))); char nonconst[]{"non-const C string"}; rw = tx.exec(pqxx::prepped{"EchoStr"}, pqxx::params{tx, nonconst}).one_row(); PQXX_CHECK_EQUAL( rw.front().as(), std::string(std::data(nonconst))); } void test_binary(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; cx.prepare("EchoBin", "SELECT $1::bytea"); constexpr char raw_bytes[]{"Binary\0bytes'\"with\tweird\xff bytes"}; std::string const input{std::data(raw_bytes), std::size(raw_bytes)}; { // C++23: Initialise as bytes{std::from_range_t, raw_bytes)? pqxx::bytes bytes; for (char c : raw_bytes) bytes.push_back(static_cast(c)); auto bp{ tx.exec(pqxx::prepped{"EchoBin"}, pqxx::params{tx, bytes}).one_row()}; auto bval{bp[0].as()}; PQXX_CHECK_EQUAL( (std::string_view{ reinterpret_cast(std::data(bval)), std::size(bval)}), input); } // Now try it with a complex type that ultimately uses the conversions of // pqx::bytes, but complex enough that the call may convert the data to a // text string on the libpqxx side. Which would be okay, except of course // it's likely to be slower. { // C++23: Initialise as data{std::from_range_t, raw_bytes)? pqxx::bytes data; for (char c : raw_bytes) data.push_back(static_cast(c)); auto ptr{std::make_shared(data)}; auto rp{ tx.exec(pqxx::prepped{"EchoBin"}, pqxx::params{tx, ptr}).one_row()}; auto pval{rp[0].as()}; PQXX_CHECK_EQUAL( (std::string_view{ reinterpret_cast(std::data(pval)), std::size(pval)}), input); } { // C++23: Initialise as {std::in_place, std::from_range_t, raw_bytes}? std::vector data; for (char c : raw_bytes) data.push_back(static_cast(c)); auto opt{std::optional{std::in_place, data}}; auto op{ tx.exec(pqxx::prepped{"EchoBin"}, pqxx::params{tx, opt}).one_row()}; auto oval{op[0].as()}; PQXX_CHECK_EQUAL( (std::string_view{ reinterpret_cast(std::data(oval)), std::size(oval)}), input); } // By the way, it doesn't have to be a pqxx::bytes. Any contiguous range // will do. { std::vector const data{std::byte{'x'}, std::byte{'v'}}; auto op{ tx.exec(pqxx::prepped{"EchoBin"}, pqxx::params{tx, data}).one_row()}; auto oval{op[0].as()}; PQXX_CHECK_EQUAL(std::size(oval), 2u); PQXX_CHECK_EQUAL(static_cast(oval[0]), int('x')); PQXX_CHECK_EQUAL(static_cast(oval[1]), int('v')); } } void test_params(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; cx.prepare("Concat2Numbers", "SELECT 10 * $1 + $2"); std::vector const values{3, 9}; pqxx::params params; params.reserve(std::size(values)); params.append_multi(values); auto const rw39{ tx.exec(pqxx::prepped{"Concat2Numbers"}, pqxx::params{tx, params}) .one_row()}; PQXX_CHECK_EQUAL(rw39.front().as(), 39); cx.prepare("Concat4Numbers", "SELECT 1000*$1 + 100*$2 + 10*$3 + $4"); auto const rw1396{ tx.exec(pqxx::prepped{"Concat4Numbers"}, pqxx::params{tx, 1, params, 6}) .one_row()}; PQXX_CHECK_EQUAL(rw1396.front().as(), 1396); } void test_optional(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; cx.prepare("EchoNum", "SELECT $1::int"); pqxx::row rw{tx.exec( pqxx::prepped{"EchoNum"}, pqxx::params{tx, std::optional{std::in_place, 10}}) .one_row()}; PQXX_CHECK_EQUAL(rw.front().as(), 10); rw = tx.exec(pqxx::prepped{"EchoNum"}, pqxx::params{tx, std::optional{}}) .one_row(); PQXX_CHECK(rw.front().is_null()); } void test_prepared_statements(pqxx::test::context &tctx) { test_registration_and_invocation(tctx); test_basic_args(tctx); test_multiple_params(tctx); test_nulls(tctx); test_strings(tctx); test_binary(tctx); test_params(tctx); test_optional(tctx); } void test_placeholders_generates_names(pqxx::test::context &) { using pqxx::operator""_zv; pqxx::placeholders name; PQXX_CHECK_EQUAL(name.view(), "$1"_zv); PQXX_CHECK_EQUAL(name.view(), "$1"sv); PQXX_CHECK_EQUAL(name.get(), "$1"); name.next(); PQXX_CHECK_EQUAL(name.view(), "$2"_zv); name.next(); PQXX_CHECK_EQUAL(name.view(), "$3"_zv); name.next(); PQXX_CHECK_EQUAL(name.view(), "$4"_zv); name.next(); PQXX_CHECK_EQUAL(name.view(), "$5"_zv); name.next(); PQXX_CHECK_EQUAL(name.view(), "$6"_zv); name.next(); PQXX_CHECK_EQUAL(name.view(), "$7"_zv); name.next(); PQXX_CHECK_EQUAL(name.view(), "$8"_zv); name.next(); PQXX_CHECK_EQUAL(name.view(), "$9"_zv); name.next(); PQXX_CHECK_EQUAL(name.view(), "$10"_zv); name.next(); PQXX_CHECK_EQUAL(name.view(), "$11"_zv); while (name.count() < 999) name.next(); PQXX_CHECK_EQUAL(name.view(), "$999"_zv, "Incorrect placeholders 999."); name.next(); PQXX_CHECK_EQUAL(name.view(), "$1000"_zv); } void test_wrong_number_of_params(pqxx::test::context &) { { pqxx::connection conn1; pqxx::transaction tx1{conn1}; conn1.prepare("broken1", "SELECT $1::int + $2::int"); PQXX_CHECK_THROWS( tx1.exec(pqxx::prepped{"broken1"}, pqxx::params{tx1, 10}), pqxx::protocol_violation); } { pqxx::connection conn2; pqxx::transaction tx2{conn2}; conn2.prepare("broken2", "SELECT $1::int + $2::int"); PQXX_CHECK_THROWS( tx2.exec(pqxx::prepped{"broken2"}, {5, 4, 3}), pqxx::protocol_violation); } } void test_query_prepped(pqxx::test::context &) { pqxx::connection cx; pqxx::transaction tx{cx}; cx.prepare("hop", "SELECT x * 3 FROM generate_series(1, 2) AS x"); std::vector out; for (auto [i] : tx.query(pqxx::prepped{"hop"})) out.push_back(i); PQXX_CHECK_EQUAL(std::size(out), 2u); PQXX_CHECK_EQUAL(out.at(0), 3); PQXX_CHECK_EQUAL(out.at(1), 6); } void test_query_value_prepped(pqxx::test::context &) { pqxx::connection cx; pqxx::transaction tx{cx}; cx.prepare("pick", "SELECT 92"); PQXX_CHECK_EQUAL(tx.query_value(pqxx::prepped{"pick"}), 92); } void test_for_query_prepped(pqxx::test::context &) { pqxx::connection cx; pqxx::transaction tx{cx}; cx.prepare("series", "SELECT * FROM generate_series(3, 4)"); std::vector out; tx.for_query(pqxx::prepped("series"), [&out](int x) { out.push_back(x); }); PQXX_CHECK_EQUAL(std::size(out), 2u); PQXX_CHECK_EQUAL(out.at(0), 3); PQXX_CHECK_EQUAL(out.at(1), 4); } void test_prepped_query_does_not_need_terminating_zero(pqxx::test::context &) { pqxx::connection cx; pqxx::transaction tx{cx}; // Create name & definition without terminating zeroes. std::string_view const name_buf{"xblah123x'><;;"}; auto const name{name_buf.substr(1, 4)}; PQXX_CHECK_EQUAL(name, "blah"); std::string_view const def_buf{"xSELECT $1+1x<>;;"}; auto const def{def_buf.substr(1, 11)}; PQXX_CHECK_EQUAL(std::string(def), "SELECT $1+1"); cx.prepare(name, def); auto const res{tx.exec(pqxx::prepped{name}, pqxx::params{6})}; PQXX_CHECK_EQUAL(res.at(0).at(0).view(), "7"); cx.unprepare(name); // It also works with std::string arguments, and with query_value(). cx.prepare(std::string{name}, def); PQXX_CHECK_EQUAL( tx.query_value(pqxx::prepped{name}, pqxx::params{89}), 90); } PQXX_REGISTER_TEST(test_prepared_statements); PQXX_REGISTER_TEST(test_placeholders_generates_names); PQXX_REGISTER_TEST(test_wrong_number_of_params); PQXX_REGISTER_TEST(test_query_prepped); PQXX_REGISTER_TEST(test_query_value_prepped); PQXX_REGISTER_TEST(test_for_query_prepped); PQXX_REGISTER_TEST(test_prepped_query_does_not_need_terminating_zero); } // namespace libpqxx-8.0.1/test/test_range.cxx000066400000000000000000000343131516427024100170530ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { void test_range_construct(pqxx::test::context &) { using optint = std::optional; using oibound = pqxx::inclusive_bound>; using oxbound = pqxx::inclusive_bound>; PQXX_CHECK_THROWS( (pqxx::range{oibound{optint{}}, oibound{optint{}}}), pqxx::argument_error); PQXX_CHECK_THROWS( (pqxx::range{oxbound{optint{}}, oxbound{optint{}}}), pqxx::argument_error); using ibound = pqxx::inclusive_bound; PQXX_CHECK_THROWS( (pqxx::range{ibound{1}, ibound{0}}), pqxx::range_error); PQXX_CHECK_THROWS( (pqxx::range{ pqxx::inclusive_bound{-1000.0}, pqxx::inclusive_bound{-std::numeric_limits::infinity()}}), pqxx::range_error); } void test_range_equality(pqxx::test::context &) { using range = pqxx::range; using ibound = pqxx::inclusive_bound; using xbound = pqxx::exclusive_bound; using ubound = pqxx::no_bound; PQXX_CHECK_EQUAL(range{}, range{}); PQXX_CHECK_EQUAL( (range{xbound{0}, xbound{0}}), (range{xbound{5}, xbound{5}})); PQXX_CHECK_EQUAL((range{ubound{}, ubound{}}), (range{ubound{}, ubound{}})); PQXX_CHECK_EQUAL( (range{ibound{5}, ibound{8}}), (range{ibound{5}, ibound{8}})); PQXX_CHECK_EQUAL( (range{xbound{5}, xbound{8}}), (range{xbound{5}, xbound{8}})); PQXX_CHECK_EQUAL( (range{xbound{5}, ibound{8}}), (range{xbound{5}, ibound{8}})); PQXX_CHECK_EQUAL( (range{ibound{5}, xbound{8}}), (range{ibound{5}, xbound{8}})); PQXX_CHECK_EQUAL((range{ubound{}, ibound{8}}), (range{ubound{}, ibound{8}})); PQXX_CHECK_EQUAL((range{ibound{8}, ubound{}}), (range{ibound{8}, ubound{}})); PQXX_CHECK_NOT_EQUAL( (range{ibound{5}, ibound{8}}), (range{xbound{5}, ibound{8}})); PQXX_CHECK_NOT_EQUAL( (range{ibound{5}, ibound{8}}), (range{ubound{}, ibound{8}})); PQXX_CHECK_NOT_EQUAL( (range{xbound{5}, ibound{8}}), (range{ubound{}, ibound{8}})); PQXX_CHECK_NOT_EQUAL( (range{ibound{5}, ibound{8}}), (range{ibound{5}, xbound{8}})); PQXX_CHECK_NOT_EQUAL( (range{ibound{5}, ibound{8}}), (range{ibound{5}, ubound{}})); PQXX_CHECK_NOT_EQUAL( (range{ibound{5}, xbound{8}}), (range{ibound{5}, ubound{}})); PQXX_CHECK_NOT_EQUAL( (range{ibound{5}, ibound{8}}), (range{ibound{4}, ibound{8}})); PQXX_CHECK_NOT_EQUAL( (range{xbound{5}, ibound{8}}), (range{xbound{4}, ibound{8}})); PQXX_CHECK_NOT_EQUAL( (range{xbound{5}, ibound{8}}), (range{xbound{5}, ibound{7}})); PQXX_CHECK_NOT_EQUAL( (range{xbound{5}, xbound{8}}), (range{xbound{5}, xbound{7}})); } void test_range_empty(pqxx::test::context &) { using range = pqxx::range; using ibound = pqxx::inclusive_bound; using xbound = pqxx::exclusive_bound; using ubound = pqxx::no_bound; PQXX_CHECK((range{}.empty())); PQXX_CHECK((range{ibound{10}, xbound{10}}).empty()); PQXX_CHECK((range{xbound{10}, ibound{10}}).empty()); PQXX_CHECK((range{xbound{10}, xbound{10}}).empty()); PQXX_CHECK(not(range{ibound{10}, ibound{10}}).empty()); PQXX_CHECK(not(range{xbound{10}, ibound{11}}.empty())); PQXX_CHECK(not(range{ubound{}, ubound{}}.empty())); PQXX_CHECK(not(range{ubound{}, xbound{0}}.empty())); PQXX_CHECK(not(range{xbound{0}, ubound{}}.empty())); } void test_range_contains(pqxx::test::context &) { using range = pqxx::range; using ibound = pqxx::inclusive_bound; using xbound = pqxx::exclusive_bound; using ubound = pqxx::no_bound; PQXX_CHECK(not(range{}.contains(-1))); PQXX_CHECK(not(range{}.contains(0))); PQXX_CHECK(not(range{}.contains(1))); PQXX_CHECK(not(range{ibound{5}, ibound{8}}.contains(4))); PQXX_CHECK((range{ibound{5}, ibound{8}}.contains(5))); PQXX_CHECK((range{ibound{5}, ibound{8}}.contains(6))); PQXX_CHECK((range{ibound{5}, ibound{8}}.contains(8))); PQXX_CHECK(not(range{ibound{5}, ibound{8}}.contains(9))); PQXX_CHECK(not(range{ibound{5}, xbound{8}}.contains(4))); PQXX_CHECK((range{ibound{5}, xbound{8}}.contains(5))); PQXX_CHECK((range{ibound{5}, xbound{8}}.contains(6))); PQXX_CHECK(not(range{ibound{5}, xbound{8}}.contains(8))); PQXX_CHECK(not(range{ibound{5}, xbound{8}}.contains(9))); PQXX_CHECK(not(range{xbound{5}, ibound{8}}.contains(4))); PQXX_CHECK(not(range{xbound{5}, ibound{8}}.contains(5))); PQXX_CHECK((range{xbound{5}, ibound{8}}.contains(6))); PQXX_CHECK((range{xbound{5}, ibound{8}}.contains(8))); PQXX_CHECK(not(range{xbound{5}, ibound{8}}.contains(9))); PQXX_CHECK(not(range{xbound{5}, xbound{8}}.contains(4))); PQXX_CHECK(not(range{xbound{5}, xbound{8}}.contains(5))); PQXX_CHECK((range{xbound{5}, xbound{8}}.contains(6))); PQXX_CHECK(not(range{xbound{5}, xbound{8}}.contains(8))); PQXX_CHECK(not(range{xbound{5}, xbound{8}}.contains(9))); PQXX_CHECK((range{ubound{}, ibound{8}}.contains(7))); PQXX_CHECK((range{ubound{}, ibound{8}}.contains(8))); PQXX_CHECK(not(range{ubound{}, ibound{8}}.contains(9))); PQXX_CHECK((range{ubound{}, xbound{8}}.contains(7))); PQXX_CHECK(not(range{ubound{}, xbound{8}}.contains(8))); PQXX_CHECK(not(range{ubound{}, xbound{8}}.contains(9))); PQXX_CHECK(not(range{ibound{5}, ubound{}}.contains(4))); PQXX_CHECK((range{ibound{5}, ubound{}}.contains(5))); PQXX_CHECK((range{ibound{5}, ubound{}}.contains(6))); PQXX_CHECK(not(range{xbound{5}, ubound{}}.contains(4))); PQXX_CHECK(not(range{xbound{5}, ubound{}}.contains(5))); PQXX_CHECK((range{xbound{5}, ubound{}}.contains(6))); PQXX_CHECK((range{ubound{}, ubound{}}.contains(-1))); PQXX_CHECK((range{ubound{}, ubound{}}.contains(0))); PQXX_CHECK((range{ubound{}, ubound{}}.contains(1))); } void test_float_range_contains(pqxx::test::context &) { using range = pqxx::range; using ibound = pqxx::inclusive_bound; using xbound = pqxx::exclusive_bound; using ubound = pqxx::no_bound; using limits = std::numeric_limits; constexpr auto inf{limits::infinity()}; PQXX_CHECK(not(range{ibound{4.0}, ibound{8.0}}.contains(3.9))); PQXX_CHECK((range{ibound{4.0}, ibound{8.0}}.contains(4.0))); PQXX_CHECK((range{ibound{4.0}, ibound{8.0}}.contains(5.0))); PQXX_CHECK((range{ibound{0}, ibound{inf}}).contains(9999.0)); PQXX_CHECK(not(range{ibound{0}, ibound{inf}}.contains(-0.1))); PQXX_CHECK((range{ibound{0}, xbound{inf}}.contains(9999.0))); PQXX_CHECK((range{ibound{0}, ibound{inf}}).contains(inf)); PQXX_CHECK(not(range{ibound{0}, xbound{inf}}.contains(inf))); PQXX_CHECK((range{ibound{0}, ubound{}}).contains(inf)); PQXX_CHECK((range{ibound{-inf}, ibound{0}}).contains(-9999.0)); PQXX_CHECK(not(range{ibound{-inf}, ibound{0}}.contains(0.1))); PQXX_CHECK((range{xbound{-inf}, ibound{0}}).contains(-9999.0)); PQXX_CHECK((range{ibound{-inf}, ibound{0}}).contains(-inf)); PQXX_CHECK(not(range{xbound{-inf}, ibound{0}}).contains(-inf)); PQXX_CHECK((range{ubound{}, ibound{0}}).contains(-inf)); } void test_range_subset(pqxx::test::context &) { using range = pqxx::range; using traits = pqxx::string_traits; constexpr std::string_view subsets[][2]{ {"empty", "empty"}, {"(,)", "empty"}, {"(0,1)", "empty"}, {"(,)", "[-10,10]"}, {"(,)", "(-10,10)"}, {"(,)", "(,)"}, {"(,10)", "(,10)"}, {"(,10)", "(,9)"}, {"(,10]", "(,10)"}, {"(,10]", "(,10]"}, {"(1,)", "(10,)"}, {"(1,)", "(9,)"}, {"[1,)", "(10,)"}, {"[1,)", "[10,)"}, {"[0,5]", "[1,4]"}, {"(0,5)", "[1,4]"}, }; for (auto const &[super, sub] : subsets) PQXX_CHECK( traits::from_string(super).contains(traits::from_string(sub)), std::format("Range '{}' did not contain ''.", super, sub)); constexpr std::string_view non_subsets[][2]{ {"empty", "[0,0]"}, {"empty", "(,)"}, {"[-10,10]", "(,)"}, {"(-10,10)", "(,)"}, {"(,9)", "(,10)"}, {"(,10)", "(,10]"}, {"[1,4]", "[0,4]"}, {"[1,4]", "[1,5]"}, {"(0,10)", "[0,10]"}, {"(0,10)", "(0,10]"}, {"(0,10)", "[0,10)"}, }; for (auto const &[super, sub] : non_subsets) PQXX_CHECK( not traits::from_string(super).contains(traits::from_string(sub)), std::format("Range '{}' contained '{}'.", super, sub)); } void test_range_to_string(pqxx::test::context &) { using range = pqxx::range; using ibound = pqxx::inclusive_bound; using xbound = pqxx::exclusive_bound; using ubound = pqxx::no_bound; PQXX_CHECK_EQUAL(pqxx::to_string(range{}), "empty"); PQXX_CHECK_EQUAL(pqxx::to_string(range{ibound{5}, ibound{8}}), "[5,8]"); PQXX_CHECK_EQUAL(pqxx::to_string(range{xbound{5}, ibound{8}}), "(5,8]"); PQXX_CHECK_EQUAL(pqxx::to_string(range{ibound{5}, xbound{8}}), "[5,8)"); PQXX_CHECK_EQUAL(pqxx::to_string(range{xbound{5}, xbound{8}}), "(5,8)"); // Unlimited boundaries can use brackets or parentheses. Doesn't matter. // We cheat and use some white-box knowledge of our implementation here. PQXX_CHECK_EQUAL(pqxx::to_string(range{ubound{}, ubound{}}), "(,)"); PQXX_CHECK_EQUAL(pqxx::to_string(range{ubound{}, ibound{8}}), "(,8]"); PQXX_CHECK_EQUAL(pqxx::to_string(range{ubound{}, xbound{8}}), "(,8)"); PQXX_CHECK_EQUAL(pqxx::to_string(range{ibound{5}, ubound{}}), "[5,)"); PQXX_CHECK_EQUAL(pqxx::to_string(range{xbound{5}, ubound{}}), "(5,)"); } void test_parse_range(pqxx::test::context &) { using range = pqxx::range; using ubound = pqxx::no_bound; using traits = pqxx::string_traits; constexpr std::string_view empties[]{"empty", "EMPTY", "eMpTy"}; for (auto empty : empties) PQXX_CHECK( traits::from_string(empty).empty(), std::format("This was supposed to produce an empty range: '{}'", empty)); constexpr std::string_view universals[]{"(,)", "[,)", "(,]", "[,]"}; for (auto univ : universals) PQXX_CHECK_EQUAL( traits::from_string(univ), (range{ubound{}, ubound{}}), std::format( "This was supposed to produce a universal range: '{}'", univ)); PQXX_CHECK(traits::from_string("(0,10]").lower_bound().is_exclusive()); PQXX_CHECK(traits::from_string("[0,10]").lower_bound().is_inclusive()); PQXX_CHECK(traits::from_string("(0,10)").upper_bound().is_exclusive()); PQXX_CHECK(traits::from_string("[0,10]").upper_bound().is_inclusive()); PQXX_CHECK_EQUAL( *traits::from_string("(\"0\",\"10\")").lower_bound().value(), 0); PQXX_CHECK_EQUAL( *traits::from_string("(\"0\",\"10\")").upper_bound().value(), 10); auto floats{ pqxx::string_traits>::from_string("(0,1.0)")}; PQXX_CHECK_GREATER(*floats.lower_bound().value(), -0.001); PQXX_CHECK_LESS(*floats.lower_bound().value(), 0.001); PQXX_CHECK_GREATER(*floats.upper_bound().value(), 0.999); PQXX_CHECK_LESS(*floats.upper_bound().value(), 1.001); } void test_parse_bad_range(pqxx::test::context &) { using range = pqxx::range; using conv_err = pqxx::conversion_error; using traits = pqxx::string_traits; constexpr std::string_view bad_ranges[]{ "", "x", "e", "empt", "emptyy", "()", "[]", "(empty)", "(empty, 0)", "(0, empty)", ",", "(,", ",)", "(1,2,3)", "(4,5x)", "(null, 0)", "[0, 1.0]", "[1.0, 0]", }; for (auto bad : bad_ranges) PQXX_CHECK_THROWS( std::ignore = traits::from_string(bad), conv_err, std::format("This range wasn't supposed to parse: '{}'", bad)); } /// Parse ranges lhs and rhs, return their intersection as a string. template std::string intersect(std::string_view lhs, std::string_view rhs) { using traits = pqxx::string_traits>; return pqxx::to_string(traits::from_string(lhs) & traits::from_string(rhs)); } void test_range_intersection(pqxx::test::context &) { // Intersections and their expected results, in text form. // Each row contains two ranges, and their intersection. constexpr std::string_view intersections[][3]{ {"empty", "empty", "empty"}, {"(,)", "empty", "empty"}, {"[,]", "empty", "empty"}, {"empty", "[0,10]", "empty"}, {"(,)", "(,)", "(,)"}, {"(,)", "(5,8)", "(5,8)"}, {"(,)", "[5,8)", "[5,8)"}, {"(,)", "(5,8]", "(5,8]"}, {"(,)", "[5,8]", "[5,8]"}, {"(-1000,10)", "(0,1000)", "(0,10)"}, {"[-1000,10)", "(0,1000)", "(0,10)"}, {"(-1000,10]", "(0,1000)", "(0,10]"}, {"[-1000,10]", "(0,1000)", "(0,10]"}, {"[0,100]", "[0,100]", "[0,100]"}, {"[0,100]", "[0,100)", "[0,100)"}, {"[0,100]", "(0,100]", "(0,100]"}, {"[0,100]", "(0,100)", "(0,100)"}, {"[0,10]", "[11,20]", "empty"}, {"[0,10]", "(11,20]", "empty"}, {"[0,10]", "[11,20)", "empty"}, {"[0,10]", "(11,20)", "empty"}, {"[0,10]", "[10,11]", "[10,10]"}, {"[0,10)", "[10,11]", "empty"}, {"[0,10]", "(10,11]", "empty"}, {"[0,10)", "(10,11]", "empty"}, }; for (auto const &[left, right, expected] : intersections) { PQXX_CHECK_EQUAL( intersect(left, right), expected, std::format( "Intersection of '{}' and '{}' produced unexpected result.", left, right)); PQXX_CHECK_EQUAL( intersect(right, left), expected, std::format( "Intersection of '{}' and '{}' was asymmetric.", left, right)); } } void test_range_conversion(pqxx::test::context &) { std::array const ranges{ "empty", "(,)", "(,10)", "(0,)", "[0,10]", "[0,10)", "(0,10]", "(0,10)", }; for (auto r : ranges) { auto const shortr{pqxx::from_string>(r)}; pqxx::range const intr{shortr}; PQXX_CHECK_EQUAL(pqxx::to_string(intr), r); } } constexpr void test_range_is_constexpr(pqxx::test::context &) { // Test compile-time operations. using range = pqxx::range; using ibound = pqxx::inclusive_bound; constexpr ibound one{1}, three{3}; constexpr range oneone{one, one}, onethree{one, three}; static_assert(oneone == range{oneone}); static_assert(oneone != onethree); static_assert(onethree.contains(oneone)); } PQXX_REGISTER_TEST(test_range_construct); PQXX_REGISTER_TEST(test_range_equality); PQXX_REGISTER_TEST(test_range_empty); PQXX_REGISTER_TEST(test_range_contains); PQXX_REGISTER_TEST(test_float_range_contains); PQXX_REGISTER_TEST(test_range_subset); PQXX_REGISTER_TEST(test_range_to_string); PQXX_REGISTER_TEST(test_parse_range); PQXX_REGISTER_TEST(test_parse_bad_range); PQXX_REGISTER_TEST(test_range_intersection); PQXX_REGISTER_TEST(test_range_conversion); PQXX_REGISTER_TEST(test_range_is_constexpr); } // namespace libpqxx-8.0.1/test/test_read_transaction.cxx000066400000000000000000000006041516427024100212730ustar00rootroot00000000000000#include #include "helpers.hxx" namespace { void test_read_transaction(pqxx::test::context &) { pqxx::connection cx; pqxx::read_transaction tx{cx}; PQXX_CHECK_EQUAL(tx.query_value("SELECT 1"), 1); PQXX_CHECK_THROWS( tx.exec("CREATE TABLE should_not_exist(x integer)"), pqxx::sql_error); } PQXX_REGISTER_TEST(test_read_transaction); } // namespace libpqxx-8.0.1/test/test_result_iteration.cxx000066400000000000000000000106351516427024100213540ustar00rootroot00000000000000#include #include #include #include "helpers.hxx" namespace { void test_result_iteration(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::result r{tx.exec("SELECT generate_series(1, 3)")}; static_assert(std::random_access_iterator); static_assert(std::random_access_iteratorbegin())>); PQXX_CHECK(std::end(r) != std::begin(r)); PQXX_CHECK(std::rend(r) != std::rbegin(r)); PQXX_CHECK(std::cbegin(r) == std::begin(r)); PQXX_CHECK(std::cend(r) == std::end(r)); PQXX_CHECK(std::crbegin(r) == std::rbegin(r)); PQXX_CHECK(std::crend(r) == std::rend(r)); PQXX_CHECK_EQUAL(r.front().front().as(), 1); PQXX_CHECK_EQUAL(r.back().front().as(), 3); PQXX_CHECK((pqxx::result::const_iterator{r, 1} != r.begin())); PQXX_CHECK((pqxx::result::const_iterator{r, 1} == r.begin() + 1)); } void test_result_iter(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::result const r{tx.exec("SELECT generate_series(1, 3)")}; int total{0}; for (auto const &[i] : r.iter()) total += i; PQXX_CHECK_EQUAL(total, 6); pqxx::result::const_iterator c{r.begin()}; auto const oldit{c++}; PQXX_CHECK(oldit == r.begin()); PQXX_CHECK(c == r.begin() + 1); auto const newit{++c}; PQXX_CHECK(newit == c); PQXX_CHECK(newit == r.begin() + 2); auto const backit{--c}; PQXX_CHECK(backit == r.begin() + 1); PQXX_CHECK(c-- == r.begin() + 1); PQXX_CHECK(c == r.begin()); } void test_result_iterator_swap(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::result r{tx.exec("SELECT generate_series(1, 3)")}; auto head{std::begin(r)}, next{head + 1}; head.swap(next); PQXX_CHECK_EQUAL((*head)[0].as(), 2); PQXX_CHECK_EQUAL((*next)[0].as(), 1); auto tail{std::rbegin(r)}, prev{tail + 1}; tail.swap(prev); PQXX_CHECK_EQUAL((*tail)[0].as(), 2); PQXX_CHECK_EQUAL((*prev)[0].as(), 3); } void test_result_iterator_assignment(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::result r{tx.exec("SELECT generate_series(1, 3)")}; pqxx::result::const_iterator fwd; pqxx::result::const_reverse_iterator rev; fwd = std::begin(r); PQXX_CHECK_EQUAL((*fwd)[0].as(), (*std::begin(r))[0].as()); rev = std::rbegin(r); PQXX_CHECK_EQUAL((*rev)[0].as(), (*std::rbegin(r))[0].as()); pqxx::result::const_reverse_iterator const rev2{fwd}; PQXX_CHECK(rev2 == std::rend(r)); pqxx::result::const_iterator pos; pos = {r, 1u}; PQXX_CHECK_EQUAL(pos->at(0).view(), "2"); ++pos; PQXX_CHECK_EQUAL(pos->at(0).view(), "3"); --pos; PQXX_CHECK_EQUAL(pos->at(0).view(), "2"); pos += 2; PQXX_CHECK(pos == r.end()); } void check_employee(std::string const &name, int salary) { PQXX_CHECK(name == "x" or name == "y" or name == "z"); PQXX_CHECK(salary == 1000 or salary == 1200 or salary == 1500); } void test_result_for_each(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; tx.exec("CREATE TEMP TABLE employee(name varchar, salary int)").no_rows(); auto fill{pqxx::stream_to::table(tx, {"employee"}, {"name", "salary"})}; fill.write_values("x", 1000); fill.write_values("y", 1200); fill.write_values("z", 1500); fill.complete(); auto const res{tx.exec("SELECT name, salary FROM employee ORDER BY name")}; // Use for_each with a function. res.for_each(check_employee); // Use for_each with a simple lambda. res.for_each( [](std::string const &name, int salary) { check_employee(name, salary); }); // Use for_each with a lambda closure. std::string names{}; int total{0}; res.for_each([&names, &total](std::string const &name, int salary) { names.append(name); total += salary; }); PQXX_CHECK_EQUAL(names, "xyz"); PQXX_CHECK_EQUAL(total, 1000 + 1200 + 1500); // In addition to regular conversions, you can receive arguments as // string_view, or as references. names.clear(); total = 0; res.for_each([&names, &total](std::string_view &&name, int const &salary) { names.append(name); total += salary; }); PQXX_CHECK_EQUAL(names, "xyz"); PQXX_CHECK_EQUAL(total, 1000 + 1200 + 1500); } PQXX_REGISTER_TEST(test_result_iteration); PQXX_REGISTER_TEST(test_result_iter); PQXX_REGISTER_TEST(test_result_iterator_swap); PQXX_REGISTER_TEST(test_result_iterator_assignment); PQXX_REGISTER_TEST(test_result_for_each); } // namespace libpqxx-8.0.1/test/test_row.cxx000066400000000000000000000117471516427024100165740ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { void test_row(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::row r{tx.exec("SELECT 1 AS one, 2 AS two, 3 AS three").one_row()}; static_assert(std::forward_iterator); PQXX_CHECK_EQUAL(std::size(r), 3); PQXX_CHECK_EQUAL(r.at(0).as(), 1); PQXX_CHECK(std::begin(r) != std::end(r)); PQXX_CHECK(std::begin(r) < std::end(r)); PQXX_CHECK(std::cbegin(r) == std::begin(r)); PQXX_CHECK(std::cend(r) == std::end(r)); PQXX_CHECK(std::rbegin(r) != std::rend(r)); PQXX_CHECK(std::crbegin(r) == std::rbegin(r)); PQXX_CHECK(std::crend(r) == std::rend(r)); PQXX_CHECK_EQUAL(r.front().as(), 1); PQXX_CHECK_EQUAL(r.back().as(), 3); PQXX_CHECK_THROWS(std::ignore = r.at(3), pqxx::range_error); PQXX_CHECK_EQUAL(r.at("two").view(), "2"); PQXX_CHECK_THROWS(std::ignore = r.at("four"), pqxx::argument_error); } void test_row_iterator(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::result const rows{tx.exec("SELECT 1, 2, 3")}; // Very important to keep this in a variable. We'll be creating an iterator // on it, and if we used a temporary here, it'd go out of scope, get // destroyed, and invalidate the accesses! auto row{rows[0]}; auto i{std::begin(row)}; PQXX_CHECK_EQUAL(i->as(), 1); auto i2{i}; PQXX_CHECK_EQUAL(i2->as(), 1); i2++; PQXX_CHECK_EQUAL(i2->as(), 2); pqxx::row::const_iterator i3; i3 = i2; PQXX_CHECK_EQUAL(i3->as(), 2); auto r{std::rbegin(row)}; PQXX_CHECK_EQUAL(r->as(), 3); auto r2{r}; PQXX_CHECK_EQUAL(r2->as(), 3); r2++; PQXX_CHECK_EQUAL(r2->as(), 2); pqxx::row::const_reverse_iterator r3; r3 = r2; PQXX_CHECK_EQUAL(i3->as(), 2); } void test_row_as(pqxx::test::context &) { using pqxx::operator""_zv; pqxx::connection cx; pqxx::work tx{cx}; pqxx::row const r{tx.exec("SELECT 1, 2, 3").one_row()}; auto [one, two, three]{r.as()}; static_assert(std::is_same_v); static_assert(std::is_same_v); static_assert(std::is_same_v); PQXX_CHECK_EQUAL(one, 1); PQXX_CHECK_GREATER(two, 1.9); PQXX_CHECK_LESS(two, 2.1); PQXX_CHECK_EQUAL(three, "3"_zv); PQXX_CHECK_EQUAL( std::get<0>(tx.exec("SELECT 999").one_row().as()), 999); } // In a random access iterator i, i[n] == *(i + n). void test_row_iterator_array_index_offsets_iterator(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; auto const row{tx.exec("SELECT 5, 4, 3, 2").one_row()}; PQXX_CHECK_EQUAL(row.begin()[1].as(), "4"); PQXX_CHECK_EQUAL(row.rbegin()[1].as(), "3"); } void test_row_as_tuple(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; auto const r{tx.exec("SELECT 1, 'Alice'").one_row()}; // A tuple type with matching number and types of columns. using correct_tuple_t = std::tuple; // Tuple types with the wrong numbers of columns. using short_tuple_t = std::tuple; using long_tuple_t = std::tuple; PQXX_CHECK_EQUAL(r.size(), 2); correct_tuple_t t{r.as_tuple()}; PQXX_CHECK_EQUAL(std::get<0>(t), 1); PQXX_CHECK_EQUAL(std::get<1>(t), "Alice"); PQXX_CHECK_THROWS( (std::ignore = r.as_tuple()), pqxx::usage_error); PQXX_CHECK_THROWS( (std::ignore = r.as_tuple()), pqxx::usage_error); } void test_row_swap(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::result const res{tx.exec("SELECT * FROM generate_series(1,3)")}; pqxx::row r1{res.at(0)}, r3{res.at(2)}; PQXX_CHECK_EQUAL(r1.at(0).view(), "1"); PQXX_CHECK_EQUAL(r3.at(0).view(), "3"); #include "pqxx/internal/ignore-deprecated-pre.hxx" r1.swap(r3); #include "pqxx/internal/ignore-deprecated-post.hxx" // The two rows' positions have switched places. PQXX_CHECK_EQUAL(r1.at(0).view(), "3"); PQXX_CHECK_EQUAL(r3.at(0).view(), "1"); // The original row remains unaffected. PQXX_CHECK_EQUAL(res.at(0).at(0).view(), "1"); PQXX_CHECK_EQUAL(res.at(1).at(0).view(), "2"); PQXX_CHECK_EQUAL(res.at(2).at(0).view(), "3"); #include "pqxx/internal/ignore-deprecated-pre.hxx" r1.swap(r3); #include "pqxx/internal/ignore-deprecated-post.hxx" // Now they're back in their original positions. PQXX_CHECK_EQUAL(r1.at(0).view(), "1"); PQXX_CHECK_EQUAL(r3.at(0).view(), "3"); // It doesn't matter whether we a.swap(b) or b.swap(a). #include "pqxx/internal/ignore-deprecated-pre.hxx" r3.swap(r1); #include "pqxx/internal/ignore-deprecated-post.hxx" PQXX_CHECK_EQUAL(r1.at(0).view(), "3"); PQXX_CHECK_EQUAL(r3.at(0).view(), "1"); } PQXX_REGISTER_TEST(test_row); PQXX_REGISTER_TEST(test_row_iterator); PQXX_REGISTER_TEST(test_row_as); PQXX_REGISTER_TEST(test_row_iterator_array_index_offsets_iterator); PQXX_REGISTER_TEST(test_row_as_tuple); PQXX_REGISTER_TEST(test_row_swap); } // namespace libpqxx-8.0.1/test/test_separated_list.cxx000066400000000000000000000012221516427024100207530ustar00rootroot00000000000000#include #include "helpers.hxx" // Test program for separated_list. namespace { void test_separated_list(pqxx::test::context &) { PQXX_CHECK_EQUAL(pqxx::separated_list(",", std::vector{}), ""); PQXX_CHECK_EQUAL(pqxx::separated_list(",", std::vector{5}), "5"); PQXX_CHECK_EQUAL(pqxx::separated_list(",", std::vector{3, 6}), "3,6"); std::vector const nums{1, 2, 3}; PQXX_CHECK_EQUAL( pqxx::separated_list( "+", std::begin(nums), std::end(nums), [](auto elt) { return *elt * 2; }), "2+4+6", "Accessors don't seem to work."); } PQXX_REGISTER_TEST(test_separated_list); } // namespace libpqxx-8.0.1/test/test_simultaneous_transactions.cxx000066400000000000000000000006401516427024100232730ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { void test_simultaneous_transactions(pqxx::test::context &) { pqxx::connection cx; pqxx::nontransaction const n1{cx}; PQXX_CHECK_THROWS( pqxx::nontransaction{cx}, pqxx::usage_error, "Allowed to open simultaneous nontransactions."); } PQXX_REGISTER_TEST(test_simultaneous_transactions); } // namespace libpqxx-8.0.1/test/test_sql_cursor.cxx000066400000000000000000000222051516427024100201500ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { void test_forward_sql_cursor(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; // Plain owned, scoped, forward-only read-only cursor. pqxx::internal::sql_cursor forward( tx, "SELECT generate_series(1, 4)", "forward", pqxx::cursor_base::forward_only, pqxx::cursor_base::read_only, pqxx::cursor_base::owned, false); PQXX_CHECK_EQUAL(forward.pos(), 0); PQXX_CHECK_EQUAL(forward.endpos(), -1); auto empty_result{forward.empty_result()}; PQXX_CHECK_EQUAL(std::size(empty_result), 0); auto displacement{0}; auto one{forward.fetch(1, displacement, pqxx::sl::current())}; PQXX_CHECK_EQUAL(std::size(one), 1); PQXX_CHECK_EQUAL(one[0][0].as(), "1"); PQXX_CHECK_EQUAL(displacement, 1); PQXX_CHECK_EQUAL(forward.pos(), 1); auto offset{forward.move(1, displacement, pqxx::sl::current())}; PQXX_CHECK_EQUAL(offset, 1); PQXX_CHECK_EQUAL(displacement, 1); PQXX_CHECK_EQUAL(forward.pos(), 2); PQXX_CHECK_EQUAL(forward.endpos(), -1); auto row{forward.fetch(0, displacement, pqxx::sl::current())}; PQXX_CHECK_EQUAL(std::size(row), 0); PQXX_CHECK_EQUAL(displacement, 0); PQXX_CHECK_EQUAL(forward.pos(), 2); row = forward.fetch(0, pqxx::sl::current()); PQXX_CHECK_EQUAL(std::size(row), 0); PQXX_CHECK_EQUAL(forward.pos(), 2); PQXX_CHECK_EQUAL(forward.pos(), 2); offset = forward.move(1, pqxx::sl::current()); PQXX_CHECK_EQUAL(offset, 1); PQXX_CHECK_EQUAL(forward.pos(), 3); row = forward.fetch(1, pqxx::sl::current()); PQXX_CHECK_EQUAL(std::size(row), 1); PQXX_CHECK_EQUAL(forward.pos(), 4); PQXX_CHECK_EQUAL(row[0][0].as(), "4"); empty_result = forward.fetch(1, displacement, pqxx::sl::current()); PQXX_CHECK_EQUAL(std::size(empty_result), 0, "Got rows at end of cursor"); PQXX_CHECK_EQUAL(forward.pos(), 5); PQXX_CHECK_EQUAL(forward.endpos(), 5); PQXX_CHECK_EQUAL(displacement, 1); offset = forward.move(5, displacement, pqxx::sl::current()); PQXX_CHECK_EQUAL(offset, 0); PQXX_CHECK_EQUAL(forward.pos(), 5, "pos() is beyond end"); PQXX_CHECK_EQUAL(forward.endpos(), 5); PQXX_CHECK_EQUAL(displacement, 0); // Move through entire result set at once. pqxx::internal::sql_cursor forward2( tx, "SELECT generate_series(1, 4)", "forward", pqxx::cursor_base::forward_only, pqxx::cursor_base::read_only, pqxx::cursor_base::owned, false); // Move through entire result set at once. offset = forward2.move(pqxx::cursor_base::all(), displacement, pqxx::sl::current()); PQXX_CHECK_EQUAL(offset, 4); PQXX_CHECK_EQUAL(displacement, 5); PQXX_CHECK_EQUAL(forward2.pos(), 5); PQXX_CHECK_EQUAL(forward2.endpos(), 5); pqxx::internal::sql_cursor forward3( tx, "SELECT generate_series(1, 4)", "forward", pqxx::cursor_base::forward_only, pqxx::cursor_base::read_only, pqxx::cursor_base::owned, false); // Fetch entire result set at once. auto rows{forward3.fetch( pqxx::cursor_base::all(), displacement, pqxx::sl::current())}; PQXX_CHECK_EQUAL(std::size(rows), 4); PQXX_CHECK_EQUAL(displacement, 5); PQXX_CHECK_EQUAL(forward3.pos(), 5); PQXX_CHECK_EQUAL(forward3.endpos(), 5); pqxx::internal::sql_cursor forward_empty( tx, "SELECT generate_series(0, -1)", "forward_empty", pqxx::cursor_base::forward_only, pqxx::cursor_base::read_only, pqxx::cursor_base::owned, false); offset = forward_empty.move(3, displacement, pqxx::sl::current()); PQXX_CHECK_EQUAL(forward_empty.pos(), 1); PQXX_CHECK_EQUAL(forward_empty.endpos(), 1); PQXX_CHECK_EQUAL(displacement, 1); PQXX_CHECK_EQUAL(offset, 0); } void test_scroll_sql_cursor(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::internal::sql_cursor scroll( tx, "SELECT generate_series(1, 10)", "scroll", pqxx::cursor_base::random_access, pqxx::cursor_base::read_only, pqxx::cursor_base::owned, false); PQXX_CHECK_EQUAL(scroll.pos(), 0); PQXX_CHECK_EQUAL(scroll.endpos(), -1); auto rows{scroll.fetch(pqxx::cursor_base::next(), pqxx::sl::current())}; PQXX_CHECK_EQUAL(std::size(rows), 1); PQXX_CHECK_EQUAL(scroll.pos(), 1); PQXX_CHECK_EQUAL(scroll.endpos(), -1); // Turn cursor around. This is where we begin to feel SQL cursors' // semantics: we pre-decrement, ending up on the position in front of the // first row and returning no rows. rows = scroll.fetch(pqxx::cursor_base::prior(), pqxx::sl::current()); PQXX_CHECK_EQUAL(std::empty(rows), true); PQXX_CHECK_EQUAL(scroll.pos(), 0); PQXX_CHECK_EQUAL(scroll.endpos(), -1); // Bounce off the left-hand side of the result set. Can't move before the // starting position. auto offset{0}, displacement{0}; offset = scroll.move(-3, displacement, pqxx::sl::current()); PQXX_CHECK_EQUAL(offset, 0); PQXX_CHECK_EQUAL(displacement, 0); PQXX_CHECK_EQUAL(scroll.pos(), 0); PQXX_CHECK_EQUAL(scroll.endpos(), -1); // Try bouncing off the left-hand side a little harder. Take 4 paces away // from the boundary and run into it. offset = scroll.move(4, displacement, pqxx::sl::current()); PQXX_CHECK_EQUAL(offset, 4); PQXX_CHECK_EQUAL(displacement, 4); PQXX_CHECK_EQUAL(scroll.pos(), 4); PQXX_CHECK_EQUAL(scroll.endpos(), -1); offset = scroll.move(-10, displacement, pqxx::sl::current()); PQXX_CHECK_EQUAL(offset, 3); PQXX_CHECK_EQUAL(displacement, -4); PQXX_CHECK_EQUAL(scroll.pos(), 0); PQXX_CHECK_EQUAL(scroll.endpos(), -1); rows = scroll.fetch(3, pqxx::sl::current()); PQXX_CHECK_EQUAL(scroll.pos(), 3); PQXX_CHECK_EQUAL(std::size(rows), 3); PQXX_CHECK_EQUAL(rows[2][0].as(), 3); rows = scroll.fetch(-1, pqxx::sl::current()); PQXX_CHECK_EQUAL(scroll.pos(), 2); PQXX_CHECK_EQUAL(rows[0][0].as(), 2); rows = scroll.fetch(1, pqxx::sl::current()); PQXX_CHECK_EQUAL(scroll.pos(), 3, "Bad pos() after inverse turnaround"); PQXX_CHECK_EQUAL(rows[0][0].as(), 3); } void test_adopted_sql_cursor(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; tx.exec( "DECLARE adopted SCROLL CURSOR FOR " "SELECT generate_series(1, 3)") .no_rows(); pqxx::internal::sql_cursor adopted(tx, "adopted", pqxx::cursor_base::owned); PQXX_CHECK_EQUAL(adopted.pos(), -1, "Adopted cursor has known pos()"); PQXX_CHECK_EQUAL(adopted.endpos(), -1, "Adopted cursor has known endpos()"); auto displacement{0}; auto rows{adopted.fetch( pqxx::cursor_base::all(), displacement, pqxx::sl::current())}; PQXX_CHECK_EQUAL(std::size(rows), 3); PQXX_CHECK_EQUAL(rows[0][0].as(), 1); PQXX_CHECK_EQUAL(rows[2][0].as(), 3); PQXX_CHECK_EQUAL(displacement, 4); PQXX_CHECK_EQUAL( adopted.pos(), -1, "End-of-result set pos() on adopted cur"); PQXX_CHECK_EQUAL(adopted.endpos(), -1, "endpos() set too early"); rows = adopted.fetch( pqxx::cursor_base::backward_all(), displacement, pqxx::sl::current()); PQXX_CHECK_EQUAL(std::size(rows), 3); PQXX_CHECK_EQUAL(rows[0][0].as(), 3); PQXX_CHECK_EQUAL(rows[2][0].as(), 1); PQXX_CHECK_EQUAL(displacement, -4); PQXX_CHECK_EQUAL(adopted.pos(), 0, "Failed to recognize starting position"); PQXX_CHECK_EQUAL(adopted.endpos(), -1, "endpos() set too early"); auto offset{adopted.move(pqxx::cursor_base::all(), pqxx::sl::current())}; PQXX_CHECK_EQUAL(offset, 3); PQXX_CHECK_EQUAL(adopted.pos(), 4); PQXX_CHECK_EQUAL(adopted.endpos(), 4); // Owned adopted cursors are cleaned up on destruction. pqxx::connection conn2; pqxx::work tx2(conn2, "tx2"); tx2 .exec( "DECLARE adopted2 CURSOR FOR " "SELECT generate_series(1, 3)") .no_rows(); { pqxx::internal::sql_cursor(tx2, "adopted2", pqxx::cursor_base::owned); } // Modern backends: accessing the cursor now is an error, as you'd expect. PQXX_CHECK_THROWS( tx2.exec("FETCH 1 IN adopted2"), pqxx::sql_error, "Owned adopted cursor not cleaned up"); tx2.abort(); pqxx::work tx3(conn2, "tx3"); tx3.exec( "DECLARE adopted3 CURSOR FOR " "SELECT generate_series(1, 3)"); { pqxx::internal::sql_cursor(tx3, "adopted3", pqxx::cursor_base::loose); } tx3.exec("MOVE 1 IN adopted3"); } void test_hold_cursor(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; // "With hold" cursor is kept after commit. pqxx::internal::sql_cursor with_hold( tx, "SELECT generate_series(1, 3)", "hold_cursor", pqxx::cursor_base::forward_only, pqxx::cursor_base::read_only, pqxx::cursor_base::owned, true); tx.commit(); pqxx::work tx2(cx, "tx2"); auto rows{with_hold.fetch(1, pqxx::sl::current())}; PQXX_CHECK_EQUAL( std::size(rows), 1, "Did not get 1 row from with-hold cursor"); // Cursor without hold is closed on commit. pqxx::internal::sql_cursor no_hold( tx2, "SELECT generate_series(1, 3)", "no_hold_cursor", pqxx::cursor_base::forward_only, pqxx::cursor_base::read_only, pqxx::cursor_base::owned, false); tx2.commit(); pqxx::work const tx3(cx, "tx3"); PQXX_CHECK_THROWS( no_hold.fetch(1, pqxx::sl::current()), pqxx::sql_error, "Cursor not closed on commit"); } PQXX_REGISTER_TEST(test_forward_sql_cursor); PQXX_REGISTER_TEST(test_scroll_sql_cursor); PQXX_REGISTER_TEST(test_adopted_sql_cursor); PQXX_REGISTER_TEST(test_hold_cursor); } // namespace libpqxx-8.0.1/test/test_stateless_cursor.cxx000066400000000000000000000045711516427024100213660ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { void test_stateless_cursor(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; pqxx::stateless_cursor< pqxx::cursor_base::read_only, pqxx::cursor_base::owned> empty(tx, "SELECT generate_series(0, -1)", "empty", false); auto rows{empty.retrieve(0, 0)}; PQXX_CHECK_EQUAL(std::empty(rows), true); rows = empty.retrieve(0, 1); PQXX_CHECK_EQUAL(std::size(rows), 0); PQXX_CHECK_EQUAL(empty.size(), 0); PQXX_CHECK_THROWS(empty.retrieve(1, 0), pqxx::range_error); pqxx::stateless_cursor< pqxx::cursor_base::read_only, pqxx::cursor_base::owned> stateless(tx, "SELECT generate_series(0, 9)", "stateless", false); PQXX_CHECK_EQUAL(stateless.size(), 10); // Retrieve nothing. rows = stateless.retrieve(1, 1); PQXX_CHECK_EQUAL(std::size(rows), 0); // Retrieve two rows. rows = stateless.retrieve(1, 3); PQXX_CHECK_EQUAL(std::size(rows), 2); PQXX_CHECK_EQUAL(rows[0][0].as(), 1); PQXX_CHECK_EQUAL(rows[1][0].as(), 2); // Retrieve same rows in reverse. rows = stateless.retrieve(2, 0); PQXX_CHECK_EQUAL(std::size(rows), 2); PQXX_CHECK_EQUAL(rows[0][0].as(), 2); PQXX_CHECK_EQUAL(rows[1][0].as(), 1); // Retrieve beyond end. rows = stateless.retrieve(9, 13); PQXX_CHECK_EQUAL(std::size(rows), 1); PQXX_CHECK_EQUAL(rows[0][0].as(), 9); // Retrieve beyond beginning. rows = stateless.retrieve(0, -4); PQXX_CHECK_EQUAL(std::size(rows), 1); PQXX_CHECK_EQUAL(rows[0][0].as(), 0); // Retrieve entire result set backwards. rows = stateless.retrieve(10, -15); PQXX_CHECK_EQUAL(std::size(rows), 10); PQXX_CHECK_EQUAL(rows[0][0].as(), 9); PQXX_CHECK_EQUAL(rows[9][0].as(), 0); // Normal usage pattern: step through result set, 4 rows at a time. rows = stateless.retrieve(0, 4); PQXX_CHECK_EQUAL(std::size(rows), 4); PQXX_CHECK_EQUAL(rows[0][0].as(), 0); PQXX_CHECK_EQUAL(rows[3][0].as(), 3); rows = stateless.retrieve(4, 8); PQXX_CHECK_EQUAL(std::size(rows), 4); PQXX_CHECK_EQUAL(rows[0][0].as(), 4); PQXX_CHECK_EQUAL(rows[3][0].as(), 7); rows = stateless.retrieve(8, 12); PQXX_CHECK_EQUAL(std::size(rows), 2); PQXX_CHECK_EQUAL(rows[0][0].as(), 8); PQXX_CHECK_EQUAL(rows[1][0].as(), 9); } PQXX_REGISTER_TEST(test_stateless_cursor); } // namespace libpqxx-8.0.1/test/test_strconv.cxx000066400000000000000000000374161516427024100174640ustar00rootroot00000000000000#include #include #include #include #include #include "helpers.hxx" namespace { enum colour { red, green, blue }; enum class weather : short { hot, cold, wet }; enum class many : unsigned long long { bottom = 0, top = std::numeric_limits::max(), }; } // namespace namespace pqxx { PQXX_DECLARE_ENUM_CONVERSION(colour); PQXX_DECLARE_ENUM_CONVERSION(weather); PQXX_DECLARE_ENUM_CONVERSION(many); } // namespace pqxx namespace { using namespace std::literals; using pqxx::operator""_zv; void test_strconv_bool(pqxx::test::context &) { PQXX_CHECK_EQUAL(pqxx::to_string(false), "false", "Wrong to_string(false)."); PQXX_CHECK_EQUAL(pqxx::to_string(true), "true", "Wrong to_string(true)."); bool result{}; pqxx::from_string("false", result); PQXX_CHECK_EQUAL(result, false); pqxx::from_string("FALSE", result); PQXX_CHECK_EQUAL(result, false); pqxx::from_string("f", result); PQXX_CHECK_EQUAL(result, false); pqxx::from_string("F", result); PQXX_CHECK_EQUAL(result, false); pqxx::from_string("0", result); PQXX_CHECK_EQUAL(result, false); pqxx::from_string("true", result); PQXX_CHECK_EQUAL(result, true); pqxx::from_string("TRUE", result); PQXX_CHECK_EQUAL(result, true); pqxx::from_string("t", result); PQXX_CHECK_EQUAL(result, true); pqxx::from_string("T", result); PQXX_CHECK_EQUAL(result, true); pqxx::from_string("1", result); PQXX_CHECK_EQUAL(result, true); // Nasty little corner case: to_buf() for bool will return a view on a // string constant, and not use the buffer you give it. But into_buf() will // copy that into the buffer, and this requires a separate overrun check. std::array small_buf{}; PQXX_CHECK_THROWS( std::ignore = pqxx::into_buf(small_buf, true), pqxx::conversion_overrun); } void test_strconv_enum(pqxx::test::context &) { PQXX_CHECK_EQUAL(pqxx::to_string(red), "0"); PQXX_CHECK_EQUAL(pqxx::to_string(green), "1"); PQXX_CHECK_EQUAL(pqxx::to_string(blue), "2"); colour col{}; pqxx::from_string("2", col); PQXX_CHECK_EQUAL(col, blue); } void test_strconv_class_enum(pqxx::test::context &) { PQXX_CHECK_EQUAL(pqxx::to_string(weather::hot), "0"); PQXX_CHECK_EQUAL(pqxx::to_string(weather::wet), "2"); weather w{}; pqxx::from_string("2", w); PQXX_CHECK_EQUAL(w, weather::wet); PQXX_CHECK_EQUAL(pqxx::to_string(many::bottom), "0"); PQXX_CHECK_EQUAL( pqxx::to_string(many::top), pqxx::to_string(std::numeric_limits::max())); pqxx::connection cx; pqxx::work tx{cx}; std::tuple out; tx.exec("SELECT 0").one_row().to(out); } void test_strconv_optional(pqxx::test::context &) { PQXX_CHECK_THROWS( pqxx::to_string(std::optional{}), pqxx::conversion_error); PQXX_CHECK_EQUAL( pqxx::to_string(std::optional{std::in_place, 10}), "10"); PQXX_CHECK_EQUAL( pqxx::to_string(std::optional{std::in_place, -10000}), "-10000"); } void test_strconv_smart_pointer(pqxx::test::context &) { PQXX_CHECK_THROWS( pqxx::to_string(std::unique_ptr{}), pqxx::conversion_error); PQXX_CHECK_EQUAL(pqxx::to_string(std::make_unique(10)), "10"); PQXX_CHECK_EQUAL(pqxx::to_string(std::make_unique(-10000)), "-10000"); PQXX_CHECK_THROWS( pqxx::to_string(std::shared_ptr{}), pqxx::conversion_error); PQXX_CHECK_EQUAL(pqxx::to_string(std::make_shared(10)), "10"); PQXX_CHECK_EQUAL(pqxx::to_string(std::make_shared(-10000)), "-10000"); } // Cast a char to an unsigned int. unsigned char_as_unsigned(char n) { return static_cast(n); } // Hash a std::size_t into a char. constexpr char hash_index(std::size_t index) { return static_cast( static_cast((index ^ 37) + (index >> 5))); } /// Estimate number of bytes needed for `value`'s string representation. /** This is the generic implementation. * * All we really need to know for the purpose of our test is: * * 1. Will `into_buf()` overflow a zero-byte buffer? * 2. Will `into_buf()` overflow a one-byte buffer? * * We can't just use `pqxx::size_buffer()` because it's designed to give a * pessimistic estimate. Also, we're trying to test the string conversions, so * we'd like to avoid circular logic where we can. */ template constexpr std::size_t needs_bytes(T const &value) { // This is the generic implementation, because it works for all types we // support, but it's kind of circular reasoning. Might still catch a bug // though. return std::size(pqxx::to_string( value, pqxx::conversion_context{pqxx::encoding_group::ascii_safe})); } /// Specialisation for some types we know `std::format()` can handle. /** There can be differences of opinion on how long the text representation of * a floating-point number should be. But not ones that will affect our test. */ template requires(std::is_arithmetic_v) constexpr std::size_t needs_bytes(T const &value) { // Implementation using standard formatting library as an authority. return std::formatted_size("{}", value); } // Extra-thorough test for to_buf() & into_buf() on a given type. template void check_write( T const &value, std::string_view expected, pqxx::sl loc = pqxx::sl::current()) { std::string_view const name{pqxx::name_type()}; std::array buf{}; for (auto i{0u}; i < std::size(buf); ++i) buf.at(i) = hash_index(i); pqxx::conversion_context const c{pqxx::encoding_group::ascii_safe}; // Test to_buf(). std::string_view const out{pqxx::to_buf(buf, value, c)}; PQXX_CHECK_EQUAL( std::size(out), std::size(expected), std::format("to_buf() for {} wrote wrong length.", name), loc); auto const sz{std::size(out)}; PQXX_CHECK_LESS_EQUAL( sz, pqxx::string_traits::size_buffer(value), std::format("Under-budgeted for to_buf on {}.", name), loc); PQXX_CHECK_LESS( sz, std::size(buf), std::format("Too much to_buf() data for {}.", name), loc); PQXX_CHECK_EQUAL( out, expected, std::format("to_buf() for {} wrote wrong value.", name), loc); if (sz > 0) PQXX_CHECK_NOT_EQUAL( char_as_unsigned(out.at(sz - 1)), 0u, std::format("to_buf() for {} put terminating zero inside result.", name), loc); // Test into_buf(). for (auto i{0u}; i < std::size(buf); ++i) buf.at(i) = hash_index(i); std::size_t const end{pqxx::into_buf(buf, value, c)}; PQXX_CHECK_LESS_EQUAL( end, std::size(buf), std::format("into_buf() for {} overran buffer.", name), loc); PQXX_CHECK_LESS_EQUAL( end, pqxx::string_traits::size_buffer(value), std::format("Under-budgeted for into_buf() on {}.", name), loc); PQXX_CHECK_EQUAL( (std::string_view{std::data(buf), end}), expected, std::format("Wrong result from into_buf() on {}.", name), loc); // Check overrun reporting. std::size_t const bytes_needed{needs_bytes(value)}; if (bytes_needed > 0u) { std::array small{'x', 'y'}; std::span const smallspan{small}; PQXX_CHECK_THROWS( std::ignore = pqxx::into_buf(smallspan.first<0>(), value, c), pqxx::conversion_overrun); PQXX_CHECK(small[0] == 'x'); PQXX_CHECK(small[1] == 'y'); if (bytes_needed > 1u) { PQXX_CHECK_THROWS( std::ignore = pqxx::into_buf(smallspan.first<1>(), value, c), pqxx::conversion_overrun); PQXX_CHECK(small[1] == 'y'); } } if constexpr (pqxx::has_null()) { auto const a_null{pqxx::make_null()}; PQXX_CHECK(pqxx::is_null(a_null)); PQXX_CHECK_THROWS(pqxx::to_string(a_null), pqxx::conversion_error); } } void test_to_buf_into_buf(pqxx::test::context &tctx) { check_write(false, "false"); check_write(true, "true"); check_write(short{0}, "0"); check_write(short{1}, "1"); check_write(short{10}, "10"); check_write(short{99}, "99"); check_write(short{100}, "100"); check_write(short{999}, "999"); check_write(short{1000}, "1000"); check_write(short{9999}, "9999"); check_write(short{10000}, "10000"); check_write(short{32767}, "32767"); check_write(short{-1}, "-1"); check_write(short{-10}, "-10"); check_write(short{-99}, "-99"); check_write(short{-100}, "-100"); check_write(short{-999}, "-999"); check_write(short{-1000}, "-1000"); check_write(short{-9999}, "-9999"); check_write(short{-10000}, "-10000"); check_write(short{-32767}, "-32767"); check_write(short{-32768}, "-32768"); check_write(static_cast(0), "0"); check_write(static_cast(1), "1"); check_write(static_cast(9), "9"); check_write(static_cast(10), "10"); check_write(static_cast(99), "99"); check_write(static_cast(32767), "32767"); check_write(static_cast(32768), "32768"); check_write(static_cast(65535), "65535"); check_write(0, "0"); check_write(1, "1"); check_write(9, "9"); check_write(10, "10"); check_write(99, "99"); check_write(2147483647, "2147483647"); check_write(-1, "-1"); check_write(-9, "-9"); check_write(-10, "-10"); check_write(-99, "-99"); check_write(-2147483647, "-2147483647"); check_write(-2147483648, "-2147483648"); check_write(0u, "0"); check_write(1u, "1"); check_write(2147483647u, "2147483647"); check_write(4294967296u, "4294967296"); check_write(0L, "0"); check_write(1L, "1"); check_write(100000L, "100000"); check_write(2147483647L, "2147483647"); check_write(-1L, "-1"); check_write(-2147483647L, "-2147483647"); check_write(-2147483648L, "-2147483648"); check_write(0uL, "0"); check_write(1uL, "1"); check_write(2147483647uL, "2147483647"); check_write(4294967296uL, "4294967296"); check_write(0LL, "0"); check_write(1LL, "1"); check_write(100000LL, "100000"); check_write(2147483647LL, "2147483647"); check_write(-1LL, "-1"); check_write(-2147483647LL, "-2147483647"); check_write(-2147483648LL, "-2147483648"); check_write(0ULL, "0"); check_write(1ULL, "1"); check_write(2147483647ULL, "2147483647"); check_write(4294967296ULL, "4294967296"); check_write(0.0f, "0"); check_write(0.125f, "0.125"); check_write(1.0f, "1"); check_write(10000.0f, "10000"); check_write(-0.0f, "-0"); check_write(-0.125f, "-0.125"); check_write(-1.0f, "-1"); check_write(-10000.0f, "-10000"); check_write(0.0, "0"); check_write(0.125, "0.125"); check_write(1.0, "1"); check_write(10000.0, "10000"); check_write(-0.0, "-0"); check_write(-0.125, "-0.125"); check_write(-1.0, "-1"); check_write(-10000.0, "-10000"); check_write(0.0L, "0"); check_write(0.125L, "0.125"); check_write(1.0L, "1"); check_write(10000.0L, "10000"); check_write(-0.0L, "-0"); check_write(-0.125L, "-0.125"); check_write(-1.0L, "-1"); check_write(-10000.0L, "-10000"); check_write(std::optional{37}, "37"); check_write(std::variant{482}, "482"); check_write(std::variant{777UL}, "777"); check_write(static_cast(""), ""); check_write(static_cast("Hello"), "Hello"); std::array chars{}; chars.at(0) = '\0'; for (auto i{1u}; i < std::size(chars); ++i) chars.at(i) = 'x'; check_write(std::data(chars), ""); chars.at(0) = 'n'; chars.at(1) = '\0'; check_write(std::data(chars), "n"); check_write("World", "World"); check_write("", ""); check_write(""s, ""); check_write("Blah"s, "Blah"); std::string const randstr{tctx.make_name("x")}; check_write(randstr, randstr); check_write(""sv, ""); // NOLINTNEXTLINE(bugprone-string-constructor) check_write(std::string_view{"abc", 0u}, ""); check_write("view"sv, "view"); check_write(std::string_view{"viewport", 4u}, "view"); check_write(std::string_view{randstr}, randstr); check_write(""_zv, ""); check_write("foo"_zv, "foo"); check_write(pqxx::zview{randstr}, randstr); check_write(std::make_unique("Boogie"), "Boogie"); check_write(std::make_shared("Woogie"), "Woogie"); check_write(std::make_shared(randstr), randstr); check_write(std::vector{}, "{}"); check_write(std::array{10, 9, 8}, "{10,9,8}"); check_write(std::vector{3, 2, 1}, "{3,2,1}"); check_write(std::vector{}, "{}"); // TODO: Use raw strings once Visual Studio copes with backslashes there. // NOLINTBEGIN(modernize-raw-string-literal) check_write(std::vector{"eins", "zwo"}, "{\"eins\",\"zwo\"}"); check_write(std::vector{"x,y", "z"}, "{\"x,y\",\"z\"}"); // NOLINTEND(modernize-raw-string-literal) check_write(std::list{"foo"}, "{\"foo\"}"); check_write( std::chrono::year_month_day{ std::chrono::year{2025}, std::chrono::month{03}, std::chrono::day{01}}, "2025-03-01"); check_write( pqxx::range{ pqxx::inclusive_bound{9}, pqxx::inclusive_bound{17}}, "[9,17]"); check_write( pqxx::range{ pqxx::exclusive_bound{0}, pqxx::exclusive_bound{10}}, "(0,10)"); check_write(pqxx::range{pqxx::no_bound{}, pqxx::no_bound{}}, "(,)"); check_write(std::vector{}, "\\x"); check_write(std::vector{std::byte{0x61}}, "\\x61"); check_write( std::array{std::byte{'a'}, std::byte{'b'}}, "\\x6162"); } void test_to_buf_multi(pqxx::test::context &) { std::vector buf{}; buf.resize(50); auto strings{pqxx::to_buf_multi(buf, "foo", -1025, "bar", 3ul, "zarg")}; PQXX_CHECK_EQUAL(std::size(strings), 5u); PQXX_CHECK_EQUAL(strings.at(0), "foo"); PQXX_CHECK_EQUAL(strings.at(1), "-1025"); PQXX_CHECK_EQUAL(strings.at(2), "bar"); PQXX_CHECK_EQUAL(strings.at(3), "3"); PQXX_CHECK_EQUAL(strings.at(4), "zarg"); // The strings start right at the beginning of buf. PQXX_CHECK(std::data(strings.at(0)) == std::data(buf)); // The strings are packed tightly together. for (std::size_t i{1}; i < std::size(strings); ++i) PQXX_CHECK( std::data(strings.at(i)) == std::data(strings.at(i - 1)) + std::size(strings.at(i - 1))); // Compare to the version that takes a conversion_context. std::vector buf2{}; buf2.resize(50); auto strings2{pqxx::to_buf_multi( pqxx::conversion_context{}, buf2, "foo", -1025, "bar", 3ul, "zarg")}; PQXX_CHECK_EQUAL(std::size(strings2), std::size(strings)); PQXX_CHECK_EQUAL(strings2.at(0), strings.at(0)); PQXX_CHECK_EQUAL(strings2.at(1), strings.at(1)); PQXX_CHECK_EQUAL(strings2.at(2), strings.at(2)); PQXX_CHECK_EQUAL(strings2.at(3), strings.at(3)); PQXX_CHECK_EQUAL(strings2.at(4), strings.at(4)); } template void check_float(T value) { PQXX_CHECK_BOUNDS( pqxx::from_string(pqxx::to_string(value)), value - 0.001, value + 0.001); } void test_to_buf_float(pqxx::test::context &tctx) { check_float(tctx.make_float_num()); check_float(tctx.make_float_num()); check_float(tctx.make_float_num()); } template void check_string(T const &value) { PQXX_CHECK_EQUAL(pqxx::to_string(value), value); PQXX_CHECK_EQUAL(pqxx::from_string(value), value); } void test_string_to_string(pqxx::test::context &tctx) { auto const str{tctx.make_name("str")}; PQXX_CHECK_EQUAL(pqxx::to_string(str), str); PQXX_CHECK_EQUAL(pqxx::from_string(str), str); PQXX_CHECK_EQUAL(pqxx::to_string(str), str); PQXX_CHECK_EQUAL(pqxx::from_string(str), str); PQXX_CHECK_EQUAL(pqxx::to_string(str), str); } PQXX_REGISTER_TEST(test_strconv_bool); PQXX_REGISTER_TEST(test_strconv_enum); PQXX_REGISTER_TEST(test_strconv_class_enum); PQXX_REGISTER_TEST(test_strconv_optional); PQXX_REGISTER_TEST(test_strconv_smart_pointer); PQXX_REGISTER_TEST(test_to_buf_into_buf); PQXX_REGISTER_TEST(test_to_buf_multi); PQXX_REGISTER_TEST(test_to_buf_float); PQXX_REGISTER_TEST(test_string_to_string); } // namespace libpqxx-8.0.1/test/test_stream_from.cxx000066400000000000000000000306031516427024100202730ustar00rootroot00000000000000#include #include #include "helpers.hxx" #include "sample_types.hxx" #include #include #include #include #include #include namespace { #include "pqxx/internal/ignore-deprecated-pre.hxx" void test_stream_from_nonoptionals(pqxx::connection &connection) { pqxx::work tx{connection}; auto extractor{pqxx::stream_from::query( tx, "SELECT * FROM stream_from_test ORDER BY number0")}; PQXX_CHECK(extractor); std::tuple got_tuple; try { // We can't read the "910" row -- it contains nulls, which our tuple does // not accept. extractor >> got_tuple; pqxx::test::check_notreached( "Failed to fail to stream null values into null-less fields."); } catch (pqxx::conversion_error const &e) { std::string const what{e.what()}; if (not pqxx::str_contains(what, "null")) throw; pqxx::test::expected_exception( "Could not stream nulls into null-less fields: " + what); } // The stream is still good though. // The second tuple is fine. extractor >> got_tuple; PQXX_CHECK(extractor); PQXX_CHECK_EQUAL(std::get<0>(got_tuple), 1234); // Don't know much about the timestamp, but let's assume it starts with a // year in the second millennium. PQXX_CHECK(std::get<1>(got_tuple).at(0) == '2'); PQXX_CHECK_LESS(std::size(std::get<1>(got_tuple)), 40u); PQXX_CHECK_GREATER(std::size(std::get<1>(got_tuple)), 20u); PQXX_CHECK_EQUAL(std::get<2>(got_tuple), 4321); PQXX_CHECK_EQUAL(std::get<3>(got_tuple), (ipv4{8, 8, 8, 8})); PQXX_CHECK_EQUAL(std::get<4>(got_tuple), "hello\n \tworld"); PQXX_CHECK_EQUAL(std::get<5>(got_tuple), (bytea{'\x00', '\x01', '\x02'})); // The third tuple contains some nulls. For what it's worth, when we *know* // that we're getting nulls, we can stream them into nullptr_t fields. std::tuple< int, std::string, std::nullptr_t, std::nullptr_t, std::string, bytea> tup_w_nulls; extractor >> tup_w_nulls; PQXX_CHECK(extractor, "Stream ended prematurely."); PQXX_CHECK_EQUAL(std::get<0>(tup_w_nulls), 5678); PQXX_CHECK(std::get<2>(tup_w_nulls) == nullptr); PQXX_CHECK(std::get<3>(tup_w_nulls) == nullptr); // We're at the end of the stream. extractor >> tup_w_nulls; PQXX_CHECK(not extractor, "Stream did not end."); // Of course we can't stream a non-null value into a nullptr field. auto ex2{pqxx::stream_from::query(tx, "SELECT 1")}; std::tuple null_tup; try { ex2 >> null_tup; pqxx::test::check_notreached( "stream_from should have refused to convert non-null value to " "nullptr_t."); } catch (pqxx::conversion_error const &e) { std::string const what{e.what()}; if (not pqxx::str_contains(what, "null")) throw; pqxx::test::expected_exception( std::string{"Could not extract row: "} + what); } ex2 >> null_tup; PQXX_CHECK(not ex2, "Stream did not end."); PQXX_CHECK_SUCCEEDS(tx.exec1("SELECT 1")); } void test_bad_tuples(pqxx::connection &cx) { pqxx::work tx{cx}; auto extractor{pqxx::stream_from::table(tx, {"stream_from_test"})}; PQXX_CHECK(extractor); std::tuple got_tuple_too_short; try { extractor >> got_tuple_too_short; pqxx::test::check_notreached("stream_from improperly read first row"); } catch (pqxx::usage_error const &e) { std::string const what{e.what()}; if (not pqxx::str_contains(what, '1') or not pqxx::str_contains(what, '6')) throw; pqxx::test::expected_exception("Tuple is wrong size: " + what); } std::tuple got_tuple_too_long; try { extractor >> got_tuple_too_long; pqxx::test::check_notreached("stream_from improperly read first row"); } catch (pqxx::usage_error const &e) { std::string const what{e.what()}; if (not pqxx::str_contains(what, '6') or not pqxx::str_contains(what, '7')) throw; pqxx::test::expected_exception("Could not extract row: " + what); } extractor.complete(); } // Annoying: clang-tidy complains about an unchecked std::optional access, // even if we check that OPT contains a value before we retrieve it. #define ASSERT_FIELD_EQUAL(OPT, VAL) \ PQXX_CHECK(static_cast(OPT), "unexpected null field"); \ if ((OPT)) \ PQXX_CHECK_EQUAL(*(OPT), (VAL), "field value mismatch") #define ASSERT_FIELD_NULL(OPT) \ PQXX_CHECK(not static_cast(OPT), "expected null field") /// Japanese text: \u3053\u3093\u306b\u3061\u308f ("konichiwa," a greeting). constexpr std::string_view japanese_utf8{ "\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x82\x8f"}; template class O> void test_stream_from_optional(pqxx::connection &connection) { pqxx::work tx{connection}; auto extractor{pqxx::stream_from::query( tx, "SELECT * FROM stream_from_test ORDER BY number0")}; PQXX_CHECK(extractor); std::tuple, O, O, O, O> got_tuple; extractor >> got_tuple; PQXX_CHECK(extractor); PQXX_CHECK_EQUAL(std::get<0>(got_tuple), 910); ASSERT_FIELD_NULL(std::get<1>(got_tuple)); ASSERT_FIELD_NULL(std::get<2>(got_tuple)); ASSERT_FIELD_NULL(std::get<3>(got_tuple)); // These look like false positives from clang-tidy: ASSERT_FIELD_EQUAL // does check for empty optionals, yet we get a warning about a check being // needed. // NOLINTBEGIN(bugprone-unchecked-optional-access) ASSERT_FIELD_EQUAL((std::get<4>(got_tuple)), "\\N"); ASSERT_FIELD_EQUAL((std::get<5>(got_tuple)), bytea{}); extractor >> got_tuple; PQXX_CHECK(extractor); PQXX_CHECK_EQUAL(std::get<0>(got_tuple), 1234); PQXX_CHECK(static_cast(std::get<1>(got_tuple))); ASSERT_FIELD_EQUAL((std::get<2>(got_tuple)), 4321); ASSERT_FIELD_EQUAL((std::get<3>(got_tuple)), (ipv4{8, 8, 8, 8})); ASSERT_FIELD_EQUAL((std::get<4>(got_tuple)), "hello\n \tworld"); ASSERT_FIELD_EQUAL( (std::get<5>(got_tuple)), (bytea{'\x00', '\x01', '\x02'})); extractor >> got_tuple; PQXX_CHECK(extractor); PQXX_CHECK_EQUAL(std::get<0>(got_tuple), 5678); ASSERT_FIELD_EQUAL((std::get<1>(got_tuple)), "2018-11-17 21:23:00"); ASSERT_FIELD_NULL(std::get<2>(got_tuple)); ASSERT_FIELD_NULL(std::get<3>(got_tuple)); ASSERT_FIELD_EQUAL((std::get<4>(got_tuple)), japanese_utf8); ASSERT_FIELD_EQUAL( (std::get<5>(got_tuple)), (bytea{'f', 'o', 'o', ' ', 'b', 'a', 'r', '\0'})); // NOLINTEND(bugprone-unchecked-optional-access) extractor >> got_tuple; PQXX_CHECK(not extractor, "stream_from failed to detect end of stream"); extractor.complete(); } void test_stream_from(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; tx.exec0( "CREATE TEMP TABLE stream_from_test (" "number0 INT NOT NULL," "ts1 TIMESTAMP NULL," "number2 INT NULL," "addr3 INET NULL," "txt4 TEXT NULL," "bin5 BYTEA NOT NULL" ")"); tx.exec( "INSERT INTO stream_from_test VALUES ($1,$2,$3,$4,$5,$6)", pqxx::params{tx, 910, nullptr, nullptr, nullptr, "\\N", bytea{}}); tx.exec( "INSERT INTO stream_from_test VALUES ($1,$2,$3,$4,$5,$6)", pqxx::params{ tx, 1234, "now", 4321, ipv4{8, 8, 8, 8}, "hello\n \tworld", bytea{'\x00', '\x01', '\x02'}}); tx.exec( "INSERT INTO stream_from_test VALUES ($1,$2,$3,$4,$5,$6)", pqxx::params{ tx, 5678, "2018-11-17 21:23:00", nullptr, nullptr, japanese_utf8, bytea{'f', 'o', 'o', ' ', 'b', 'a', 'r', '\0'}}); tx.commit(); test_stream_from_nonoptionals(cx); test_bad_tuples(cx); test_stream_from_optional(cx); test_stream_from_optional(cx); } void test_stream_from_does_escaping(pqxx::test::context &) { std::string const input{"a\t\n\n\n \\b\nc"}; pqxx::connection cx; pqxx::work tx{cx}; tx.exec("CREATE TEMP TABLE badstr (str text)").no_rows(); tx.exec("INSERT INTO badstr (str) VALUES ($1)", pqxx::params{tx, input}) .no_rows(); auto reader{pqxx::stream_from::table(tx, {"badstr"})}; std::tuple out; reader >> out; PQXX_CHECK_EQUAL(std::get<0>(out), input); } void test_stream_from_does_iteration(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; tx.exec0("CREATE TEMP TABLE str (s text)"); tx.exec0("INSERT INTO str (s) VALUES ('foo')"); auto reader{pqxx::stream_from::table(tx, {"str"})}; int i{0}; std::string out; for (std::tuple const &t : reader.iter()) { i++; out = std::get<0>(t); } PQXX_CHECK_EQUAL(i, 1); PQXX_CHECK_EQUAL(out, "foo"); tx.exec0("INSERT INTO str (s) VALUES ('bar')"); i = 0; std::set strings; auto reader2{pqxx::stream_from::table(tx, {"str"})}; for (std::tuple const &t : reader2.iter()) { i++; strings.insert(std::get<0>(t)); } PQXX_CHECK_EQUAL(i, 2); PQXX_CHECK_EQUAL(std::size(strings), 2u); PQXX_CHECK(strings.contains("foo")); PQXX_CHECK(strings.contains("bar")); } void test_stream_from_read_row(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; tx.exec0("CREATE TEMP TABLE sample (id integer, name varchar, opt integer)"); tx.exec0("INSERT INTO sample (id, name) VALUES (321, 'something')"); auto stream{pqxx::stream_from::table(tx, {"sample"})}; auto fields{stream.read_row()}; PQXX_CHECK(fields != nullptr); // (Work around a weird false positive in clang-tidy where the check that // fields is _not_ null somehow convinces the checker that it _is_ null.) assert(fields != nullptr); PQXX_CHECK_EQUAL(fields->size(), 3ul); PQXX_CHECK_EQUAL(std::string((*fields)[0]), "321"); PQXX_CHECK_EQUAL(std::string((*fields)[1]), "something"); PQXX_CHECK(std::data((*fields)[2]) == nullptr); auto last{stream.read_row()}; PQXX_CHECK(last == nullptr, "No null pointer at end of stream."); } void test_stream_from_parses_awkward_strings(pqxx::test::context &) { pqxx::connection cx; bool const ascii_db{cx.get_var("server_encoding") == "SQL_ASCII"}; // This is a particularly awkward encoding that we should test. Its // multibyte characters can include byte values that *look* like ASCII // characters, such as quotes and backslashes. It is crucial that we parse // those properly. A byte-for-byte scan could find special ASCII characters // that aren't really there. cx.set_client_encoding("SJIS"); pqxx::work tx{cx}; tx.exec("CREATE TEMP TABLE nasty(id integer, value varchar)").no_rows(); tx.exec( "INSERT INTO nasty(id, value) VALUES " // A proper null. "(0, NULL), " // Some strings that could easily be mis-parsed as null. "(1, 'NULL'), " "(2, '\\N'), " "(3, '''NULL''')") .no_rows(); if (not ascii_db) { // An SJIS multibyte character that ends in a byte that happens to be the // ASCII value for a backslash. This is one example of how an SJIS SQL // injection can break out of a string. tx.exec("INSERT INTO nasty(id, value) VALUES (4, '\x81\x5c')").no_rows(); } std::vector> values; for (auto const &[id, value] : tx.query>( "SELECT id, value FROM nasty ORDER BY id")) { PQXX_CHECK_EQUAL(id, std::size(values), "Test data is broken."); values.push_back(value); } PQXX_CHECK(not values.at(0).has_value(), "Null did not work properly."); PQXX_CHECK(values.at(1).has_value(), "String 'NULL' became a NULL."); PQXX_CHECK_EQUAL( values.at(1).value_or("empty"), "NULL", "String 'NULL' went badly."); PQXX_CHECK(values.at(2).has_value(), "String '\\N' became a NULL."); PQXX_CHECK_EQUAL( values.at(2).value_or("empty"), "\\N", "String '\\N' went badly."); PQXX_CHECK(values.at(3).has_value(), "String \"'NULL'\" became a NULL."); PQXX_CHECK_EQUAL( values.at(3).value_or("empty"), "'NULL'", "String \"'NULL'\" went badly."); if (not ascii_db) PQXX_CHECK_EQUAL( values.at(4).value_or("empty"), "\x81\x5c", "Finicky SJIS character went badly."); } #include "pqxx/internal/ignore-deprecated-post.hxx" PQXX_REGISTER_TEST(test_stream_from); PQXX_REGISTER_TEST(test_stream_from_does_escaping); PQXX_REGISTER_TEST(test_stream_from_does_iteration); PQXX_REGISTER_TEST(test_stream_from_read_row); PQXX_REGISTER_TEST(test_stream_from_parses_awkward_strings); } // namespace libpqxx-8.0.1/test/test_stream_query.cxx000066400000000000000000000231641516427024100205010ustar00rootroot00000000000000#include #include "helpers.hxx" #include "sample_types.hxx" #include #include #include #include namespace { void test_stream_handles_empty(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; for (auto [out] : tx.stream("SELECT generate_series(1, 0)")) PQXX_CHECK(false, "Unexpectedly got a value: " + pqxx::to_string(out)); PQXX_CHECK_EQUAL(tx.query_value("SELECT 99"), 99); } void test_stream_does_escaping(pqxx::test::context &) { std::string const input{"a\t\n\n\n \\b\nc"}; pqxx::connection cx; pqxx::work tx{cx}; int counter{0}; for (auto [out] : tx.stream("SELECT " + tx.quote(input))) { PQXX_CHECK_EQUAL(out, input); ++counter; } PQXX_CHECK_EQUAL(counter, 1); } void test_stream_iterates(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; std::vector ids; std::vector values; for (auto [id, value] : tx.stream( "SELECT generate_series, 'String ' || generate_series::text || '.' " "FROM generate_series(1, 2)")) { ids.push_back(id); values.push_back(value); } PQXX_CHECK_EQUAL(tx.query_value("SELECT 99"), 99); tx.commit(); PQXX_CHECK_EQUAL(std::size(ids), 2u); PQXX_CHECK_EQUAL(std::size(values), 2u); PQXX_CHECK_EQUAL(ids.at(0), 1); PQXX_CHECK_EQUAL(values.at(0), "String 1."); PQXX_CHECK_EQUAL(ids.at(1), 2); PQXX_CHECK_EQUAL(values.at(1), "String 2."); } void test_stream_reads_simple_values(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; int counter{0}; for (auto [id, name] : tx.stream("SELECT 213, 'Hi'")) { PQXX_CHECK_EQUAL(id, 213u); PQXX_CHECK_EQUAL(name, "Hi"); ++counter; } PQXX_CHECK_EQUAL(counter, 1); PQXX_CHECK_EQUAL(tx.query_value("SELECT 333"), 333); } void test_stream_reads_string_view(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; std::vector out; for (auto [v] : tx.stream( "SELECT 'x' || generate_series FROM generate_series(1, 2)")) { static_assert(std::is_same_v); out.emplace_back(v); } PQXX_CHECK_EQUAL(std::size(out), 2u); PQXX_CHECK_EQUAL(out.at(0), "x1"); PQXX_CHECK_EQUAL(out.at(1), "x2"); } void test_stream_reads_nulls_as_optionals(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; for (auto [null] : tx.stream>("SELECT NULL")) PQXX_CHECK(not null.has_value(), "NULL translated to nonempty optional."); for (auto [val] : tx.stream>("SELECT 'x'")) { PQXX_CHECK(val.has_value()); PQXX_CHECK_EQUAL(val.value_or("empty"), "x"); } } void test_stream_reads_arrays(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; int count{0}; for (auto [a] : tx.stream>("SELECT ARRAY[1,-42]")) { PQXX_CHECK_EQUAL(a[0], 1); PQXX_CHECK_EQUAL(a[1], -42); ++count; } PQXX_CHECK_EQUAL(count, 1); count = 0; cx.set_client_encoding("SJIS"); // Some SJIS-encoded strings with multibyte characters that happen to contain // bytes with the same numeric values as the ASCII characters for backslash // and a closing brace. If we were to parse this in the wrong encoding // group, things would go horribly wrong. auto const painful_array{"SELECT ARRAY['\x81\x5c', '\x81\x7d']"}; for (auto [a] : tx.stream>(painful_array)) { PQXX_CHECK_EQUAL(a.dimensions(), 1u); auto const sizes{a.sizes()}; PQXX_CHECK_EQUAL(std::size(sizes), 1u); PQXX_CHECK_EQUAL(sizes[0], 2u); PQXX_CHECK_EQUAL(a[0], "\x81\x5c"); PQXX_CHECK_EQUAL(a[1], "\x81\x7d"); ++count; } PQXX_CHECK_EQUAL(count, 1); } void test_stream_parses_awkward_strings(pqxx::test::context &) { pqxx::connection cx; bool const ascii_db{cx.get_var("server_encoding") == "SQL_ASCII"}; // This is a particularly awkward encoding that we should test. Its // multibyte characters can include byte values that *look* like ASCII // characters, such as quotes and backslashes. It is crucial that we parse // those properly. A byte-for-byte scan could find special ASCII characters // that aren't really there. cx.set_client_encoding("SJIS"); pqxx::work tx{cx}; tx.exec("CREATE TEMP TABLE nasty(id integer, value varchar)").no_rows(); tx.exec( "INSERT INTO nasty(id, value) VALUES " // A proper null. "(0, NULL), " // Some strings that could easily be mis-parsed as null. "(1, 'NULL'), " "(2, '\\N'), " "(3, '''NULL'''), " "(4, '\t'), " "(5, '\\\\\\\n\\\\')") .no_rows(); if (not ascii_db) { // An SJIS multibyte character that ends in a byte that happens to be the // ASCII value for a backslash. This is one example of how an SJIS SQL // injection can break out of a string. tx.exec("INSERT INTO nasty(id, value) VALUES (6, '\x81\x5c')").no_rows(); } std::vector> values; for (auto [id, value] : tx.stream>( "SELECT id, value FROM nasty ORDER BY id")) { PQXX_CHECK_EQUAL(id, std::size(values), "Test data is broken."); values.push_back(value); } PQXX_CHECK(not values.at(0).has_value(), "Null did not work properly."); PQXX_CHECK(values.at(1).has_value(), "String 'NULL' became a NULL."); PQXX_CHECK_EQUAL( values.at(1).value_or("empty"), "NULL", "String 'NULL' went badly."); PQXX_CHECK(values.at(2).has_value(), "String '\\N' became a NULL."); PQXX_CHECK_EQUAL( values.at(2).value_or("empty"), "\\N", "String '\\N' went badly."); PQXX_CHECK(values.at(3).has_value(), "String \"'NULL'\" became a NULL."); PQXX_CHECK_EQUAL( values.at(3).value_or("empty"), "'NULL'", "String \"'NULL'\" went badly."); PQXX_CHECK_EQUAL( values.at(4).value_or("empty"), "\t", "Tab unescaped wrong."); PQXX_CHECK_EQUAL( values.at(5).value_or("empty"), "\\\\\\\n\\\\", "Backslashes confused stream."); if (not ascii_db) PQXX_CHECK_EQUAL( values.at(6).value_or("empty"), "\x81\x5c", "Finicky SJIS character went badly."); } void test_stream_handles_nulls_in_all_places(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; for (auto [a, b, c, d, e] : tx.stream< std::optional, std::optional, int, std::optional, std::optional>( "SELECT NULL::text, NULL::integer, 11, NULL::text, NULL::text")) { PQXX_CHECK(not a, "Starting null did not come through."); PQXX_CHECK(not b, "Null in 2nd column did not come through."); PQXX_CHECK_EQUAL(c, 11, "Integer in the middle went wrong."); PQXX_CHECK(not d, "Null further in did not come through."); PQXX_CHECK(not e, "Final null did not come through."); } } void test_stream_handles_empty_string(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; std::string out{""}; for (auto [empty] : tx.stream("SELECT ''")) out = empty; PQXX_CHECK_EQUAL(out, "", "Empty string_view parsed wrong."); out = ""; int num{0}; for (auto [i, s] : tx.stream("SELECT 99, ''")) { num = i; out = s; } PQXX_CHECK_EQUAL(num, 99, "Integer came out wrong before empty string."); PQXX_CHECK_EQUAL(out, "", "Final empty string came out wrong."); for (auto [s2, i2] : tx.stream("SELECT '', 33")) { out = s2; num = i2; } PQXX_CHECK_EQUAL(out, "", "Leading empty string came out wrong."); PQXX_CHECK_EQUAL(num, 33, "Integer came out wrong after empty string."); } /// A simple type with move constructor only, no assignment operators. /** We'll show that even this type can be streamed. */ struct limited_type { // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) int n; limited_type() = delete; limited_type(limited_type const &) = delete; limited_type(limited_type &&) = default; limited_type const &operator=(limited_type const &) = delete; limited_type const &operator=(limited_type &&) = delete; ~limited_type() = default; explicit limited_type(int number) : n{number} {} }; static_assert(std::move_constructible); static_assert(not std::copy_constructible); static_assert(not std::assignable_from); } // namespace namespace pqxx { template<> struct nullness : pqxx::no_null {}; template<> struct string_traits final { static limited_type from_string(std::string_view v, ctx = {}) { return limited_type{pqxx::from_string(v)}; } }; } // namespace pqxx namespace { void test_stream_only_requires_move_constructor(pqxx::test::context &tctx) { pqxx::connection cx; pqxx::work tx{cx}; bool found{false}; int const number{tctx.make_num()}; for (auto [lt] : tx.stream(std::format("SELECT {}", number))) { found = true; PQXX_CHECK_EQUAL(lt.n, number); } PQXX_CHECK(found); } PQXX_REGISTER_TEST(test_stream_handles_empty); PQXX_REGISTER_TEST(test_stream_does_escaping); PQXX_REGISTER_TEST(test_stream_reads_simple_values); PQXX_REGISTER_TEST(test_stream_reads_string_view); PQXX_REGISTER_TEST(test_stream_iterates); PQXX_REGISTER_TEST(test_stream_reads_nulls_as_optionals); PQXX_REGISTER_TEST(test_stream_reads_arrays); PQXX_REGISTER_TEST(test_stream_parses_awkward_strings); PQXX_REGISTER_TEST(test_stream_handles_nulls_in_all_places); PQXX_REGISTER_TEST(test_stream_handles_empty_string); PQXX_REGISTER_TEST(test_stream_only_requires_move_constructor); } // namespace libpqxx-8.0.1/test/test_stream_to.cxx000066400000000000000000000553011516427024100177540ustar00rootroot00000000000000#include #include #include #include #include "helpers.hxx" #include "sample_types.hxx" namespace { using namespace std::literals; std::string truncate_sql_error(std::string const &what) { auto trunc{what.substr(0, what.find('\n'))}; if (std::size(trunc) > 64) trunc = trunc.substr(0, 61) + "..."; return trunc; } void test_stream_to_nonoptionals(pqxx::connection &cx) { pqxx::work tx{cx}; auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; PQXX_CHECK(inserter); // Japanese "konichiwa" encoded in UTF-8. auto const nonascii{ "\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x82\x8f"}; bytea const binary{'\x00', '\x01', '\x02'}, text{'f', 'o', 'o', ' ', 'b', 'a', 'r', '\0'}; inserter << std::make_tuple( 1234, "now", 4321, ipv4{8, 8, 4, 4}, "hello nonoptional world", binary); inserter << std::make_tuple( 5678, "2018-11-17 21:23:00", nullptr, nullptr, nonascii, text); inserter << std::make_tuple(910, nullptr, nullptr, nullptr, "\\N", bytea{}); inserter.complete(); auto r1{ tx.exec("SELECT * FROM stream_to_test WHERE number0 = 1234").one_row()}; PQXX_CHECK_EQUAL(r1[0].as(), 1234); PQXX_CHECK_EQUAL(r1[4].as(), "hello nonoptional world"); PQXX_CHECK_EQUAL(r1[3].as(), ipv4(8, 8, 4, 4)); PQXX_CHECK_EQUAL(r1[5].as(), binary); auto r2{ tx.exec("SELECT * FROM stream_to_test WHERE number0 = 5678").one_row()}; PQXX_CHECK_EQUAL(r2[0].as(), 5678); PQXX_CHECK(r2[2].is_null()); PQXX_CHECK(r2[3].is_null()); PQXX_CHECK_EQUAL(r2[4].as(), nonascii); tx.commit(); } void test_nonoptionals_fold(pqxx::connection &connection) { pqxx::work tx{connection}; auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; PQXX_CHECK(inserter); auto const nonascii{ "\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x82\x8f"}; bytea const binary{'\x00', '\x01', '\x02'}, text{'f', 'o', 'o', ' ', 'b', 'a', 'r', '\0'}; inserter.write_values( 1234, "now", 4321, ipv4{8, 8, 4, 4}, "hello nonoptional world", binary); inserter.write_values( 5678, "2018-11-17 21:23:00", nullptr, nullptr, nonascii, text); inserter.write_values(910, nullptr, nullptr, nullptr, "\\N", bytea{}); inserter.complete(); auto r1{ tx.exec("SELECT * FROM stream_to_test WHERE number0 = 1234").one_row()}; PQXX_CHECK_EQUAL(r1[0].as(), 1234); PQXX_CHECK_EQUAL(r1[4].as(), "hello nonoptional world"); PQXX_CHECK_EQUAL(r1[3].as(), ipv4(8, 8, 4, 4)); PQXX_CHECK_EQUAL(r1[5].as(), binary); auto r2{ tx.exec("SELECT * FROM stream_to_test WHERE number0 = 5678").one_row()}; PQXX_CHECK_EQUAL(r2[0].as(), 5678); PQXX_CHECK(r2[2].is_null()); PQXX_CHECK(r2[3].is_null()); PQXX_CHECK_EQUAL(r2[4].as(), nonascii); tx.commit(); } /// Try to violate stream_to_test's not-null constraint using a stream_to. void insert_bad_null_tuple(pqxx::stream_to &inserter) { inserter << std::make_tuple( nullptr, "now", 4321, ipv4{8, 8, 8, 8}, "hello world", bytea{'\x00', '\x01', '\x02'}); inserter.complete(); } void test_bad_null(pqxx::connection &connection) { pqxx::work tx{connection}; auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; PQXX_CHECK(inserter); PQXX_CHECK_THROWS( insert_bad_null_tuple(inserter), pqxx::not_null_violation, "Did not detect insertion of a bad null into stream_to."); } /// Try to violate stream_to_test's not-null construct using a stream_to. void insert_bad_null_write(pqxx::stream_to &inserter) { inserter.write_values( nullptr, "now", 4321, ipv4{8, 8, 8, 8}, "hello world", bytea{'\x00', '\x01', '\x02'}); inserter.complete(); } void test_bad_null_fold(pqxx::connection &connection) { pqxx::work tx{connection}; auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; PQXX_CHECK(inserter); PQXX_CHECK_THROWS( insert_bad_null_write(inserter), pqxx::not_null_violation, "Did not detect insertion of a bad null into stream_to."); } void test_too_few_fields(pqxx::connection &connection) { pqxx::work tx{connection}; auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; PQXX_CHECK(inserter); try { inserter << std::make_tuple(1234, "now", 4321, ipv4{8, 8, 8, 8}); inserter.complete(); tx.commit(); pqxx::test::check_notreached("stream_from improperly inserted row"); } catch (pqxx::sql_error const &e) { std::string const what{e.what()}; if (not pqxx::str_contains(what, "missing data for column")) throw; pqxx::test::expected_exception( "Could not insert row: " + truncate_sql_error(what)); } } void test_too_few_fields_fold(pqxx::connection &connection) { pqxx::work tx{connection}; auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; PQXX_CHECK(inserter); try { inserter.write_values(1234, "now", 4321, ipv4{8, 8, 8, 8}); inserter.complete(); tx.commit(); pqxx::test::check_notreached("stream_from_fold improperly inserted row"); } catch (pqxx::sql_error const &e) { std::string const what{e.what()}; if (not pqxx::str_contains(what, "missing data for column")) throw; pqxx::test::expected_exception( "Fold - Could not insert row: " + truncate_sql_error(what)); } } void test_too_many_fields(pqxx::connection &connection) { pqxx::work tx{connection}; auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; PQXX_CHECK(inserter); try { inserter << std::make_tuple( 1234, "now", 4321, ipv4{8, 8, 8, 8}, "hello world", bytea{'\x00', '\x01', '\x02'}, 5678); inserter.complete(); tx.commit(); pqxx::test::check_notreached("stream_from improperly inserted row"); } catch (pqxx::sql_error const &e) { std::string const what{e.what()}; if (not pqxx::str_contains(what, "extra data")) throw; pqxx::test::expected_exception( "Could not insert row: " + truncate_sql_error(what)); } } void test_too_many_fields_fold(pqxx::connection &connection) { pqxx::work tx{connection}; auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; PQXX_CHECK(inserter); try { inserter.write_values( 1234, "now", 4321, ipv4{8, 8, 8, 8}, "hello world", bytea{'\x00', '\x01', '\x02'}, 5678); inserter.complete(); tx.commit(); pqxx::test::check_notreached("stream_from_fold improperly inserted row"); } catch (pqxx::sql_error const &e) { std::string const what{e.what()}; if (not pqxx::str_contains(what, "extra data")) throw; pqxx::test::expected_exception( "Fold - Could not insert row: " + truncate_sql_error(what)); } } void test_stream_to_does_nonnull_optional(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; tx.exec("CREATE TEMP TABLE foo(x integer, y text)").no_rows(); auto inserter{pqxx::stream_to::table(tx, {"foo"})}; inserter.write_values( std::optional{368}, std::optional{"Text"}); inserter.complete(); auto const row{tx.exec("SELECT x, y FROM foo").one_row()}; PQXX_CHECK_EQUAL(row[0].as(), "368"); PQXX_CHECK_EQUAL(row[1].as(), "Text"); } template class O> void test_stream_to_optional(pqxx::connection &connection) { pqxx::work tx{connection}; auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; PQXX_CHECK(inserter); inserter << std::make_tuple( 910, O{pqxx::nullness>::null()}, O{pqxx::nullness>::null()}, O{pqxx::nullness>::null()}, "\\N", bytea{}); inserter.complete(); tx.commit(); } template class O> void test_stream_to_optional_fold(pqxx::connection &connection) { pqxx::work tx{connection}; auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; PQXX_CHECK(inserter); inserter.write_values( 910, O{pqxx::nullness>::null()}, O{pqxx::nullness>::null()}, O{pqxx::nullness>::null()}, "\\N", bytea{}); inserter.complete(); tx.commit(); } // As an alternative to a tuple, you can also insert a container. void test_container_stream_to(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; tx.exec("CREATE TEMP TABLE test_container(a integer, b integer)").no_rows(); auto inserter{pqxx::stream_to::table(tx, {"test_container"})}; inserter << std::vector{112, 244}; inserter.complete(); auto read{tx.exec("SELECT * FROM test_container").one_row()}; PQXX_CHECK_EQUAL(read[0].as(), 112); PQXX_CHECK_EQUAL(read[1].as(), 244); tx.commit(); } void test_variant_fold(pqxx::connection &cx) { pqxx::work tx{cx}; auto inserter{pqxx::stream_to::table(tx, {"stream_to_test"})}; PQXX_CHECK(inserter); inserter.write_values( std::variant{1234}, std::variant{"now"}, 4321, ipv4{8, 8, 8, 8}, "hello world", bytea{'\x00', '\x01', '\x02'}); inserter.write_values( 5678, "2018-11-17 21:23:00", nullptr, nullptr, "\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x82\x8f", bytea{'f', 'o', 'o', ' ', 'b', 'a', 'r', '\0'}); inserter.write_values(910, nullptr, nullptr, nullptr, "\\N", bytea{}); inserter.complete(); tx.commit(); } void clear_table(pqxx::connection &cx) { pqxx::work tx{cx}; tx.exec("DELETE FROM stream_to_test").no_rows(); tx.commit(); } void test_stream_to(pqxx::test::context &) { pqxx::connection cx; cx.set_client_encoding("UTF8"); pqxx::work tx{cx}; tx.exec( "CREATE TEMP TABLE stream_to_test (" "number0 INT NOT NULL," "ts1 TIMESTAMP NULL," "number2 INT NULL," "addr3 INET NULL," "txt4 TEXT NULL," "bin5 BYTEA NOT NULL" ")") .no_rows(); tx.commit(); test_stream_to_nonoptionals(cx); clear_table(cx); test_nonoptionals_fold(cx); clear_table(cx); test_bad_null(cx); clear_table(cx); test_bad_null_fold(cx); clear_table(cx); test_too_few_fields(cx); clear_table(cx); test_too_few_fields_fold(cx); clear_table(cx); test_too_many_fields(cx); clear_table(cx); test_too_many_fields_fold(cx); clear_table(cx); test_stream_to_optional(cx); clear_table(cx); test_stream_to_optional_fold(cx); clear_table(cx); test_stream_to_optional(cx); clear_table(cx); test_stream_to_optional_fold(cx); clear_table(cx); test_variant_fold(cx); } void test_stream_to_factory_with_static_columns(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; tx.exec("CREATE TEMP TABLE pqxx_stream_to(a integer, b varchar)").no_rows(); auto stream{pqxx::stream_to::table(tx, {"pqxx_stream_to"}, {"a", "b"})}; stream.write_values(3, "three"); stream.complete(); auto r{tx.exec("SELECT a, b FROM pqxx_stream_to").one_row()}; PQXX_CHECK_EQUAL(r[0].as(), 3); PQXX_CHECK_EQUAL(r[1].as(), "three"); } void test_stream_to_factory_with_dynamic_columns(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; tx.exec("CREATE TEMP TABLE pqxx_stream_to(a integer, b varchar)").no_rows(); std::vector const columns{"a", "b"}; auto stream{pqxx::stream_to::table(tx, {"pqxx_stream_to"}, columns)}; stream.write_values(4, "four"); stream.complete(); auto r{tx.exec("SELECT a, b FROM pqxx_stream_to").one_row()}; PQXX_CHECK_EQUAL(r[0].as(), 4); PQXX_CHECK_EQUAL(r[1].as(), "four"); } void test_stream_to_quotes_arguments(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; std::string const table{R"--(pqxx_Stream"'x)--"}, column{R"--(a'"b)--"}; tx.exec( "CREATE TEMP TABLE " + tx.quote_name(table) + "(" + tx.quote_name(column) + " integer)") .no_rows(); auto write{pqxx::stream_to::table(tx, {table}, {column})}; write.write_values(12); write.complete(); PQXX_CHECK_EQUAL( tx.query_value( "SELECT " + tx.quote_name(column) + " FROM " + tx.quote_name(table)), 12); } void test_stream_to_optionals(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; tx.exec("CREATE TEMP TABLE pqxx_strings(key integer, value varchar)") .no_rows(); auto stream{pqxx::stream_to::table(tx, {"pqxx_strings"}, {"key", "value"})}; stream.write_values(1, std::optional{}); stream.write_values(2, std::optional{}); stream.write_values(3, std::optional{}); stream.write_values(4, std::optional{"Opt str."}); stream.write_values(5, std::optional{"Opt sv."}); stream.write_values(6, std::optional{"Opt zv."}); stream.write_values(7, std::shared_ptr{}); stream.write_values(8, std::shared_ptr{}); stream.write_values(9, std::shared_ptr{}); stream.write_values(10, std::make_shared("Shared str.")); stream.write_values(11, std::make_shared("Shared sv.")); stream.write_values(12, std::make_shared("Shared zv.")); stream.write_values(13, std::unique_ptr{}); stream.write_values(14, std::unique_ptr{}); stream.write_values(15, std::unique_ptr{}); stream.write_values(16, std::make_unique("Uq str.")); stream.write_values(17, std::make_unique("Uq sv.")); stream.write_values(18, std::make_unique("Uq zv.")); stream.complete(); // clang-tidy rule bug: // NOLINTNEXTLINE(misc-const-correctness) std::string nulls; for (auto [key] : tx.query( "SELECT key FROM pqxx_strings WHERE value IS NULL ORDER BY key")) nulls += pqxx::to_string(key) + '.'; PQXX_CHECK_EQUAL(nulls, "1.2.3.7.8.9.13.14.15."); // clang-tidy rule bug: // NOLINTNEXTLINE(misc-const-correctness) std::string values; for (auto const &[value] : tx.query("SELECT value FROM pqxx_strings WHERE value IS " "NOT NULL ORDER BY key")) values += value; PQXX_CHECK_EQUAL( values, "Opt str.Opt sv.Opt zv.Shared str.Shared sv.Shared zv.Uq str.Uq sv.Uq " "zv."); } void test_stream_to_escaping(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; tx.exec("CREATE TEMP TABLE foo (i integer, t varchar)").no_rows(); // We'll check that streaming these strings to the database and querying them // back reproduces them faithfully. // TODO: Use raw strings once Visual Studio copes with backslashes there. // NOLINTBEGIN(modernize-raw-string-literal) std::array const inputs = { ""sv, "hello"sv, "a\tb"sv, "a\nb"sv, "don't"sv, "\\\\\\''"sv, "\\N"sv, "\\Nfoo"sv, }; // NOLINTEND(modernize-raw-string-literal) // Stream the input strings into the database. pqxx::stream_to out{pqxx::stream_to::table(tx, {"foo"}, {"i", "t"})}; std::size_t i{0}; for (auto const &value : inputs) { out.write_values(i, value); ++i; } out.complete(); // Verify. auto outputs{tx.exec("SELECT i, t FROM foo ORDER BY i")}; PQXX_CHECK_EQUAL( static_cast(std::size(outputs)), std::size(inputs)); for (i = 0; i < std::size(inputs); ++i) { int const idx{static_cast(i)}; PQXX_CHECK_EQUAL(outputs[idx][0].as(), i); PQXX_CHECK_EQUAL(outputs[idx][1].as(), inputs.at(i)); } } void test_stream_to_moves_into_optional(pqxx::test::context &) { pqxx::connection cx; // clang-tidy rule bug: // NOLINTNEXTLINE(misc-const-correctness) pqxx::transaction tx{cx}; tx.exec("CREATE TEMP TABLE foo (a integer)").no_rows(); std::optional org{ std::in_place, pqxx::stream_to::table(tx, {"foo"}, {"a"})}; org->write_values(1); auto copy{std::move(org)}; copy->write_values(2); copy->complete(); auto values{tx.exec("SELECT a FROM foo ORDER BY a").expect_rows(2)}; PQXX_CHECK_EQUAL(values[0][0].as(), 1); PQXX_CHECK_EQUAL(values[1][0].as(), 2); } void test_stream_to_empty_strings(pqxx::test::context &) { // Reproduce #816: Streaming an array of 4 or more empty strings to a table // using stream_to crashes. pqxx::connection cx; // clang-tidy rule bug: // NOLINTNEXTLINE(misc-const-correctness) pqxx::transaction tx{cx}; tx.exec("CREATE TEMP TABLE strs (list text[])").no_rows(); std::vector empties{"", "", "", ""}; auto stream{pqxx::stream_to::table(tx, {"strs"})}; stream.write_values(std::variant>{empties}); stream.complete(); tx.commit(); } /// One encoding name for every encoding group. /** There can actually be many encodings in one encoding group. We pick one. */ template constexpr pqxx::zview encoding_name; template<> constexpr pqxx::zview encoding_name{"UTF8"}; template<> constexpr pqxx::zview encoding_name{"BIG5"}; template<> constexpr pqxx::zview encoding_name{"gb18030"}; template<> constexpr pqxx::zview encoding_name{"SJIS"}; /// A Japanese greeting in various encodings. template constexpr std::string_view hello; template<> constexpr std::string_view hello{ "\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x82\x8f"}; template<> constexpr std::string_view hello{ "\xc6\xb7\xc6\xf7\xc6\xcf\xc6\xc5\xc6\xf3"}; template<> constexpr std::string_view hello{ "\xa4\xb3\xa4\xf3\xa4\xcb\xa4\xc1\xa4\xef"}; template<> constexpr std::string_view hello{ "\x82\xb1\x82\xf1\x82\xc9\x82\xbf\x82\xed"}; /// Test streaming Japanese text to a table in `ENC`. Reset to UTF-8. template void check_stream_to_encodes(pqxx::connection &cx) { cx.set_client_encoding(encoding_name); { pqxx::work tx1{cx}; tx1.exec("DELETE FROM greeting").no_rows(); auto stream{pqxx::stream_to::table(tx1, {"greeting"}, {"hi"})}; stream.write_values(hello); stream.complete(); tx1.commit(); } cx.set_client_encoding("UTF8"); { pqxx::work tx2{cx}; auto const out{tx2.query_value("SELECT * FROM greeting")}; PQXX_CHECK_EQUAL(out, hello); } } void test_stream_to_transcodes(pqxx::test::context &) { pqxx::connection cx; { pqxx::nontransaction tx{cx}; tx.exec("CREATE TEMP TABLE greeting (hi varchar)").no_rows(); } check_stream_to_encodes(cx); check_stream_to_encodes(cx); check_stream_to_encodes(cx); check_stream_to_encodes(cx); } /// In each unsafe encoding, a string embedding fake special ASCII characters. /** This is for testing how resilient the streams are to bytes embedded inside * multibyte characters that happen to have the same numeric value as any of * the special characters: tab, newline, backslash. * * By definition, there are no such characters in the ASCII-safe encodings. * Same for UHC actually: it's actually ASCII-safe for characters other than * the ASCII letters (A-Z and a-z). So for these encodings, the strings are * empty. * * The other supported encodings are only slightly less safe: they can embed a * backslash byte, but not a tab or newline byte. */ template constexpr std::string_view attack; template<> constexpr std::string_view attack{"\xa5\\"}; template<> constexpr std::string_view attack{"\x95\\"}; template<> constexpr std::string_view attack{"\x95\\"}; /// The respective attack strings, but encoded in UTF-8. template constexpr std::string_view safe_attack; template<> constexpr std::string_view safe_attack{ "\xe5\x8a\x9f"}; template<> constexpr std::string_view safe_attack{ "\xe6\x98\x9e"}; template<> constexpr std::string_view safe_attack{ "\xe8\xa1\xa8"}; /// Verify that streaming in ENC is resilient to ASCII embedding attacks. template void check_attack(pqxx::connection &cx) { // Some extra nastiness we add for good measure. constexpr std::string_view extra_nastiness{"\t\r\n\\"}; // Attack attempt's text body. auto const text{std::format("{}{}", attack, extra_nastiness)}; // Same text, correctly encoded in UTF-8. auto const utf{std::format("{}{}", safe_attack, extra_nastiness)}; cx.set_client_encoding(encoding_name); { pqxx::nontransaction tx{cx}; tx.exec("DELETE FROM attack").no_rows(); auto stream{pqxx::stream_to::table(tx, {"attack"}, {"data"})}; stream.write_values(text); stream.complete(); } // Verify the text that got into the table. { pqxx::nontransaction tx{cx}; PQXX_CHECK_EQUAL( tx.query_value("SELECT * FROM attack"), text); } // To be sure that it's not just broken in a _consistent_ way, also query the // UTF-8 equivalent. cx.set_client_encoding("UTF8"); { pqxx::nontransaction tx{cx}; PQXX_CHECK_EQUAL(tx.query_value("SELECT * FROM attack"), utf); } } void test_stream_to_handles_embedded_special_values(pqxx::test::context &) { pqxx::connection cx; { pqxx::nontransaction tx{cx}; tx.exec("CREATE TEMP TABLE attack (data varchar)").no_rows(); } check_attack(cx); check_attack(cx); check_attack(cx); check_attack(cx); } void test_stream_to_bool(pqxx::test::context &tctx) { pqxx::connection cx; pqxx::work tx{cx}; auto const table{tctx.make_name("pqxx_test_bool")}; tx.exec(std::format( "CREATE TEMP TABLE {} (time TEXT, value BOOLEAN)", tx.quote_name(table))); auto stream{pqxx::stream_to::table(tx, {table}, {"time", "value"})}; // In #1203, this triggered an assertion failure. stream.write_values("2026", true); stream.complete(); } PQXX_REGISTER_TEST(test_stream_to); PQXX_REGISTER_TEST(test_container_stream_to); PQXX_REGISTER_TEST(test_stream_to_does_nonnull_optional); PQXX_REGISTER_TEST(test_stream_to_factory_with_static_columns); PQXX_REGISTER_TEST(test_stream_to_factory_with_dynamic_columns); PQXX_REGISTER_TEST(test_stream_to_quotes_arguments); PQXX_REGISTER_TEST(test_stream_to_optionals); PQXX_REGISTER_TEST(test_stream_to_escaping); PQXX_REGISTER_TEST(test_stream_to_moves_into_optional); PQXX_REGISTER_TEST(test_stream_to_empty_strings); PQXX_REGISTER_TEST(test_stream_to_transcodes); PQXX_REGISTER_TEST(test_stream_to_handles_embedded_special_values); PQXX_REGISTER_TEST(test_stream_to_bool); } // namespace libpqxx-8.0.1/test/test_string_conversion.cxx000066400000000000000000000210321516427024100215240ustar00rootroot00000000000000#include #include #include #include #include "helpers.hxx" using namespace std::literals; // Some enums with string conversions. enum EnumA { ea0, ea1, ea2 }; enum EnumB { eb0, eb1, eb2 }; namespace pqxx { PQXX_DECLARE_ENUM_CONVERSION(EnumA); PQXX_DECLARE_ENUM_CONVERSION(EnumB); } // namespace pqxx namespace { // "A minimal difference." constexpr double thres{0.00001}; void test_string_conversion(pqxx::test::context &tctx) { PQXX_CHECK_EQUAL("C string array", pqxx::to_string("C string array")); char const text_array[]{"C char array"}; PQXX_CHECK_EQUAL("C char array", pqxx::to_string(text_array)); char const *text_ptr{"C string pointer"}; PQXX_CHECK_EQUAL("C string pointer", pqxx::to_string(text_ptr)); std::string const cxx_string{"C++ string"}; PQXX_CHECK_EQUAL("C++ string", pqxx::to_string(cxx_string)); PQXX_CHECK_EQUAL("0", pqxx::to_string(0)); PQXX_CHECK_EQUAL("1", pqxx::to_string(1)); PQXX_CHECK_EQUAL("-1", pqxx::to_string(-1)); PQXX_CHECK_EQUAL("9999", pqxx::to_string(9999)); PQXX_CHECK_EQUAL("-9999", pqxx::to_string(-9999)); int x{}; pqxx::from_string("0", x); PQXX_CHECK_EQUAL(0, x); pqxx::from_string("1", x); PQXX_CHECK_EQUAL(1, x); pqxx::from_string("-1", x); PQXX_CHECK_EQUAL(-1, x); pqxx::from_string("9999", x); PQXX_CHECK_EQUAL(9999, x); pqxx::from_string("-9999", x); PQXX_CHECK_EQUAL(-9999, x); auto const num{tctx.make_num()}; PQXX_CHECK_EQUAL(pqxx::to_string(num), std::format("{}", num)); auto const numstr{std::format("{}", num)}; PQXX_CHECK_EQUAL(pqxx::to_string(num), pqxx::to_string(numstr)); PQXX_CHECK_EQUAL( pqxx::to_string(num), pqxx::to_string(std::string_view{numstr})); PQXX_CHECK_EQUAL(pqxx::from_string(numstr), num); // Bug #263 describes a case where this kind of overflow went undetected. if constexpr (sizeof(unsigned int) == 4) { // clang-tidy rule bug: // NOLINTNEXTLINE(misc-const-correctness) std::uint32_t u{}; PQXX_CHECK_THROWS( pqxx::from_string("4772185884", u), pqxx::conversion_error, "Overflow not detected."); } // Valgrind doesn't seem to support long double, so skip "long double" // tests when compiling for a Valgrind run. :-/ #if !defined(PQXX_VALGRIND) // We can convert to and from long double. The implementation may fall // back on a thread-local std::stringstream. Each call does its own // cleanup, so the conversion works multiple times. constexpr long double ld1{123456789.25}, ld2{9876543210.5}; constexpr char lds1[]{"123456789.25"}, lds2[]{"9876543210.5"}; PQXX_CHECK_EQUAL(pqxx::to_string(ld1).substr(0, 12), lds1); PQXX_CHECK_EQUAL(pqxx::to_string(ld2).substr(0, 12), lds2); long double ldi1{}, ldi2{}; pqxx::from_string(std::data(lds1), ldi1); PQXX_CHECK_BOUNDS(ldi1, ld1 - thres, ld1 + thres); pqxx::from_string(std::data(lds2), ldi2); PQXX_CHECK_BOUNDS(ldi2, ld2 - thres, ld2 + thres); #endif // We can define string conversions for enums. PQXX_CHECK_EQUAL(pqxx::to_string(ea0), "0"); PQXX_CHECK_EQUAL(pqxx::to_string(eb0), "0"); PQXX_CHECK_EQUAL(pqxx::to_string(ea1), "1"); EnumA ea{}; pqxx::from_string("2", ea); PQXX_CHECK_EQUAL(ea, ea2); } void test_convert_variant_to_string(pqxx::test::context &) { PQXX_CHECK_EQUAL(pqxx::to_string(std::variant{99}), "99"); PQXX_CHECK_EQUAL( pqxx::to_string(std::variant{"Text"}), "Text"); } void test_integer_conversion(pqxx::test::context &) { PQXX_CHECK_EQUAL(pqxx::from_string("12"), 12); PQXX_CHECK_EQUAL(pqxx::from_string(" 12"), 12); PQXX_CHECK_THROWS( std::ignore = pqxx::from_string(""), pqxx::conversion_error); PQXX_CHECK_THROWS( std::ignore = pqxx::from_string(" "), pqxx::conversion_error); PQXX_CHECK_EQUAL(pqxx::from_string("-6"), -6); PQXX_CHECK_THROWS( std::ignore = pqxx::from_string("- 3"), pqxx::conversion_error); PQXX_CHECK_THROWS( std::ignore = pqxx::from_string("-"), pqxx::conversion_error); } void test_convert_null(pqxx::test::context &) { pqxx::connection cx; pqxx::work const tx{cx}; PQXX_CHECK_EQUAL(tx.quote(nullptr), "NULL"); PQXX_CHECK_EQUAL(tx.quote(std::nullopt), "NULL"); PQXX_CHECK_EQUAL(tx.quote(std::monostate{}), "NULL"); } void test_string_view_conversion(pqxx::test::context &) { using traits = pqxx::string_traits; PQXX_CHECK_EQUAL(pqxx::to_string("view here"sv), "view here"s); std::array buf{}; // clang-tidy rule bug: // NOLINTNEXTLINE(cppcoreguidelines-init-variables) std::size_t const stop{pqxx::into_buf(buf, "more view"sv)}; PQXX_CHECK_LESS(stop, std::size(buf)); assert(stop > 0); PQXX_CHECK_EQUAL( (std::string{std::data(buf), static_cast(stop)}), "more view"s); PQXX_CHECK(buf.at(stop - 1) == 'w'); std::string_view const org{"another!"sv}, out{traits::to_buf(buf, org)}; PQXX_CHECK_EQUAL(std::string{out}, "another!"s); } void test_binary_converts_to_string(pqxx::test::context &) { std::array const bin_data{ std::byte{0x41}, std::byte{0x42}, std::byte{0x43}}; std::string_view const text_data{"\\x414243"}; PQXX_CHECK_EQUAL(pqxx::to_string(bin_data), text_data); std::array x{std::byte{0x78}}; PQXX_CHECK_EQUAL(std::size(x), 1u); std::span const span{x}; PQXX_CHECK_EQUAL(std::size(span), 1u); PQXX_CHECK_EQUAL(pqxx::to_string(span), "\\x78"); } void test_string_converts_to_binary(pqxx::test::context &) { std::array const bin_data{ std::byte{0x41}, std::byte{0x42}, std::byte{0x43}}; std::string_view const text_data{"\\x414243"}; // We can convert a bytea SQL string to a vector of bytes. auto const vec{pqxx::from_string>(text_data)}; PQXX_CHECK_EQUAL(std::size(vec), std::size(bin_data)); for (std::size_t i{0}; i < std::size(vec); ++i) PQXX_CHECK( vec.at(i) == bin_data.at(i), std::format("Difference in binary byte #{}.", i)); // We can also convert a bytea SQL string to an array of bytes of the right // size. auto const arr{pqxx::from_string>(text_data)}; for (std::size_t i{0}; i < std::size(arr); ++i) PQXX_CHECK( arr.at(i) == bin_data.at(i), std::format("Difference in binary byte #{}.", i)); // However we can _not_ convert a bytea SQL string to an array of bytes of a // different size. PQXX_CHECK_THROWS( (std::ignore = pqxx::from_string>(text_data)), pqxx::conversion_error); } struct legacy_item final { constexpr explicit legacy_item(int i) noexcept : val{i} {} [[nodiscard]] constexpr int get_val() const noexcept { return val; } private: int val; }; } // namespace namespace pqxx { template<> struct nullness final : no_null {}; template<> struct string_traits final { // The clang-tidy rule is just wrong here. // NOLINTBEGIN(readability-non-const-parameter) static inline zview to_buf(char *begin, char const *end, legacy_item const &value) { auto const bufsz{static_cast(end - begin)}, need{size_buffer(value)}; if (std::cmp_less(bufsz, need)) throw conversion_overrun{std::format( "Needed {} bytes to convert '{}', got {}.", need, value.get_val(), bufsz)}; auto const outsz{pqxx::into_buf({begin, bufsz}, value.get_val())}; if (outsz >= bufsz) throw conversion_error{"No room for legacy terminating zero."}; begin[outsz] = '\0'; return zview{begin, outsz}; } // NOLINTEND(readability-non-const-parameter) static inline legacy_item from_string(std::string_view text) { return legacy_item{pqxx::from_string(text)}; } static inline std::size_t size_buffer(legacy_item const &value) noexcept { return pqxx::size_buffer(value.get_val()) + 1; } }; } // namespace pqxx namespace { void test_legacy_7_conversion_support(pqxx::test::context &tctx) { legacy_item const leg{tctx.make_num()}; auto const as_string{pqxx::to_string(leg)}; PQXX_CHECK_EQUAL(as_string, pqxx::to_string(leg.get_val())); PQXX_CHECK_EQUAL( pqxx::from_string(as_string).get_val(), leg.get_val()); } PQXX_REGISTER_TEST(test_string_conversion); PQXX_REGISTER_TEST(test_convert_variant_to_string); PQXX_REGISTER_TEST(test_integer_conversion); PQXX_REGISTER_TEST(test_convert_null); PQXX_REGISTER_TEST(test_string_view_conversion); PQXX_REGISTER_TEST(test_binary_converts_to_string); PQXX_REGISTER_TEST(test_string_converts_to_binary); PQXX_REGISTER_TEST(test_legacy_7_conversion_support); } // namespace libpqxx-8.0.1/test/test_subtransaction.cxx000066400000000000000000000030341516427024100210120ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { void make_table(pqxx::transaction_base &tx) { tx.exec("CREATE TEMP TABLE foo (x INTEGER)").no_rows(); } void insert_row(pqxx::transaction_base &tx) { tx.exec("INSERT INTO foo(x) VALUES (1)").no_rows(); } int count_rows(pqxx::transaction_base &tx) { return tx.query_value("SELECT count(*) FROM foo"); } void test_subtransaction_commits_if_commit_called(pqxx::connection &cx) { pqxx::work tx(cx); make_table(tx); { pqxx::subtransaction sub(tx); insert_row(sub); sub.commit(); } PQXX_CHECK_EQUAL( count_rows(tx), 1, "Work done in committed subtransaction was lost."); } void test_subtransaction_aborts_if_abort_called(pqxx::connection &cx) { pqxx::work tx(cx); make_table(tx); { pqxx::subtransaction sub(tx); insert_row(sub); sub.abort(); } PQXX_CHECK_EQUAL( count_rows(tx), 0, "Aborted subtransaction was not rolled back."); } void test_subtransaction_aborts_implicitly(pqxx::connection &cx) { pqxx::work tx(cx); make_table(tx); { pqxx::subtransaction sub(tx); insert_row(sub); } PQXX_CHECK_EQUAL( count_rows(tx), 0, "Uncommitted subtransaction was not rolled back uring destruction."); } void test_subtransaction(pqxx::test::context &) { pqxx::connection cx; test_subtransaction_commits_if_commit_called(cx); test_subtransaction_aborts_if_abort_called(cx); test_subtransaction_aborts_implicitly(cx); } PQXX_REGISTER_TEST(test_subtransaction); } // namespace libpqxx-8.0.1/test/test_thread_safety_model.cxx000066400000000000000000000005741516427024100217630ustar00rootroot00000000000000#include "helpers.hxx" #include namespace { void test_thread_safety_model(pqxx::test::context &) { auto const model{pqxx::describe_thread_safety()}; if (model.safe_libpq and model.safe_kerberos) PQXX_CHECK_EQUAL(model.description, ""); else PQXX_CHECK_NOT_EQUAL(model.description, ""); } PQXX_REGISTER_TEST(test_thread_safety_model); } // namespace libpqxx-8.0.1/test/test_time.cxx000066400000000000000000000050501516427024100167110ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { #if defined(PQXX_HAVE_YEAR_MONTH_DAY) using namespace std::literals; using date_tup = std::tuple; /// Build a `date_tup`. constexpr date_tup make_date(int y, unsigned m, unsigned d, std::string_view text) { return date_tup{ y, std::chrono::month{m}, std::chrono::day{d}, text, }; } void test_date_string_conversion(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; date_tup const conversions[]{ make_date(-542, 1, 1, "0543-01-01 BC"sv), make_date(-1, 2, 3, "0002-02-03 BC"sv), make_date(0, 9, 14, "0001-09-14 BC"sv), make_date(1, 12, 8, "0001-12-08"sv), make_date(2021, 10, 24, "2021-10-24"sv), make_date(10191, 8, 30, "10191-08-30"sv), make_date(-4712, 1, 1, "4713-01-01 BC"sv), make_date(32767, 12, 31, "32767-12-31"sv), make_date(2000, 2, 29, "2000-02-29"sv), make_date(2004, 2, 29, "2004-02-29"sv), // This one won't work in postgres, but we can test the conversions. make_date(-32767, 11, 3, "32768-11-03 BC"sv), }; for (auto const &[y, m, d, text] : std::span{conversions}) { std::chrono::year_month_day const date{ std::chrono::year{y}, std::chrono::month{m}, std::chrono::day{d}}; PQXX_CHECK_EQUAL(pqxx::to_string(date), text); PQXX_CHECK_EQUAL( pqxx::from_string(text), date); if (int{date.year()} > -4712) { // We can't test this for years before 4713 BC (4712 BCE), because // postgres doesn't handle earlier years. PQXX_CHECK_EQUAL( tx.query_value( "SELECT '" + pqxx::to_string(date) + "'::date"), text); } } std::string_view const invalid[]{ ""sv, "yesterday"sv, "1981-01"sv, "2010"sv, "2010-8-9"sv, "1900-02-29"sv, "2021-02-29"sv, "2000-11-29-3"sv, "1900-02-29"sv, "2003-02-29"sv, "12-12-12"sv, "0000-09-16"sv, "-01-01"sv, "-1000-01-01"sv, "1000-00-01"sv, "1000-01-00"sv, "2001y-01-01"sv, "10-09-08"sv, "0-01-01"sv, "0000-01-01"sv, "2021-13-01"sv, "2021-+02-01"sv, "2021-12-32"sv, }; for (auto const text : invalid) PQXX_CHECK_THROWS( std::ignore = pqxx::from_string(text), pqxx::conversion_error, std::format("Invalid date '{}' parsed as if valid.", text)); } PQXX_REGISTER_TEST(test_date_string_conversion); #endif // PQXX_HAVE_YEAR_MONTH_DAY } // namespace libpqxx-8.0.1/test/test_transaction.cxx000066400000000000000000000064651516427024100203130ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { void test_nontransaction_continues_after_error(pqxx::test::context &) { pqxx::connection cx; pqxx::nontransaction tx{cx}; PQXX_CHECK_EQUAL(tx.query_value("SELECT 9"), 9); PQXX_CHECK_THROWS(tx.exec("SELECT 1/0"), pqxx::sql_error); PQXX_CHECK_EQUAL(tx.query_value("SELECT 5"), 5); } std::string_view const table{"pqxx_test_transaction"}; void delete_temp_table(pqxx::transaction_base &tx) { tx.exec(std::format("DROP TABLE IF EXISTS {}", table)).no_rows(); } void create_temp_table(pqxx::transaction_base &tx) { tx.exec(std::format("CREATE TEMP TABLE {} (x integer)", table)).no_rows(); } void insert_temp_table(pqxx::transaction_base &tx, int value) { tx.exec( std::format("INSERT INTO {} (x) VALUES (", table) + pqxx::to_string(value) + ")") .no_rows(); } int count_temp_table(pqxx::transaction_base &tx) { return tx.query_value(std::format("SELECT count(*) FROM {}", table)); } void test_nontransaction_autocommits(pqxx::test::context &) { pqxx::connection cx; pqxx::nontransaction tx1{cx}; delete_temp_table(tx1); create_temp_table(tx1); tx1.commit(); pqxx::nontransaction tx2{cx}; insert_temp_table(tx2, 4); tx2.abort(); pqxx::nontransaction tx3{cx}; PQXX_CHECK_EQUAL( count_temp_table(tx3), 1, "Did not keep effect of aborted nontransaction."); delete_temp_table(tx3); } template void test_double_close(pqxx::test::context &) { pqxx::connection cx; TX tx1{cx}; tx1.exec("SELECT 1").one_row(); tx1.commit(); tx1.commit(); TX tx2{cx}; tx2.exec("SELECT 2").one_row(); tx2.abort(); tx2.abort(); TX tx3{cx}; tx3.exec("SELECT 3").one_row(); tx3.commit(); PQXX_CHECK_THROWS(tx3.abort(), pqxx::usage_error); ; TX tx4{cx}; tx4.exec("SELECT 4").one_row(); tx4.abort(); PQXX_CHECK_THROWS(tx4.commit(), pqxx::usage_error); } template void test_failed_commit(pqxx::test::context &) { pqxx::connection cx; TX tx{cx}; tx.exec("CREATE TEMP TABLE foo (id integer UNIQUE INITIALLY DEFERRED)"); tx.exec("INSERT INTO foo VALUES (1), (1)"); // Database checks the unique constraint (and fails it) at commit. PQXX_CHECK_THROWS(tx.commit(), pqxx::unique_violation); // Repeated attempt to commit fails because the transaction aborted. PQXX_CHECK_THROWS(tx.commit(), pqxx::usage_error); // Repeated abort does nothing. tx.abort(); tx.abort(); } template void test_commit_on_broken_connection(pqxx::test::context &) { pqxx::connection cx; TX tx{cx}; cx.close(); PQXX_CHECK_THROWS(tx.commit(), pqxx::broken_connection); } void test_transaction(pqxx::test::context &tctx) { test_double_close>(tctx); test_double_close(tctx); test_double_close(tctx); test_double_close>(tctx); test_failed_commit>(tctx); test_failed_commit>(tctx); test_commit_on_broken_connection>(tctx); test_commit_on_broken_connection>(tctx); } PQXX_REGISTER_TEST(test_nontransaction_continues_after_error); PQXX_REGISTER_TEST(test_nontransaction_autocommits); PQXX_REGISTER_TEST(test_transaction); } // namespace libpqxx-8.0.1/test/test_transaction_base.cxx000066400000000000000000000201251516427024100212720ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { void test_exec0(pqxx::transaction_base &tx) { #include "pqxx/internal/ignore-deprecated-pre.hxx" pqxx::result const E{tx.exec0("SELECT * FROM pg_tables WHERE 0 = 1")}; PQXX_CHECK(std::empty(E)); PQXX_CHECK_THROWS(tx.exec0("SELECT 99"), pqxx::unexpected_rows); #include "pqxx/internal/ignore-deprecated-post.hxx" } void test_exec1(pqxx::transaction_base &tx) { #include "pqxx/internal/ignore-deprecated-pre.hxx" pqxx::row const R{tx.exec1("SELECT 99")}; PQXX_CHECK_EQUAL(std::size(R), 1); PQXX_CHECK_EQUAL(R.front().as(), 99); PQXX_CHECK_THROWS( tx.exec1("SELECT * FROM pg_tables WHERE 0 = 1"), pqxx::unexpected_rows); PQXX_CHECK_THROWS( tx.exec1("SELECT * FROM generate_series(1, 2)"), pqxx::unexpected_rows); #include "pqxx/internal/ignore-deprecated-post.hxx" } void test_exec_n(pqxx::transaction_base &tx) { #include "pqxx/internal/ignore-deprecated-pre.hxx" pqxx::result const R{tx.exec_n(3u, "SELECT * FROM generate_series(1, 3)")}; PQXX_CHECK_EQUAL(std::size(R), 3); PQXX_CHECK_THROWS( tx.exec_n(2u, "SELECT * FROM generate_series(1, 3)"), pqxx::unexpected_rows); PQXX_CHECK_THROWS( tx.exec_n(4u, "SELECT * FROM generate_series(1, 3)"), pqxx::unexpected_rows); #include "pqxx/internal/ignore-deprecated-post.hxx" } void test_query_value(pqxx::connection &cx) { pqxx::work tx{cx}; PQXX_CHECK_EQUAL(tx.query_value("SELECT 84 / 2"), 42); PQXX_CHECK_THROWS(tx.query_value("SAVEPOINT dummy"), pqxx::usage_error); PQXX_CHECK_THROWS( tx.query_value("SELECT generate_series(1, 2)"), pqxx::unexpected_rows); PQXX_CHECK_THROWS(tx.query_value("SELECT 1, 2"), pqxx::usage_error); PQXX_CHECK_THROWS( tx.query_value("SELECT 3.141"), pqxx::conversion_error); // Now with parameters: PQXX_CHECK_EQUAL(tx.query_value("SELECT $1 + 1", {tx, 5}), 6); } void test_transaction_base(pqxx::test::context &) { pqxx::connection cx; { pqxx::work tx{cx}; test_exec_n(tx); test_exec0(tx); test_exec1(tx); } test_query_value(cx); } void test_transaction_query(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; std::vector names; std::vector salaries; for (auto const &[name, salary] : tx.query( "SELECT 'name' || i, i * 1000 FROM generate_series(1, 5) AS i")) { names.emplace_back(name); salaries.emplace_back(salary); } PQXX_CHECK_EQUAL(std::size(names), 5u); PQXX_CHECK_EQUAL(std::size(salaries), 5u); PQXX_CHECK_EQUAL(names.at(0), "name1"); PQXX_CHECK_EQUAL(names.at(4), "name5"); PQXX_CHECK_EQUAL(salaries.at(0), 1'000); PQXX_CHECK_EQUAL(salaries.at(4), 5'000, ); } void test_transaction_query_params(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; int outcome{-1}; for (auto [value] : tx.query("SELECT $1 * 2", {32})) { PQXX_CHECK_EQUAL(outcome, -1); outcome = value; } PQXX_CHECK_EQUAL(outcome, 64); outcome = -1; #include "pqxx/internal/ignore-deprecated-pre.hxx" for (auto [value] : tx.query_n(1, "SELECT * FROM generate_series(1, $1)", {1})) { PQXX_CHECK_EQUAL(outcome, -1); outcome = value; } PQXX_CHECK_EQUAL(outcome, 1); PQXX_CHECK_THROWS( tx.query_n(2, "SELECT $1", {9}), pqxx::unexpected_rows); std::tuple const res{tx.query1("SELECT $1 / 3", {33})}; auto [res_int] = res; PQXX_CHECK_EQUAL(res_int, 11); PQXX_CHECK_THROWS( std::ignore = tx.query1("SELECT * from generate_series(1, $1)", {4}), pqxx::unexpected_rows); std::tuple const res2{ tx.query1("SELECT $1, $2", {3, 6})}; auto [res2_a, res2_b] = res2; PQXX_CHECK_EQUAL(res2_a, 3); PQXX_CHECK_EQUAL(res2_b, 6); std::optional> const opt1{ tx.query01("SELECT 1 WHERE 1 = $1", {0})}; PQXX_CHECK(not opt1); std::optional> const opt2{ tx.query01("SELECT $1 - 10", {12})}; PQXX_CHECK(opt2.has_value()); auto const [opt2_val] = opt2.value_or(0); PQXX_CHECK_EQUAL(opt2_val, 2); auto const [opt3_a, opt3_b] = tx.query01("SELECT $1, $2", {12, 99}) .value_or(std::tuple{}); PQXX_CHECK_EQUAL(opt3_a, 12); PQXX_CHECK_EQUAL(opt3_b, 99); #include "pqxx/internal/ignore-deprecated-post.hxx" } void test_transaction_for_query(pqxx::test::context &) { constexpr auto query{ "SELECT i, concat('x', (2*i)::text) " "FROM generate_series(1, 3) AS i " "ORDER BY i"}; pqxx::connection cx; pqxx::work tx{cx}; std::string ints; std::string strings; tx.for_query(query, [&ints, &strings](int i, std::string const &s) { ints += pqxx::to_string(i) + " "; strings += s + " "; }); PQXX_CHECK_EQUAL(ints, "1 2 3 "); PQXX_CHECK_EQUAL(strings, "x2 x4 x6 "); // And now with parameters... int x{0}, y{0}; tx.for_query( "SELECT $1, $2", [&x, &y](int xout, int yout) { PQXX_CHECK_EQUAL(x, 0); PQXX_CHECK_EQUAL(y, 0); x = xout; y = yout; }, {42, 67}); PQXX_CHECK_EQUAL(x, 42); PQXX_CHECK_EQUAL(y, 67); } void test_transaction_for_stream(pqxx::test::context &) { constexpr auto query{ "SELECT i, concat('x', (2*i)::text) " "FROM generate_series(1, 3) AS i " "ORDER BY i"}; pqxx::connection cx; pqxx::work tx{cx}; std::string ints; std::string strings; tx.for_stream(query, [&ints, &strings](int i, std::string const &s) { ints += pqxx::to_string(i) + " "; strings += s + " "; }); PQXX_CHECK_EQUAL(ints, "1 2 3 "); PQXX_CHECK_EQUAL(strings, "x2 x4 x6 "); } void test_transaction_query01(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; #include "pqxx/internal/ignore-deprecated-pre.hxx" std::optional> o{ tx.query01("SELECT * FROM generate_series(1, 1) AS i WHERE i = 5")}; PQXX_CHECK(not o.has_value()); o = tx.query01("SELECT * FROM generate_series(8, 8)"); PQXX_CHECK(o.has_value()); // The "if" is redundant (see the check above). But gcc 11 complains when // enabling maintainer mode but not audit mode: something inside the optional // "may be used uninitialized." if (o.has_value()) PQXX_CHECK_EQUAL(std::get<0>(*o), 8); PQXX_CHECK_THROWS( o = tx.query01("SELECT * FROM generate_series(1, 2)"), pqxx::unexpected_rows); PQXX_CHECK_THROWS(o = tx.query01("SELECT 1, 2"), pqxx::usage_error); #include "pqxx/internal/ignore-deprecated-post.hxx" } void test_transaction_query1(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; [[maybe_unused]] std::tuple x; PQXX_CHECK_THROWS( x = tx.query1("SELECT * FROM generate_series(1, 1) AS i WHERE i = 5"), pqxx::unexpected_rows); std::optional> const o{ tx.query1("SELECT * FROM generate_series(8, 8)")}; PQXX_CHECK(o.has_value()); PQXX_CHECK_EQUAL(std::get<0>(*o), 8); PQXX_CHECK_THROWS( x = tx.query1("SELECT * FROM generate_series(1, 2)"), pqxx::unexpected_rows); PQXX_CHECK_THROWS(x = tx.query1("SELECT 1, 2"), pqxx::usage_error); } void test_transaction_query_n(pqxx::test::context &) { pqxx::connection cx; pqxx::work tx{cx}; #include "pqxx/internal/ignore-deprecated-pre.hxx" PQXX_CHECK_THROWS( std::ignore = tx.query_n(5, "SELECT generate_series(1, 3)"), pqxx::unexpected_rows); PQXX_CHECK_THROWS( std::ignore = tx.query_n(5, "SELECT generate_series(1, 10)"), pqxx::unexpected_rows); std::vector v; for (auto [n] : tx.query_n(3, "SELECT generate_series(7, 9)")) v.push_back(n); #include "pqxx/internal/ignore-deprecated-post.hxx" PQXX_CHECK_EQUAL(std::size(v), 3u); PQXX_CHECK_EQUAL(v.at(0), 7); PQXX_CHECK_EQUAL(v.at(2), 9); } PQXX_REGISTER_TEST(test_transaction_base); PQXX_REGISTER_TEST(test_transaction_query); PQXX_REGISTER_TEST(test_transaction_query_params); PQXX_REGISTER_TEST(test_transaction_for_query); PQXX_REGISTER_TEST(test_transaction_for_stream); PQXX_REGISTER_TEST(test_transaction_query01); PQXX_REGISTER_TEST(test_transaction_query1); PQXX_REGISTER_TEST(test_transaction_query_n); } // namespace libpqxx-8.0.1/test/test_transaction_focus.cxx000066400000000000000000000037421516427024100215050ustar00rootroot00000000000000#include #include #include #include "helpers.hxx" namespace { auto make_focus(pqxx::dbtransaction &tx) { #include "pqxx/internal/ignore-deprecated-pre.hxx" return pqxx::stream_from::query(tx, "SELECT * from generate_series(1, 10)"); #include "pqxx/internal/ignore-deprecated-post.hxx" } void test_cannot_run_statement_during_focus(pqxx::test::context &) { pqxx::connection cx; pqxx::transaction tx{cx}; tx.exec("SELECT 1"); auto focus{make_focus(tx)}; PQXX_CHECK_THROWS( tx.exec("SELECT 1"), pqxx::usage_error, "Command during focus did not throw expected error."); } void test_cannot_run_prepared_statement_during_focus(pqxx::test::context &) { pqxx::connection cx; cx.prepare("foo", "SELECT 1"); pqxx::transaction tx{cx}; tx.exec(pqxx::prepped{"foo"}); auto focus{make_focus(tx)}; PQXX_CHECK_THROWS( tx.exec(pqxx::prepped{"foo"}), pqxx::usage_error, "Prepared statement during focus did not throw expected error."); } void test_cannot_run_params_statement_during_focus(pqxx::test::context &) { pqxx::connection cx; pqxx::transaction tx{cx}; tx.exec("select $1", pqxx::params{tx, 10}); auto focus{make_focus(tx)}; PQXX_CHECK_THROWS( tx.exec("select $1", pqxx::params{tx, 10}), pqxx::usage_error, "Parameterized statement during focus did not throw expected error."); } void test_should_not_end_transaction_before_focus(pqxx::test::context &) { pqxx::connection cx; pqxx::transaction tx{cx}; tx.exec("CREATE TEMP TABLE foo(a integer)"); auto stream{pqxx::stream_to::table(tx, {"foo"}, {"a"})}; stream.write_values(1); // Fail to complete() the stream... PQXX_CHECK_THROWS(tx.commit(), pqxx::failure); } PQXX_REGISTER_TEST(test_cannot_run_statement_during_focus); PQXX_REGISTER_TEST(test_cannot_run_prepared_statement_during_focus); PQXX_REGISTER_TEST(test_cannot_run_params_statement_during_focus); PQXX_REGISTER_TEST(test_should_not_end_transaction_before_focus); } // namespace libpqxx-8.0.1/test/test_transactor.cxx000066400000000000000000000061531516427024100201400ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { void test_transactor_newstyle_executes_simple_query(pqxx::test::context &) { pqxx::connection cx; auto const r{pqxx::perform( [&cx] { return pqxx::work{cx}.exec("SELECT generate_series(1, 4)"); })}; PQXX_CHECK_EQUAL(std::size(r), 4); PQXX_CHECK_EQUAL(r.columns(), 1); PQXX_CHECK_EQUAL(r[0][0].as(), 1); PQXX_CHECK_EQUAL(r[3][0].as(), 4); } void test_transactor_newstyle_can_return_void(pqxx::test::context &) { bool done{false}; pqxx::perform([&done]() noexcept { done = true; }); PQXX_CHECK(done); } void test_transactor_newstyle_completes_upon_success(pqxx::test::context &) { int attempts{0}; pqxx::perform([&attempts]() noexcept { attempts++; }); PQXX_CHECK_EQUAL(attempts, 1); } void test_transactor_newstyle_retries_broken_connection(pqxx::test::context &) { int counter{0}; auto const &callback{[&counter] { ++counter; if (counter == 1) throw pqxx::broken_connection{}; return counter; }}; int const result{pqxx::perform(callback)}; PQXX_CHECK_EQUAL(result, 2); PQXX_CHECK_EQUAL(counter, result); } void test_transactor_newstyle_retries_rollback(pqxx::test::context &) { int counter{0}; auto const &callback{[&counter] { ++counter; if (counter == 1) throw pqxx::transaction_rollback("Simulated error"); return counter; }}; int const result{pqxx::perform(callback)}; PQXX_CHECK_EQUAL(result, 2); PQXX_CHECK_EQUAL(counter, result); } void test_transactor_newstyle_does_not_retry_in_doubt_error( pqxx::test::context &) { int counter{0}; auto const &callback{[&counter] { ++counter; throw pqxx::in_doubt_error("Simulated error"); }}; PQXX_CHECK_THROWS(pqxx::perform(callback), pqxx::in_doubt_error); PQXX_CHECK_EQUAL(counter, 1, "Transactor retried after in_doubt_error."); } void test_transactor_newstyle_does_not_retry_other_error(pqxx::test::context &) { int counter{0}; auto const &callback{[&counter] { ++counter; throw std::runtime_error("Simulated error"); }}; PQXX_CHECK_THROWS(pqxx::perform(callback), std::runtime_error); PQXX_CHECK_EQUAL(counter, 1); } void test_transactor_newstyle_repeats_up_to_given_number_of_attempts( pqxx::test::context &) { int const attempts{5}; int counter{0}; auto const &callback{[&counter] { ++counter; throw pqxx::transaction_rollback("Simulated error"); }}; PQXX_CHECK_THROWS( pqxx::perform(callback, attempts), pqxx::transaction_rollback); PQXX_CHECK_EQUAL(counter, attempts); } void test_transactor(pqxx::test::context &tctx) { test_transactor_newstyle_executes_simple_query(tctx); test_transactor_newstyle_can_return_void(tctx); test_transactor_newstyle_completes_upon_success(tctx); test_transactor_newstyle_retries_broken_connection(tctx); test_transactor_newstyle_retries_rollback(tctx); test_transactor_newstyle_does_not_retry_in_doubt_error(tctx); test_transactor_newstyle_does_not_retry_other_error(tctx); test_transactor_newstyle_repeats_up_to_given_number_of_attempts(tctx); } PQXX_REGISTER_TEST(test_transactor); } // namespace libpqxx-8.0.1/test/test_type_name.cxx000066400000000000000000000017601516427024100177400ustar00rootroot00000000000000#include "helpers.hxx" namespace { void test_type_name(pqxx::test::context &) { #include // It's hard to test in more detail, because spellings may differ. // For instance, one compiler might call "const unsigned int*" what another // might call "unsigned const *". And Visual Studio prefixes "class" to // class types. auto const &i{pqxx::type_name}; PQXX_CHECK_LESS(std::size(i), 5u, "type_name is suspiciously long."); PQXX_CHECK_EQUAL( i.substr(0, 1), "i", "type_name does not start with 'i'."); #include } void test_name_type(pqxx::test::context &) { // We have a few hand-defined type names. PQXX_CHECK_EQUAL(pqxx::name_type(), "std::string"); PQXX_CHECK_EQUAL(pqxx::name_type(), "std::string_view"); PQXX_CHECK_EQUAL(pqxx::name_type(), "int"); } PQXX_REGISTER_TEST(test_type_name); PQXX_REGISTER_TEST(test_name_type); } // namespace libpqxx-8.0.1/test/test_util.cxx000066400000000000000000000356611516427024100167430ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { void test_make_num(pqxx::test::context &tctx) { bool same{true}; int const last{tctx.make_num()}; for (int i{0}; same and (i < 10); ++i) if (tctx.make_num() != last) same = false; PQXX_CHECK( not same, std::format("Random numbers all came out as {}.", last)); for (int i{0}; i < 100; ++i) PQXX_CHECK_BOUNDS(tctx.make_num(10), 0, 10); } template void test_for(T const &val) { auto const name{pqxx::name_type()}; auto const sz{std::size(val)}; std::span const out{pqxx::binary_cast(val)}; PQXX_CHECK_EQUAL( std::size(out), sz, std::format("Got bad size on binary_cast<{}().", name)); for (std::size_t i{0}; i < sz; ++i) PQXX_CHECK_EQUAL( static_cast(out[i]), static_cast(val[i]), std::format("Mismatch in {} byte {}.", name, i)); } void test_binary_cast(pqxx::test::context &) { std::byte const bytes_c_array[]{ std::byte{0x22}, std::byte{0x23}, std::byte{0x24}}; test_for(bytes_c_array); test_for("Hello world"); test_for(std::string{"I'm a string"}); test_for(std::string_view{"I'm a string_view"}); test_for(std::vector{'n', 'o', 'p', 'q'}); test_for(std::vector{'n', 'o', 'p', 'q'}); test_for(std::vector{'n', 'o', 'p', 'q'}); } /// Shorthand for `std::source_location::current()` or `pqxx::sl::current()`. constexpr inline pqxx::sl here(pqxx::sl loc = pqxx::sl::current()) { return loc; } /// Test @ref pqxx::check_cast() for casting 0 from `FROM` to `TO`. template inline void check_val(int n) { PQXX_CHECK_EQUAL( pqxx::check_cast( static_cast(n), std::format("check_cast failed for value {}.", n), here()), static_cast(n), std::format("check_fast test failed for integral value {}", n)); } template inline void check_val_to(int n) { check_val(n); check_val(n); check_val(n); check_val(n); if (n >= 0) { check_val(n); check_val(n); check_val(n); check_val(n); } } /// Test @ref pqxx::check_cast() for casting 0 from `FROM` to `TO`. template inline void check_val(float n) { auto const cast_result{pqxx::check_cast(n, "fail", here())}; // Check that the value we get falls between the immediately neighbouring // float values. PQXX_CHECK_GREATER( cast_result, std::nextafterf(n, -std::numeric_limits::infinity())); PQXX_CHECK_LESS( cast_result, std::nextafterf(n, std::numeric_limits::infinity())); } template inline void check_val_to(float n) { check_val(n); check_val(n); // Valgrind doesn't support long double, so skip those tests when building // for testing with Valgrind. Horrible, but there are no good options. #if !defined(PQXX_VALGRIND) check_val(n); #endif } inline void check_all_casts(int n) { check_val_to(n); check_val_to(n); check_val_to(n); check_val_to(n); if (n >= 0) { check_val_to(n); check_val_to(n); check_val_to(n); check_val_to(n); } } inline void check_all_casts(float n) { check_val_to(n); check_val_to(n); #if !defined(PQXX_VALGRIND) check_val_to(n); #endif } /// Test @ref pqxx::check_cast() for casting NaNs to type `TO`. template inline void check_nan() { PQXX_CHECK(std::isnan(pqxx::check_cast(std::nanf("1"), "fail", here()))); PQXX_CHECK(std::isnan(pqxx::check_cast(std::nan("1"), "fail", here()))); PQXX_CHECK(std::isnan(pqxx::check_cast(std::nanl("1"), "fail", here()))); } /// Test @ref pqxx::check_cast() for casting infinities from `FROM` to `TO`. template inline void check_inf() { PQXX_CHECK(std::isinf(pqxx::check_cast( std::numeric_limits::infinity(), "fail", here()))); PQXX_CHECK(std::isinf(pqxx::check_cast( -std::numeric_limits::infinity(), "fail", here()))); } /// Test @ref pqxx::check_cast() for casting infinities to `TO`. template inline void check_inf_to() { check_inf(); check_inf(); #if !defined(PQXX_VALGRIND) check_inf(); #endif } void test_check_cast(pqxx::test::context &) { check_all_casts(0); check_all_casts(1); check_all_casts(-1); check_all_casts(999); check_all_casts(-999); check_all_casts(32767); check_all_casts(-32767); check_all_casts(0.0f); check_all_casts(-0.0f); check_all_casts(-1.0f); check_all_casts(1.0f); check_all_casts(999.0f); PQXX_CHECK_EQUAL(pqxx::check_cast(-1, "fail", here()), -1); PQXX_CHECK_EQUAL(pqxx::check_cast(-1LL, "fail", here()), -1); PQXX_CHECK_EQUAL(pqxx::check_cast(-1, "fail", here()), -1); PQXX_CHECK_EQUAL(pqxx::check_cast(-1LL, "fail", here()), -1); PQXX_CHECK_EQUAL(pqxx::check_cast(-1LL, "fail", here()), -1); PQXX_CHECK_THROWS( pqxx::check_cast(-1, "fail", here()), pqxx::range_error); PQXX_CHECK_THROWS( pqxx::check_cast(-1, "fail", here()), pqxx::range_error); PQXX_CHECK_THROWS( pqxx::check_cast( (std::numeric_limits::max)(), "fail", here()), pqxx::range_error); PQXX_CHECK_THROWS( pqxx::check_cast( (std::numeric_limits::max)() + 1LL, "fail", here()), pqxx::range_error); PQXX_CHECK_THROWS( pqxx::check_cast( std::numeric_limits::lowest() - 1LL, "fail", here()), pqxx::range_error); PQXX_CHECK_THROWS( pqxx::check_cast( (std::numeric_limits::max)() * 1.1, "fail", here()), pqxx::range_error); PQXX_CHECK_THROWS( pqxx::check_cast( std::numeric_limits::lowest() * 1.1, "fail", here()), pqxx::range_error); int const threshold{(std::numeric_limits::max)()}; if constexpr (std::numeric_limits::max() > threshold) { PQXX_CHECK_THROWS( pqxx::check_cast(threshold + 1, "fail", here()), pqxx::range_error); } check_nan(); check_nan(); #if !defined(PQXX_VALGRIND) check_nan(); #endif check_inf_to(); check_inf_to(); #if !defined(PQXX_VALGRIND) check_inf_to(); #endif } void test_source_loc_renders_real_source_location(pqxx::test::context &) { auto const loc{pqxx::sl::current()}; auto const loc_text{pqxx::source_loc(loc)}; PQXX_CHECK_EQUAL( loc_text, (std::format( "{}:{}:{}: ({})", loc.file_name(), loc.line(), loc.column(), loc.function_name()))); PQXX_CHECK(pqxx::str_contains( loc_text, "test_source_loc_renders_real_source_location")); PQXX_CHECK(pqxx::str_contains(loc_text, __FILE__)); } /// Make up an arbitrary source code filename. std::string make_filename(pqxx::test::context &tctx) { char const *suffix{nullptr}; switch (tctx.make_num(7)) { case 0: suffix = "cxx"; break; case 1: suffix = "cpp"; break; case 2: suffix = "cc"; break; case 3: suffix = "C"; break; case 4: suffix = "hxx"; break; case 5: suffix = "hpp"; break; case 6: suffix = "h"; break; } assert(suffix != nullptr); return std::format("{}.{}", tctx.make_name("source"), suffix); } /// Make up an arbitrary C++ type name. std::string make_type(pqxx::test::context &tctx) { switch (tctx.make_num(10)) { case 0: return "int"; case 1: return "char *"; case 2: return "const char *"; case 3: return "std::string"; case 4: return "unsigned int"; case 5: return "double"; case 6: return std::format("std::vector<{}> &", make_type(tctx)); case 7: { auto const tp1{make_type(tctx)}; auto const tp2{make_type(tctx)}; return std::format("std::map<{}, {}> &", tp1, tp2); } case 8: return "bool"; case 9: return "char"; default: break; } throw pqxx::internal_error{"Unexpected value from make_num()."}; } /// Make up an arbitrary C++ parameters list. std::string make_params(pqxx::test::context &tctx) { switch (tctx.make_num(3)) { case 0: return ""; case 1: return make_type(tctx); case 2: { auto const tp1{make_type(tctx)}; auto const tp2{make_type(tctx)}; return std::format("{}, {}", tp1, tp2); } default: break; } throw pqxx::internal_error{"Unexpected value from make_num()."}; } /// Make up an arbitrary function name. std::string make_function(pqxx::test::context &tctx) { std::string rettype{"void"}; if (tctx.make_num(5) > 0) rettype = make_type(tctx); auto const name{tctx.make_name("func")}; return std::format("{} {}({})", rettype, name, make_params(tctx)); } /// Test double for a `std::source_location`. struct fake_sl { // NOLINTBEGIN(misc-non-private-member-variables-in-classes) std::string fil; char const *fun{""}; std::uint_least32_t lin{0}; std::uint_least32_t col{0}; // NOLINTEND(misc-non-private-member-variables-in-classes) [[nodiscard]] constexpr char const *file_name() const noexcept { return fil.c_str(); } [[nodiscard]] constexpr char const *function_name() const noexcept { return fun; } [[nodiscard]] constexpr std::uint_least32_t line() const noexcept { return lin; } [[nodiscard]] constexpr std::uint_least32_t column() const noexcept { return col; } }; /// Return an arbitrary positive number. std::uint_least32_t make_pos_num(pqxx::test::context &tctx) { return static_cast(tctx.make_num(9999) + 1); } void test_source_loc_handles_full_location(pqxx::test::context &tctx) { std::string const func{make_function(tctx)}; fake_sl const loc{ .fil = make_filename(tctx), .fun = func.c_str(), .lin = make_pos_num(tctx), .col = make_pos_num(tctx), }; PQXX_CHECK_EQUAL( pqxx::source_loc(loc), std::format("{}:{}:{}: ({})", loc.fil, loc.lin, loc.col, loc.fun)); } void test_source_loc_handles_missing_column(pqxx::test::context &tctx) { std::string const func{make_function(tctx)}; fake_sl const loc{ .fil = make_filename(tctx), .fun = func.c_str(), .lin = make_pos_num(tctx), }; PQXX_CHECK_EQUAL( pqxx::source_loc(loc), std::format("{}:{}: ({})", loc.fil, loc.lin, loc.fun)); } void test_source_loc_handles_missing_line(pqxx::test::context &tctx) { std::string const func{make_function(tctx)}; fake_sl const loc{ .fil = make_filename(tctx), .fun = func.c_str(), .col = make_pos_num(tctx), }; PQXX_CHECK_EQUAL( pqxx::source_loc(loc), std::format("{}: ({})", loc.fil, loc.fun)); } void test_source_loc_handles_missing_function(pqxx::test::context &tctx) { fake_sl const loc{ .fil = make_filename(tctx), .lin = make_pos_num(tctx), .col = make_pos_num(tctx), }; PQXX_CHECK_EQUAL( pqxx::source_loc(loc), std::format("{}:{}:{}:", loc.fil, loc.lin, loc.col)); } void test_source_loc_handles_line_only(pqxx::test::context &tctx) { fake_sl const loc{ .fil = make_filename(tctx), .lin = make_pos_num(tctx), }; PQXX_CHECK_EQUAL( pqxx::source_loc(loc), std::format("{}:{}:", loc.fil, loc.lin)); } void test_source_loc_handles_column_only(pqxx::test::context &tctx) { fake_sl const loc{.fil = make_filename(tctx), .col = make_pos_num(tctx)}; // We don't bother printing a column number without a line number. PQXX_CHECK_EQUAL(pqxx::source_loc(loc), std::format("{}:", loc.fil)); } void test_source_loc_handles_func_only(pqxx::test::context &tctx) { std::string const func{make_function(tctx)}; fake_sl const loc{.fil = make_filename(tctx), .fun = func.c_str()}; PQXX_CHECK_EQUAL( pqxx::source_loc(loc), std::format("{}: ({})", loc.fil, loc.fun)); } void test_source_loc_handles_minimal_source_location(pqxx::test::context &tctx) { fake_sl const loc{.fil = make_filename(tctx)}; PQXX_CHECK_EQUAL(pqxx::source_loc(loc), std::format("{}:", loc.fil)); } void test_version_check_requires_identical_abi(pqxx::test::context &) { // (Baseline check) PQXX_CHECK_SUCCEEDS(pqxx::internal::check_libpqxx_version( pqxx::version_major, pqxx::version_minor, pqxx::version_patch, pqxx::version)); PQXX_CHECK_THROWS( pqxx::internal::check_libpqxx_version( pqxx::version_major + 1, pqxx::version_minor, pqxx::version_patch, pqxx::version), pqxx::version_mismatch); PQXX_CHECK_THROWS( pqxx::internal::check_libpqxx_version( pqxx::version_major, pqxx::version_minor + 1, pqxx::version_patch, pqxx::version), pqxx::version_mismatch); } void test_version_check_accepts_patch_upgrade(pqxx::test::context &) { // (Baseline check) PQXX_CHECK_SUCCEEDS(pqxx::internal::check_libpqxx_version( pqxx::version_major, pqxx::version_minor, pqxx::version_patch, pqxx::version)); // We don't meddle with the version numbers stored inside the library binary, // meaning we can't test both the "special version" scenario and the // "regular" scenario. We'll just check which kind of version we are, and // test the corresponding scenario. In time, all shall be tested. if constexpr (pqxx::version_patch >= 0) { // We're a regular version. // Checking an older app build for the same ABI version succeeds. PQXX_CHECK_SUCCEEDS(pqxx::internal::check_libpqxx_version( pqxx::version_major, pqxx::version_minor, pqxx::version_patch - 1, pqxx::version)); // Checking a newer app build for the same ABI version fails. // // In the special case where our patch level is zero, subtracting one will // simulate a special version, which should also fail. PQXX_CHECK_THROWS( pqxx::internal::check_libpqxx_version( pqxx::version_major, pqxx::version_minor, pqxx::version_patch + 1, pqxx::version), pqxx::version_mismatch); } else { // We're a special version. Even if the application was compiled against // the oldest possible patch level, it fails. PQXX_CHECK_THROWS( pqxx::internal::check_libpqxx_version( pqxx::version_major, pqxx::version_minor, 0, pqxx::version), pqxx::version_mismatch); } } PQXX_REGISTER_TEST(test_make_num); PQXX_REGISTER_TEST(test_binary_cast); PQXX_REGISTER_TEST(test_check_cast); PQXX_REGISTER_TEST(test_source_loc_renders_real_source_location); PQXX_REGISTER_TEST(test_source_loc_handles_full_location); PQXX_REGISTER_TEST(test_source_loc_handles_missing_column); PQXX_REGISTER_TEST(test_source_loc_handles_missing_line); PQXX_REGISTER_TEST(test_source_loc_handles_missing_function); PQXX_REGISTER_TEST(test_source_loc_handles_line_only); PQXX_REGISTER_TEST(test_source_loc_handles_column_only); PQXX_REGISTER_TEST(test_source_loc_handles_func_only); PQXX_REGISTER_TEST(test_source_loc_handles_minimal_source_location); PQXX_REGISTER_TEST(test_version_check_requires_identical_abi); PQXX_REGISTER_TEST(test_version_check_accepts_patch_upgrade); } // namespace libpqxx-8.0.1/test/test_zview.cxx000066400000000000000000000031441516427024100171210ustar00rootroot00000000000000#include #include #include "helpers.hxx" namespace { void test_zview_is_a_range(pqxx::test::context &) { static_assert(std::ranges::range); static_assert(std::ranges::borrowed_range); static_assert(std::ranges::contiguous_range); } void test_zview_literal(pqxx::test::context &) { using pqxx::operator""_zv; PQXX_CHECK_EQUAL(("foo"_zv), pqxx::zview{"foo"}); } void test_zview_converts_to_string(pqxx::test::context &) { using pqxx::operator""_zv; using traits = pqxx::string_traits; PQXX_CHECK_EQUAL(pqxx::to_string("hello"_zv), (std::string{"hello"})); std::array buf{}; auto const v{traits::to_buf(buf, "myview"_zv)}; PQXX_CHECK_EQUAL((std::string{v}), "myview"); auto const p{pqxx::into_buf(buf, "moreview"_zv)}; PQXX_CHECK( p == std::strlen("moreview"), "into_buf of zview did not store in buffer."); PQXX_CHECK(buf.at(p - 1) == 'w'); PQXX_CHECK_EQUAL((std::string{std::data(buf), p}), "moreview"); } void test_zview_properties(pqxx::test::context &tctx) { auto const str{tctx.make_name("zv")}; PQXX_CHECK_EQUAL( (pqxx::zview{str.c_str(), std::size(str)}), (pqxx::zview{str})); PQXX_CHECK_EQUAL((pqxx::zview{str.c_str()}), (pqxx::zview{str})); PQXX_CHECK_EQUAL((pqxx::zview{std::string_view{str}}), (pqxx::zview{str})); PQXX_CHECK_EQUAL((std::string{pqxx::zview{str}.c_str()}), str); } PQXX_REGISTER_TEST(test_zview_is_a_range); PQXX_REGISTER_TEST(test_zview_literal); PQXX_REGISTER_TEST(test_zview_converts_to_string); PQXX_REGISTER_TEST(test_zview_properties); } // namespace libpqxx-8.0.1/tools/000077500000000000000000000000001516427024100143515ustar00rootroot00000000000000libpqxx-8.0.1/tools/check_ascii.py000077500000000000000000000051311516427024100171530ustar00rootroot00000000000000#! /usr/bin/env python3 """Check that all source files are pure ASCII.""" from argparse import ArgumentParser from pathlib import Path import sys def find_source_files(srcdir: Path) -> list[Path]: """Find source file paths in `srcdir`.""" paths = [] for dirpath, _, filenames in srcdir.walk(): if dirpath.relative_to(srcdir) == Path("include") / "pqxx": # The header code in this directory is in files without suffixes. for filename in filenames: path = dirpath / filename if path.suffix in (".cxx", ".hxx") or "." not in filename: paths.append(path) else: for filename in filenames: path = dirpath / filename if path.suffix in (".cxx", ".hxx"): paths.append(path) return paths def check_file(path: Path) -> list[int]: """Return any line numbers in file at `path` that are not pure ASCII. Actually we're not properly checking _lines,_ because there is no such notion in a binary file. But we'll pretend we can split the contents by '\n', since it's mostly supposed to be ASCII (where this works). """ lines = path.read_bytes().split(b"\n") bad_lines = [] for n, data in enumerate(lines, start=1): # Why in blazes am I getting an int at the end of the file!? if isinstance(data, bytes): try: data.decode("ascii") except UnicodeDecodeError: bad_lines.append(n) return bad_lines def parse_args(): """Parse command line.""" parser = ArgumentParser(description=__doc__) parser.add_argument( "-v", "--verbose", action="append_const", default=[], help="Print more detail. Double this for even more.", ) parser.add_argument( "-s", "--srcdir", default=Path(), type=Path, help="Source directory. Defaults to current directory.", ) return parser.parse_args() def main() -> int: """Main entry point.""" args = parse_args() files = sorted(find_source_files(args.srcdir)) if len(args.verbose) > 1: print("\n".join(str(path) for path in files)) ok = True for path in files: lines = check_file(path) if lines != []: ok = False print(f"*** Non-ASCII characters in {path}: ***", file=sys.stderr) for line in lines: print(f" - line {line}", file=sys.stderr) if ok: return 0 else: return 1 if __name__ == "__main__": sys.exit(main()) libpqxx-8.0.1/tools/compiler_flags.py000077500000000000000000000061531516427024100177210ustar00rootroot00000000000000#! /usr/bin/env python3 """Check whether the compiler accepts various options. Prints any of the flags that are accepted when used in combination with the base command line and the previously accepted flags. """ from argparse import ( ArgumentParser, Namespace, ) from contextlib import nullcontext from pathlib import Path from subprocess import ( DEVNULL, run, ) import sys EPILOG = """The flags file may contain comments, on lines starting with '#' as the first non-whitespace character. Any whitespace between flags other than newlines is ignored, as are blank lines. """ def parse_args() -> Namespace: """Parse command-line options.""" parser = ArgumentParser(description=__doc__, epilog=EPILOG) parser.add_argument( "-c", "--command", required=True, help="The basic compiler command line, e.g. 'c++ -std=c++20 -Werror'.", ) parser.add_argument( "-f", "--flags", default="-", type=str, help="File with compiler flags to check, one per line; '-' for stdin.", ) parser.add_argument( "-s", "--single-line", action="store_true", default=False, help="Print all command-line options on a single line.", ) parser.add_argument( "-o", "--output", default="-", type=str, help="Output file, or '-' for stdout (the default).", ) return parser.parse_args() def run_quietly(cmd: str) -> bool: """Run `cmd`, suppressing output; return whether it succeeds. **This will run `cmd` through shell interpretation.** """ proc = run(cmd, stdout=DEVNULL, stderr=DEVNULL, shell=True, check=False) return proc.returncode == 0 def compiler_accepts( command: str, source: Path, flag: str, prev: str = "" ) -> bool: """Return whether the compiler seems to accept `flag`.""" return run_quietly(f"{command} {prev} {flag} -c {source}") def open_in(path: str): """Open file passed on command line for reading, unless it's '-'. If it's a dash (`-`), open standard input instead. """ if path == "-": return nullcontext(sys.stdin) else: return Path(path).open() def open_out(path: str): """Open file passed on command line for writing, unless it's '-'. If it's a dash (`-`), open standard output instead. """ if path == "-": return nullcontext(sys.stdout) else: return Path(path).open("w") def main() -> None: """Main entry point.""" args = parse_args() good_flags: list[str] = [] source = Path("config-tests") / "minimal.cxx" src = source.name with open_in(args.flags) as flags: for line in flags: flag = line.strip() if flag == "" or flag.startswith("#"): continue prev = " ".join(good_flags) if compiler_accepts(args.command, Path(src), flag, prev=prev): good_flags.append(flag) sep = " " if args.single_line else "\n" with open_out(args.output) as output: print(sep.join(good_flags), file=output) if __name__ == "__main__": main() libpqxx-8.0.1/tools/deprecations.sh000077500000000000000000000002031516427024100173630ustar00rootroot00000000000000#! /bin/sh set -Cue MARKER='include.*ignore-deprecated-pre' grep -Ircl "$MARKER" src include tools/*.cxx test config-tests | sort libpqxx-8.0.1/tools/extract_version.py000077500000000000000000000063371516427024100201560ustar00rootroot00000000000000#! /usr/bin/env python3 """Print libpqxx version information based on the source tree's VERSION file. Version strings look like: "..". """ from argparse import ArgumentParser, Namespace from os import getenv from pathlib import Path import sys class Fail(Exception): """A well-handled exception. Show message only, no traceback.""" def parse_args() -> Namespace: """Parse command-line arguments.""" parser = ArgumentParser(description=__doc__) parser.add_argument( "--abi", "-a", action="store_true", help="Show ABI version only; omit patch.", ) parser.add_argument( "--full", "-f", action="store_true", help="Show full version string (the default).", ) parser.add_argument( "--major", "-M", action="store_true", help="Show major version." ) parser.add_argument( "--minor", "-m", action="store_true", help="Show minor version." ) parser.add_argument( "--patch", "-p", action="store_true", help="Show patch version." ) parser.add_argument( "--patch-num", "-P", action="store_true", help="Show patch version if it's a number, or -1 otherwise.", ) parser.add_argument( "--srcdir", "-s", type=Path, help="Source directory; defaults to '$srcdir' or '.'.", ) args = parser.parse_args() actions = list( filter( None, [ args.abi, args.full, args.major, args.minor, args.patch, args.patch_num, ], ) ) if len(actions) > 1: raise Fail( "Parse at most one of --abi, --full, --major, --minor, --patch, or --patch-num." ) return args def find_srcdir(args_srcdir: Path) -> Path: """Locate the root source directory.""" return Path(args_srcdir or getenv("srcdir") or Path.cwd()) def read_version(srcdir: Path) -> str: """Read the VERSION file.""" try: version = (srcdir / "VERSION").read_text().strip() except FileNotFoundError: raise Fail(f"Did not find VERSION file in {srcdir}.") if len(list(version.split("."))) != 3: raise Fail(f"Expected 3 components in version, found '{version}'.") return version def patch_num(patch_str: str) -> int: """Return patch number as `int`, or -1 if it's not numeric.""" if patch_str.isdigit(): return int(patch_str) else: return -1 def work() -> None: """Do the actual work.""" args = parse_args() version = read_version(find_srcdir(args.srcdir)) if args.major: print(version.split(".")[0]) elif args.minor: print(version.split(".")[1]) elif args.patch: print(version.split(".")[2]) elif args.patch_num: print(patch_num(version.split(".")[2])) elif args.abi: print(version.rsplit(".", 1)[0]) else: # Default to full version. print(version) def main() -> int: """Main entry point.""" try: work() except Fail as e: print(e, file=sys.stderr) return 1 return 0 if __name__ == "__main__": sys.exit(main()) libpqxx-8.0.1/tools/extract_version.sh000077500000000000000000000027111516427024100201300ustar00rootroot00000000000000#! /bin/sh set -Cue echo "*** DEPRECATED: Use extract_version.py, not extract_version.sh. ***" >&2 ARG="${1:-}" # Source directory. In out-of-tree builds, Automake sets this for us. srcdir=${srcdir:-.} # Print usage information. usage() { cat <... Acceptable option values are: -h, --help Print this message, and exit. -a, --abi Show libpqxx ABI version; leave out revision number. -f, --full Show full libpqxx version string (the default). -M, --major Show major libpqxx version. -m, --minor Show minor libpqxx version (between major and revision). EOF } # Print "unknown argument" error. unknown_arg() { cat <&2 Unknown argument: $1. Try $0 --help for usage information. EOF } case "$ARG" in ''|-f|--full) # Default: Print full version. cat "$srcdir/VERSION" ;; -h|--help) # Print usage information, and exit. usage exit ;; -a|--abi) # Print just the ABI version (major & minor). sed -e 's/^\([^.]*\.[^.]*\)\..*/\1/' "$srcdir/VERSION" ;; -M|--major) # Print the major version number. sed -e 's/^\([^.]*\)\..*/\1/' "$srcdir/VERSION" ;; -m|--minor) # Print the minor version number. sed -e 's/^[^.]*\.\([^.]*\)\..*/\1/' "$srcdir/VERSION" ;; *) unknown_arg "$ARG" exit 1 ;; esac libpqxx-8.0.1/tools/filter_config.py000077500000000000000000000023521516427024100175420ustar00rootroot00000000000000#! /usr/bin/env python3 """Extract relevant configuration macros from generated header. We run `configure` or `cmake` to configure a build. It spits out a config header, but there are a lot of definitions in there that we don't actually want. Not just because they're not needed, but also because they pollute the macro namespace. It'd be fine if it was just inside libpqxx source files, but the header affects client applications as well. So, we write our own header file that contains only the macro definitions with "PQXX" in the name. Also, we add some boilerplate. """ from pathlib import Path import sys HEADER = """\ #ifndef PQXX_CONFIG_COMPILER_H #define PQXX_CONFIG_COMPILER_H """ FOOTER = """\ #endif """ # TODO: Use argparse. # TODO: Supporting stdin/stdout might be nice. def main() -> int: """Main entry point. Returns exit code.""" infile = Path(sys.argv[1]) outfile = Path(sys.argv[2]) with infile.open("r") as instream, outfile.open("w") as outstream: print(HEADER, file=outstream) for line in instream: if "PQXX" in line: print(line.strip(), file=outstream) print(FOOTER, file=outstream, end="") return 0 if __name__ == "__main__": sys.exit(main()) libpqxx-8.0.1/tools/format.sh000077500000000000000000000007221516427024100162010ustar00rootroot00000000000000#! /bin/bash # # Reformat source code using clang-format. # # This script requires "uv" to be installed. set -Cue -o pipefail # Reformat C++ files. find . -name '*.[ch]xx' -print0 | xargs -0 clang-format -i # Reformat CMake files. (Requires "uv" to be installed.) find . -name '*.cmake' -exec \ uv run --with='pyaml,cmake-format' cmake-format -i '{}' '+' if which black >/dev/null then black -l80 . else uv run --with=black==24.2.0 black -l80 . fi libpqxx-8.0.1/tools/generate_check_config.py000077500000000000000000000062751516427024100212140ustar00rootroot00000000000000#! /usr/bin/env python3 """Write autoconf and CMake configuration for our C++ feature checks. Produces configuration files for inclusion in the autoconf script and the CMake configuration, respectively. The config will ask the build systems to try and compile each of the snippets of check code in `config-tests/`, and where that succeeds, define the C++ macro of the same name as the base name of the check snippet. """ from argparse import ( ArgumentParser, Namespace, ) import os.path from pathlib import Path from textwrap import dedent # Name of the autoconf configuration script that we produce. (Lives in the # main source directory.) AUTOCONF_CONFIG = "pqxx_cxx_feature_checks.ac" # Name of the CMake config that we produce. (Lives in the cmake directory.) CMAKE_CONFIG = "pqxx_cxx_feature_checks.cmake" def parse_args() -> Namespace: """Parse command line.""" parser = ArgumentParser(__doc__) parser.add_argument( "--source", "-s", metavar="DIR", type=Path, default=Path(), help="Location of the source tree. Defaults to current directory.", ) return parser.parse_args() def list_snippets(source: Path) -> list[str]: """Return list of C++ snippets.""" return sorted(map(str, (source / "config-tests").glob("PQXX_*.cxx"))) # Comment header for either autoconf or CMake config we generate. HEAD = dedent( """\ # Configuration for feature checks. Generated by %(script)s. """ ) def compose_header() -> str: """Produce a config header.""" return HEAD % {"script": os.path.basename(__file__)} FOOT = "# End of config.\n" # Template for an autoconf feature check. AUTOCONF_TEMPLATE = dedent( """\ AC_MSG_CHECKING([%(macro)s]) %(macro)s=yes AC_COMPILE_IFELSE( [read_test(%(macro)s.cxx)], AC_DEFINE( [%(macro)s], 1, [Define if this feature is available.]), %(macro)s=no) AC_MSG_RESULT($%(macro)s) """ ) def generate_autoconf(source: Path, snippets: list[str]) -> None: """Generate autoconf configuration.""" dest = source / AUTOCONF_CONFIG with dest.open("w", encoding="ascii") as stream: stream.write(compose_header()) for snippet in snippets: stream.write(AUTOCONF_TEMPLATE % {"macro": Path(snippet).stem}) stream.write(FOOT) # Template for a CMake feature check. # # Makes use of a custom function, try_compile. CMAKE_TEMPLATE = dedent( """\ try_compile( %(macro)s ${PROJECT_BINARY_DIR} SOURCES ${PROJECT_SOURCE_DIR}/config-tests/%(macro)s.cxx ) """ ) def generate_cmake(source: Path, snippets: list[str]) -> None: """Generate CMake configuration.""" dest = source / "cmake" / CMAKE_CONFIG with dest.open("w", encoding="ascii") as stream: stream.write(compose_header()) for snippet in snippets: stream.write(CMAKE_TEMPLATE % {"macro": Path(snippet).stem}) stream.write(FOOT) def main(args: Namespace) -> None: """Main entry point.""" snippets = list_snippets(args.source) generate_autoconf(args.source, snippets) generate_cmake(args.source, snippets) if __name__ == "__main__": main(parse_args()) libpqxx-8.0.1/tools/generate_cxx_checks.py000077500000000000000000000067711516427024100207350ustar00rootroot00000000000000#! /usr/bin/env python3 """Generate autoconf/CMake checks for C++ feature check macros. Produces feature checks for those features that we can detect based on just the C++ feature check macros. Reads the test libpqxx feature macro names, as well as the C++ feature check macros that control them, from cxx_features.txt in the source tree. """ from argparse import ( ArgumentParser, Namespace, ) import os.path from pathlib import Path from textwrap import dedent from typing import cast # Name of the config file listing, one per line, the macros to test and set. # # Ignoring whitespace, a line can be: # * empty, or # * a comment starting with '#', or # * a tuple of macro names. # # In that last case, the line must consist of a libpqxx feature macro name # (which the configuration will either define or not define depening on whether # there is support for the corresponding feature), followed by the name of the # C++ feature test macro that we will need to check in order to determinue # whether that feature is present. CONFIG = "cxx_features.txt" def parse_args() -> Namespace: """Parse command line.""" parser = ArgumentParser(description=__doc__) parser.add_argument( "--source", "-s", metavar="DIR", type=Path, default=Path(), help="Location of the source tree. Defaults to current directory.", ) return parser.parse_args() def read_config(config: Path) -> list[tuple[str, str]]: """Read config file, return as list of tuples. Each item is a tuple of a libpqxx feature macro, and the corresponding C++ feature check macro. """ contents = config.read_text(encoding="ascii") lines = [line.strip() for line in contents.splitlines()] return [ cast(tuple[str, str], tuple(line.split())) for line in lines if line != "" and not line.startswith("#") ] # Template for a check snippet. # # Strictly speaking, this is unnecessarily verbose. Why does it check first # whether the macro is defined, and only then what its value is? Because it's # just conceivable that a user might have their compiler set to be extremely # strict when it comes to checking undefined macros in a conditional. The # C++ standard says that in a conditional, an undefined macro shows up as if # its value were zero. But I can imagine some people wanting the compiler to # warn them when they evaluate an undefined macro. TEMPLATE = dedent( """\ // Feature check for '%(pqxx_macro)s'. // Generated by %(script)s. #include #if !defined(%(cxx_macro)s) # error "No %(pqxx_macro)s: %(cxx_macro)s is not set." #endif #if !%(cxx_macro)s # error "No %(pqxx_macro)s: %(cxx_macro)s is false." #endif int main() {} """ ) def write_check( source: Path, pqxx_macro: str, cxx_macro: str, base_params: dict ) -> None: """Write a piece of C++ for checking a feature macro.""" params = dict( { "pqxx_macro": pqxx_macro, "cxx_macro": cxx_macro, }, **base_params, ) check = source / "config-tests" / f"{pqxx_macro}.cxx" check.write_text(TEMPLATE % params, encoding="ascii") def main(args: Namespace) -> None: """Main entry point.""" items = read_config(args.source / "cxx_features.txt") base_params = { "script": os.path.basename(__file__), } for pqxx_macro, cxx_macro in items: write_check(args.source, pqxx_macro, cxx_macro, base_params) if __name__ == "__main__": main(parse_args()) libpqxx-8.0.1/tools/idock.sh000077500000000000000000000021461516427024100160040ustar00rootroot00000000000000#! /bin/bash # # Run an interactive docker container with the standard options, bind-mounting # the libpqxx source directory as /mnt/pqxx. # # Passes all arguments on to docker, so give, in this order: # # 1. Any further command-line options to "docker run", e.g. "--log-level=warn". # 2. Image name, e.g. "debian:unstable". # 3. Optional command line to run inside the container, e.g. "ksh". set -Cue -o pipefail case "${1:-}" in -h|--help|'') cat <&2 Runs an interactive docker container with less typing. You can run an optional command line inside the container, or it will run an interactive shell by default. Usage: $0 [docker options] [command line] Inside the container, the libpqxx source tree will be bind-mounted at '/mnt/pqxx'. EOF exit 1 ;; esac # (This trick is bash-specific. It's surprisingly difficult in pure POSIX to # just get the location of the current script.) PQXX="$(dirname "$(dirname "${BASH_SOURCE[0]}")")" MOUNT=/mnt/pqxx echo "Running docker with '$PQXX' bind-mounted as '$MOUNT'." # The actual work. docker run -ti -v "$PQXX:/mnt/pqxx" "$@" libpqxx-8.0.1/tools/install-deps.sh000077500000000000000000000214111516427024100173060ustar00rootroot00000000000000#! /bin/bash # Install packages we need to get a full test run working. # # Must be run with root privileges. This is meant for use in disposable # containers and VMs. # # Usage: install-deps.sh # # Where is one of the environments for which this script works: # * archlinux # * archlinux-coverage (for running test coverage analysis) # * archlinux-lint (for running full lint) # * debian # * fedora # * macos # * ubuntu # * ubuntu-codeql (for CodeQL analysis) # * ubuntu-valgrind (for running Valgrind tests) # * windows # # The script may output shell commands that you'll need to run in your own # shell process, to set variables and such. # # It also logs package installation to /tmp/install.log. set -Cue -o pipefail # For Debian-flavoured distros: export DEBIAN_FRONTEND=noninteractive TZ=UTC # Common case: OS package we need to install to get compiler $1. # # If $1 equals "clang++", print $2 (or "clang" by default). If $1 equals # "g++", print $3 (or "gcc" by default). Otherwise, fail. compiler_pkg() { local compiler="$1" case "$1" in clang++) echo "${2:-clang}" ;; g++) echo "${3:-gcc}" ;; *) echo >&2 "Unsupported compiler: '$compiler'." exit 1 ;; esac } # Install packages using apt. Includes database update. apt_install() { ( apt-get -q update apt-get -qy install "$@" ) >>/tmp/install.log } # Install packages using Homebrew. brew_install() { brew install --quiet "$@" >>/tmp/install.log } # Install packages using dnf. dnf_install() { dnf -qy install "$@" >>/tmp/install.log } # Install packages using pacman. Includes database update. pacman_install() { pacman -qSuy --needed --noconfirm "$@" >>/tmp/install.log } PKGS_ALL_AUTOTOOLS=(autoconf autoconf-archive automake libtool) PKGS_ARCHLINUX_BASE=(diffutils postgresql-libs python3 uv) PKGS_ARCHLINUX_AUTOTOOLS=("${PKGS_ALL_AUTOTOOLS[@]}" make) PKGS_DEBIAN_BASE=(libpq-dev postgresql-server-dev-all python3) PKGS_DEBIAN_AUTOTOOLS=("${PKGS_ALL_AUTOTOOLS[@]}" make) install_archlinux() { pacman_install \ "${PKGS_ARCHLINUX_BASE[@]}" "${PKGS_ARCHLINUX_AUTOTOOLS[@]}" \ postgresql which \ "$(compiler_pkg "$1")" echo "export PGHOST=/run/postgresql" } # Install test coveraage tools. install_archlinux_coverage() { pacman_install \ "${PKGS_ARCHLINUX_BASE[@]}" "${PKGS_ARCHLINUX_AUTOTOOLS[@]}" \ lcov postgresql which \ "$(compiler_pkg "$1")" echo "export PGHOST=/run/postgresql" } # Install Facebook's Infer static analysis tool. install_archlinux_infer() { local infer_ver="1.2.0" local downloads="https://github.com/facebook/infer/releases/download" local tarball="infer-linux-x86_64-v$infer_ver.tar.xz" local url="$downloads/v$infer_ver/$tarball" if [ "$1" != "g++" ] then echo >&2 "Facebook's 'infer' only seems to work with g++, not '%1'." exit 1 fi pacman_install \ "${PKGS_ARCHLINUX_BASE[@]}" "${PKGS_ARCHLINUX_AUTOTOOLS[@]}" \ tzdata wget xz \ "$(compiler_pkg "$1")" cd /opt # This is not idempotent. I wasn't joking about using a disposable # environment. wget -q "$url" >>/tmp/install.log tar -xJf "$tarball" >>/tmp/install.log ln -s /opt/infer-*/bin/infer /usr/local/bin/infer } # Install for a "lint.sh --full" run (but no actual build). install_archlinux_lint() { pacman_install \ "${PKGS_ARCHLINUX_BASE[@]}" \ cmake cppcheck make markdownlint python-pyflakes ruff shellcheck \ which yamllint \ "$(compiler_pkg "$1")" } install_debian() { apt_install \ "${PKGS_DEBIAN_BASE[@]}" "${PKGS_DEBIAN_AUTOTOOLS[@]}" \ postgresql \ "$(compiler_pkg "$1" clang g++)" echo "export PGHOST=/tmp" echo "export PATH='$PATH:$HOME/.local/bin'" echo "export PGBIN='$(ls -d /usr/lib/postgresql/*/bin)/'" } install_fedora() { dnf_install \ "${PKGS_ALL_AUTOTOOLS[@]}" \ libasan libubsan postgresql postgresql-devel postgresql-server \ python3 uv which \ "$(compiler_pkg "$1" clang g++)" echo "export PGHOST=/tmp" } install_macos() { # Looks like our compilers come pre-installed on this image. local pg_ver=18 brew_install \ "${PKGS_ALL_AUTOTOOLS[@]}" \ postgresql@$pg_ver uv libpq echo "export PGHOST=/tmp PGBIN=/opt/homebrew/bin/ PGVER=$pg_ver" } install_ubuntu_codeql() { # Can't use apt_install here, since we're running it in sudo. ( sudo -E apt-get -q -o DPkg::Lock::Timeout=120 update sudo -E apt-get -q install -y -o DPkg::Lock::Timeout=120 \ cmake git libpq-dev make \ "$(compiler_pkg "$1" clang g++)" ) >>/tmp/install.log } install_ubuntu() { apt_install \ "${PKGS_DEBIAN_BASE[@]}" "${PKGS_DEBIAN_AUTOTOOLS[@]}" \ postgresql \ "$(compiler_pkg "$1" clang g++)" echo "export PGHOST=/tmp" echo "export PATH='$PATH:$HOME/.local/bin'" echo "export PGBIN='$(ls -d /usr/lib/postgresql/*/bin)/'" } install_ubuntu_valgrind() { apt_install \ "${PKGS_DEBIAN_BASE[@]}" \ cmake ninja-build postgresql valgrind \ "$(compiler_pkg "$1" clang g++)" echo "export PGHOST=/tmp" echo "export PATH='$PATH:$HOME/.local/bin'" echo "export PGBIN='$(ls -d /usr/lib/postgresql/*/bin)/'" } install_windows() { local arch="mingw-w64-x86_64" local cxxpkg local msys="/C/tools/msys64" local mingw="$msys/mingw64" cxxpkg="$(compiler_pkg "$1")" if [ -n "$cxxpkg" ] then cxxpkg="$arch-$cxxpkg" fi # This dumps an unacceptable amount of garbage to stderr, even with the # --limit-output option which AFAICT does nothing to limit output (and # why is there no --quiet option?). # # But if we let this run quietly, then it times out. And we can't let the # output go to stdout because that's where we write our variables. So we # let it generate progress information and send the output to stderr. :-/ choco install msys2 --limit-output --stoponfirstfailure -y 2>&1 | tee -a install.log >&2 # We need the msys version of libpq, because the one we'd get from choco # is for MSVC (odd, for a C library). Ironically Microsoft's own vcpkg is # supposed to have a libpq that works with gcc, but it failed to install. # # The order matters. We must prefer MinGW binaries over MSYS ones, or we # get weird problems like failing as it tries to include # . export PATH="$mingw/bin:$msys:$msys/usr/bin:$PATH" # Now bootstrap the rest using the MSYS shell. "$msys/usr/bin/bash.exe" -l -c " ( # Grok says we may need to let pacman run 2 upgrades. pacman -Sy --needed --noconfirm && pacman -Syu --needed --noconfirm ; ) || pacman -Su --needed --noconfirm && pacman -S \ $arch-cmake \ $arch-postgresql \ $arch-toolchain \ cmake \ ninja \ $cxxpkg \ --noconfirm " | tee -a install.log >&2 echo "export PGHOST=localhost" echo "export PATH='$PATH'" echo "export PGBIN='$mingw/bin/'" } if [ -z "${1:-}" ] || [ -z "${2:-}" ] then cat >&2 < Where is usually an OS name, sometimes a combination of OS and purpose: archlinux, archilinux-lint, debian, fedora, macos, windows... And is the compiler: g++ or clang++ (or in future perhaps more). EOF exit 1 fi PROFILE="$1" COMPILER="$2" case "$PROFILE" in archlinux) install_archlinux "$COMPILER" ;; archlinux-coverage) install_archlinux_coverage "$COMPILER" ;; archlinux-infer) install_archlinux_infer "$COMPILER" ;; archlinux-lint) install_archlinux_lint "$COMPILER" ;; debian) install_debian "$COMPILER" ;; fedora) install_fedora "$COMPILER" ;; macos) install_macos "$COMPILER" ;; ubuntu) install_ubuntu "$COMPILER" ;; # Ubuntu system, but only for the purpose of running a CodeQL scan. ubuntu_codeql) install_ubuntu_codeql "$COMPILER" ;; # Ubuntu, but only for the purpose of running valgrind. ubuntu-valgrind) install_ubuntu_valgrind "$COMPILER" ;; windows) install_windows "$COMPILER" ;; *) echo >&2 "$0 does not support $1." exit 1 ;; esac echo "export PGDATA=/tmp/db" # Skip routine lint check except in the actual lint run. case "$PROFILE" in *lint) # We're doing a lint check, which is actually the default. # But we only need 1 job per run to do this. ;; *) # Regular job. Skip redundant lint check. echo "export PQXX_LINT=skip" ;; esac libpqxx-8.0.1/tools/lint.sh000077500000000000000000000146521516427024100156660ustar00rootroot00000000000000#! /bin/bash # # Routine sanity checks for libpqxx source tree. # # This script requires "uv" to be installed. # # Optionally, set environment variable "srcdir" to the source directory. It # defaults to the parent directory of the one where this script is. This trick # requires bash (or a close equivalent) as the shell. # # Set PQXX_LINT=skip to suppress lint checks. set -Cue -o pipefail if [ "${PQXX_LINT:-}" = "skip" ] then echo "PQXX_LINT is set to 'skip'. Skipping lint check." exit 0 fi SRCDIR="${srcdir:-$(dirname "${BASH_SOURCE[0]}")/..}" PQXXVERSION="$(cd "$SRCDIR" && "$SRCDIR/tools/extract_version.py")" ARGS="${1:-}" # Check that all source code is pure ASCII. # # I'd love to have rich Unicode, but I can live without it. Mainly we don't # want any surprises in contributions. # # MD files are different. I love me some Unicode in there. They're UTF-8. check_ascii() { "$SRCDIR/tools/check_ascii.py" -v } # This version must be at the top of the NEWS file. check_news_version() { if ! head -n1 "$SRCDIR/NEWS" | grep -q "^$PQXXVERSION\$" then cat <&2 Version $PQXXVERSION is not at the top of NEWS. EOF exit 1 fi } # Count number of times header $1 is included from each of given input files. # Output is lines of :, one line per file, sorted. count_includes() { local HEADER_NAME PAT HEADER_NAME="$1" shift PAT='^[[:space:]]*#[[:space:]]*include[[:space:]]*[<"]'"$HEADER_NAME"'[>"]' # It's OK for the grep to fail. find "$SRCDIR/include/pqxx" -type f -print0 | ( xargs -0 grep -c "$PAT" || true ) | sort } # Check that any includes of $1-pre.hxx are matched by $1-post.hxx ones. # TODO: Probably time to rewrite this in python. match_pre_post_headers() { local NAME PRE POST NAME="$1" TEMPDIR="$(mktemp -d)" # In case we get interrupted before we can clean up $TEMPDIR ourselves. # (Next invocation will overwrite the trap.) trap 'rm -rf -- "$TEMPDIR"' EXIT PRE="$TEMPDIR/pre" POST="$TEMPDIR/post" count_includes "$SRCDIR/$NAME-pre.hxx" >"$PRE" count_includes "$SRCDIR/$NAME-post.hxx" >"$POST" DIFF="$(diff "$PRE" "$POST")" || true rm -rf -- "$TEMPDIR" if test -n "$DIFF" then cat <&2 Mismatched pre/post header pairs: $DIFF EOF exit 1 fi } # Any file that includes header-pre.hxx must also include header-post.hxx, and # vice versa. Similar for ignore-deprecated-{pre|post}.hxx. check_compiler_internal_headers() { match_pre_post_headers "pqxx/internal/header" match_pre_post_headers "pqxx/internal/ignore-deprecated" } check_yaml() { yamllint -- \ "$SRCDIR" "$SRCDIR/.clang-format" "$SRCDIR/.clang-tidy" \ "$SRCDIR/.cmake-format" } cpplint() { local dialect includes if [ -e compile_commands.json ] then # This wrapper script runs in parallel, making it run faster on most # systems. It uses the "compilation database" that cmake writes into # compile_commands.json. # # It does look as if there's massive overhead to concurrent runs. A # run with -j16 (on a 16-core system) ran less than twice as fast, but # racked up almost ten times as much CPU time. A run with -j1 took # more than four times as long as the original tool. Around -j5 it # overtakes the original tool, but using five times as much CPU. # At -j8 it actually seems to run faster than at -j16, and still with # "only" five times the original CPU time used. run-clang-tidy -q -j8 -warnings-as-errors=* \ -config-file="$SRCDIR/.clang-tidy" elif [ -e compile_flags ] then # The configure-based build writes its compiler options into this # file, so we use that to figure out preprocessor paths, language # flag, etc. # # Pick out relevant flags, but leave out the rest. If we're not # compiling with clang, compile_flags may contain options that # clang-tidy doesn't recognise. readarray -t dialect < <( \ grep -o -- '-std=c++[^[:space:]]*' compile_flags || true ) readarray -t includes < <( \ grep -o -- '-I[[:space:]]*[^[:space:]]*' compile_flags || true ) clang-tidy \ --quiet '-warnings-as-errors=*' \ "$SRCDIR"/src/*.cxx "$SRCDIR"/tools/*.cxx \ "$SRCDIR"/test/*.cxx \ -- \ -I"$SRCDIR/include" -Iinclude "${dialect[@]}" "${includes[@]}" else cat <&2 Could not find compile flags for clang-tidy run. Run this script from a build directry prepared with either configure or cmake. EOF exit 1 fi } pylint() { if which pyflakes >/dev/null then pyflakes "$SRCDIR" else uv -q run --with=pyflakes==3.4.0 pyflakes "$SRCDIR" fi if which ruff >/dev/null then ruff check -q "$SRCDIR" else uv -q run --with=ruff==0.14.14 ruff check -q "$SRCDIR" fi if which pyrefly >/dev/null then pyrefly check . else uv -q run --with=pyrefly==0.50.1 pyrefly check --summary=none "$SRCDIR" fi } shelllint() { local cmd if which shellcheck >/dev/null then cmd=(shellcheck) else cmd=(uv -q run --with=shellcheck.py shellcheck) fi find "$SRCDIR/tools" -name '*.sh' -exec "${cmd[@]}" '{}' '+' } mdlint() { if which mdl >/dev/null then find "$SRCDIR" -name \*.md -exec \ mdl -s "$SRCDIR/.mdl_style.rb" -c "$SRCDIR/.markdownlint.yaml" \ '{}' '+' fi } check_cmake() { find "$SRCDIR" \( -name '*.cmake' -o -name CMakeLists.txt \) -exec \ uv -q run --with=cmake-format cmake-lint --suppress-decorations '{}' '+' } main() { local full="no" for arg in $ARGS do case $arg in -h|--help) cat <&2 "Unknown argument: '$arg'" exit 1 ;; esac done check_ascii pylint shelllint check_news_version check_compiler_internal_headers # check_cmake mdlint check_yaml if [ $full == "yes" ] then cpplint fi } main libpqxx-8.0.1/tools/m4esc.py000077500000000000000000000031721516427024100157440ustar00rootroot00000000000000#! /usr/bin/env python3 """M4-quote text, for use as a literal in configure.ac. Produces M4 "code" which evaluates to the input text. It's not easy to read plain text from an input file in M4, without having it expanded as M4. Sometimes all we want is literal text! """ from __future__ import ( absolute_import, print_function, unicode_literals, ) from argparse import ArgumentParser from sys import ( stdin, stdout, ) def parse_args(): parser = ArgumentParser(description=__doc__) parser.add_argument( "--open", "-a", default="[[", help="Current open-quote symbol." ) parser.add_argument( "--close", "-b", default="]]", help="Current close-quote symbol." ) parser.add_argument( "--input", "-i", default="-", help="Input file, or '-' for stdin." ) parser.add_argument( "--output", "-o", default="-", help="Output file, or '-' for stdout." ) return parser.parse_args() def open_input(in_file): if in_file == "-": return stdin else: return open(in_file) def open_output(out_file): if out_file == "-": return stdout else: return open(out_file, "w") def escape(line): return ( line.replace("[", "@<:@") .replace("]", "@:>@") .replace("#", "@%:@") .replace("$", "@S|@") ) def main(args): with open_input(args.input) as istr, open_output(args.output) as ostr: ostr.write(args.open) for line in istr: ostr.write(escape(line)) ostr.write("\n") ostr.write(args.close) if __name__ == "__main__": main(parse_args()) libpqxx-8.0.1/tools/run-test-postgres.sh000077500000000000000000000101161516427024100203340ustar00rootroot00000000000000#! /bin/bash # # Start a PostgreSQL server & database for temporary use in tests. # Creates a database for the current user, with trust authentication. # # THIS IS NOT A GENERIC UTILITY. It's meant just to get a database running on # a disposable VM in our specific CI. # # Run as root. First set PGHOST and PGDATA. The postgres binaries must be in # $PATH. Pass an optional username for a system user with privileged access to # the cluster. On a normal Linux install this should be "postgres" but it # defaults to the current user. # # If the PostgreSQL binaries (initdb, createdb etc.) are not in the command # path, set PGBIN to their location, ending in a trailing slash. # # If pg_ctl and pg_isready have a release suffix (e.g. pg_ctl-18) as is the # case with Homebrew, set PGVER to the release number (e.g. "18"). set -Cue -o pipefail if test -z "${PGDATA:-}" then echo >&2 "Set PGDATA." exit 1 fi if test -z "${PGHOST:-}" then echo >&2 "Set PGHOST." exit 1 fi LOG="postgres.log" ME="$(whoami)" RUN_AS="${1:-$ME}" mkdir -p -- "$PGDATA" "$PGHOST" if [ -d /run ] && [ ! -d /run/postgresql ] then MAKE_RUN=yes mkdir -p /run/postgresql fi touch $LOG if [ "$ME" != "$RUN_AS" ] then # Must be writable to both $ME an $RUN_AS. chmod a+w $LOG # Assuming privileges. chown "$RUN_AS" -- "$PGDATA" "$PGHOST" if [ "${MAKE_RUN:-no}" = "yes" ] then # Assuming privileges. chown "$RUN_AS" /run/postgresql fi fi # If PGVER is set, append it to $1. # # This is something annoying that the Homebrew postgres package does. add_version_suffix() { local ver="${PGVER:-}" local executable="$1" local suffixed="$executable-$ver" if [ -n "$ver" ] && [ -x "$suffixed" ] then echo "$suffixed" else echo "$executable" fi } # Add optional path & release suffix to a postgres binary's name. adorn_bin() { add_version_suffix "${PGBIN:-}$1" } CREATEDB="$(adorn_bin createdb)" CREATEUSER="$(adorn_bin createuser)" PGCTL="$(adorn_bin pg_ctl)" PGISREADY="$(adorn_bin pg_isready)" PSQL="$(adorn_bin psql)" if $PSQL -c "SELECT 'Database already works.'" then exit 0 fi if [ "$PGHOST" = "localhost" ] then # This is the case for Windows, where there's no Unix domain sockets. SOCKDIR= else # Unix-like systems can use the local socket to connect to postgres. # Pass this option directly to postgres, using pg_ctl's -o. SOCKDIR="-o-k$PGHOST" fi # -o passes options to initdb. # -o-N disables sync during init, trading restartability for speed. RUN_INITDB="$PGCTL init \ -D $PGDATA -o-Atrust -o--no-instructions -o-N -o-EUTF8" # -o-F disables fsync, trading restartability for speed. RUN_POSTGRES="$PGCTL start -D $PGDATA -l $LOG -o-F $SOCKDIR" RUN_CREATEUSER="$CREATEUSER -w -d $ME" # Log $1 as a big, clearly recognisable banner. banner() { cat <postgres-start-stdout.log 2>postgres-start-stderr.log \ &2 "ERROR: Database is not ready." exit 1 fi fi banner "createuser $ME" if [ "$RUN_AS" != "$ME" ] then # TODO: Better check for role presence. if ! $PSQL --host="$PGHOST" -c "SELECT 'New database user can log in.'" then su "$RUN_AS" -c "$RUN_CREATEUSER" fi fi banner "Checking for database $ME" if ! $PSQL --list | grep "^$ME$" then banner "createdb $ME" $CREATEDB "$ME" fi libpqxx-8.0.1/tools/template2mak.py000077500000000000000000000124341516427024100173200ustar00rootroot00000000000000#! /usr/bin/env python3 """Minimal macro processor. Used for generating VC++ makefiles. The available template commands are: Expand a template section for each file in a list of file patterns:: ###MAKTEMPLATE:FOREACH my/path*/*.cxx,other*.cxx ... ###MAKTEMPLATE:ENDFOREACH In the template section, you can use `###BASENAME###` to get the base name of the file being processed (e.g. "base" for "../base.cxx"), and you can use `###FILENAME###` to get the full filename. Copyright (c) 2000-2026, Bart Samwel and Jeroen T. Vermeulen. """ from __future__ import ( absolute_import, print_function, unicode_literals, ) from argparse import ( ArgumentError, ArgumentParser, RawDescriptionHelpFormatter, ) from contextlib import contextmanager from glob import glob import os from sys import ( argv, stdin, stderr, stdout, ) import sys from textwrap import dedent def expand_foreach_file(path, block, outfile): """Expand a "foreach" block for a single file path. Write the results to outfile. """ basepath, _ = os.path.splitext(os.path.basename(path)) for line in block: line = line.replace("###FILENAME###", path) line = line.replace("###BASENAME###", basepath) outfile.write(line) def match_globs(globs): """List all files matching any item in globs. Eliminates duplicates. """ return sorted({path for pattern in globs for path in glob(pattern)}) def expand_foreach(globs, block, outfile): """Expand a foreach block for each file matching one of globs. Write the results to outfile. """ # We'll be iterating over block a variable number of times. Turn it # from a generic iterable into an immutable array. block = tuple(block) for path in match_globs(globs): expand_foreach_file(path, block, outfile) # Header to be prefixed to the generated file. OUTPUT_HEADER = dedent( """\ # AUTOMATICALLY GENERATED FILE -- DO NOT EDIT. # # This file is generated automatically by libpqxx's {script} script, and # will be rewritten from time to time. # # If you modify this file, chances are your modifications will be lost. # # The {script} script should be available in the tools directory of the # libpqxx source archive. """ ) foreach_marker = r"###MAKTEMPLATE:FOREACH " end_foreach_marker = r"###MAKTEMPLATE:ENDFOREACH" def parse_foreach(line): """Parse FOREACH directive, if line contains one. :param line: One line of template input. :return: A list of FOREACH globs, or None if this was not a FOREACH line. """ line = line.strip() if line.startswith(foreach_marker): return line[len(foreach_marker) :].split(",") else: return None def read_foreach_block(infile): """Read a FOREACH block from infile (not including the FOREACH directive). Assumes that the FOREACH directive was in the preceding line. Consumes the line with the ENDFOREACH directive, but does not yield it. :return: Iterable of lines. """ for line in infile: if line.strip().startswith(end_foreach_marker): return yield line def expand_template(infile, outfile): """Expand the template in infile, and write the results to outfile.""" for line in infile: globs = parse_foreach(line) if globs is None: # Not a FOREACH line. Copy to output. outfile.write(line) else: block = read_foreach_block(infile) expand_foreach(globs, block, outfile) @contextmanager def open_stream(path=None, default=None, mode="r"): """Open file at given path, or yield default. Close as appropriate. The default should be a stream, not a path; closing the context will not close it. """ if path is None: yield default else: with open(path, mode) as stream: yield stream def parse_args(): """Parse command-line arguments. :return: Tuple of: input path (or None for stdin), output path (or None for stdout). """ parser = ArgumentParser( description=__doc__, formatter_class=RawDescriptionHelpFormatter ) parser.add_argument( "template", nargs="?", help="Input template. Defaults to standard input.", ) parser.add_argument( "output", nargs="?", help="Output file. Defaults to standard output." ) args = parser.parse_args() return args.template, args.output def write_header(stream, template_path=None): """Write header to stream.""" hr = ("# " + "#" * 78) + "\n" script = os.path.basename(argv[0]) stream.write(hr) stream.write(OUTPUT_HEADER.format(script=script)) if template_path is not None: stream.write("#\n") stream.write("# Generated from template '%s'.\n" % template_path) stream.write(hr) if __name__ == "__main__": try: template_path, output_path = parse_args() except ArgumentError as error: stderr.write("%s\n" % error) sys.exit(2) input_stream = open_stream(template_path, stdin, "r") output_stream = open_stream(output_path, stdout, "w") with input_stream as instream, output_stream as outstream: write_header(outstream, template_path) expand_template(instream, outstream) libpqxx-8.0.1/tools/todo.sh000077500000000000000000000011111516427024100156470ustar00rootroot00000000000000#! /bin/bash # # List "TODO" and "XXX" items in the given files, or throughout the source # code. set -Cue -o pipefail # TODO: Make location-independent? find_source() { echo configure.ac find . -name '*.[ch]xx' | sed -e 's|^\./||' | sort echo tools/* } FILES=${*:-$(find_source)} # Search for "$1:" in files $2. # (This function adds the colon. That way, the search statement itself won't # show up in the search.) search_for() { local key="$1:" shift find_source | xargs grep "$key" } search_for XXX "$FILES" || true search_for TODO "$FILES" || true libpqxx-8.0.1/tools/update-copyright.sh000077500000000000000000000017611516427024100202050ustar00rootroot00000000000000#! /bin/bash # # Update the libpqxx copyright strings in the current directory. # # Usage: update-copyright.sh [year] # # Where "year" is the new copyright year. Defaults to the current year. # # Assumes GNU grep and GNU sed. set -Cue -o pipefail # The regexes are a bit awkward because they must work in both grep and sed. # # F'rinstance, PREFIX can't include the dash because our replacement string in # sed would have a backreference (e.g. "\3") immediately followed by a year # (e.g. 2022), and there's no clear boundary between the backreference number # and the year: "\32022". PREFIX='Copyright (c),* 2000' YEAR='20[0-9][0-9]' NEW_YEAR="${1:-$(date '+%Y')}" SUFFIX=',* \(.* and \)*Jeroen T\. Vermeulen' grep -rIl "$PREFIX-$YEAR$SUFFIX" | xargs -r sed -i -e "s/\\($PREFIX\\)-$YEAR\\($SUFFIX\\)/\\1-$NEW_YEAR\\2/" # This one is so different that I'd rather keep it a special case. sed \ -i \ -e "s/\\(2000\\)-$YEAR\\(,* Jeroen T\\. Vermeulen\\)/\1-$NEW_YEAR\\2/" \ doc/source/conf.py