Compare commits
No commits in common. "gh-pages" and "master" have entirely different histories.
309 changed files with 112895 additions and 385 deletions
149
.clang-tidy
Normal file
149
.clang-tidy
Normal file
|
@ -0,0 +1,149 @@
|
|||
# Generated from CLion Inspection settings
|
||||
#bugprone-reserved-identifier,
|
||||
---
|
||||
Checks: '-*,
|
||||
-deprecated-non-prototype
|
||||
bugprone-argument-comment,
|
||||
bugprone-assert-side-effect,
|
||||
bugprone-bad-signal-to-kill-thread,
|
||||
bugprone-branch-clone,
|
||||
bugprone-copy-constructor-init,
|
||||
bugprone-dangling-handle,
|
||||
bugprone-dynamic-static-initializers,
|
||||
bugprone-fold-init-type,
|
||||
bugprone-forward-declaration-namespace,
|
||||
bugprone-forwarding-reference-overload,
|
||||
bugprone-inaccurate-erase,
|
||||
bugprone-incorrect-roundings,
|
||||
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-no-escape,
|
||||
bugprone-not-null-terminated-result,
|
||||
bugprone-parent-virtual-call,
|
||||
bugprone-posix-return,
|
||||
bugprone-sizeof-container,
|
||||
bugprone-sizeof-expression,
|
||||
bugprone-spuriously-wake-up-functions,
|
||||
bugprone-string-constructor,
|
||||
bugprone-string-integer-assignment,
|
||||
bugprone-string-literal-with-embedded-nul,
|
||||
bugprone-suspicious-enum-usage,
|
||||
bugprone-suspicious-include,
|
||||
bugprone-suspicious-memset-usage,
|
||||
bugprone-suspicious-missing-comma,
|
||||
bugprone-suspicious-semicolon,
|
||||
bugprone-suspicious-string-compare,
|
||||
bugprone-suspicious-memory-comparison,
|
||||
bugprone-suspicious-realloc-usage,
|
||||
bugprone-swapped-arguments,
|
||||
bugprone-terminating-continue,
|
||||
bugprone-throw-keyword-missing,
|
||||
bugprone-too-small-loop-variable,
|
||||
bugprone-undefined-memory-manipulation,
|
||||
bugprone-undelegated-constructor,
|
||||
bugprone-unhandled-self-assignment,
|
||||
bugprone-unused-raii,
|
||||
bugprone-unused-return-value,
|
||||
bugprone-use-after-move,
|
||||
bugprone-virtual-near-miss,
|
||||
cert-dcl21-cpp,
|
||||
cert-dcl58-cpp,
|
||||
cert-err34-c,
|
||||
cert-err52-cpp,
|
||||
cert-err60-cpp,
|
||||
cert-flp30-c,
|
||||
cert-msc50-cpp,
|
||||
cert-msc51-cpp,
|
||||
cert-str34-c,
|
||||
cppcoreguidelines-interfaces-global-init,
|
||||
cppcoreguidelines-narrowing-conversions,
|
||||
cppcoreguidelines-pro-type-member-init,
|
||||
cppcoreguidelines-pro-type-static-cast-downcast,
|
||||
cppcoreguidelines-slicing,
|
||||
google-default-arguments,
|
||||
google-explicit-constructor,
|
||||
google-runtime-operator,
|
||||
hicpp-exception-baseclass,
|
||||
hicpp-multiway-paths-covered,
|
||||
misc-misplaced-const,
|
||||
misc-new-delete-overloads,
|
||||
misc-no-recursion,
|
||||
misc-non-copyable-objects,
|
||||
misc-throw-by-value-catch-by-reference,
|
||||
misc-unconventional-assign-operator,
|
||||
misc-uniqueptr-reset-release,
|
||||
modernize-avoid-bind,
|
||||
modernize-concat-nested-namespaces,
|
||||
modernize-deprecated-headers,
|
||||
modernize-deprecated-ios-base-aliases,
|
||||
modernize-loop-convert,
|
||||
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-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,
|
||||
mpi-buffer-deref,
|
||||
mpi-type-mismatch,
|
||||
openmp-use-default-none,
|
||||
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-noexcept-move-constructor,
|
||||
performance-trivially-destructible,
|
||||
performance-type-promotion-in-math-fn,
|
||||
performance-unnecessary-copy-initialization,
|
||||
performance-unnecessary-value-param,
|
||||
portability-simd-intrinsics,
|
||||
readability-avoid-const-params-in-decls,
|
||||
readability-const-return-type,
|
||||
readability-container-size-empty,
|
||||
readability-convert-member-functions-to-static,
|
||||
readability-delete-null-pointer,
|
||||
readability-deleted-default,
|
||||
readability-inconsistent-declaration-parameter-name,
|
||||
readability-make-member-function-const,
|
||||
readability-misleading-indentation,
|
||||
readability-misplaced-array-index,
|
||||
readability-non-const-parameter,
|
||||
readability-redundant-control-flow,
|
||||
readability-redundant-declaration,
|
||||
readability-redundant-function-ptr-dereference,
|
||||
readability-redundant-smartptr-get,
|
||||
readability-redundant-string-cstr,
|
||||
readability-redundant-string-init,
|
||||
readability-simplify-subscript-expr,
|
||||
readability-static-accessed-through-instance,
|
||||
readability-static-definition-in-anonymous-namespace,
|
||||
readability-string-compare,
|
||||
readability-uniqueptr-delete-release,
|
||||
readability-use-anyofallof'
|
30
.editorconfig
Normal file
30
.editorconfig
Normal file
|
@ -0,0 +1,30 @@
|
|||
# Editor configuration, see http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
# Ignore diffs/patches
|
||||
[*.{diff,patch}]
|
||||
end_of_line = unset
|
||||
insert_final_newline = unset
|
||||
trim_trailing_whitespace = unset
|
||||
indent_size = unset
|
||||
|
||||
[*.c]
|
||||
ident_style = tab
|
||||
ident_size = 8
|
||||
|
||||
[{Makefile,**.mk}]
|
||||
# Use tabs for indentation (Makefiles require tabs)
|
||||
indent_style = tab
|
||||
ident_size = 4
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
6
.envrc
Normal file
6
.envrc
Normal file
|
@ -0,0 +1,6 @@
|
|||
export DBSQL_VERSION="$(sh -c '. ./dist/RELEASE; echo $DBSQL_VERSION')"
|
||||
export DBSQL_VERSION_STRING="$(sh -c '. ./dist/RELEASE; echo $DBSQL_VERSION_STRING')"
|
||||
|
||||
#dotenv
|
||||
watch_file devShell.nix shell.nix flake.nix
|
||||
use flake || use nix
|
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
build_unix/**
|
||||
*~
|
||||
TAGS
|
||||
tags
|
||||
.direnv/
|
||||
.idea/
|
||||
dist/autom4te.cache/
|
||||
dist/config.hin
|
||||
dist/configure
|
||||
dist/config.log
|
||||
src/py/setup.py
|
||||
test/scr050/Makefile
|
||||
result-bin
|
674
LICENSE
Normal file
674
LICENSE
Normal file
|
@ -0,0 +1,674 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
108
LICENSE_EXCEPTIONS
Normal file
108
LICENSE_EXCEPTIONS
Normal file
|
@ -0,0 +1,108 @@
|
|||
FLOSS License Exception v2.0
|
||||
20 October 2007
|
||||
|
||||
The DBSQL Exception for Free/Libre and Open Source Software-only Applications
|
||||
using DBSQL libraries and related resources (the "FLOSS Exception").
|
||||
|
||||
Exception Intent
|
||||
|
||||
We want specified Free/Libre and Open Source Software ("FLOSS") applications
|
||||
to be able to use specified GPL-licensed DBSQL client libraries (the "Program")
|
||||
despite the fact that not all FLOSS licenses are compatible with version 3 of
|
||||
the GNU General Public License (the "GPL").
|
||||
|
||||
Legal Terms and Conditions
|
||||
|
||||
As a special exception to the terms and conditions of version 3 or later of
|
||||
the GPL you are free to distribute a Derivative Work that is formed entirely
|
||||
from the Program and one or more works (each, a "FLOSS Work") licensed under
|
||||
one or more of the licenses listed below in section 1, as long as:
|
||||
|
||||
1. You obey the GPL in all respects for the Program and the Derivative
|
||||
Work, except for identifiable sections of the Derivative Work which
|
||||
are not derived from the Program, and which can reasonably be considered
|
||||
independent and separate works in themselves,
|
||||
2. All identifiable sections of the Derivative Work which are not derived
|
||||
from the Program, and which can reasonably be considered independent and
|
||||
separate works in themselves,
|
||||
1. are distributed subject to one of the FLOSS licenses listed below,
|
||||
and
|
||||
2. the object code or executable form of those sections are
|
||||
accompanied by the complete corresponding machine-readable source
|
||||
code for those sections on the same medium and under the same
|
||||
FLOSS license as the corresponding object code or executable forms
|
||||
of those sections, and
|
||||
3. any works which are aggregated with the Program or with a
|
||||
Derivative Work on a volume of a storage or distribution medium in
|
||||
accordance with the GPL, can reasonably be considered independent
|
||||
and separate works in themselves which are not derivatives of
|
||||
either the Program, a Derivative Work or a FLOSS Work.
|
||||
|
||||
If the above conditions are not met, then the Program may only be copied,
|
||||
modified, distributed or used under the terms and conditions of the GPL or
|
||||
another valid licensing option from The DBSQL Group, Inc.
|
||||
|
||||
1. FLOSS License List
|
||||
|
||||
License name Version(s)/Copyright Date
|
||||
-----------------------------------------------------|-------------------------
|
||||
Academic Free License | 2.0
|
||||
Apache Software License | 1.0/1.1/2.0 or later
|
||||
Apple Public Source License | 2.0
|
||||
Artistic license | From Perl 5.8.0
|
||||
BSD license | "July 22 1999"
|
||||
Common Development and Distribution License (CDDL) | 1.0
|
||||
Common Public License | 1.0
|
||||
GNU Library or "Lesser" General Public License (LGPL)| 2.0/2.1/3.0
|
||||
Jabber Open Source License | 1.0
|
||||
MIT License (As listed in file MIT-License.txt) | -
|
||||
Microsoft Public License (Ms-PL) | 2007
|
||||
Microsoft Reciprocal License (Ms-RL) | 2007
|
||||
Mozilla Public License (MPL) | 1.0/1.1
|
||||
Open Software License | 2.0
|
||||
OpenSSL license (with original SSLeay license) | "2003" ("1998")
|
||||
PHP License | 3.0
|
||||
Python license (CNRI Python License) | -
|
||||
Python Software Foundation License | 2.1.1
|
||||
Sleepycat License | "1999"
|
||||
University of Illinois/NCSA Open Source License | -
|
||||
W3C License | "2001"
|
||||
X11 License | "2001"
|
||||
Zlib/libpng License | -
|
||||
Zope Public License | 2.0
|
||||
|
||||
Due to the many variants of some of the above licenses, we require that any
|
||||
version follow the 2003 version of the Free Software Foundation's Free
|
||||
Software Definition (http://www.gnu.org/philosophy/free-sw.html) or version
|
||||
1.9 of the Open Source Definition by the Open Source Initiative
|
||||
(http://www.opensource.org/docs/definition.php).
|
||||
|
||||
2. Definitions
|
||||
1. Terms used, but not defined, herein shall have the meaning
|
||||
provided in the GPL.
|
||||
2. Derivative Work means a derivative work under copyright law.
|
||||
|
||||
3. Applicability
|
||||
|
||||
This FLOSS Exception applies to all Programs that contain a notice placed by
|
||||
The DBSQL Group, Inc. saying that the Program may be distributed under the
|
||||
terms of this FLOSS Exception. If you create or distribute a work which is a
|
||||
Derivative Work of both the Program and any other work licensed under the GPL,
|
||||
then this FLOSS Exception is not available for that work; thus, you must
|
||||
remove the FLOSS Exception notice from that work and comply with the GPL in
|
||||
all respects, including by retaining all GPL notices. You may choose to
|
||||
redistribute a copy of the Program exclusively under the terms of the GPL by
|
||||
removing the FLOSS Exception notice from that copy of the Program, provided
|
||||
that the copy has never been modified by you or any third party.
|
||||
|
||||
Appendix A. Qualified Libraries and
|
||||
|
||||
The following is a a non-exhaustive list of libraries and packages which are
|
||||
covered by the FLOSS License Exception. Please note that appendix is merely
|
||||
provided as an additional service to specific FLOSS projects who wish to
|
||||
simplify licensing information for their users. Compliance with one of the
|
||||
licenses noted under the "FLOSS license list" section remains a prerequisite.
|
||||
|
||||
Package name | Qualifying License | Version
|
||||
------------------------------|--------------------------|---------------------
|
||||
Apache Portable Runtime (APR) | Apache Software License | 2.0 or later
|
46
README
Normal file
46
README
Normal file
|
@ -0,0 +1,46 @@
|
|||
DBSQL 0.4.0: (May 8, 2024)
|
||||
|
||||
This is version 0.4.0 of DBSQL.
|
||||
|
||||
To view the release and installation documentation, load the distribution
|
||||
file docs/index.html into your web browser.
|
||||
|
||||
This work started from the SQLite project (found on the web at
|
||||
http://www.sqlite.org/). SQLite and all contributions to the SQLite
|
||||
project have been placed in the public domain by its author, Dr. Richard Hipp.
|
||||
There was no assertion of copyright at all on the code I used as a starting
|
||||
point for my work. In fact there are statements that explicitly disclaim
|
||||
copyright. I am asserting copyright on this work, DBSQL. I believe
|
||||
that if you examine the extent to which I've changed, updated, and
|
||||
modified the SQLite code you'll respect my copyright assertion. This
|
||||
is a new product, heavily inspired by another.
|
||||
|
||||
The goal for DBSQL is to provide a small SQL92 relational database layer
|
||||
on top of the Berkeley DB database. Berkeley DB is copyright Oracle
|
||||
Corporation (formerly Sleepycat Software, acquired in Feb 2006) and
|
||||
licensed under the Sleepycat Public License. That license is compatible
|
||||
with the GPL for open source use. Recognize that you, as someone using
|
||||
DBSQL, will need to review the Sleepycat License and the GPL before you
|
||||
use and redistribute your incorporating work. It is your responsibility
|
||||
to comply with those licenses as I am in my work on DBSQL itself. My
|
||||
motivation on a personal level is quite simple, I am in product management
|
||||
these days and not in the code itself. I believe that product managers
|
||||
should be engineers at heart with an ability to understand business,
|
||||
politics, and software sales and support. This is my playground to keep
|
||||
my engineering skills sharp enough to speak fluent geek. As a former
|
||||
engineer at Sleepycat I understand and value the Berkeley DB programming
|
||||
infrasture, design, and methodologies and I have liberally copied and
|
||||
reused them in this project to improve SQLite in ways that I hope will
|
||||
be of value to open source users out there. I did this because I see the
|
||||
value of SQLite to its userbase, it is a perfect example of the 80/20
|
||||
rule and the KISS method and I admire those qualities in software. My
|
||||
hope is that the Berkeley DB database engine will provide some significant
|
||||
features that SQLite cannot such as replication for high availability
|
||||
while remaining small enough to live comfortably inside applications,
|
||||
services, and devices.
|
||||
|
||||
Information and resources pertaining to DBSQL can be found at dbsql.org.
|
||||
|
||||
Commercial licenses without the restrictions found in the GPL can be
|
||||
purchased for this product. See http://dbsql.org/wiki/CommercialUse
|
||||
|
78
TODO
Normal file
78
TODO
Normal file
|
@ -0,0 +1,78 @@
|
|||
|
||||
* Rename dbsql_strerror to dbsql_strerr
|
||||
|
||||
* Fix logic issue in query processing
|
||||
tests/smoke2.sql produces incorrect joins
|
||||
|
||||
* Check all DB API calls
|
||||
Make sure a) we check return codes for for all calls into DB and
|
||||
that b) when there is an error we output it only when configured
|
||||
to be verbose and c) then return the proper DBSQL error indicating
|
||||
what went wrong at a higher level.
|
||||
|
||||
* Review all reused DB code
|
||||
Make sure that we're up to date with the latest in DB. Things such
|
||||
as hashing, etc.
|
||||
|
||||
* Find printf/fprintf calls which print error messages
|
||||
The library should never print messages unless configured to be
|
||||
verbose.
|
||||
|
||||
* tests/
|
||||
Fix testing infrastructure.
|
||||
- api.c/__os_sleep()
|
||||
This is now static in DB's code, so to hack the compile I
|
||||
commented out the use of __os_sleep() in api.c
|
||||
- test/scr026
|
||||
This test has not been updated to check for DBSQL API calls
|
||||
rather than DB API calls. Review and fix it.
|
||||
- test/scr030
|
||||
Update this test to match the configure script. Augment it so
|
||||
that as the configure script changes the script reports options
|
||||
not tested.
|
||||
- A few scr??? < 050
|
||||
Some of these tests examine source code but do not include the
|
||||
TCL testing code and so produce false positive FAILures.
|
||||
- Add test/scr0?? to highlight code notes
|
||||
FIXME, TODO, and other source source markers
|
||||
|
||||
* Code quality and build tools
|
||||
- valgrind
|
||||
Fix all memory related bugs.
|
||||
- splint
|
||||
Clean up all items pointed out by splint.
|
||||
- makedepend
|
||||
Finish integrating this into the dist/Makefile
|
||||
|
||||
* Review code for trailing spaces, tab characters, lines > 79 col
|
||||
|
||||
* review dbsql/dbsql.c
|
||||
General clean-up including changing calls to malloc, free, etc to
|
||||
__os_malloc, __os_free, etc.
|
||||
|
||||
* Review SQLite's latest lemon.c and lempar.c code
|
||||
Consider updating to the newest versions of the parser generator.
|
||||
|
||||
* Use LIST/QUEUE macros for linked lists, queues, etc.
|
||||
Find/replace all custom code implementing these simple data
|
||||
structures.
|
||||
|
||||
* Review memory allocation code in general
|
||||
|
||||
* Consider using MPOOL to manage some of DBSQL state across processes
|
||||
Function pools and other aspects of the DBSQL runtime need not be
|
||||
re-created in-memory across multiple processes. When doing this
|
||||
revisit data structures using the LIST/QUEUE macros and shift them
|
||||
to the SH_ equivalents.
|
||||
|
||||
* Random number generator
|
||||
SQLite implements its own suggesting that rand32_r() (and other
|
||||
random number generators) are both truely random and bug free.
|
||||
Some portion of the VDBE requires random numbers to be,
|
||||
well... random, or as close as possible.
|
||||
|
||||
* Review src/vdbe, finish converting to DBSQL-style
|
||||
|
||||
* Investigate the TCL Extension Architecture
|
||||
http://www.tcl.tk/doc/tea/
|
||||
|
490
dist/Makefile.in
vendored
Normal file
490
dist/Makefile.in
vendored
Normal file
|
@ -0,0 +1,490 @@
|
|||
# DBSQL - A SQL database engine.
|
||||
#
|
||||
# Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# There are special exceptions to the terms and conditions of the GPL as it
|
||||
# is applied to this software. View the full text of the exception in file
|
||||
# LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
#
|
||||
# This library 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.
|
||||
|
||||
srcdir= @srcdir@/../src
|
||||
tstdir= @srcdir@/../test
|
||||
distdir= @srcdir@/../dist
|
||||
builddir=.
|
||||
|
||||
##################################################
|
||||
# Installation directories and permissions.
|
||||
##################################################
|
||||
prefix= @prefix@
|
||||
exec_prefix= @exec_prefix@
|
||||
bindir= @bindir@
|
||||
includedir= @includedir@
|
||||
libdir= @libdir@
|
||||
docdir= $(prefix)/docs
|
||||
|
||||
dmode= 755
|
||||
emode= 555
|
||||
fmode= 444
|
||||
|
||||
transform=@program_transform_name@
|
||||
|
||||
##################################################
|
||||
# Paths for standard user-level commands.
|
||||
##################################################
|
||||
SHELL= @db_cv_path_sh@
|
||||
ar= @db_cv_path_ar@
|
||||
awk= @db_cv_path_awk@
|
||||
chmod= @db_cv_path_chmod@
|
||||
cp= @db_cv_path_cp@
|
||||
depend= @db_cv_path_makedepend@
|
||||
grep= @db_cv_path_grep@
|
||||
ln= @db_cv_path_ln@
|
||||
mkdir= @db_cv_path_mkdir@
|
||||
ranlib= @db_cv_path_ranlib@
|
||||
rm= @db_cv_path_rm@
|
||||
rpm= @db_cv_path_rpm@
|
||||
sed= @db_cv_path_sed@
|
||||
perl= @db_cv_path_perl@
|
||||
splint= @db_cv_path_splint@
|
||||
strip= @db_cv_path_strip@
|
||||
|
||||
##################################################
|
||||
# General library information.
|
||||
##################################################
|
||||
DEF_LIB= @DEFAULT_LIB@
|
||||
DEF_LIB_CXX= @DEFAULT_LIB_CXX@
|
||||
INSTALLER= @INSTALLER@
|
||||
LIBTOOL= @LIBTOOL@
|
||||
POSTLINK= @POSTLINK@
|
||||
SOLINK= @MAKEFILE_SOLINK@
|
||||
SOFLAGS= @SOFLAGS@
|
||||
LIBMAJOR= @DBSQL_VERSION_MAJOR@
|
||||
LIBVERSION= @DBSQL_VERSION_MAJOR@.@DBSQL_VERSION_MINOR@
|
||||
CPPFLAGS= -I$(builddir) -I$(srcdir) @CPPFLAGS@
|
||||
|
||||
##################################################
|
||||
# Lemon parser generator information.
|
||||
##################################################
|
||||
LEMON= ./lemon
|
||||
LEMON_FLAGS=
|
||||
|
||||
##################################################
|
||||
# C API.
|
||||
##################################################
|
||||
CFLAGS= -c $(CPPFLAGS) @CFLAGS@
|
||||
CC= @MAKEFILE_CC@
|
||||
CCLINK= @MAKEFILE_CCLINK@
|
||||
|
||||
LDFLAGS= @LDFLAGS@
|
||||
LIBS= @LIBS@
|
||||
LIBSO_LIBS= @LIBSO_LIBS@
|
||||
|
||||
libdbsql_base= libdbsql
|
||||
libdbsql= $(libdbsql_base).a
|
||||
libdbsql_version= $(libdbsql_base)-$(LIBVERSION).a
|
||||
libso= $(libdbsql_base)-$(LIBVERSION)@SOSUFFIX@
|
||||
libso_target= $(libdbsql_base)-$(LIBVERSION).la
|
||||
libso_default= $(libdbsql_base)@SOSUFFIX@
|
||||
libso_major= $(libdbsql_base)-$(LIBMAJOR)@SOSUFFIX@
|
||||
|
||||
##################################################
|
||||
# Python Language Bindings
|
||||
#
|
||||
# Python support is optional and requires shared libraries.
|
||||
##################################################
|
||||
|
||||
##################################################
|
||||
# NOTHING BELOW THIS LINE SHOULD EVER NEED TO BE MODIFIED.
|
||||
##################################################
|
||||
|
||||
##################################################
|
||||
# Source file lists.
|
||||
##################################################
|
||||
|
||||
C_FILES=\
|
||||
$(srcdir)/api.c $(srcdir)/api_table.c $(srcdir)/cg_attach.c \
|
||||
$(srcdir)/cg_auth.c $(srcdir)/cg_build.c $(srcdir)/cg_copy.c \
|
||||
$(srcdir)/cg_date.c $(srcdir)/cg_delete.c $(srcdir)/cg_expr.c \
|
||||
$(srcdir)/cg_insert.c $(srcdir)/cg_pragma.c $(srcdir)/cg_select.c \
|
||||
$(srcdir)/cg_trigger.c $(srcdir)/cg_update.c $(srcdir)/cg_where.c \
|
||||
$(srcdir)/clib/xvprintf.c $(srcdir)/dbsql/dbsql.c \
|
||||
$(srcdir)/sm.c $(srcdir)/common/hash.c $(srcdir)/lemon/lemon.c \
|
||||
$(srcdir)/lemon/lempar.c $(srcdir)/os/os.c $(srcdir)/clib/random.c \
|
||||
$(srcdir)/sql_fns.c $(srcdir)/sql_tokenize.c \
|
||||
$(srcdir)/cg_vacuum.c $(srcdir)/vdbe.c $(srcdir)/vdbe_method.c \
|
||||
$(srcdir)/common/dbsql_err.c (srcdir)/clib/snprintf.c \
|
||||
$(srcdir)/os/os_jtime.c $(srcdir)/os/os_sleep.c $(srcdir)/clib/memcmp.c \
|
||||
$(srcdir)/clib/strcasecmp.c $(srcdir)/os/dbsql_alloc.c \
|
||||
$(srcdir)/common/str.c $(srcdir)/common/dbsql_atoi.c \
|
||||
$(srcdir)/common/dbsql_atof.c $(srcdir)/common/dbsql_fop.c \
|
||||
$(srcdir)/safety.c $(srcdir)/clib/strdup.c
|
||||
|
||||
##################################################
|
||||
# Object and utility lists.
|
||||
##################################################
|
||||
|
||||
C_OBJS= cg_attach@o@ cg_insert@o@ sql_tokenize@o@ cg_auth@o@ \
|
||||
cg_copy@o@ api_table@o@ cg_date@o@ api@o@ xvprintf@o@ \
|
||||
cg_pragma@o@ cg_where@o@ cg_trigger@o@ cg_build@o@ \
|
||||
sql_fns@o@ random@o@ cg_update@o@ cg_delete@o@ hash@o@ \
|
||||
cg_expr@o@ opcodes@o@ sql_parser@o@ cg_vacuum@o@ \
|
||||
vdbe@o@ vdbe_method@o@ sm@o@ snprintf@o@ dbsql_err@o@ \
|
||||
dbsql_fop@o@ cg_select@o@ os_sleep@o@ os_jtime@o@ memcmp@o@ \
|
||||
dbsql_atof@o@ safety@o@ dbsql_atoi@o@ strcasecmp@o@ \
|
||||
strdup@o@ dbsql_alloc@o@ str@o@
|
||||
|
||||
LEMON_OBJS=\
|
||||
lemon@o@
|
||||
|
||||
UTIL_PROGS=\
|
||||
@ADDITIONAL_PROGS@ \
|
||||
dbsql
|
||||
|
||||
##################################################
|
||||
# List of files installed into the library directory.
|
||||
##################################################
|
||||
LIB_INSTALL_FILE_LIST=\
|
||||
$(libdbsql) \
|
||||
$(libso) \
|
||||
$(libso_default) \
|
||||
$(libso_major) \
|
||||
$(libdbsql_version) \
|
||||
$(libso_target) \
|
||||
$(libtso) \
|
||||
$(libtso_default) \
|
||||
$(libtso_major) \
|
||||
$(libtso_static) \
|
||||
$(libtso_target)
|
||||
|
||||
##################################################
|
||||
# We're building a standard library or a RPM file hierarchy.
|
||||
# Note: "all" must be the first target in the Makefile.
|
||||
##################################################
|
||||
all: @BUILD_TARGET@
|
||||
|
||||
install-strip install: all @INSTALL_TARGET@
|
||||
|
||||
##################################################
|
||||
# Library and standard utilities build.
|
||||
##################################################
|
||||
library_build: @INSTALL_LIBS@ @ADDITIONAL_LANG@ $(UTIL_PROGS)
|
||||
|
||||
# Static C library named libdbsql.a.
|
||||
$(libdbsql): $(DEF_LIB)
|
||||
$(rm) -f $@
|
||||
test ! -f .libs/$(libdbsql_version) || \
|
||||
$(ln) -s .libs/$(libdbsql_version) $@
|
||||
test -f .libs/$(libdbsql_version) || \
|
||||
(test -f $(libdbsql_version) &&
|
||||
$(ln) -s $(libdbsql_version) $@)
|
||||
|
||||
# Real static C library.
|
||||
$(libdbsql_version): dbsql_int.h db_int.h sql_parser.h opcodes.h $(C_OBJS)
|
||||
$(ar) cr $@ $(C_OBJS)
|
||||
test ! -f $(ranlib) || $(ranlib) $@
|
||||
|
||||
# Shared C library.
|
||||
$(libso_target): dbsql_int.h db_int.h sql_parser.h opcodes.h $(C_OBJS)
|
||||
$(SOLINK) $(SOFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) $(LIBSO_LIBS)
|
||||
|
||||
##################################################
|
||||
# Utilities
|
||||
##################################################
|
||||
lemon: $(LEMON_OBJS)
|
||||
$(CCLINK) -o $@ $(LDFLAGS) \
|
||||
$(LEMON_OBJS) $(LIBS)
|
||||
$(POSTLINK) $@
|
||||
$(cp) $(srcdir)/lemon/lempar.c .
|
||||
|
||||
dbsql: $(DEF_LIB) dbsql@o@
|
||||
$(CCLINK) -o $@ $(LDFLAGS) \
|
||||
dbsql@o@ $(DEF_LIB) $(LIBS)
|
||||
$(POSTLINK) $@
|
||||
|
||||
##################################################
|
||||
# Testing.
|
||||
##################################################
|
||||
test: $(tstdir)/scr050/dbsql_tclsh
|
||||
$(tstdir)/scr050/dbsql_tclsh $(tstdir)/quick.test
|
||||
|
||||
##################################################
|
||||
# Library and standard utilities install.
|
||||
##################################################
|
||||
library_install: install_setup
|
||||
library_install: install_include install_lib install_utilities install_docs
|
||||
|
||||
uninstall: uninstall_include uninstall_lib uninstall_utilities uninstall_docs
|
||||
|
||||
install_setup:
|
||||
@test -d $(DESTDIR)$(prefix) || \
|
||||
($(mkdir) -p $(DESTDIR)$(prefix) && \
|
||||
$(chmod) $(dmode) $(DESTDIR)$(prefix))
|
||||
|
||||
INCDOT= dbsql.h @ADDITIONAL_INCS@
|
||||
install_include:
|
||||
@echo "Installing DBSQL include files: $(DESTDIR)$(includedir) ..."
|
||||
@test -d $(DESTDIR)$(includedir) || \
|
||||
($(mkdir) -p $(DESTDIR)$(includedir) && \
|
||||
$(chmod) $(dmode) $(DESTDIR)$(includedir))
|
||||
@cd $(DESTDIR)$(includedir) && $(rm) -f $(INCDOT)
|
||||
@$(cp) -p $(INCDOT) $(DESTDIR)$(includedir)
|
||||
@cd $(DESTDIR)$(includedir) && $(chmod) $(fmode) $(INCDOT)
|
||||
|
||||
uninstall_include:
|
||||
@cd $(DESTDIR)$(includedir) && $(rm) -f $(INCDOT)
|
||||
|
||||
install_lib:
|
||||
@echo "Installing DBSQL library: $(DESTDIR)$(libdir) ..."
|
||||
@test -d $(DESTDIR)$(libdir) || \
|
||||
($(mkdir) -p $(DESTDIR)$(libdir) && \
|
||||
$(chmod) $(dmode) $(DESTDIR)$(libdir))
|
||||
@cd $(DESTDIR)$(libdir) && $(rm) -f $(LIB_INSTALL_FILE_LIST)
|
||||
@$(INSTALLER) @INSTALL_LIBS@ $(DESTDIR)$(libdir)
|
||||
@(cd $(DESTDIR)$(libdir) && \
|
||||
test -f $(libso) && $(ln) -s $(libso) $(libso_default); \
|
||||
test -f $(libso) && $(ln) -s $(libso) $(libso_major); \
|
||||
test -f $(libtso) && $(ln) -s $(libtso) $(libtso_default); \
|
||||
test -f $(libtso) && $(ln) -s $(libtso) $(libtso_major);
|
||||
|
||||
uninstall_lib:
|
||||
@cd $(DESTDIR)$(libdir) && $(rm) -f $(LIB_INSTALL_FILE_LIST)
|
||||
|
||||
install_utilities:
|
||||
@echo "Installing DBSQL utilities: $(DESTDIR)$(bindir) ..."
|
||||
@test -d $(DESTDIR)$(bindir) || \
|
||||
($(mkdir) -p $(DESTDIR)$(bindir) && \
|
||||
$(chmod) $(dmode) $(DESTDIR)$(bindir))
|
||||
@for i in $(UTIL_PROGS); do \
|
||||
$(rm) -f $(DESTDIR)$(bindir)/$$i $(DESTDIR)$(bindir)/$$i.exe; \
|
||||
test -f $$i.exe && i=$$i.exe || true; \
|
||||
$(INSTALLER) $$i $(DESTDIR)$(bindir)/$$i; \
|
||||
test -f $(strip) && $(strip) $(DESTDIR)$(bindir)/$$i || true; \
|
||||
$(chmod) $(emode) $(DESTDIR)$(bindir)/$$i; \
|
||||
done
|
||||
|
||||
uninstall_utilities:
|
||||
@(cd $(DESTDIR)$(bindir); for i in $(UTIL_PROGS); do \
|
||||
$(rm) -f $$i $$i.exe; \
|
||||
done)
|
||||
|
||||
##################################################
|
||||
# RPM, build and install.
|
||||
##################################################
|
||||
rpm_build:
|
||||
@test -f @db_cv_path_rpm_archive@ || \
|
||||
(echo "@db_cv_path_rpm_archive@: archive file not found" && false)
|
||||
@$(rm) -rf BUILD RPMS SOURCES SPECS SRPMS RPM_INSTALL
|
||||
@$(mkdir) -p BUILD && $(chmod) $(dmode) BUILD
|
||||
@$(mkdir) -p RPMS/i386 && $(chmod) $(dmode) RPMS RPMS/i386
|
||||
@$(mkdir) -p SOURCES && $(chmod) $(dmode) SOURCES
|
||||
@$(mkdir) -p SPECS && $(chmod) $(dmode) SPECS
|
||||
@$(mkdir) -p SRPMS && $(chmod) $(dmode) SRPMS
|
||||
$(cp) @db_cv_path_rpm_archive@ SOURCES/
|
||||
$(cp) dbsql.spec SPECS/dbsql.spec
|
||||
@RPM_BUILD@ --define="`cat rpm-macro-defines`" -ba SPECS/dbsql.spec
|
||||
|
||||
rpm_install:
|
||||
|
||||
RPM_SRPMS=dbsql-@DBSQL_VERSION_MAJOR@.@DBSQL_VERSION_MINOR@.@DBSQL_VERSION_PATCH@-1.src.rpm
|
||||
|
||||
##################################################
|
||||
# Remaining standard Makefile targets.
|
||||
##################################################
|
||||
CLEAN_LIST=\
|
||||
lemon
|
||||
|
||||
mostly-clean clean:
|
||||
$(rm) -rf $(C_OBJS)
|
||||
$(rm) -rf $(UTIL_PROGS) *.exe $(CLEAN_LIST)
|
||||
$(rm) -rf $(JAVA_CLASSTOP) $(JAVA_EXCLASSTOP)
|
||||
$(rm) -rf tags *@o@ *~ *.o *.o.lock *.lo core *.core *.loT
|
||||
$(rm) -rf .libs $(LIB_INSTALL_FILE_LIST)
|
||||
$(rm) -rf sql_parser.c sql_parser.h sql_parser.out
|
||||
$(rm) -rf opcodes.c opcodes.h
|
||||
$(rm) -rf lempar.c
|
||||
$(rm) -rf test.db test?.db test.db-journal test1.bt data?.txt
|
||||
$(rm) -f log.*
|
||||
|
||||
REALCLEAN_LIST=\
|
||||
Makefile config.cache config.log config.status \
|
||||
configure.lineno dbsql.h dbsql.spec dbsql_config.h \
|
||||
db_int.h dbsql_int.h db_int_def.h rpm-macro-defines win_dbsql.h
|
||||
|
||||
distclean maintainer-clean realclean: clean
|
||||
$(rm) -rf $(REALCLEAN_LIST)
|
||||
$(rm) -rf libtool
|
||||
|
||||
LIBTOOL_DEPS = @LIBTOOL_DEPS@
|
||||
libtool: $(LIBTOOL_DEPS)
|
||||
$(SHELL) ./deps/config.status $(builddir)/libtool
|
||||
|
||||
check dvi info obj TAGS:
|
||||
@echo "$@: make target not supported" && true
|
||||
|
||||
dist:
|
||||
@echo "$@: make target not supported" && false
|
||||
|
||||
##################################################
|
||||
# TODO Example programs for C.
|
||||
##################################################
|
||||
|
||||
##################################################
|
||||
# Opcodes are generated from the vdbe.[ch] files.
|
||||
##################################################
|
||||
opcodes.c: $(srcdir)/vdbe.c
|
||||
@echo '/* Automatically generated file. Do not edit */' >opcodes.c
|
||||
@echo 'char *__opcode_names[] = { "???", ' >>opcodes.c
|
||||
@$(grep) '^case OP_' $(srcdir)/vdbe.c | \
|
||||
$(sed) -e 's/^.*OP_/ "/' -e 's/:.*$$/", /' >>opcodes.c
|
||||
@echo '};' >>opcodes.c
|
||||
|
||||
opcodes.h: $(srcdir)/vdbe.c
|
||||
@echo '/* Automatically generated file. Do not edit */' >opcodes.h
|
||||
@$(grep) '^case OP_' $(srcdir)/vdbe.c | \
|
||||
$(sed) -e 's/://' | \
|
||||
$(awk) '{printf "#define %-30s %3d\n", $$2, ++cnt}' >>opcodes.h
|
||||
|
||||
##################################################
|
||||
# C API build rules.
|
||||
##################################################
|
||||
api@o@: $(srcdir)/api.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
api_table@o@: $(srcdir)/api_table.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
cg_attach@o@: $(srcdir)/cg_attach.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
cg_auth@o@: $(srcdir)/cg_auth.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
cg_build@o@: $(srcdir)/cg_build.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
cg_copy@o@: $(srcdir)/cg_copy.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
cg_date@o@: $(srcdir)/cg_date.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
cg_delete@o@: $(srcdir)/cg_delete.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
cg_expr@o@: $(srcdir)/cg_expr.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
cg_insert@o@: $(srcdir)/cg_insert.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
cg_pragma@o@: $(srcdir)/cg_pragma.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
cg_select@o@: $(srcdir)/cg_select.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
cg_trigger@o@: $(srcdir)/cg_trigger.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
cg_update@o@: $(srcdir)/cg_update.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
cg_where@o@: $(srcdir)/cg_where.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
cg_vacuum@o@: $(srcdir)/cg_vacuum.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
db_int.h: $(srcdir)/inc/db_int.h
|
||||
@$(sed) -e 's/__DB_UNIQUE_NAME__/@DB_UNIQUE_NAME@/g' \
|
||||
$(srcdir)/inc/db_int.h > db_int.h
|
||||
dbsql_atof@o@: $(srcdir)/common/dbsql_atof.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
dbsql_atoi@o@: $(srcdir)/common/dbsql_atoi.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
dbsql_err@o@: $(srcdir)/common/dbsql_err.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
dbsql_fop@o@: $(srcdir)/common/dbsql_fop.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
str@o@: $(srcdir)/common/str.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
hash@o@: $(srcdir)/common/hash.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
opcodes.c: opcodes.h
|
||||
opcodes@o@: opcodes.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
dbsql_alloc@o@: $(srcdir)/common/dbsql_alloc.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
os_jtime@o@: $(srcdir)/os/os_jtime.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
os_sleep@o@: $(srcdir)/os/os_sleep.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
lemon@o@: $(srcdir)/lemon/lemon.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
memcmp@o@: $(srcdir)/clib/memcmp.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
xvprintf@o@: $(srcdir)/clib/xvprintf.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
random@o@: $(srcdir)/clib/random.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
safety@o@: $(srcdir)/safety.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
sm@o@: $(srcdir)/sm.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
snprintf@o@: $(srcdir)/clib/snprintf.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
sql_fns@o@: $(srcdir)/sql_fns.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
sql_parser.c: $(srcdir)/sql_parser.y lemon
|
||||
@$(cp) $(srcdir)/sql_parser.y .
|
||||
@$(LEMON) $(LEMON_FLAGS) sql_parser.y
|
||||
@$(cp) ./sql_parser.c ./_sql_parser.c
|
||||
@$(sed) -e 's/dbsql_parserAlloc/__sql_parser_alloc/g' \
|
||||
-e 's/dbsql_parserFree/__sql_parser_free/g' \
|
||||
-e 's/dbsql_parserTrace/__sql_parser_trace/g' \
|
||||
-e 's/dbsql_parser(/__sql_parser(/g' \
|
||||
-e 's/__set_stringn/__str_nappend/g' \
|
||||
-e 's/__set_string/__str_append/g' \
|
||||
./_sql_parser.c > ./sql_parser.c
|
||||
@$(rm) -f ./_sql_parser.c
|
||||
@$(rm) -f ./sql_parser.y
|
||||
sql_parser.h: sql_parser.c
|
||||
sql_parser@o@: sql_parser.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
sql_tokenize@o@: $(srcdir)/sql_tokenize.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
strcasecmp@o@: $(srcdir)/clib/strcasecmp.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
strdup@o@: $(srcdir)/clib/strdup.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
vdbe@o@: $(srcdir)/vdbe.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
vdbe_method@o@: $(srcdir)/vdbe_method.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
dbsql.h: $(srcdir)/dbsql.in
|
||||
@echo dbsql.h is out of date, re-configure to regenerate it.
|
||||
|
||||
|
||||
##################################################
|
||||
# Utility build rules.
|
||||
##################################################
|
||||
dbsql@o@: $(srcdir)/dbsql/dbsql.c
|
||||
$(CC) $(CFLAGS) $?
|
||||
|
||||
|
||||
##################################################
|
||||
# Lint.
|
||||
##################################################
|
||||
|
||||
splint:
|
||||
$(splint) -nof -f $(distdir)/splint.rc -strict \
|
||||
$(CPPFLAGS) @CFLAGS@ -I. $(C_FILES)
|
||||
|
||||
lint: splint
|
||||
|
||||
##################################################
|
||||
# Dependencies
|
||||
##################################################
|
||||
|
||||
#depend:
|
||||
# @$(depend) -o @o@ $(CPPFLAGS) @CFLAGS@ $(C_FILES)
|
||||
# @$(perl) -p -i -e 's#^@srcdir@/../src/common/##g' Makefile
|
||||
# @$(perl) -p -i -e 's#^@srcdir@/../src/os/##g' Makefile
|
||||
# @$(perl) -p -i -e 's#^@srcdir@/../src/clib/##g' Makefile
|
||||
# @$(perl) -p -i -e 's#^@srcdir@/../src/lemon/##g' Makefile
|
||||
# @$(perl) -p -i -e 's#^@srcdir@/../src/##g' Makefile
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
27
dist/RELEASE
vendored
Normal file
27
dist/RELEASE
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
# DBSQL - A SQL database engine.
|
||||
#
|
||||
# Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# There are special exceptions to the terms and conditions of the GPL as it
|
||||
# is applied to this software. View the full text of the exception in file
|
||||
# LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
#
|
||||
# This library 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.
|
||||
|
||||
DBSQL_VERSION_MAJOR=0
|
||||
DBSQL_VERSION_MINOR=4
|
||||
DBSQL_VERSION_PATCH=0
|
||||
DBSQL_VERSION="$DBSQL_VERSION_MAJOR.$DBSQL_VERSION_MINOR.$DBSQL_VERSION_PATCH"
|
||||
|
||||
DBSQL_VERSION_UNIQUE_NAME=`printf "_%d%03d" $DBSQL_VERSION_MAJOR $DBSQL_VERSION_MINOR`
|
||||
|
||||
DBSQL_RELEASE_DATE=`date "+%B %e, %Y"`
|
||||
DBSQL_VERSION_STRING="DBSQL $DBSQL_VERSION: ($DBSQL_RELEASE_DATE)"
|
26
dist/aclocal/config.m4
vendored
Normal file
26
dist/aclocal/config.m4
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
# Features we don't test for, but want the #defines to exist for
|
||||
# other ports.
|
||||
AH_TEMPLATE(DBSQL_WIN32,
|
||||
[We use DBSQL_WIN32 much as one would use _WIN32 -- to specify that
|
||||
we're using an operating system environment that supports Win32
|
||||
calls and semantics. We don't use _WIN32 because Cygwin/GCC also
|
||||
defines _WIN32, even though Cygwin/GCC closely emulates the Unix
|
||||
environment.])
|
||||
|
||||
AH_TEMPLATE(HAVE_FILESYSTEM_NOTZERO,
|
||||
[Define to 1 if allocated filesystem blocks are not zeroed.])
|
||||
|
||||
AH_TEMPLATE(HAVE_UNLINK_WITH_OPEN_FAILURE,
|
||||
[Define to 1 if unlink of file with open file descriptors will fail.])
|
||||
|
||||
AH_BOTTOM([/*
|
||||
* Exit success/failure macros.
|
||||
*/
|
||||
#ifndef HAVE_EXIT_SUCCESS
|
||||
#define EXIT_FAILURE 1
|
||||
#define EXIT_SUCCESS 0
|
||||
#endif
|
||||
|
||||
#ifdef DBSQL_WIN32
|
||||
#include "win_dbsql.h"
|
||||
#endif])
|
313
dist/aclocal/cxx.m4
vendored
Normal file
313
dist/aclocal/cxx.m4
vendored
Normal file
|
@ -0,0 +1,313 @@
|
|||
# C++ language checks
|
||||
|
||||
AC_DEFUN(AC_CXX_STDHEADERS, [
|
||||
AC_SUBST(cxx_have_stdheaders)
|
||||
AC_MSG_CHECKING(whether C++ supports the ISO C++ standard includes)
|
||||
AC_LANG_SAVE
|
||||
AC_LANG([C++])
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
|
||||
[[#include <iostream>]],
|
||||
[[std::ostream *o; return 0;]])],
|
||||
db_cv_cxx_have_stdheaders=yes, db_cv_cxx_have_stdheaders=no)
|
||||
AC_LANG_RESTORE
|
||||
AC_MSG_RESULT($db_cv_cxx_have_stdheaders)
|
||||
if test "$db_cv_cxx_have_stdheaders" = yes; then
|
||||
cxx_have_stdheaders="#define HAVE_CXX_STDHEADERS 1"
|
||||
fi])
|
||||
|
||||
AC_DEFUN(AC_CXX_WSTRING, [
|
||||
AC_MSG_CHECKING(whether C++ supports the wstring class)
|
||||
AC_SUBST(WSTRING_decl)
|
||||
AC_LANG_SAVE
|
||||
AC_LANG([C++])
|
||||
AC_LINK_IFELSE(AC_LANG_SOURCE(
|
||||
[[#include <string>]],
|
||||
[[using std::wstring;
|
||||
wstring ws; ws.find_first_of(ws);]]),
|
||||
[WSTRING_decl="#define HAVE_WSTRING 1" ;
|
||||
AC_MSG_RESULT(yes)],
|
||||
[WSTRING_decl="#undef HAVE_WSTRING" ;
|
||||
AC_MSG_RESULT(no)])
|
||||
AC_LANG_RESTORE
|
||||
])
|
||||
|
||||
AC_DEFUN(AC_CXX_SUPPORTS_TEMPLATES, [
|
||||
AC_MSG_CHECKING(whether the C++ compiler supports templates for STL)
|
||||
AC_LANG_SAVE
|
||||
AC_LANG([C++])
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
]], [[
|
||||
using std::string;
|
||||
using std::vector;
|
||||
namespace dbstl_configure_test {
|
||||
|
||||
template<typename T1, typename T2 = int>
|
||||
class MyClass
|
||||
{
|
||||
public:
|
||||
explicit MyClass(int i) { imem = i;}
|
||||
|
||||
MyClass(const T1& t1, const T2& t2, int i)
|
||||
{
|
||||
mem1 = t1;
|
||||
mem2 = t2;
|
||||
imem = i;
|
||||
}
|
||||
|
||||
template <typename T3>
|
||||
T2 templ_mem_func(T1 t1, T3 t3)
|
||||
{
|
||||
mem2 = t1;
|
||||
T3 t32 = t3;
|
||||
T2 t2;
|
||||
return t2;
|
||||
}
|
||||
|
||||
double templ_mem_func(T1 t1, double t3)
|
||||
{
|
||||
mem1 = t1;
|
||||
double t32 = t3;
|
||||
return t3;
|
||||
}
|
||||
|
||||
template <typename ReturnType, typename T7, typename T8>
|
||||
ReturnType templ_mem_func(T7, T8);
|
||||
|
||||
operator T1() const {return mem1;}
|
||||
private:
|
||||
T1 mem1;
|
||||
T2 mem2;
|
||||
int imem;
|
||||
};
|
||||
|
||||
template<typename T1, typename T2>
|
||||
template <typename ReturnType, typename T7, typename T8>
|
||||
ReturnType MyClass<T1, T2>::templ_mem_func(T7, T8)
|
||||
{
|
||||
ReturnType rt;
|
||||
return rt;
|
||||
}
|
||||
|
||||
template<>
|
||||
class MyClass<double, float>
|
||||
{
|
||||
public:
|
||||
explicit MyClass(int i) { imem = i;}
|
||||
|
||||
MyClass(const double& t1, const float& t2, int i)
|
||||
{
|
||||
mem1 = t1;
|
||||
mem2 = t2;
|
||||
imem = i;
|
||||
}
|
||||
|
||||
template <typename T3>
|
||||
float templ_mem_func(double t1, T3 t3)
|
||||
{
|
||||
mem2 = t1;
|
||||
T3 t32 = t3;
|
||||
float t2;
|
||||
return t2;
|
||||
}
|
||||
|
||||
double templ_mem_func(double t1, double t3)
|
||||
{
|
||||
mem1 = t1;
|
||||
double t32 = t3;
|
||||
return t3;
|
||||
}
|
||||
|
||||
template <typename ReturnType, typename T7, typename T8>
|
||||
ReturnType templ_mem_func(T7, T8);
|
||||
|
||||
operator double() const {return mem1;}
|
||||
private:
|
||||
double mem1;
|
||||
float mem2;
|
||||
int imem;
|
||||
};
|
||||
|
||||
template <typename ReturnType, typename T7, typename T8>
|
||||
ReturnType MyClass<double, float>::templ_mem_func(T7, T8)
|
||||
{
|
||||
ReturnType rt;
|
||||
return rt;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
class MyClass2 {
|
||||
public:
|
||||
MyClass2(const T1& t1, const T2&t2){}
|
||||
};
|
||||
|
||||
// partial specialization: both template parameters have same type
|
||||
template <typename T>
|
||||
class MyClass2<T,T> {
|
||||
public:
|
||||
MyClass2(const T& t1, const T&t2){}
|
||||
};
|
||||
|
||||
// partial specialization: second type is int
|
||||
template <typename T>
|
||||
class MyClass2<T,int> {
|
||||
public:
|
||||
MyClass2(const T& t1, const int&t2){}
|
||||
};
|
||||
|
||||
// partial specialization: both template parameters are pointer types
|
||||
template <typename T1, typename T2>
|
||||
class MyClass2<T1*,T2*> {
|
||||
public:
|
||||
MyClass2(const T1* t1, const T2*t2){}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class MyClass2<T*,T*> {
|
||||
public:
|
||||
MyClass2(const T* t1, const T*t2){}
|
||||
};
|
||||
|
||||
template <typename T4, typename T5>
|
||||
int part_spec_func(T4 t4, T5 t5)
|
||||
{
|
||||
// Zero Initialization should work.
|
||||
T4 t44 = T4();
|
||||
T5 t55 = T5();
|
||||
|
||||
t44 = t4;
|
||||
t55 = t5;
|
||||
}
|
||||
|
||||
template <typename T4>
|
||||
int part_spec_func(T4 t4, std::vector<T4> t55)
|
||||
{
|
||||
T4 t44 = t4;
|
||||
std::vector<T4> abc = t55;
|
||||
}
|
||||
|
||||
// maximum of two int values
|
||||
inline int const& max (int const& a, int const& b)
|
||||
{
|
||||
return a<b?b:a;
|
||||
}
|
||||
|
||||
// maximum of two values of any type
|
||||
template <typename T1, typename T2>
|
||||
inline T2 const max (T1 const& a, T2 const& b)
|
||||
{
|
||||
return a<b?b:a;
|
||||
}
|
||||
// maximum of two values of any type
|
||||
template <typename T>
|
||||
inline T const& max (T const& a, T const& b)
|
||||
{
|
||||
return a<b?b:a;
|
||||
}
|
||||
|
||||
// maximum of three values of any type
|
||||
template <typename T>
|
||||
inline T const& max (T const& a, T const& b, T const& c)
|
||||
{
|
||||
return max (max(a,b), c);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class Base {
|
||||
public:
|
||||
void exit2(){}
|
||||
Base(){}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Derived : public Base<T> {
|
||||
public:
|
||||
// Call Base<T>() explicitly here, otherwise can't access it.
|
||||
// Kind of like this->.
|
||||
Derived() : Base<T>(){}
|
||||
|
||||
void foo() {
|
||||
this->exit2();
|
||||
}
|
||||
};
|
||||
|
||||
} // dbstl_configure_test
|
||||
|
||||
using namespace dbstl_configure_test;], [
|
||||
char cc = 'a';
|
||||
int i = 4;
|
||||
double pi = 3.14;
|
||||
float gold = 0.618;
|
||||
|
||||
MyClass2<int,float> mif(i, gold); // uses MyClass2<T1,T2>
|
||||
MyClass2<float,float> mff(gold, gold); // uses MyClass2<T,T>
|
||||
MyClass2<float,int> mfi(gold, i); // uses MyClass2<T,int>
|
||||
MyClass2<int*,float*> mp(&i, &gold); // uses MyClass2<T1*,T2*>
|
||||
MyClass2<int*,int*> m(&i, &i); // uses MyClass2<T*, T*>
|
||||
|
||||
MyClass<char> obj1(i);
|
||||
obj1.templ_mem_func(cc, pi);
|
||||
obj1.templ_mem_func(cc, gold);
|
||||
obj1.templ_mem_func(i, pi);
|
||||
obj1.templ_mem_func(cc, cc);
|
||||
char ch = (char)obj1;
|
||||
|
||||
string str1("abc"), str2("def");
|
||||
MyClass<const char*, std::string> obj2(str1.c_str(), str2, i);
|
||||
obj2.templ_mem_func("klm", str2);
|
||||
obj2.templ_mem_func("hij", pi);
|
||||
|
||||
// Use j to help distinguish, otherwise unable to use the one defined
|
||||
// outside of class body.
|
||||
int j = obj2.templ_mem_func<int, char, char>(cc, cc);
|
||||
// Call explicitly.
|
||||
obj2.templ_mem_func<int, float, double>(gold, pi);
|
||||
const char *pch = (const char*)obj2;
|
||||
|
||||
MyClass<double, float> obj3(pi, gold, i);
|
||||
obj3.templ_mem_func(pi, i);
|
||||
obj3.templ_mem_func(pi, str1);
|
||||
obj3.templ_mem_func(pi, pi);
|
||||
obj3.templ_mem_func(cc, pi);
|
||||
obj3.templ_mem_func(cc, cc);
|
||||
double tmpd = (double)obj3;
|
||||
|
||||
MyClass<double, float> obj4(i);
|
||||
obj4.templ_mem_func(pi, i);
|
||||
obj4.templ_mem_func(pi, str1);
|
||||
obj4.templ_mem_func(pi, pi);
|
||||
obj4.templ_mem_func(gold, pi);
|
||||
tmpd = (double)obj4;
|
||||
|
||||
// Function template partial specialization.
|
||||
part_spec_func(pi, gold);
|
||||
part_spec_func(gold, i);
|
||||
part_spec_func(str1, str2);
|
||||
std::vector<std::string> strv;
|
||||
part_spec_func(str1, strv);
|
||||
std::vector<double> dblv;
|
||||
part_spec_func(pi, dblv);
|
||||
|
||||
// Function template overloads and explicit call and deduction.
|
||||
dbstl_configure_test::max(7, 42, 68); // calls the template for three arguments
|
||||
dbstl_configure_test::max(7.0, 42.0); // calls max<double> (by argument deduction)
|
||||
dbstl_configure_test::max('a', 'b'); // calls max<char> (by argument deduction)
|
||||
dbstl_configure_test::max(7, 42.0);
|
||||
dbstl_configure_test::max<double>(4,4.2); // instantiate T as double
|
||||
dbstl_configure_test::max(7, 42); // calls the nontemplate for two ints
|
||||
dbstl_configure_test::max<>(7, 42); // calls max<int> (by argument deduction)
|
||||
dbstl_configure_test::max<double, double>(7, 42); // calls max<double> (no argument deduction)
|
||||
dbstl_configure_test::max('a', 42.7); // calls the nontemplate for two ints
|
||||
|
||||
Base<double> bobj;
|
||||
bobj.exit2();
|
||||
// Using this-> to access base class members.
|
||||
Derived<double> dobj;
|
||||
dobj.foo();
|
||||
dobj.exit2();
|
||||
]])], AC_MSG_RESULT(yes), AC_MSG_ERROR(no))
|
||||
|
||||
AC_LANG_RESTORE
|
||||
])
|
19
dist/aclocal/gcc.m4
vendored
Normal file
19
dist/aclocal/gcc.m4
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Version 2.96 of gcc (shipped with RedHat Linux 7.[01] and Mandrake) had
|
||||
# serious problems.
|
||||
AC_DEFUN(AC_GCC_CONFIG1, [
|
||||
AC_CACHE_CHECK([whether we are using gcc version 2.96],
|
||||
db_cv_gcc_2_96, [
|
||||
db_cv_gcc_2_96=no
|
||||
if test "$GCC" = "yes"; then
|
||||
GCC_VERSION=`${MAKEFILE_CC} --version`
|
||||
case ${GCC_VERSION} in
|
||||
2.96*)
|
||||
db_cv_gcc_2_96=yes;;
|
||||
esac
|
||||
fi])
|
||||
if test "$db_cv_gcc_2_96" = "yes"; then
|
||||
CFLAGS=`echo "$CFLAGS" | sed 's/-O2/-O/'`
|
||||
CXXFLAGS=`echo "$CXXFLAGS" | sed 's/-O2/-O/'`
|
||||
AC_MSG_WARN([INSTALLED GCC COMPILER HAS SERIOUS BUGS; PLEASE UPGRADE.])
|
||||
AC_MSG_WARN([GCC OPTIMIZATION LEVEL SET TO -O.])
|
||||
fi])
|
8400
dist/aclocal/libtool.m4
vendored
Normal file
8400
dist/aclocal/libtool.m4
vendored
Normal file
File diff suppressed because it is too large
Load diff
437
dist/aclocal/ltoptions.m4
vendored
Normal file
437
dist/aclocal/ltoptions.m4
vendored
Normal file
|
@ -0,0 +1,437 @@
|
|||
# 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])])
|
123
dist/aclocal/ltsugar.m4
vendored
Normal file
123
dist/aclocal/ltsugar.m4
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
|
||||
#
|
||||
# Copyright (C) 2004, 2005, 2007, 2008 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
|
||||
])
|
24
dist/aclocal/ltversion.m4
vendored
Normal file
24
dist/aclocal/ltversion.m4
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
# 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)
|
||||
])
|
99
dist/aclocal/lt~obsolete.m4
vendored
Normal file
99
dist/aclocal/lt~obsolete.m4
vendored
Normal file
|
@ -0,0 +1,99 @@
|
|||
# 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])])
|
255
dist/aclocal/options.m4
vendored
Normal file
255
dist/aclocal/options.m4
vendored
Normal file
|
@ -0,0 +1,255 @@
|
|||
# $Id: options.ac 7 2007-02-03 13:34:17Z gburd $
|
||||
|
||||
# Process user-specified options.
|
||||
AC_DEFUN(AM_OPTIONS_SET, [
|
||||
|
||||
AC_MSG_CHECKING(if --enable-utf8-encoding option specified)
|
||||
AC_ARG_ENABLE(utf8-encoding,
|
||||
AS_HELP_STRING([--enable-utf8-encoding],
|
||||
[Encode strings as UTF-8 or ISO-8859.]),, enableval="yes")
|
||||
db_cv_utf8_strings="$enableval"
|
||||
case "$enableval" in
|
||||
no) AC_MSG_RESULT(yes);;
|
||||
yes) AC_MSG_RESULT(no);;
|
||||
esac
|
||||
if test "$cv_utf8_strings" = "yes"; then
|
||||
ENCODING=UTF8
|
||||
AC_DEFINE(DBSQL_UTF8_ENCODING)
|
||||
else
|
||||
ENCODING=ISO8859
|
||||
AC_DEFINE(DBSQL_ISO8859_ENCODING)
|
||||
fi
|
||||
AH_TEMPLATE(DBSQL_ISO8859_ENCODING,
|
||||
[Define to use ISO8859 string encoding.])
|
||||
AH_TEMPLATE(DBSQL_UTF8_ENCODING,
|
||||
[Define use UTF8 string encoding.])
|
||||
|
||||
|
||||
AC_MSG_CHECKING(if --enable-incore-databases option specified)
|
||||
AC_ARG_ENABLE(incore-databases,
|
||||
AS_HELP_STRING([--enable-incore-databases],
|
||||
[Enable incore databases for ATTACH and OPEN.]),, enableval="yes")
|
||||
db_cv_incore_databases="$enableval"
|
||||
case "$enableval" in
|
||||
no) AC_MSG_RESULT(yes);;
|
||||
yes) AC_MSG_RESULT(no);;
|
||||
esac
|
||||
if test "$db_cv_incore_databases" = "no"; then
|
||||
INMEMORYDB=0
|
||||
else
|
||||
INMEMORYDB=1
|
||||
fi
|
||||
AC_DEFINE(INMEMORYDB)
|
||||
AH_TEMPLATE(INMEMORYDB,
|
||||
[Define to 1 to enable incore databases for ATTACH and OPEN.])
|
||||
|
||||
AC_MSG_CHECKING(if --enable-authentication option specified)
|
||||
AC_ARG_ENABLE(authentication,
|
||||
AS_HELP_STRING([--enable-authentication],
|
||||
[Include authorization validation code.]),, enableval="yes")
|
||||
db_cv_auth="$enableval"
|
||||
case "$enableval" in
|
||||
no) AC_MSG_RESULT(no);;
|
||||
yes) AC_MSG_RESULT(yes);;
|
||||
esac
|
||||
if test "$db_cv_auth" = "no"; then
|
||||
AC_DEFINE(DBSQL_OMIT_AUTHORIZATION)
|
||||
fi
|
||||
AH_TEMPLATE(DBSQL_OMIT_AUTHORIZATION,
|
||||
[Define to 1 to omit authorization code from the build.])
|
||||
|
||||
|
||||
AC_MSG_CHECKING(if --enable-vacuum option specified)
|
||||
AC_ARG_ENABLE(vacuum,
|
||||
AS_HELP_STRING([--enable-vacuum],
|
||||
[Include the VACUUM command.]),, enableval="yes")
|
||||
db_cv_auth="$enableval"
|
||||
case "$enableval" in
|
||||
no) AC_MSG_RESULT(no);;
|
||||
yes) AC_MSG_RESULT(yes);;
|
||||
esac
|
||||
if test "$db_cv_auth" = "no"; then
|
||||
AC_DEFINE(DBSQL_OMIT_VACUUM)
|
||||
fi
|
||||
AH_TEMPLATE(DBSQL_OMIT_VACUUM,
|
||||
[Define to 1 to omit the code for the VACCUM command from the build.])
|
||||
|
||||
AC_MSG_CHECKING(if --enable-datetime option specified)
|
||||
AC_ARG_ENABLE(enable-datetime,
|
||||
AS_HELP_STRING([--enable-datetime],
|
||||
[Include datetime functions.]),, enableval="yes")
|
||||
db_cv_datetime="$enableval"
|
||||
case "$enableval" in
|
||||
no) AC_MSG_RESULT(no);;
|
||||
yes) AC_MSG_RESULT(yes);;
|
||||
esac
|
||||
if test "$db_cv_datetime" = "no"; then
|
||||
AC_DEFINE(DBSQL_OMIT_DATETIME_FUNCS)
|
||||
|
||||
fi
|
||||
AH_TEMPLATE(DBSQL_OMIT_DATETIME_FUNCS,
|
||||
[Define to 1 to omit support for datetime functions from the build.])
|
||||
|
||||
|
||||
AC_MSG_CHECKING([if --with-berkeleydb=DIR option specified])
|
||||
AC_ARG_WITH(berkeleydb,
|
||||
[AS_HELP_STRING([--with-berkeleydb=DIR],
|
||||
[Path of Berkeley DB. [DIR="/usr/local/BerkeleyDB.4.5"]])],
|
||||
[with_berkeleydb="$withval"], [with_berkeleydb="no"])
|
||||
AC_MSG_RESULT($with_berkeleydb)
|
||||
# If --with-berkeleydb isn't specified, assume it's here | wc -l` -gt 0
|
||||
if test "$with_berkeleydb" = "no"; then
|
||||
with_berkeleydb="/usr/local/BerkeleyDB.4.5"
|
||||
fi
|
||||
DB_PATH="$with_berkeleydb"
|
||||
if test `ls "$with_berkeleydb"/lib/libdb-*.la 2>/dev/null | wc -l` -gt 0 ; then
|
||||
AC_MSG_CHECKING([for Berkeley DB version from install tree])
|
||||
db_version=`ls "$with_berkeleydb"/lib/libdb-*.la | sed 's/.*db-\(.*\).la/\1/'`
|
||||
AC_MSG_RESULT([$db_version])
|
||||
echo "$CPPFLAGS" | grep "$with_berkeleydb/include" >/dev/null 2>&1 || CPPFLAGS="$CPPFLAGS -I$with_berkeleydb/include"
|
||||
if test `ls "$with_berkeleydb"/lib/libdb-$db_version.* 2>/dev/null | wc -l` -gt 0 ; then
|
||||
LIBSO_LIBS="$LIBS -L$with_berkeleydb/lib -ldb-$db_version"
|
||||
else
|
||||
LIBS="$LIBS -l$with_berkeleydb/lib/libdb-$db_version.a"
|
||||
fi
|
||||
elif test `ls /usr/local/lib/db?? 2>/dev/null | wc -l` -gt 0 ; then
|
||||
AC_MSG_CHECKING([if Berkeley DB was installed using BSD ports])
|
||||
db_num=`ls /usr/local/lib | grep db | grep -v lib | sed -e 's/db//' | sort -n | head -1`
|
||||
db_version=`echo $db_num | sed 's/\(.\)\(.\)/\1.\2/'`
|
||||
AC_MSG_RESULT([yes, $db_version])
|
||||
echo "$CPPFLAGS" | grep /usr/local/include/db$db_num >/dev/null 2>&1 || CPPFLAGS="$CPPFLAGS -I/usr/local/include/db$db_num"
|
||||
if test `ls /usr/local/lib/libdb-$db_version.* 2>/dev/null | wc -l` -gt 0 ; then
|
||||
LIBSO_LIBS="$LIBS -L/usr/local/lib -ldb-$db_version"
|
||||
else
|
||||
LIBS="$LIBS -l/usr/local/lib/libdb-$db_version.a"
|
||||
fi
|
||||
else
|
||||
AC_MSG_ERROR([$with_berkeleydb not a valid Berkeley DB install tree.])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([if --with-db-uniquename=NAME option specified])
|
||||
AC_ARG_WITH(db-uniquename,
|
||||
[AS_HELP_STRING([--with-db-uniquename=NAME],
|
||||
[Unique name used when building DB library.])],
|
||||
[with_db_uniquename="$withval"], [with_db_uniquename="no"])
|
||||
if test "$with_db_uniquename" = "no"; then
|
||||
db_cv_uniquename="no"
|
||||
DB_UNIQUE_NAME=""
|
||||
AC_MSG_RESULT($with_db_uniquename)
|
||||
else
|
||||
db_cv_uniquename="yes"
|
||||
if test "$with_db_uniquename" = "yes"; then
|
||||
DB_UNIQUE_NAME="__EDIT_DB_VERSION_UNIQUE_NAME__"
|
||||
else
|
||||
DB_UNIQUE_NAME="$with_db_uniquename"
|
||||
fi
|
||||
AC_MSG_RESULT($DB_UNIQUE_NAME)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(if --enable-incore-temp-databases option specified)
|
||||
AC_ARG_ENABLE(incore-temp-databases,
|
||||
AS_HELP_STRING([--enable-incore-temp-databases],
|
||||
[Enable incore databases for temporary tables.]),, enableval="no")
|
||||
db_cv_incore_temp_databases="$enableval"
|
||||
case "$db_cv_incore_temp_databases" in
|
||||
never)
|
||||
TEMP_STORE=0
|
||||
AC_MSG_RESULT([never])
|
||||
;;
|
||||
no)
|
||||
INMEMORYDB=1
|
||||
TEMP_STORE=1
|
||||
AC_MSG_RESULT([no])
|
||||
;;
|
||||
always)
|
||||
INMEMORYDB=1
|
||||
TEMP_STORE=3
|
||||
AC_MSG_RESULT([always])
|
||||
;;
|
||||
*)
|
||||
INMEMORYDB=1
|
||||
TEMP_STORE=2
|
||||
AC_MSG_RESULT([yes])
|
||||
;;
|
||||
esac
|
||||
AC_DEFINE(INMEMORYDB)
|
||||
AH_TEMPLATE(INMEMORYDB,
|
||||
[Define to 1 to enable memory resident databases.])
|
||||
AC_DEFINE(TEMP_STORE)
|
||||
AH_TEMPLATE(TEMP_STORE,
|
||||
[Determines where TEMP databases can be stored, see table in source code.])
|
||||
|
||||
AC_MSG_CHECKING(if --disable-statistics option specified)
|
||||
AC_ARG_ENABLE(statistics,
|
||||
AS_HELP_STRING([--disable-statistics],
|
||||
[Do not build statistics support.]),, enableval="yes")
|
||||
db_cv_build_statistics="$enableval"
|
||||
case "$enableval" in
|
||||
no) AC_MSG_RESULT(yes);;
|
||||
yes) AC_MSG_RESULT(no);;
|
||||
esac
|
||||
|
||||
AC_MSG_CHECKING(if --enable-sqlite-compat option specified)
|
||||
AC_ARG_ENABLE(sqlite-compat,
|
||||
[AS_HELP_STRING([--enable-sqlite-compat],
|
||||
[Build SQLite compatibility API.])],
|
||||
[db_cv_sqlite_compat="$enable_sqlite_compat"],
|
||||
[db_cv_sqlite_compat="no"])
|
||||
AC_MSG_RESULT($db_cv_sqlite_compat)
|
||||
|
||||
AC_MSG_CHECKING(if --enable-soundex-sqlfn option specified)
|
||||
AC_ARG_ENABLE(soundex-sqlfn,
|
||||
[AS_HELP_STRING([--enable-soundex-sqlfn],
|
||||
[Include soundex() sql function support.])],
|
||||
[db_cv_sqlite_compat="$enable_soundex_sqlfn"],
|
||||
[db_cv_sqlite_compat="no"])
|
||||
AC_MSG_RESULT($db_cv_soundex_sqlfn)
|
||||
|
||||
AC_MSG_CHECKING(if --enable-posixmutexes option specified)
|
||||
AC_ARG_ENABLE(posixmutexes,
|
||||
[AS_HELP_STRING([--enable-posixmutexes],
|
||||
[Force use of POSIX standard mutexes.])],
|
||||
[db_cv_posixmutexes="$enable_posixmutexes"], [db_cv_posixmutexes="no"])
|
||||
AC_MSG_RESULT($db_cv_posixmutexes)
|
||||
|
||||
AC_MSG_CHECKING(if --enable-debug option specified)
|
||||
AC_ARG_ENABLE(debug,
|
||||
[AS_HELP_STRING([--enable-debug],
|
||||
[Build a debugging version.])],
|
||||
[db_cv_debug="$enable_debug"], [db_cv_debug="no"])
|
||||
AC_MSG_RESULT($db_cv_debug)
|
||||
|
||||
AC_MSG_CHECKING(if --enable-diagnostic option specified)
|
||||
AC_ARG_ENABLE(diagnostic,
|
||||
[AS_HELP_STRING([--enable-diagnostic],
|
||||
[Build a version with run-time diagnostics.])],
|
||||
[db_cv_diagnostic="$enable_diagnostic"], [db_cv_diagnostic="no"])
|
||||
AC_MSG_RESULT($db_cv_diagnostic)
|
||||
|
||||
AC_MSG_CHECKING(if --enable-tcl option specified)
|
||||
AC_ARG_ENABLE(tcl,
|
||||
[AS_HELP_STRING([--enable-tcl],
|
||||
[Build Tcl API.])],
|
||||
[db_cv_tcl="$enable_tcl"], [db_cv_tcl="no"])
|
||||
AC_MSG_RESULT($db_cv_tcl)
|
||||
|
||||
AC_MSG_CHECKING([if --with-tcl=DIR option specified])
|
||||
AC_ARG_WITH(tcl,
|
||||
[AS_HELP_STRING([--with-tcl=DIR],
|
||||
[Directory location of tclConfig.sh.])],
|
||||
[with_tclconfig="$withval"], [with_tclconfig="no"])
|
||||
AC_MSG_RESULT($with_tclconfig)
|
||||
|
||||
AC_MSG_CHECKING(if --enable-test option specified)
|
||||
AC_ARG_ENABLE(test,
|
||||
[AS_HELP_STRING([--enable-test],
|
||||
[Configure to run the test suite.])],
|
||||
[db_cv_test="$enable_test"], [db_cv_test="no"])
|
||||
AC_MSG_RESULT($db_cv_test)
|
||||
|
||||
# Test requires Tcl
|
||||
if test "$db_cv_test" = "yes"; then
|
||||
if test "$db_cv_tcl" = "no"; then
|
||||
AC_MSG_ERROR([--enable-test requires --enable-tcl])
|
||||
fi
|
||||
fi])
|
118
dist/aclocal/programs.m4
vendored
Normal file
118
dist/aclocal/programs.m4
vendored
Normal file
|
@ -0,0 +1,118 @@
|
|||
# $Id: programs.ac 7 2007-02-03 13:34:17Z gburd $
|
||||
|
||||
# Check for programs used in building/installation.
|
||||
AC_DEFUN(AM_PROGRAMS_SET, [
|
||||
|
||||
AC_CHECK_TOOL(db_cv_path_ar, ar, missing_ar)
|
||||
if test "$db_cv_path_ar" = missing_ar; then
|
||||
AC_MSG_ERROR([No ar utility found.])
|
||||
fi
|
||||
|
||||
AC_CHECK_TOOL(db_cv_path_chmod, chmod, missing_chmod)
|
||||
if test "$db_cv_path_chmod" = missing_chmod; then
|
||||
AC_MSG_ERROR([No chmod utility found.])
|
||||
fi
|
||||
|
||||
AC_CHECK_TOOL(db_cv_path_sed, sed, missing_sed)
|
||||
if test "$db_cv_path_sed" = missing_sed; then
|
||||
AC_MSG_ERROR([No sed utility found.])
|
||||
fi
|
||||
|
||||
AC_CHECK_TOOL(db_cv_path_perl, perl, missing_perl)
|
||||
if test "$db_cv_path_perl" = missing_perl; then
|
||||
AC_MSG_ERROR([No perl utility found.])
|
||||
fi
|
||||
|
||||
AC_CHECK_TOOL(db_cv_path_makedepend, makedepend, missing_makedepend)
|
||||
if test "$db_cv_path_makedepend" = missing_makedepend; then
|
||||
AC_MSG_RESULT([no])
|
||||
db_cv_path_makedepend=echo
|
||||
fi
|
||||
|
||||
AC_CHECK_TOOL(db_cv_path_splint, splint, missing_splint)
|
||||
if test "$db_cv_path_splint" = missing_splint; then
|
||||
AC_MSG_RESULT([no])
|
||||
db_cv_path_splint=echo
|
||||
fi
|
||||
|
||||
AC_CHECK_TOOL(db_cv_path_python, python, missing_python)
|
||||
if test "$db_cv_path_python" = missing_python; then
|
||||
AC_MSG_RESULT([no])
|
||||
db_cv_path_python=echo
|
||||
fi
|
||||
|
||||
AC_CHECK_TOOL(db_cv_path_grep, grep, missing_grep)
|
||||
if test "$db_cv_path_grep" = missing_grep; then
|
||||
AC_MSG_ERROR([No grep utility found.])
|
||||
fi
|
||||
|
||||
AC_CHECK_TOOL(db_cv_path_awk, awk, missing_awk)
|
||||
if test "$db_cv_path_awk" = missing_awk; then
|
||||
AC_MSG_ERROR([No awk utility found.])
|
||||
fi
|
||||
|
||||
AC_CHECK_TOOL(db_cv_path_cp, cp, missing_cp)
|
||||
if test "$db_cv_path_cp" = missing_cp; then
|
||||
AC_MSG_ERROR([No cp utility found.])
|
||||
fi
|
||||
|
||||
if test "$db_cv_rpm" = "yes"; then
|
||||
AC_CHECK_TOOL(path_ldconfig, ldconfig, missing_ldconfig)
|
||||
AC_PATH_PROG(db_cv_path_ldconfig, $path_ldconfig, missing_ldconfig)
|
||||
if test "$db_cv_path_ldconfig" != missing_ldconfig; then
|
||||
RPM_POST_INSTALL="%post -p $db_cv_path_ldconfig"
|
||||
RPM_POST_UNINSTALL="%postun -p $db_cv_path_ldconfig"
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_CHECK_TOOL(db_cv_path_ln, ln, missing_ln)
|
||||
if test "$db_cv_path_ln" = missing_ln; then
|
||||
AC_MSG_ERROR([No ln utility found.])
|
||||
fi
|
||||
|
||||
AC_CHECK_TOOL(db_cv_path_mkdir, mkdir, missing_mkdir)
|
||||
if test "$db_cv_path_mkdir" = missing_mkdir; then
|
||||
AC_MSG_ERROR([No mkdir utility found.])
|
||||
fi
|
||||
|
||||
# We need a complete path for ranlib, because it doesn't exist on some
|
||||
# architectures because the ar utility packages the library itself.
|
||||
AC_CHECK_TOOL(path_ranlib, ranlib, missing_ranlib)
|
||||
AC_PATH_PROG(db_cv_path_ranlib, $path_ranlib, missing_ranlib)
|
||||
|
||||
AC_CHECK_TOOL(db_cv_path_rm, rm, missing_rm)
|
||||
if test "$db_cv_path_rm" = missing_rm; then
|
||||
AC_MSG_ERROR([No rm utility found.])
|
||||
fi
|
||||
|
||||
if test "$db_cv_rpm" = "yes"; then
|
||||
AC_CHECK_TOOL(db_cv_path_rpm, rpm, missing_rpm)
|
||||
if test "$db_cv_path_rpm" = missing_rpm; then
|
||||
AC_MSG_ERROR([No rpm utility found.])
|
||||
fi
|
||||
fi
|
||||
|
||||
# We need a complete path for sh, because some implementations of make
|
||||
# get upset if SHELL is set to just the command name.
|
||||
AC_CHECK_TOOL(path_sh, sh, missing_sh)
|
||||
AC_PATH_PROG(db_cv_path_sh, $path_sh, missing_sh)
|
||||
if test "$db_cv_path_sh" = missing_sh; then
|
||||
AC_MSG_ERROR([No sh utility found.])
|
||||
fi
|
||||
|
||||
# Don't strip the binaries if --enable-debug was specified.
|
||||
if test "$db_cv_debug" = yes; then
|
||||
db_cv_path_strip=debug_build_no_strip
|
||||
else
|
||||
AC_CHECK_TOOL(path_strip, strip, missing_strip)
|
||||
AC_PATH_PROG(db_cv_path_strip, $path_strip, missing_strip)
|
||||
fi
|
||||
|
||||
if test "$db_cv_test" = "yes"; then
|
||||
AC_CHECK_TOOL(db_cv_path_kill, kill, missing_kill)
|
||||
if test "$db_cv_path_kill" = missing_kill; then
|
||||
AC_MSG_ERROR([No kill utility found.])
|
||||
fi
|
||||
fi
|
||||
|
||||
])
|
47
dist/aclocal/readline.m4
vendored
Normal file
47
dist/aclocal/readline.m4
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
# $Id: readline.ac 7 2007-02-03 13:34:17Z gburd $
|
||||
|
||||
# Find a readline compatible library.
|
||||
|
||||
AC_DEFUN([VL_LIB_READLINE], [
|
||||
AC_CACHE_CHECK([for a readline compatible library],
|
||||
vl_cv_lib_readline, [
|
||||
ORIG_LIBS="$LIBS"
|
||||
for readline_lib in readline edit editline; do
|
||||
for termcap_lib in "" termcap curses ncurses; do
|
||||
if test -z "$termcap_lib"; then
|
||||
TRY_LIB="-l$readline_lib"
|
||||
else
|
||||
TRY_LIB="-l$readline_lib -l$termcap_lib"
|
||||
fi
|
||||
LIBS="$ORIG_LIBS $TRY_LIB"
|
||||
AC_TRY_LINK_FUNC(readline, vl_cv_lib_readline="$TRY_LIB")
|
||||
if test -n "$vl_cv_lib_readline"; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -n "$vl_cv_lib_readline"; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$vl_cv_lib_readline"; then
|
||||
vl_cv_lib_readline="no"
|
||||
LIBS="$ORIG_LIBS"
|
||||
fi
|
||||
])
|
||||
|
||||
if test "$vl_cv_lib_readline" != "no"; then
|
||||
AC_DEFINE(HAVE_LIBREADLINE, 1,
|
||||
[Define if you have a readline compatible library])
|
||||
AC_CHECK_HEADERS(readline.h readline/readline.h)
|
||||
AC_CACHE_CHECK([whether readline supports history],
|
||||
vl_cv_lib_readline_history, [
|
||||
vl_cv_lib_readline_history="no"
|
||||
AC_TRY_LINK_FUNC(add_history, vl_cv_lib_readline_history="yes")
|
||||
])
|
||||
if test "$vl_cv_lib_readline_history" = "yes"; then
|
||||
AC_DEFINE(HAVE_READLINE_HISTORY, 1,
|
||||
[Define if your readline library has \`add_history'])
|
||||
AC_CHECK_HEADERS(history.h readline/history.h)
|
||||
fi
|
||||
fi
|
||||
])dnl
|
75
dist/aclocal/sosuffix.m4
vendored
Normal file
75
dist/aclocal/sosuffix.m4
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
# $Id$
|
||||
# Determine shared object suffixes.
|
||||
#
|
||||
# Our method is to use the libtool variable $library_names_spec,
|
||||
# set by using LT_INIT. This variable is a snippet of shell
|
||||
# defined in terms of $versuffix, $release, $libname and $module
|
||||
# We want to eval it and grab the suffix used for shared objects.
|
||||
# By setting $module to yes/no, we obtain the suffixes
|
||||
# used to create dlloadable, or java loadable modules.
|
||||
# On many (*nix) systems, these all evaluate to .so, but there
|
||||
# are some notable exceptions.
|
||||
# Before calling this macro, libtool must have been configured.
|
||||
|
||||
# This macro is used internally to discover the suffix for the current
|
||||
# settings of $module. The result is stored in $_SOSUFFIX.
|
||||
AC_DEFUN(_SOSUFFIX_INTERNAL, [
|
||||
versuffix=""
|
||||
release=""
|
||||
libname=libfoo
|
||||
eval _SOSUFFIX=\"$shrext_cmds\"
|
||||
if test "$_SOSUFFIX" = "" ; then
|
||||
_SOSUFFIX=".so"
|
||||
if test "$enable_shared" != "yes"; then
|
||||
if test "$_SOSUFFIX_MESSAGE" = ""; then
|
||||
_SOSUFFIX_MESSAGE=yes
|
||||
AC_MSG_WARN([libtool may not know about this architecture.])
|
||||
AC_MSG_WARN([assuming $_SOSUFFIX suffix for dynamic libraries.])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
# SOSUFFIX_CONFIG will set the variable SOSUFFIX to be the
|
||||
# shared library extension used for general linking, not dlopen.
|
||||
AC_DEFUN(SOSUFFIX_CONFIG, [
|
||||
AC_MSG_CHECKING([SOSUFFIX from libtool])
|
||||
module=no
|
||||
_SOSUFFIX_INTERNAL
|
||||
SOSUFFIX=$_SOSUFFIX
|
||||
AC_MSG_RESULT($SOSUFFIX)
|
||||
AC_SUBST(SOSUFFIX)
|
||||
])
|
||||
|
||||
# MODSUFFIX_CONFIG will set the variable MODSUFFIX to be the
|
||||
# shared library extension used for dlopen'ed modules.
|
||||
# To discover this, we set $module, simulating libtool's -module option.
|
||||
AC_DEFUN(MODSUFFIX_CONFIG, [
|
||||
AC_MSG_CHECKING([MODSUFFIX from libtool])
|
||||
module=yes
|
||||
_SOSUFFIX_INTERNAL
|
||||
MODSUFFIX=$_SOSUFFIX
|
||||
AC_MSG_RESULT($MODSUFFIX)
|
||||
AC_SUBST(MODSUFFIX)
|
||||
])
|
||||
|
||||
# JMODSUFFIX_CONFIG will set the variable JMODSUFFIX to be the
|
||||
# shared library extension used JNI modules opened by Java.
|
||||
# To discover this, we set $jnimodule, simulating libtool's -shrext option.
|
||||
##########################################################################
|
||||
# Robert Boehne: Not much point in this macro any more because apparently
|
||||
# Darwin is the only OS that wants or needs the .jnilib extension.
|
||||
##########################################################################
|
||||
AC_DEFUN(JMODSUFFIX_CONFIG, [
|
||||
AC_MSG_CHECKING([JMODSUFFIX from libtool])
|
||||
module=yes
|
||||
_SOSUFFIX_INTERNAL
|
||||
if test `uname` = "Darwin"; then
|
||||
JMODSUFFIX=".jnilib"
|
||||
else
|
||||
JMODSUFFIX=$_SOSUFFIX
|
||||
fi
|
||||
AC_MSG_RESULT($JMODSUFFIX)
|
||||
AC_SUBST(JMODSUFFIX)
|
||||
])
|
||||
|
128
dist/aclocal/tcl.m4
vendored
Normal file
128
dist/aclocal/tcl.m4
vendored
Normal file
|
@ -0,0 +1,128 @@
|
|||
# $Id: tcl.ac 7 2007-02-03 13:34:17Z gburd $
|
||||
|
||||
# The SC_* macros in this file are from the unix/tcl.m4 files in the Tcl
|
||||
# 8.3.0 distribution, with some minor changes. For this reason, license
|
||||
# terms for the Berkeley DB distribution dist/aclocal/tcl.m4 file are as
|
||||
# follows (copied from the license.terms file in the Tcl 8.3 distribution):
|
||||
#
|
||||
# This software is copyrighted by the Regents of the University of
|
||||
# California, Sun Microsystems, Inc., Scriptics Corporation,
|
||||
# and other parties. The following terms apply to all files associated
|
||||
# with the software unless explicitly disclaimed in individual files.
|
||||
#
|
||||
# The authors hereby grant permission to use, copy, modify, distribute,
|
||||
# and license this software and its documentation for any purpose, provided
|
||||
# that existing copyright notices are retained in all copies and that this
|
||||
# notice is included verbatim in any distributions. No written agreement,
|
||||
# license, or royalty fee is required for any of the authorized uses.
|
||||
# Modifications to this software may be copyrighted by their authors
|
||||
# and need not follow the licensing terms described here, provided that
|
||||
# the new terms are clearly indicated on the first page of each file where
|
||||
# they apply.
|
||||
#
|
||||
# IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||
# FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
# ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||
# DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
||||
# IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
||||
# NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
||||
# MODIFICATIONS.
|
||||
#
|
||||
# GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||
# U.S. government, the Government shall have only "Restricted Rights"
|
||||
# in the software and related documentation as defined in the Federal
|
||||
# Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
|
||||
# are acquiring the software on behalf of the Department of Defense, the
|
||||
# software shall be classified as "Commercial Computer Software" and the
|
||||
# Government shall have only "Restricted Rights" as defined in Clause
|
||||
# 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||
# authors grant the U.S. Government and others acting in its behalf
|
||||
# permission to use and distribute the software in accordance with the
|
||||
# terms specified in this license.
|
||||
|
||||
AC_DEFUN(SC_PATH_TCLCONFIG, [
|
||||
AC_CACHE_VAL(ac_cv_c_tclconfig,[
|
||||
|
||||
# First check to see if --with-tclconfig was specified.
|
||||
if test x"${with_tclconfig}" != x; then
|
||||
if test -f "${with_tclconfig}/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
|
||||
else
|
||||
AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
|
||||
fi
|
||||
fi
|
||||
|
||||
# check in a few common install locations
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
for i in `ls -d /usr/local/lib 2>/dev/null` ; do
|
||||
if test -f "$i/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig=`(cd $i; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
])
|
||||
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
TCL_BIN_DIR="# no Tcl configs found"
|
||||
AC_MSG_ERROR(can't find Tcl configuration definitions)
|
||||
else
|
||||
TCL_BIN_DIR=${ac_cv_c_tclconfig}
|
||||
fi
|
||||
AC_SUBST(TCL_BIN_DIR)
|
||||
])
|
||||
|
||||
AC_DEFUN(SC_LOAD_TCLCONFIG, [
|
||||
AC_MSG_CHECKING([for existence of $TCL_BIN_DIR/tclConfig.sh])
|
||||
|
||||
if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then
|
||||
AC_MSG_RESULT([loading])
|
||||
. $TCL_BIN_DIR/tclConfig.sh
|
||||
else
|
||||
AC_MSG_RESULT([file not found])
|
||||
fi
|
||||
|
||||
# DBSQL requires at least version 8.4.
|
||||
if test ${TCL_MAJOR_VERSION} -lt 8 \
|
||||
-o ${TCL_MAJOR_VERSION} -eq 8 -a ${TCL_MINOR_VERSION} -lt 4; then
|
||||
AC_MSG_ERROR([Berkeley DB requires Tcl version 8.4 or better.])
|
||||
fi
|
||||
|
||||
if test x"$TCL_INCLUDE_SPEC" != x; then
|
||||
TCL_CFLAGS="$TCL_INCLUDE_SPEC"
|
||||
fi
|
||||
|
||||
AC_SUBST(TCL_LD_FLAGS)
|
||||
AC_SUBST(TCL_LIBS)
|
||||
AC_SUBST(TCL_LIB_SPEC)
|
||||
])
|
||||
|
||||
# Optional Tcl API.
|
||||
AC_DEFUN(AM_TCL_LOAD, [
|
||||
if test "$db_cv_tcl" = "yes"; then
|
||||
if test `$LIBTOOL_PROG --config | grep build_libtool_libs | grep no` 2>/dev/null; then
|
||||
AC_MSG_ERROR([Tcl requires shared libraries])
|
||||
fi
|
||||
|
||||
SC_PATH_TCLCONFIG
|
||||
SC_LOAD_TCLCONFIG
|
||||
|
||||
if test x"$TCL_INCLUDE_SPEC" != x && test -f "$TCL_INCLUDE_SPEC/tcl.h"; then
|
||||
TCL_CFLAGS="${TCL_CFLAGS} -I$TCL_INCLUDE_SPEC"
|
||||
fi
|
||||
|
||||
INSTALL_LIBS="${INSTALL_LIBS} \$(libtso_target)"
|
||||
|
||||
TCL_TCLSH="${TCL_PREFIX}/bin/tclsh${TCL_VERSION}"
|
||||
|
||||
AC_SUBST(TCL_SRC_DIR)
|
||||
AC_SUBST(TCL_LIB_FILE)
|
||||
AC_SUBST(TCL_CFLAGS)
|
||||
AC_SUBST(TCL_TCLSH)
|
||||
fi])
|
218
dist/aclocal/types.m4
vendored
Normal file
218
dist/aclocal/types.m4
vendored
Normal file
|
@ -0,0 +1,218 @@
|
|||
# $Id$
|
||||
|
||||
# Check the sizes we know about, and see if any of them match what's needed.
|
||||
#
|
||||
# Prefer ints to anything else, because read, write and others historically
|
||||
# returned an int.
|
||||
AC_DEFUN(AM_SEARCH_USIZES, [
|
||||
case "$3" in
|
||||
"$ac_cv_sizeof_unsigned_int")
|
||||
$1="typedef unsigned int $2;";;
|
||||
"$ac_cv_sizeof_unsigned_char")
|
||||
$1="typedef unsigned char $2;";;
|
||||
"$ac_cv_sizeof_unsigned_short")
|
||||
$1="typedef unsigned short $2;";;
|
||||
"$ac_cv_sizeof_unsigned_long")
|
||||
$1="typedef unsigned long $2;";;
|
||||
"$ac_cv_sizeof_unsigned_long_long")
|
||||
$1="typedef unsigned long long $2;";;
|
||||
*)
|
||||
if test "$4" != "notfatal"; then
|
||||
AC_MSG_ERROR([No unsigned $3-byte integral type])
|
||||
fi;;
|
||||
esac])
|
||||
AC_DEFUN(AM_SEARCH_SSIZES, [
|
||||
case "$3" in
|
||||
"$ac_cv_sizeof_int")
|
||||
$1="typedef int $2;";;
|
||||
"$ac_cv_sizeof_char")
|
||||
$1="typedef char $2;";;
|
||||
"$ac_cv_sizeof_short")
|
||||
$1="typedef short $2;";;
|
||||
"$ac_cv_sizeof_long")
|
||||
$1="typedef long $2;";;
|
||||
"$ac_cv_sizeof_long_long")
|
||||
$1="typedef long long $2;";;
|
||||
*)
|
||||
if test "$4" != "notfatal"; then
|
||||
AC_MSG_ERROR([No signed $3-byte integral type])
|
||||
fi;;
|
||||
esac])
|
||||
|
||||
# Check for the standard system types.
|
||||
AC_DEFUN(AM_TYPES, [
|
||||
|
||||
# db.h includes <sys/types.h> and <stdio.h>, not the other default includes
|
||||
# autoconf usually includes. For that reason, we specify a set of includes
|
||||
# for all type checking tests. [#5060]
|
||||
#
|
||||
# C99 says types should be in <stdint.h>; include <stdint.h> if it exists.
|
||||
#
|
||||
# Some systems have types in <stddef.h>; include <stddef.h> if it exists.
|
||||
#
|
||||
# IBM's OS/390 and z/OS releases have types in <inttypes.h> not also found
|
||||
# in <sys/types.h>; include <inttypes.h> if it exists.
|
||||
db_includes="#include <sys/types.h>"
|
||||
AC_SUBST(inttypes_h_decl)
|
||||
AC_CHECK_HEADER(inttypes.h, [
|
||||
db_includes="$db_includes
|
||||
#include <inttypes.h>"
|
||||
inttypes_h_decl="#include <inttypes.h>"])
|
||||
|
||||
# IRIX has stdint.h that is only available when using c99 (i.e. __c99
|
||||
# is defined). Problem with having it in a public header is that a c++
|
||||
# compiler cannot #include <db.h> if db.h #includes stdint.h, so we
|
||||
# need to check that stdint.h is available for all cases. Also the
|
||||
# IRIX compiler does not exit with a non-zero exit code when it sees
|
||||
# #error, so we actually need to use the header for the compiler to fail.
|
||||
AC_SUBST(stdint_h_decl)
|
||||
AC_MSG_CHECKING(for stdint.h)
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <stdint.h>
|
||||
int main() {
|
||||
uint_least8_t x=0;
|
||||
return x;
|
||||
}]])],[AC_MSG_RESULT(yes)
|
||||
if test "$db_cv_cxx" = "yes"; then
|
||||
AC_MSG_CHECKING([if stdint.h can be used by C++])
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <stdint.h>
|
||||
int main() {
|
||||
uint_least8_t x=0;
|
||||
return x;
|
||||
}]])],[AC_MSG_RESULT(yes)
|
||||
stdint_h_decl="#include <stdint.h>"
|
||||
db_includes="$db_includes
|
||||
#include <stdint.h>"
|
||||
],[AC_MSG_RESULT(no)
|
||||
stdint_h_decl="#ifndef __cplusplus
|
||||
#include <stdint.h>
|
||||
#endif"
|
||||
db_includes="$db_includes
|
||||
#ifndef __cplusplus
|
||||
#include <stdint.h>
|
||||
#endif"
|
||||
])
|
||||
AC_LANG_POP
|
||||
else
|
||||
stdint_h_decl="#include <stdint.h>"
|
||||
db_includes="$db_includes
|
||||
#include <stdint.h>"
|
||||
fi],[AC_MSG_RESULT(no)])
|
||||
|
||||
AC_SUBST(stddef_h_decl)
|
||||
AC_CHECK_HEADER(stddef.h, [
|
||||
db_includes="$db_includes
|
||||
#include <stddef.h>"
|
||||
stddef_h_decl="#include <stddef.h>"])
|
||||
AC_SUBST(unistd_h_decl)
|
||||
AC_CHECK_HEADER(unistd.h, [
|
||||
db_includes="$db_includes
|
||||
#include <unistd.h>"
|
||||
unistd_h_decl="#include <unistd.h>"])
|
||||
db_includes="$db_includes
|
||||
#include <stdio.h>"
|
||||
|
||||
# We need to know the sizes of various objects on this system.
|
||||
AC_CHECK_SIZEOF(char,, $db_includes)
|
||||
AC_CHECK_SIZEOF(unsigned char,, $db_includes)
|
||||
AC_CHECK_SIZEOF(short,, $db_includes)
|
||||
AC_CHECK_SIZEOF(unsigned short,, $db_includes)
|
||||
AC_CHECK_SIZEOF(int,, $db_includes)
|
||||
AC_CHECK_SIZEOF(unsigned int,, $db_includes)
|
||||
AC_CHECK_SIZEOF(long,, $db_includes)
|
||||
AC_CHECK_SIZEOF(unsigned long,, $db_includes)
|
||||
AC_CHECK_SIZEOF(long long,, $db_includes)
|
||||
AC_CHECK_SIZEOF(unsigned long long,, $db_includes)
|
||||
AC_CHECK_SIZEOF(char *,, $db_includes)
|
||||
AC_CHECK_SIZEOF(long double,, $db_includes)
|
||||
|
||||
# We look for u_char, u_short, u_int, u_long -- if we can't find them,
|
||||
# we create our own.
|
||||
AC_SUBST(u_char_decl)
|
||||
AC_CHECK_TYPE(u_char,,
|
||||
[u_char_decl="typedef unsigned char u_char;"], $db_includes)
|
||||
|
||||
AC_SUBST(u_short_decl)
|
||||
AC_CHECK_TYPE(u_short,,
|
||||
[u_short_decl="typedef unsigned short u_short;"], $db_includes)
|
||||
|
||||
AC_SUBST(u_int_decl)
|
||||
AC_CHECK_TYPE(u_int,,
|
||||
[u_int_decl="typedef unsigned int u_int;"], $db_includes)
|
||||
|
||||
AC_SUBST(u_long_decl)
|
||||
AC_CHECK_TYPE(u_long,,
|
||||
[u_long_decl="typedef unsigned long u_long;"], $db_includes)
|
||||
|
||||
# We look for fixed-size variants of u_char, u_short, u_int, u_long as well.
|
||||
AC_SUBST(u_int8_decl)
|
||||
AC_CHECK_TYPE(u_int8_t,,
|
||||
[AM_SEARCH_USIZES(u_int8_decl, u_int8_t, 1)], $db_includes)
|
||||
|
||||
AC_SUBST(u_int16_decl)
|
||||
AC_CHECK_TYPE(u_int16_t,,
|
||||
[AM_SEARCH_USIZES(u_int16_decl, u_int16_t, 2)], $db_includes)
|
||||
|
||||
AC_SUBST(int16_decl)
|
||||
AC_CHECK_TYPE(int16_t,,
|
||||
[AM_SEARCH_SSIZES(int16_decl, int16_t, 2)], $db_includes)
|
||||
|
||||
AC_SUBST(u_int32_decl)
|
||||
AC_CHECK_TYPE(u_int32_t,,
|
||||
[AM_SEARCH_USIZES(u_int32_decl, u_int32_t, 4)], $db_includes)
|
||||
|
||||
AC_SUBST(int32_decl)
|
||||
AC_CHECK_TYPE(int32_t,,
|
||||
[AM_SEARCH_SSIZES(int32_decl, int32_t, 4)], $db_includes)
|
||||
|
||||
AC_SUBST(u_int64_decl)
|
||||
AC_CHECK_TYPE(u_int64_t,,
|
||||
[AM_SEARCH_USIZES(u_int64_decl, u_int64_t, 8, notfatal)], $db_includes)
|
||||
|
||||
AC_SUBST(int64_decl)
|
||||
AC_CHECK_TYPE(int64_t,,
|
||||
[AM_SEARCH_SSIZES(int64_decl, int64_t, 8, notfatal)], $db_includes)
|
||||
|
||||
AC_SUBST(long_double_decl)
|
||||
AC_CHECK_TYPE(long double,
|
||||
[long_double_decl="typedef long double long_double_t;"],
|
||||
[long_double_decl="typedef long double long_double_t;"], $db_includes)
|
||||
|
||||
# No currently autoconf'd systems lack FILE, off_t pid_t, size_t, time_t.
|
||||
#
|
||||
# We require them, we don't try to substitute our own if we can't find them.
|
||||
AC_SUBST(FILE_t_decl)
|
||||
AC_CHECK_TYPE(FILE *,, AC_MSG_ERROR([No FILE type.]), $db_includes)
|
||||
AC_SUBST(off_t_decl)
|
||||
AC_CHECK_TYPE(off_t,, AC_MSG_ERROR([No off_t type.]), $db_includes)
|
||||
AC_SUBST(pid_t_decl)
|
||||
AC_CHECK_TYPE(pid_t,, AC_MSG_ERROR([No pid_t type.]), $db_includes)
|
||||
AC_SUBST(size_t_decl)
|
||||
AC_CHECK_TYPE(size_t,, AC_MSG_ERROR([No size_t type.]), $db_includes)
|
||||
AC_SUBST(time_t_decl)
|
||||
AC_CHECK_TYPE(time_t,, AC_MSG_ERROR([No time_t type.]), $db_includes)
|
||||
|
||||
# Check for ssize_t -- if none exists, find a signed integral type that's
|
||||
# the same size as a size_t.
|
||||
AC_CHECK_SIZEOF(size_t,, $db_includes)
|
||||
AC_SUBST(ssize_t_decl)
|
||||
AC_CHECK_TYPE(ssize_t,,
|
||||
[AM_SEARCH_SSIZES(ssize_t_decl, ssize_t, $ac_cv_sizeof_size_t)],
|
||||
$db_includes)
|
||||
|
||||
# Check for uintmax_t -- if none exists, find the largest unsigned integral
|
||||
# type available.
|
||||
AC_SUBST(uintmax_t_decl)
|
||||
AC_CHECK_TYPE(uintmax_t,, [AC_CHECK_TYPE(unsigned long long,
|
||||
[uintmax_t_decl="typedef unsigned long long uintmax_t;"],
|
||||
[uintmax_t_decl="typedef unsigned long uintmax_t;"], $db_includes)])
|
||||
|
||||
# Check for uintptr_t -- if none exists, find an integral type which is
|
||||
# the same size as a pointer.
|
||||
AC_SUBST(uintptr_t_decl)
|
||||
AC_CHECK_TYPE(uintptr_t,,
|
||||
[AM_SEARCH_USIZES(uintptr_t_decl, uintptr_t, $ac_cv_sizeof_char_p)])
|
||||
|
||||
])
|
135
dist/buildrel
vendored
Normal file
135
dist/buildrel
vendored
Normal file
|
@ -0,0 +1,135 @@
|
|||
# DBSQL - A SQL database engine.
|
||||
#
|
||||
# Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# There are special exceptions to the terms and conditions of the GPL as it
|
||||
# is applied to this software. View the full text of the exception in file
|
||||
# LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
#
|
||||
# This library 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.
|
||||
|
||||
#
|
||||
# Build the distribution package.
|
||||
# A set of commands intended to be cut and pasted into a csh window.
|
||||
#
|
||||
|
||||
# Development tree, release home.
|
||||
setenv D `pwd`
|
||||
|
||||
# Update the release number.
|
||||
cd $D/dist
|
||||
cvs -q update RELEASE
|
||||
vi RELEASE
|
||||
setenv VERSION `sh -c '. RELEASE; echo $DBSQL_VERSION'`
|
||||
echo "Version: $VERSION"
|
||||
|
||||
# Make sure the source tree is up-to-date
|
||||
cd $D && cvs -q update
|
||||
|
||||
# Build the documentation.
|
||||
cd db.docs && cvs -q update
|
||||
cd db.docs && sh build ../db.rel clean && sh build ../db.rel |& sed '/.html$/d'
|
||||
cd db.docs && sh build ../db.rel javadoc
|
||||
|
||||
# Generate new support files, commit anything that's changed.
|
||||
cd $D/dist && sh s_all
|
||||
cd $D && cvs -q commit
|
||||
|
||||
# Copy a development tree into a release tree.
|
||||
setenv R /var/tmp/db-$VERSION
|
||||
rm -rf $R && mkdir -p $R
|
||||
cd $D && cvs -q status | \
|
||||
grep "Repository revision" | \
|
||||
sed -e 's;.*CVSROOT/db/;;' \
|
||||
-e 's;.*CVSROOT/;;' \
|
||||
-e 's;,v$;;' | pax -rw $R/
|
||||
|
||||
# Copy the already-built documentation into place
|
||||
rm -rf $R/docs && cp -r $D/docs $R/docs
|
||||
|
||||
# Remove source directories we don't distribute.
|
||||
cd $R && rm -rf docs_src docs/api_java
|
||||
cd $R && rm -rf test/TODO test/upgrade test_perf test_purify
|
||||
cd $R && rm -rf test_server test_thread test_vxworks test_xa
|
||||
cd $R && rm -rf java/src/com/sleepycat/xa
|
||||
|
||||
# Fix symbolic links and permissions.
|
||||
cd $R/dist && sh s_perm
|
||||
cd $R/dist && sh s_symlink
|
||||
|
||||
# Build a version.
|
||||
cd $R && rm -rf build_run && mkdir build_run
|
||||
cd $R/build_run && ~bostic/bin/dbconf && make >& mklog
|
||||
|
||||
# Smoke test.
|
||||
cd $R/build_run && ./ex_access
|
||||
|
||||
# Check the install
|
||||
cd $R/build_run && make prefix=`pwd`/BDB install
|
||||
|
||||
# Build a small-footprint version.
|
||||
cd $R && rm -rf build_run && mkdir build_run
|
||||
cd $R/build_run && ../dist/configure --enable-smallbuild && make >& mklog
|
||||
|
||||
# Remove the build directory
|
||||
cd $R && rm -rf build_run
|
||||
|
||||
# ACQUIRE ROOT PRIVILEGES
|
||||
cd $R && find . -type d | xargs chmod 775
|
||||
cd $R && find . -type f | xargs chmod 444
|
||||
cd $R && chmod 664 build_win32/*.dsp
|
||||
cd $R/dist && sh s_perm
|
||||
chown -R 100 $R
|
||||
chgrp -R 100 $R
|
||||
# DISCARD ROOT PRIVILEGES
|
||||
|
||||
# Create the crypto tar archive release.
|
||||
setenv T "$R/../db-$VERSION.tar.gz"
|
||||
cd $R/.. && tar cf - db-$VERSION | gzip --best > $T
|
||||
chmod 444 $T
|
||||
|
||||
# Create the non-crypto tree.
|
||||
setenv RNC "$R/../db-$VERSION.NC"
|
||||
rm -rf $RNC $R/../__TMP && mkdir $R/../__TMP
|
||||
cd $R/../__TMP && gzcat $T | tar xpf - && mv -i db-$VERSION $RNC
|
||||
cd $R && rm -rf $R/../__TMP
|
||||
cd $RNC/dist && sh s_crypto
|
||||
|
||||
# ACQUIRE ROOT PRIVILEGES
|
||||
cd $RNC && find . -type d | xargs chmod 775
|
||||
cd $RNC && find . -type f | xargs chmod 444
|
||||
cd $RNC && chmod 664 build_win32/*.dsp
|
||||
cd $RNC/dist && sh s_perm
|
||||
chown -R 100 $RNC
|
||||
chgrp -R 100 $RNC
|
||||
# DISCARD ROOT PRIVILEGES
|
||||
|
||||
# Create the non-crypto tar archive release.
|
||||
setenv T "$R/../db-$VERSION.NC.tar.gz"
|
||||
cd $RNC/.. && tar cf - db-$VERSION.NC | gzip --best > $T
|
||||
chmod 444 $T
|
||||
|
||||
# Remove tags files. They're large and we don't want to store symbolic links
|
||||
# in the zip archive for portability reasons.
|
||||
# ACQUIRE ROOT PRIVILEGES
|
||||
cd $R && rm -f `find . -name 'tags'`
|
||||
cd $RNC && rm -f `find . -name 'tags'`
|
||||
# DISCARD ROOT PRIVILEGES
|
||||
|
||||
# Create the crypto zip archive release.
|
||||
setenv T "$R/../db-$VERSION.zip"
|
||||
cd $R/.. && zip -r - db-$VERSION > $T
|
||||
chmod 444 $T
|
||||
|
||||
# Create the non-crypto zip archive release.
|
||||
setenv T "$R/../db-$VERSION.NC.zip"
|
||||
cd $RNC/.. && zip -r - db-$VERSION.NC > $T
|
||||
chmod 444 $T
|
1803
dist/config.guess
vendored
Executable file
1803
dist/config.guess
vendored
Executable file
File diff suppressed because it is too large
Load diff
1895
dist/config.sub
vendored
Executable file
1895
dist/config.sub
vendored
Executable file
File diff suppressed because it is too large
Load diff
527
dist/configure.ac
vendored
Normal file
527
dist/configure.ac
vendored
Normal file
|
@ -0,0 +1,527 @@
|
|||
# DBSQL - A SQL database engine.
|
||||
#
|
||||
# Copyright (C) 2007-2009 The DBSQL Group, Inc. - All rights reserved.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# There are special exceptions to the terms and conditions of the GPL as it
|
||||
# is applied to this software. View the full text of the exception in file
|
||||
# LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
#
|
||||
# This library 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.
|
||||
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
PACKAGE=dbsql
|
||||
AC_INIT([DBSQL],[__EDIT_DBSQL_VERSION__],[support@dbsql.org],[dbsql-__EDIT_DBSQL_VERSION__])
|
||||
AC_LANG(C)
|
||||
AC_CONFIG_SRCDIR([../src/clib/memcmp.c])
|
||||
AC_CONFIG_HEADERS([dbsql_config.h:config.hin])
|
||||
|
||||
# Configure setup.
|
||||
AC_CANONICAL_HOST()
|
||||
AC_ARG_PROGRAM()
|
||||
|
||||
# Don't build in the top-level or dist directories.
|
||||
AC_MSG_CHECKING(if building in the top-level or dist directories)
|
||||
if [ test -d build_unix -o -d aclocal ] ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_MSG_ERROR(
|
||||
[DBSQL should not be built in the top-level or dist directories.])
|
||||
fi
|
||||
AC_MSG_RESULT(no)
|
||||
|
||||
# Substitution variables.
|
||||
AC_SUBST(ADDITIONAL_INCS)
|
||||
AC_SUBST(ADDITIONAL_LANG)
|
||||
AC_SUBST(ADDITIONAL_OBJS)
|
||||
AC_SUBST(ADDITIONAL_PROGS)
|
||||
AC_SUBST(BUILD_TARGET)
|
||||
AC_SUBST(CFLAGS)
|
||||
AC_SUBST(CONFIGURATION_ARGS)
|
||||
AC_SUBST(CONFIGURATION_PATH)
|
||||
AC_SUBST(CPPFLAGS)
|
||||
AC_SUBST(CXX)
|
||||
AC_SUBST(CXXFLAGS)
|
||||
AC_SUBST(DB_PATH)
|
||||
AC_SUBST(DB_UNIQUE_NAME)
|
||||
AC_SUBST(DEFAULT_LIB)
|
||||
AC_SUBST(DEFAULT_LIB_CXX)
|
||||
AC_SUBST(ENCODING)
|
||||
AC_SUBST(INSTALLER)
|
||||
AC_SUBST(INSTALL_LIBS)
|
||||
AC_SUBST(INSTALL_TARGET)
|
||||
AC_SUBST(LDFLAGS)
|
||||
AC_SUBST(LIBS)
|
||||
AC_SUBST(LIBSO_LIBS)
|
||||
AC_SUBST(LIBTOOL)
|
||||
AC_SUBST(LIBTSO_LIBS)
|
||||
AC_SUBST(LIBTSO_MODSUFFIX)
|
||||
AC_SUBST(LIBTSO_MODULE)
|
||||
AC_SUBST(LIBXSO_LIBS)
|
||||
AC_SUBST(LOAD_LIBS)
|
||||
AC_SUBST(MAKEFILE_CC)
|
||||
AC_SUBST(MAKEFILE_CCLINK)
|
||||
AC_SUBST(MAKEFILE_CXX)
|
||||
AC_SUBST(MAKEFILE_CXXLINK)
|
||||
AC_SUBST(MAKEFILE_SOLINK)
|
||||
AC_SUBST(MAKEFILE_XSOLINK)
|
||||
AC_SUBST(OSDIR)
|
||||
AC_SUBST(PATH_SEPARATOR)
|
||||
AC_SUBST(POSTLINK)
|
||||
AC_SUBST(REPLACEMENT_OBJS)
|
||||
AC_SUBST(RPC_CLIENT_OBJS)
|
||||
AC_SUBST(RPM_BUILD)
|
||||
AC_SUBST(RPM_POST_INSTALL)
|
||||
AC_SUBST(RPM_POST_UNINSTALL)
|
||||
AC_SUBST(SOFLAGS)
|
||||
AC_SUBST(o)
|
||||
|
||||
# RPM needs the current absolute path.
|
||||
# RPM needs the list of original arguments, but we don't include the RPM
|
||||
# option itself.
|
||||
CONFIGURATION_PATH=${PWD-`pwd`}
|
||||
CONFIGURATION_ARGS=`echo "$*" | sed -e 's/--with-rpm[[^ ]]*//'`
|
||||
|
||||
# Set the default installation location.
|
||||
AC_PREFIX_DEFAULT(/usr/local/DBSQL.__EDIT_DBSQL_VERSION_MAJOR__.__EDIT_DBSQL_VERSION_MINOR__)
|
||||
|
||||
# Configure the version information.
|
||||
AC_SUBST(DBSQL_VERSION_MAJOR)
|
||||
DBSQL_VERSION_MAJOR="__EDIT_DBSQL_VERSION_MAJOR__"
|
||||
AC_SUBST(DBSQL_VERSION_MINOR)
|
||||
DBSQL_VERSION_MINOR="__EDIT_DBSQL_VERSION_MINOR__"
|
||||
AC_SUBST(DBSQL_VERSION_PATCH)
|
||||
DBSQL_VERSION_PATCH="__EDIT_DBSQL_VERSION_PATCH__"
|
||||
AC_SUBST(DBSQL_VERSION_STRING)
|
||||
DBSQL_VERSION_STRING='"__EDIT_DBSQL_VERSION_STRING__"'
|
||||
AC_SUBST(DBSQL_VERSION_UNIQUE_NAME)
|
||||
|
||||
# Process all options before using them.
|
||||
AM_OPTIONS_SET
|
||||
|
||||
# Set some #defines based on configuration options.
|
||||
if test "$db_cv_diagnostic" = "yes"; then
|
||||
AC_DEFINE(DIAGNOSTIC)
|
||||
AH_TEMPLATE(DIAGNOSTIC,
|
||||
[Define to 1 if you want a version with run-time diagnostic checking.])
|
||||
fi
|
||||
if test "$db_cv_test" = "yes"; then
|
||||
AC_DEFINE(CONFIG_TEST)
|
||||
AH_TEMPLATE(CONFIG_TEST,
|
||||
[Define to 1 if you want to build a version for running the test suite.])
|
||||
fi
|
||||
|
||||
# Check for programs used in building and installation.
|
||||
AM_PROGRAMS_SET
|
||||
AC_PROG_INSTALL
|
||||
|
||||
# RPM support: change the standard make and install targets
|
||||
if test "$db_cv_rpm" = "yes"; then
|
||||
BUILD_TARGET="rpm_build"
|
||||
|
||||
# Check if we are running RPM version 3 or 4.
|
||||
case "`rpm --version`" in
|
||||
*version\ 4*)
|
||||
RPM_BUILD="rpmbuild"
|
||||
echo "_topdir $CONFIGURATION_PATH" > rpm-macro-defines;;
|
||||
*version\ 3*)
|
||||
RPM_BUILD="rpm"
|
||||
echo "topdir: $CONFIGURATION_PATH" > rpm-macro-defines;;
|
||||
esac
|
||||
INSTALL_TARGET="rpm_install"
|
||||
else
|
||||
BUILD_TARGET="library_build"
|
||||
INSTALL_TARGET="library_install"
|
||||
fi
|
||||
|
||||
# This is where we handle stuff that autoconf can't handle: compiler,
|
||||
# preprocessor and load flags, libraries that the standard tests don't
|
||||
# look for. The default optimization is -O. We would like to set the
|
||||
# default optimization for systems using gcc to -O2, but we can't. By
|
||||
# the time we know we're using gcc, it's too late to set optimization
|
||||
# flags.
|
||||
#
|
||||
# There are additional libraries we need for some compiler/architecture
|
||||
# combinations.
|
||||
#
|
||||
# Some architectures require DB to be compiled with special flags and/or
|
||||
# libraries for threaded applications
|
||||
#
|
||||
# The makefile CC may be different than the CC used in config testing,
|
||||
# because the makefile CC may be set to use $(LIBTOOL).
|
||||
#
|
||||
# XXX
|
||||
# Don't override anything if it's already set from the environment.
|
||||
optimize_def="-O"
|
||||
case "$host_os" in
|
||||
aix4.3.*|aix5*)
|
||||
optimize_def="-O2"
|
||||
CC=${CC-"xlc_r"}
|
||||
CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE"
|
||||
LDFLAGS="$LDFLAGS -Wl,-brtl";;
|
||||
bsdi3*) optimize_def="-O2"
|
||||
CC=${CC-"shlicc2"}
|
||||
LIBS="$LIBS -lipc";;
|
||||
bsdi*) optimize_def="-O2";;
|
||||
cygwin*)
|
||||
optimize_def="-O2"
|
||||
CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE -D_REENTRANT";;
|
||||
freebsd*)
|
||||
optimize_def="-O2"
|
||||
CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE"
|
||||
LDFLAGS="$LDFLAGS -pthread";;
|
||||
gnu*|k*bsd*-gnu|linux*)
|
||||
optimize_def="-O2"
|
||||
CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE -D_REENTRANT";;
|
||||
hpux*) CPPFLAGS="$CPPFLAGS -D_REENTRANT";;
|
||||
irix*) optimize_def="-O2"
|
||||
CPPFLAGS="$CPPFLAGS -D_SGI_MP_SOURCE";;
|
||||
mpeix*) CPPFLAGS="$CPPFLAGS -D_POSIX_SOURCE -D_SOCKET_SOURCE"
|
||||
LIBS="$LIBS -lsocket -lsvipc";;
|
||||
osf*) CPPFLAGS="$CPPFLAGS -pthread";;
|
||||
*qnx*) AC_DEFINE(HAVE_QNX)
|
||||
AH_TEMPLATE(HAVE_QNX, [Define to 1 if building on QNX.]);;
|
||||
solaris*)
|
||||
CPPFLAGS="$CPPFLAGS -D_REENTRANT";;
|
||||
esac
|
||||
|
||||
# Set CFLAGS/CXXFLAGS. We MUST set the flags before we call autoconf
|
||||
# compiler configuration macros, because if we don't, they set CFLAGS
|
||||
# to no optimization and -g, which isn't what we want.
|
||||
if test "$db_cv_debug" = "no"; then
|
||||
CFLAGS=${CFLAGS-$optimize_def}
|
||||
fi
|
||||
CXXFLAGS=${CXXFLAGS-"$CFLAGS"}
|
||||
|
||||
# If the user wants a TCL library interface setup for testing, add
|
||||
# -DCONFIG_TEST to the CFLAGS value.
|
||||
if test "$db_cv_test" = "yes"; then
|
||||
AC_DEFINE(CONFIG_TEST)
|
||||
AH_TEMPLATE(CONFIG_TEST,
|
||||
[Define to 1 if you want a TCL API with test support.])
|
||||
|
||||
CFLAGS="$CFLAGS -DCONFIG_TEST"
|
||||
CXXFLAGS="$CXXFLAGS -DCONFIG_TEST"
|
||||
db_cv_build_tcl_test_objs=TCL_TEST_OBJS
|
||||
else
|
||||
db_cv_build_tcl_test_objs=
|
||||
fi
|
||||
AC_SUBST(db_cv_build_tcl_test_objs)
|
||||
|
||||
|
||||
# If the user wants a debugging environment, add -g to the CFLAGS value.
|
||||
#
|
||||
# XXX
|
||||
# Some compilers can't mix optimizing and debug flags. The only way to
|
||||
# handle this is to specify CFLAGS in the environment before configuring.
|
||||
if test "$db_cv_debug" = "yes"; then
|
||||
AC_DEFINE(DEBUG)
|
||||
AH_TEMPLATE(DEBUG, [Define to 1 if you want a debugging version.])
|
||||
|
||||
CFLAGS="$CFLAGS -g"
|
||||
CXXFLAGS="$CXXFLAGS -g"
|
||||
db_cv_build_type=debug
|
||||
else
|
||||
db_cv_build_type=release
|
||||
fi
|
||||
AC_SUBST(db_cv_build_type)
|
||||
|
||||
# The default compiler is cc (NOT gcc), the default CFLAGS is as specified
|
||||
# above, NOT what is set by AC_PROG_CC, as it won't set optimization flags
|
||||
# for any compiler other than gcc.
|
||||
AC_PROG_CC(cc gcc)
|
||||
|
||||
# Checks for compiler characteristics.
|
||||
AC_SUBST(DB_PROTO1)
|
||||
AC_SUBST(DB_PROTO2)
|
||||
|
||||
# Clear __P, some other systems use it too.
|
||||
DB_PROTO1="#undef __P"
|
||||
if test "$ac_cv_prog_cc_c89" = "no"; then
|
||||
DB_PROTO2="#define __P(protos) ()"
|
||||
else
|
||||
DB_PROTO2="#define __P(protos) protos"
|
||||
fi
|
||||
|
||||
# Check for "const" and "inline" keywords.
|
||||
AC_C_CONST
|
||||
AC_SUBST(DB_CONST)
|
||||
if test "$ac_cv_c_const" != "yes"; then
|
||||
DB_CONST="#define const"
|
||||
fi
|
||||
AC_C_INLINE
|
||||
|
||||
# Because of shared library building, the ${CC} used for config tests
|
||||
# may be different than the ${CC} we want to put in the Makefile.
|
||||
# The latter is known as ${MAKEFILE_CC} in this script.
|
||||
MAKEFILE_CC="${CC}"
|
||||
MAKEFILE_CCLINK="${CC}"
|
||||
MAKEFILE_CXX="nocxx"
|
||||
MAKEFILE_CXXLINK="nocxx"
|
||||
|
||||
# See if we need the C++ compiler at all. If so, we'd like to find one that
|
||||
# interoperates with the C compiler we chose. Since we prefered cc over gcc,
|
||||
# we'll also prefer the vendor's compiler over g++/gcc. If we're wrong, the
|
||||
# user can set CC and CXX in their environment before running configure.
|
||||
#
|
||||
# AC_PROG_CXX sets CXX, but it uses $CXX and $CCC (in that order) as its
|
||||
# first choices.
|
||||
if test "$db_cv_cxx" = "yes"; then
|
||||
if test "$GCC" != "yes"; then
|
||||
case "$host_os" in
|
||||
aix*) AC_CHECK_TOOL(CCC, xlC_r)
|
||||
LIBXSO_LIBS="-lC_r $LIBXSO_LIBS"
|
||||
LIBS="-lC_r $LIBS";;
|
||||
hpux*) AC_CHECK_TOOL(CCC, aCC);;
|
||||
irix*) AC_CHECK_TOOL(CCC, CC);;
|
||||
osf*) AC_CHECK_TOOL(CCC, cxx);;
|
||||
solaris*) AC_CHECK_TOOL(CCC, CC);;
|
||||
esac
|
||||
fi
|
||||
AC_PROG_CXX
|
||||
###### WORKAROUND: SEE SR #7938
|
||||
AC_PROG_CXXCPP
|
||||
###############################
|
||||
AC_CXX_STDHEADERS
|
||||
MAKEFILE_CXX="${CXX}"
|
||||
MAKEFILE_CXXLINK="${CXX}"
|
||||
fi
|
||||
|
||||
# Do some gcc specific configuration.
|
||||
AC_GCC_CONFIG1
|
||||
|
||||
# We need the -Kthread/-pthread flag when compiling on SCO/Caldera's UnixWare
|
||||
# and OpenUNIX releases. We can't make the test until we know which compiler
|
||||
# we're using.
|
||||
case "$host_os" in
|
||||
sysv5UnixWare*|sysv5OpenUNIX8*)
|
||||
if test "$GCC" == "yes"; then
|
||||
CPPFLAGS="$CPPFLAGS -pthread"
|
||||
LDFLAGS="$LDFLAGS -pthread"
|
||||
else
|
||||
CPPFLAGS="$CPPFLAGS -Kthread"
|
||||
LDFLAGS="$LDFLAGS -Kthread"
|
||||
fi;;
|
||||
esac
|
||||
|
||||
# Export our compiler preferences for the libtool configuration.
|
||||
export CC CCC
|
||||
CCC=CXX
|
||||
|
||||
# Libtool configuration.
|
||||
LT_INIT
|
||||
AC_SUBST([LIBTOOL_DEPS])
|
||||
|
||||
SOFLAGS="-rpath \$(libdir)"
|
||||
LIBTOOL_PROG="${SHELL} ./libtool"
|
||||
|
||||
# Set SOSUFFIX and friends
|
||||
SOSUFFIX_CONFIG
|
||||
MODSUFFIX_CONFIG
|
||||
|
||||
INSTALLER="\$(LIBTOOL) --mode=install cp -p"
|
||||
|
||||
MAKEFILE_CC="\$(LIBTOOL) --mode=compile ${MAKEFILE_CC}"
|
||||
MAKEFILE_SOLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CCLINK} -avoid-version"
|
||||
MAKEFILE_CCLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CCLINK}"
|
||||
MAKEFILE_CXX="\$(LIBTOOL) --mode=compile ${MAKEFILE_CXX}"
|
||||
MAKEFILE_XSOLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CXXLINK} -avoid-version"
|
||||
MAKEFILE_CXXLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CXXLINK}"
|
||||
|
||||
LIBTOOL="\$(SHELL) ./libtool"
|
||||
|
||||
case "$host_os" in
|
||||
cygwin*)
|
||||
MAKEFILE_SOLINK="$MAKEFILE_SOLINK -no-undefined"
|
||||
MAKEFILE_XSOLINK="$MAKEFILE_XSOLINK -no-undefined";;
|
||||
esac
|
||||
|
||||
# Configure for shared libraries, static libraries, or both. If both are
|
||||
# configured, build the utilities and example programs with shared versions.
|
||||
#
|
||||
# $o is set to ".o" or ".lo", and is the file suffix used in the Makefile
|
||||
# instead of .o
|
||||
if test `$LIBTOOL_PROG --config |
|
||||
grep build_libtool_libs | grep no` 2>/dev/null; then
|
||||
enable_shared="no"
|
||||
else
|
||||
enable_shared="yes"
|
||||
fi
|
||||
if test `$LIBTOOL_PROG --config |
|
||||
grep build_old_libs | grep no` 2>/dev/null; then
|
||||
enable_static="no"
|
||||
else
|
||||
enable_static="yes"
|
||||
fi
|
||||
|
||||
# C API.
|
||||
if test "$enable_shared" = "no"; then
|
||||
DEFAULT_LIB="\$(libdb_version)"
|
||||
POSTLINK=": "
|
||||
o=".o"
|
||||
else
|
||||
DEFAULT_LIB="\$(libso_target)"
|
||||
POSTLINK="\$(LIBTOOL) --mode=execute true"
|
||||
o=".lo"
|
||||
fi
|
||||
INSTALL_LIBS="$DEFAULT_LIB"
|
||||
if test "$enable_static" = "yes"; then
|
||||
INSTALL_LIBS="$INSTALL_LIBS \$(libdb)"
|
||||
fi
|
||||
|
||||
# Optional C++ API.
|
||||
if test "$db_cv_cxx" = "yes"; then
|
||||
if test "$enable_shared" = "no"; then
|
||||
DEFAULT_LIB_CXX="\$(libcxx_version)"
|
||||
fi
|
||||
if test "$enable_shared" = "yes"; then
|
||||
DEFAULT_LIB_CXX="\$(libxso_target)"
|
||||
fi
|
||||
INSTALL_LIBS="$INSTALL_LIBS $DEFAULT_LIB_CXX"
|
||||
if test "$enable_static" = "yes"; then
|
||||
INSTALL_LIBS="$INSTALL_LIBS \$(libcxx)"
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl # Optional Java API. TODO
|
||||
|
||||
# MinGW support.
|
||||
if test "$db_cv_mingw" = "yes"; then
|
||||
OSDIR=os_win32
|
||||
PATH_SEPARATOR="\\\\/:"
|
||||
|
||||
AC_DEFINE(DBSQL_WIN32)
|
||||
AC_DEFINE(STDC_HEADERS)
|
||||
else
|
||||
OSDIR=os
|
||||
PATH_SEPARATOR="/"
|
||||
fi
|
||||
|
||||
# Apple's Mac OS/X had to rename shared libraries, so much for standards.
|
||||
case "$host_os" in
|
||||
darwin*)
|
||||
LIBTSO_MODULE=""
|
||||
LIBTSO_MODSUFFIX=".dylib"
|
||||
;;
|
||||
*)
|
||||
LIBTSO_MODULE="-module"
|
||||
LIBTSO_MODSUFFIX=@MODSUFFIX@
|
||||
;;
|
||||
esac
|
||||
|
||||
AM_TCL_LOAD
|
||||
|
||||
# You can disable pieces of functionality to save space.
|
||||
|
||||
# The stat code.
|
||||
if test "$db_cv_build_statistics" = "yes"; then
|
||||
AC_DEFINE(HAVE_STATISTICS)
|
||||
AH_TEMPLATE(HAVE_STATISTICS,
|
||||
[Define to 1 if building statistics support.])
|
||||
fi
|
||||
|
||||
# Checks for include files, structures, C types.
|
||||
AC_HEADER_STAT
|
||||
AC_CHECK_HEADERS_ONCE([sys/time.h])
|
||||
# End of obsolete code.
|
||||
|
||||
AC_HEADER_DIRENT
|
||||
AC_CHECK_HEADERS(sys/select.h sys/time.h sys/fcntl.h)
|
||||
AC_CHECK_MEMBERS([struct stat.st_blksize])
|
||||
AM_TYPES
|
||||
|
||||
AC_CACHE_CHECK([for ANSI C exit success/failure values], db_cv_exit_defines, [
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
|
||||
[[#include <stdlib.h>]],
|
||||
[[return (EXIT_SUCCESS);]])],
|
||||
[db_cv_exit_defines=yes],[db_cv_exit_defines=no])])
|
||||
if test "$db_cv_exit_defines" = "yes"; then
|
||||
AC_DEFINE(HAVE_EXIT_SUCCESS)
|
||||
AH_TEMPLATE(HAVE_EXIT_SUCCESS,
|
||||
[Define to 1 if you have EXIT_SUCCESS/EXIT_FAILURE #defines.])
|
||||
fi
|
||||
|
||||
# Test for various functions/libraries that the test and example programs use:
|
||||
# sched_yield function
|
||||
# pthreads, socket and math libraries
|
||||
AC_CHECK_FUNC(sched_yield,,
|
||||
AC_SEARCH_LIBS(sched_yield, rt, LOAD_LIBS="$LOAD_LIBS -lrt"))
|
||||
|
||||
# XXX
|
||||
# We can't check for pthreads in the same way we did the test for sched_yield
|
||||
# because the Solaris C library includes pthread interfaces which are not
|
||||
# thread-safe. For that reason we always add -lpthread if we find a pthread
|
||||
# library. Also we can't depend on any specific call existing (pthread_create,
|
||||
# for example), as it may be #defined in an include file -- OSF/1 (Tru64) has
|
||||
# this problem.
|
||||
AC_CHECK_LIB([pthread],[main],[LOAD_LIBS="$LOAD_LIBS -lpthread"],[],[])ac_cv_lib_pthread=ac_cv_lib_pthread_main
|
||||
|
||||
|
||||
# We use sqrt() so we need the math library -lm
|
||||
AC_CHECK_LIB([m],[main],[LIBS="$LIBS -lm"],[],[])ac_cv_lib_m=ac_cv_lib_m_main
|
||||
|
||||
|
||||
# Checks for system functions for which we have replacements.
|
||||
AC_REPLACE_FUNCS(getopt memcmp memcpy memmove strdup strndup strerror)
|
||||
AC_REPLACE_FUNCS(snprintf localtime_r strcasecmp strncasecmp)
|
||||
AC_REPLACE_FUNCS(srand48_r lrand48_r)
|
||||
|
||||
# Check for system functions we use.
|
||||
AC_CHECK_FUNCS(usleep)
|
||||
|
||||
# A/UX has a broken getopt(3).
|
||||
case "$host_os" in
|
||||
aux*) AC_LIBOBJ([getopt]);;
|
||||
esac
|
||||
|
||||
# Apple's Mac OS/X complains about long doubles, make it stop.
|
||||
case "$host_os" in
|
||||
darwin*)
|
||||
CFLAGS="$CFLAGS -Wno-long-double -no-cpp-precomp"
|
||||
;;
|
||||
esac
|
||||
|
||||
# We need to add the additional object files into the Makefile with the correct
|
||||
# suffix. We can't use $LTLIBOBJS itself, because that variable has $U encoded
|
||||
# in it for automake, and that's not what we want.
|
||||
REPLACEMENT_OBJS=`echo "$LIB@&t@OBJS" |
|
||||
sed "s,\.[[^.]]* ,$o ,g;s,\.[[^.]]*$,$o,"`
|
||||
|
||||
# This is necessary so that .o files in LIBOBJS are also built via
|
||||
# the ANSI2KNR-filtering rules.
|
||||
LIB@&t@OBJS=`echo "$LIB@&t@OBJS" |
|
||||
sed 's,\.[[^.]]* ,$U&,g;s,\.[[^.]]*$,$U&,'`
|
||||
LTLIBOBJS=`echo "$LIB@&t@OBJS" |
|
||||
sed 's,\.[[^.]]* ,.lo ,g;s,\.[[^.]]*$,.lo,'`
|
||||
AC_SUBST(LTLIBOBJS)
|
||||
|
||||
# Initial output file list.
|
||||
CREATE_LIST="Makefile
|
||||
dbsql_int.h:$srcdir/../src/inc/dbsql_int.in
|
||||
$srcdir/../src/py/setup.py:$srcdir/../src/py/setup.py.in
|
||||
$srcdir/../test/scr050/Makefile:$srcdir/../test/scr050/Makefile.in"
|
||||
|
||||
# MinGW needs win_db.h.
|
||||
if test "$db_cv_mingw" = "yes"; then
|
||||
CREATE_LIST="$CREATE_LIST
|
||||
win_db.h:$srcdir/win_dbsql.in"
|
||||
fi
|
||||
|
||||
# Create the dbsql.h file from a source file and a list of global function
|
||||
# prototypes.
|
||||
CREATE_LIST="$CREATE_LIST
|
||||
dbsql.h:$srcdir/../src/dbsql.in"
|
||||
|
||||
if test "$db_cv_rpm" = "yes"; then
|
||||
CREATE_LIST="$CREATE_LIST db.spec:../dist/dbsql.spec.in"
|
||||
fi
|
||||
|
||||
AC_CONFIG_FILES($CREATE_LIST)
|
||||
AC_OUTPUT
|
31
dist/dbsql.pc.in
vendored
Normal file
31
dist/dbsql.pc.in
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
# DBSQL - A SQL database engine.
|
||||
#
|
||||
# Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# There are special exceptions to the terms and conditions of the GPL as it
|
||||
# is applied to this software. View the full text of the exception in file
|
||||
# LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
|
||||
# Package Information for pkg-config
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: dbsql
|
||||
Description: A SQL database engine.
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -ldbsql -ldb
|
||||
Cflags: -I${includedir}
|
53
dist/dbsql.spec.in
vendored
Normal file
53
dist/dbsql.spec.in
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
# DBSQL - A SQL database engine.
|
||||
#
|
||||
# Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# There are special exceptions to the terms and conditions of the GPL as it
|
||||
# is applied to this software. View the full text of the exception in file
|
||||
# LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# DBSQL @DBSQL_VERSION_MAJOR@.@DBSQL_VERSION_MINOR@.@DBSQL_VERSION_PATCH@
|
||||
|
||||
Summary: DBSQL - A SQL database library.
|
||||
Name: dbsql
|
||||
Version: @DBSQL_VERSION_MAJOR@.@DBSQL_VERSION_MINOR@.@DBSQL_VERSION_PATCH@
|
||||
Release: 1
|
||||
Copyright: GPL - Freely redistributable, see LICENSE for details.
|
||||
Source: http://www.dbsql.org/update/@DBSQL_VERSION_MAJOR@.@DBSQL_VERSION_MINOR@.@DBSQL_VERSION_PATCH@/dbsql-@DBSQL_VERSION_MAJOR@.@DBSQL_VERSION_MINOR@.@DBSQL_VERSION_PATCH@.tar.gz
|
||||
URL: http://www.dbsql.org
|
||||
Group: System Environment/Libraries
|
||||
BuildRoot: @CONFIGURATION_PATH@/RPM_INSTALL
|
||||
|
||||
%define _unpackaged_files_terminate_build 0
|
||||
|
||||
%description
|
||||
DBSQL is a programmatic toolkit that provides fast, scalable and
|
||||
reliable SQL implementation.
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
cd build_unix
|
||||
CFLAGS="$RPM_OPT_FLAGS" ../dist/configure @CONFIGURATION_ARGS@
|
||||
make library_build
|
||||
|
||||
%install
|
||||
cd build_unix
|
||||
make prefix=@CONFIGURATION_PATH@/RPM_INSTALL install
|
||||
|
||||
@RPM_POST_INSTALL@
|
||||
|
||||
@RPM_POST_UNINSTALL@
|
||||
|
||||
%changelog
|
39
dist/dot-gdbinit
vendored
Normal file
39
dist/dot-gdbinit
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
break __db_loadme
|
||||
break __db_err
|
||||
define dd
|
||||
print __db_dump(dbp, "a", "/tmp/o")
|
||||
end
|
||||
define dc
|
||||
print __db_dump(dbc->dbp, "a", "/tmp/o")
|
||||
end
|
||||
break __sm_create
|
||||
break __sm_create_table
|
||||
break __sm_create_index
|
||||
break __sm_close_db
|
||||
break __sm_checkpoint
|
||||
break __sm_get_database_name
|
||||
break __sm_begin_txn
|
||||
break __sm_commit_txn
|
||||
break __sm_abort_txn
|
||||
break __sm_cursor
|
||||
break __sm_close_cursor
|
||||
break __sm_moveto
|
||||
break __sm_next
|
||||
break __sm_prev
|
||||
break __sm_key_size
|
||||
break __sm_data_size
|
||||
break __sm_key_compare
|
||||
break __sm_key
|
||||
break __sm_data
|
||||
break __sm_first
|
||||
break __sm_last
|
||||
break __sm_insert
|
||||
break __sm_delete
|
||||
break __sm_drop_table
|
||||
break __sm_clear_table
|
||||
break __sm_set_format_version
|
||||
break __sm_get_format_version
|
||||
break __sm_set_schema_sig
|
||||
break __sm_get_schema_sig
|
||||
break process_input
|
||||
break __process_sql
|
80
dist/gen_inc.awk
vendored
Normal file
80
dist/gen_inc.awk
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
# DBSQL - A SQL database engine.
|
||||
#
|
||||
# Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# There are special exceptions to the terms and conditions of the GPL as it
|
||||
# is applied to this software. View the full text of the exception in file
|
||||
# LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
#
|
||||
# This library 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.
|
||||
|
||||
# This awk script parses C input files looking for lines marked "PUBLIC:"
|
||||
# and "EXTERN:". (PUBLIC lines are DB internal function prototypes and
|
||||
# #defines, EXTERN are DB external function prototypes and #defines.)
|
||||
#
|
||||
# PUBLIC lines are put into two versions of per-directory include files:
|
||||
# one file that contains the prototypes, and one file that contains a
|
||||
# #define for the name to be processed during configuration when creating
|
||||
# unique names for every global symbol in the DB library.
|
||||
#
|
||||
# The EXTERN lines are put into two files: one of which contains prototypes
|
||||
# which are always appended to the db.h file, and one of which contains a
|
||||
# #define list for use when creating unique symbol names.
|
||||
#
|
||||
# Four arguments:
|
||||
# e_dfile list of EXTERN #defines
|
||||
# e_pfile include file that contains EXTERN prototypes
|
||||
# i_dfile list of internal (PUBLIC) #defines
|
||||
# i_pfile include file that contains internal (PUBLIC) prototypes
|
||||
# i_sfile include file that contains internal (STATIC) prototypes
|
||||
/PUBLIC:/ {
|
||||
sub("^.*PUBLIC:[ ][ ]*", "")
|
||||
if ($0 ~ "^#if|^#ifdef|^#ifndef|^#else|^#endif") {
|
||||
print $0 >> i_pfile
|
||||
print $0 >> i_dfile
|
||||
next
|
||||
}
|
||||
pline = sprintf("%s %s", pline, $0)
|
||||
if (pline ~ "\\)\\);") {
|
||||
sub("^[ ]*", "", pline)
|
||||
print pline >> i_pfile
|
||||
pline = ""
|
||||
}
|
||||
}
|
||||
|
||||
/STATIC:/ {
|
||||
sub("^.*STATIC:[ ][ ]*", "")
|
||||
if ($0 ~ "^#if|^#ifdef|^#ifndef|^#else|^#endif") {
|
||||
print $0 >> i_sfile
|
||||
next
|
||||
}
|
||||
sline = sprintf("%s %s", sline, $0)
|
||||
if (sline ~ "\\)\\);") {
|
||||
sub("^[ ]*", "", sline)
|
||||
print sline >> i_sfile
|
||||
sline = ""
|
||||
}
|
||||
}
|
||||
|
||||
/EXTERN:/ {
|
||||
sub("^.*EXTERN:[ ][ ]*", "")
|
||||
if ($0 ~ "^#if|^#ifdef|^#ifndef|^#else|^#endif") {
|
||||
print $0 >> e_pfile
|
||||
print $0 >> e_dfile
|
||||
next
|
||||
}
|
||||
eline = sprintf("%s %s", eline, $0)
|
||||
if (eline ~ "\\)\\);") {
|
||||
sub("^[ ]*", "", eline)
|
||||
print eline >> e_pfile
|
||||
eline = ""
|
||||
}
|
||||
}
|
541
dist/install-sh
vendored
Executable file
541
dist/install-sh
vendored
Executable file
|
@ -0,0 +1,541 @@
|
|||
#!/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:
|
11436
dist/ltmain.sh
vendored
Normal file
11436
dist/ltmain.sh
vendored
Normal file
File diff suppressed because it is too large
Load diff
0
dist/pubdef.in
vendored
Normal file
0
dist/pubdef.in
vendored
Normal file
29
dist/s_all
vendored
Executable file
29
dist/s_all
vendored
Executable file
|
@ -0,0 +1,29 @@
|
|||
#!/bin/sh -
|
||||
# DBSQL - A SQL database engine.
|
||||
#
|
||||
# Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# There are special exceptions to the terms and conditions of the GPL as it
|
||||
# is applied to this software. View the full text of the exception in file
|
||||
# LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
#
|
||||
# This library 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.
|
||||
|
||||
sh s_perm # permissions.
|
||||
sh s_symlink # symbolic links.
|
||||
sh s_readme # distribution README file.
|
||||
|
||||
#
|
||||
# The following order is important, s_include must run last.
|
||||
#
|
||||
sh s_config # autoconf.
|
||||
sh s_include # standard include files.
|
||||
sh s_tags # Tags files.
|
50
dist/s_config
vendored
Executable file
50
dist/s_config
vendored
Executable file
|
@ -0,0 +1,50 @@
|
|||
#!/bin/sh -x
|
||||
# DBSQL - A SQL database engine.
|
||||
#
|
||||
# Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# There are special exceptions to the terms and conditions of the GPL as it
|
||||
# is applied to this software. View the full text of the exception in file
|
||||
# LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# Build the autoconfiguration files.
|
||||
|
||||
trap 'rm -f aclocal.m4 ; exit 0' 0 1 2 3 13 15
|
||||
|
||||
. ./RELEASE
|
||||
|
||||
echo "autoconf: building aclocal.m4..."
|
||||
cat aclocal/*.m4 > aclocal.m4
|
||||
|
||||
echo "autoconf: running autoheader to build config.hin..."
|
||||
rm -f config.hin
|
||||
autoheader --warnings=all
|
||||
chmod 444 config.hin
|
||||
|
||||
echo "autoconf: running autoconf to build configure"
|
||||
rm -f configure
|
||||
autoconf
|
||||
|
||||
# Edit version information we couldn't pre-compute.
|
||||
(echo "1,\$s/__EDIT_DBSQL_VERSION_MAJOR__/$DBSQL_VERSION_MAJOR/g" &&
|
||||
echo "1,\$s/__EDIT_DBSQL_VERSION_MINOR__/$DBSQL_VERSION_MINOR/g" &&
|
||||
echo "1,\$s/__EDIT_DBSQL_VERSION_PATCH__/$DBSQL_VERSION_PATCH/g" &&
|
||||
echo "1,\$s/__EDIT_DBSQL_VERSION_STRING__/$DBSQL_VERSION_STRING/g" &&
|
||||
echo "1,\$s/__EDIT_DBSQL_VERSION__/$DBSQL_VERSION/g" &&
|
||||
echo "w" &&
|
||||
echo "q") | ed -s configure
|
||||
|
||||
rm -rf autom4te.cache
|
||||
chmod 555 configure
|
||||
|
||||
chmod 555 config.guess config.sub install-sh
|
111
dist/s_include
vendored
Executable file
111
dist/s_include
vendored
Executable file
|
@ -0,0 +1,111 @@
|
|||
#!/bin/sh -
|
||||
# DBSQL - A SQL database engine.
|
||||
#
|
||||
# Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# There are special exceptions to the terms and conditions of the GPL as it
|
||||
# is applied to this software. View the full text of the exception in file
|
||||
# LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# Build the automatically generated function prototype files.
|
||||
|
||||
msgc="/* DO NOT EDIT: automatically built by dist/s_include. */"
|
||||
|
||||
head()
|
||||
{
|
||||
defonly=0
|
||||
while :
|
||||
do case "$1" in
|
||||
space)
|
||||
echo ""; shift;;
|
||||
defonly)
|
||||
defonly=1; shift;;
|
||||
*)
|
||||
name="$1"; break;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "$msgc"
|
||||
echo "#ifndef $name"
|
||||
echo "#define $name"
|
||||
echo ""
|
||||
if [ $defonly -eq 0 ]; then
|
||||
echo "#if defined(__cplusplus)"
|
||||
echo "extern \"C\" {"
|
||||
echo "#endif"
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
tail()
|
||||
{
|
||||
defonly=0
|
||||
while :
|
||||
do case "$1" in
|
||||
defonly)
|
||||
defonly=1; shift;;
|
||||
*)
|
||||
name="$1"; break;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo ""
|
||||
if [ $defonly -eq 0 ]; then
|
||||
echo "#if defined(__cplusplus)"
|
||||
echo "}"
|
||||
echo "#endif"
|
||||
fi
|
||||
echo "#endif /* !$name */"
|
||||
}
|
||||
|
||||
# We are building several files:
|
||||
# 1 external #define file
|
||||
# 1 external prototype file
|
||||
# 1 internal #define file
|
||||
# N internal prototype files
|
||||
e_dfile=/tmp/__db_c.$$
|
||||
e_pfile=/tmp/__db_a.$$
|
||||
i_dfile=/tmp/__db_d.$$
|
||||
i_pfile=/tmp/__db_b.$$
|
||||
i_sfile=/tmp/__db_e.$$
|
||||
trap 'rm -f $e_dfile $e_pfile $i_dfile $i_pfile $i_sfile; exit 0' 0 1 2 3 13 15
|
||||
|
||||
head defonly space _DBSQL_EXT_DEF_IN_ > $e_dfile
|
||||
head space _DBSQL_EXT_PROT_IN_ > $e_pfile
|
||||
head defonly _DBSQL_INT_DEF_IN_ > $i_dfile
|
||||
|
||||
# Process the standard directories, creating per-directory prototype
|
||||
# files and adding to the external prototype and #define files.
|
||||
for pkg in dbsql os clib common ; do
|
||||
head "_${pkg}_ext_h_" > $i_pfile
|
||||
cfiles="../src/${pkg}/*.c"
|
||||
[ "$cfiles" = "../src/dbsql/*.c" ] && cfiles="../src/*.c"
|
||||
for file in $(ls $cfiles); do
|
||||
fname="$(echo $file | sed -n 's/^\(.*\/\)*\([^.]*\)\(.*\)/\2/p')"
|
||||
head "_${fname}_decl_h_" > $i_sfile
|
||||
awk -f gen_inc.awk \
|
||||
-v e_dfile=$e_dfile \
|
||||
-v e_pfile=$e_pfile \
|
||||
-v i_dfile=$i_dfile \
|
||||
-v i_pfile=$i_pfile \
|
||||
-v i_sfile=$i_sfile $file
|
||||
tail "_${fname}_decl_h_" >> $i_sfile
|
||||
decl="../src/inc/${fname}_decl.h"
|
||||
# cmp $i_sfile $decl > /dev/null 2>&1 ||
|
||||
# (echo "Building $decl" && rm -f $decl && cp $i_sfile $decl && chmod 444 $decl)
|
||||
done
|
||||
tail "_${pkg}_ext_h_" >> $i_pfile
|
||||
ext="../src/inc/${pkg}_ext.h"
|
||||
cmp $i_pfile $ext > /dev/null 2>&1 ||
|
||||
(echo "Building $ext" && rm -f $ext && cp $i_pfile $ext && chmod 444 $ext)
|
||||
done
|
45
dist/s_perm
vendored
Executable file
45
dist/s_perm
vendored
Executable file
|
@ -0,0 +1,45 @@
|
|||
#!/bin/sh -
|
||||
# DBSQL - A SQL database engine.
|
||||
#
|
||||
# Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# There are special exceptions to the terms and conditions of the GPL as it
|
||||
# is applied to this software. View the full text of the exception in file
|
||||
# LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
#
|
||||
# This library 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.
|
||||
|
||||
d=..
|
||||
echo 'Updating DBSQL source tree permissions...'
|
||||
|
||||
run()
|
||||
{
|
||||
#echo " $1 ($2)"
|
||||
if [ -f "$d/$1" ]; then
|
||||
chmod "$2" "$d/$1"
|
||||
else
|
||||
echo "$d/$1: no such file or directory"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
run dist/config.guess 555
|
||||
run dist/config.sub 555
|
||||
run dist/configure 555
|
||||
run dist/install-sh 555
|
||||
run dist/s_all 555
|
||||
run dist/s_config 555
|
||||
run dist/s_include 555
|
||||
run dist/s_perm 555
|
||||
run dist/s_readme 555
|
||||
run dist/s_symlink 555
|
||||
run dist/s_tags 555
|
||||
run dist/s_test 555
|
82
dist/s_readme
vendored
Executable file
82
dist/s_readme
vendored
Executable file
|
@ -0,0 +1,82 @@
|
|||
#!/bin/sh -
|
||||
# DBSQL - A SQL database engine.
|
||||
#
|
||||
# Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# There are special exceptions to the terms and conditions of the GPL as it
|
||||
# is applied to this software. View the full text of the exception in file
|
||||
# LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# Build the README.
|
||||
|
||||
echo 'Updating DBSQL README file...'
|
||||
|
||||
d=..
|
||||
|
||||
t=/tmp/__t
|
||||
trap 'rm -f $t; exit 0' 0 1 2 3 13 15
|
||||
|
||||
. ./RELEASE
|
||||
|
||||
cat << END_OF_README>$t
|
||||
$DBSQL_VERSION_STRING
|
||||
|
||||
This is version $DBSQL_VERSION_MAJOR.$DBSQL_VERSION_MINOR.$DBSQL_VERSION_PATCH of DBSQL.
|
||||
|
||||
To view the release and installation documentation, load the distribution
|
||||
file docs/index.html into your web browser.
|
||||
|
||||
This work started from the SQLite project (found on the web at
|
||||
http://www.sqlite.org/). SQLite and all contributions to the SQLite
|
||||
project have been placed in the public domain by its author, Dr. Richard Hipp.
|
||||
There was no assertion of copyright at all on the code I used as a starting
|
||||
point for my work. In fact there are statements that explicitly disclaim
|
||||
copyright. I am asserting copyright on this work, DBSQL. I believe
|
||||
that if you examine the extent to which I've changed, updated, and
|
||||
modified the SQLite code you'll respect my copyright assertion. This
|
||||
is a new product, heavily inspired by another.
|
||||
|
||||
The goal for DBSQL is to provide a small SQL92 relational database layer
|
||||
on top of the Berkeley DB database. Berkeley DB is copyright Oracle
|
||||
Corporation (formerly Sleepycat Software, acquired in Feb 2006) and
|
||||
licensed under the Sleepycat Public License. That license is compatible
|
||||
with the GPL for open source use. Recognize that you, as someone using
|
||||
DBSQL, will need to review the Sleepycat License and the GPL before you
|
||||
use and redistribute your incorporating work. It is your responsibility
|
||||
to comply with those licenses as I am in my work on DBSQL itself. My
|
||||
motivation on a personal level is quite simple, I am in product management
|
||||
these days and not in the code itself. I believe that product managers
|
||||
should be engineers at heart with an ability to understand business,
|
||||
politics, and software sales and support. This is my playground to keep
|
||||
my engineering skills sharp enough to speak fluent geek. As a former
|
||||
engineer at Sleepycat I understand and value the Berkeley DB programming
|
||||
infrasture, design, and methodologies and I have liberally copied and
|
||||
reused them in this project to improve SQLite in ways that I hope will
|
||||
be of value to open source users out there. I did this because I see the
|
||||
value of SQLite to its userbase, it is a perfect example of the 80/20
|
||||
rule and the KISS method and I admire those qualities in software. My
|
||||
hope is that the Berkeley DB database engine will provide some significant
|
||||
features that SQLite cannot such as replication for high availability
|
||||
while remaining small enough to live comfortably inside applications,
|
||||
services, and devices.
|
||||
|
||||
Information and resources pertaining to DBSQL can be found at dbsql.org.
|
||||
|
||||
Commercial licenses without the restrictions found in the GPL can be
|
||||
purchased for this product. See http://dbsql.org/wiki/CommercialUse
|
||||
|
||||
END_OF_README
|
||||
|
||||
f=../README
|
||||
cmp $t $f > /dev/null 2>&1 ||
|
||||
(echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
|
40
dist/s_symlink
vendored
Executable file
40
dist/s_symlink
vendored
Executable file
|
@ -0,0 +1,40 @@
|
|||
#!/bin/sh -
|
||||
# DBSQL - A SQL database engine.
|
||||
#
|
||||
# Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# There are special exceptions to the terms and conditions of the GPL as it
|
||||
# is applied to this software. View the full text of the exception in file
|
||||
# LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
#
|
||||
# This library 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.
|
||||
|
||||
echo 'Creating DBSQL source tree symbolic links...'
|
||||
|
||||
build()
|
||||
{
|
||||
#echo " $1 -> $2"
|
||||
(cd ../`dirname $1` && rm -f `basename $1` && ln -s $2 `basename $1`)
|
||||
}
|
||||
|
||||
build src/tags ../dist/tags
|
||||
build src/os/tags ../../dist/tags
|
||||
build src/clib/tags ../../dist/tags
|
||||
build src/py/tags ../../dist/tags
|
||||
build test/scr050/tags ../../dist/tags
|
||||
build build_unix/tags ../dist/tags
|
||||
|
||||
build src/TAGS ../dist/TAGS
|
||||
build src/os/TAGS ../../dist/TAGS
|
||||
build src/clib/TAGS ../../dist/TAGS
|
||||
build src/py/TAGS ../../dist/TAGS
|
||||
build test/scr050/TAGS ../../dist/tags
|
||||
build build_unix/TAGS ../dist/TAGS
|
48
dist/s_tags
vendored
Executable file
48
dist/s_tags
vendored
Executable file
|
@ -0,0 +1,48 @@
|
|||
#!/bin/sh -
|
||||
# DBSQL - A SQL database engine.
|
||||
#
|
||||
# Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# There are special exceptions to the terms and conditions of the GPL as it
|
||||
# is applied to this software. View the full text of the exception in file
|
||||
# LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# Build tags files.
|
||||
|
||||
files=`echo ../src/*.[ch] \
|
||||
../src/inc/*.h \
|
||||
../src/os/*.[ch] \
|
||||
../src/py/*.[ch] \
|
||||
../test/scr050/*.[ch]`
|
||||
|
||||
f=tags
|
||||
echo "Building $f"
|
||||
rm -f $f
|
||||
|
||||
# Figure out what flags this ctags accepts.
|
||||
flags=""
|
||||
if ctags -d ../src/api.c 2>/dev/null; then
|
||||
flags="-d $flags"
|
||||
fi
|
||||
if ctags -t ../src/api.c 2>/dev/null; then
|
||||
flags="-t $flags"
|
||||
fi
|
||||
if ctags -w ../src/api.c 2>/dev/null; then
|
||||
flags="-w $flags"
|
||||
fi
|
||||
|
||||
ctags $flags $files 2>/dev/null
|
||||
chmod 444 $f
|
||||
|
||||
etags $files -o TAGS 2>/dev/null
|
||||
chmod 444 $f
|
104
dist/s_test
vendored
Executable file
104
dist/s_test
vendored
Executable file
|
@ -0,0 +1,104 @@
|
|||
#!/bin/sh -
|
||||
# DBSQL - A SQL database engine.
|
||||
#
|
||||
# Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# There are special exceptions to the terms and conditions of the GPL as it
|
||||
# is applied to this software. View the full text of the exception in file
|
||||
# LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# Build the Tcl test files.
|
||||
|
||||
msg1="# Automatically built by dist/s_test; may require local editing."
|
||||
msg2="# Automatically built by dist/s_test; may require local editing."
|
||||
|
||||
t=/tmp/__t
|
||||
trap 'rm -f $t; exit 0' 0 1 2 3 13 15
|
||||
|
||||
. RELEASE
|
||||
|
||||
(echo "$msg1" && \
|
||||
echo "" && \
|
||||
echo "set tclsh_path @TCL_TCLSH@" && \
|
||||
echo "set tcllib .libs/libdbsql_tcl-@DBSQL_VERSION_MAJOR@.@DBSQL_VERSION_MINOR@@LIBTSO_MODSUFFIX@" && \
|
||||
echo "" && \
|
||||
echo "set src_root @srcdir@/.." && \
|
||||
echo "set test_path @srcdir@/../test" && \
|
||||
echo "" && \
|
||||
echo "global testdir" && \
|
||||
echo "set testdir ./TESTDIR" && \
|
||||
echo "" && \
|
||||
echo "global dict" && \
|
||||
echo "global util_path" && \
|
||||
echo "" && \
|
||||
echo "global is_hp_test" && \
|
||||
echo "global is_qnx_test" && \
|
||||
echo "global is_windows_test" && \
|
||||
echo "" && \
|
||||
echo "set KILL \"@db_cv_path_kill@\"") > $t
|
||||
|
||||
f=../test/include.tcl
|
||||
cmp $t $f > /dev/null 2>&1 ||
|
||||
(echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
|
||||
|
||||
(echo "$msg1" && \
|
||||
echo "" && \
|
||||
echo "set tclsh_path SET_YOUR_TCLSH_PATH" && \
|
||||
echo "set tcllib ./Debug/libdbsql_tcl${DBSQL_VERSION_MAJOR}${DBSQL_VERSION_MINOR}d.dll" && \
|
||||
echo "" && \
|
||||
echo "set src_root .." && \
|
||||
echo "set test_path ../test" && \
|
||||
echo "" && \
|
||||
echo "global testdir" && \
|
||||
echo "set testdir ./TESTDIR" && \
|
||||
echo "" && \
|
||||
echo "global dict" && \
|
||||
echo "global util_path" && \
|
||||
echo "" && \
|
||||
echo "global is_hp_test" && \
|
||||
echo "global is_qnx_test" && \
|
||||
echo "global is_windows_test" && \
|
||||
echo "" && \
|
||||
echo "set KILL ./dbkill.exe") > $t
|
||||
|
||||
f=../build_win32/include.tcl
|
||||
cmp $t $f > /dev/null 2>&1 ||
|
||||
(echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
|
||||
|
||||
# Build the test directory TESTS file.
|
||||
(echo $msg2;
|
||||
cat `egrep -l '^#[ ][ ]*TEST' ../test/*.tcl` |
|
||||
sed -e '/^#[ ][ ]*TEST/!{' \
|
||||
-e 's/.*//' \
|
||||
-e '}' |
|
||||
cat -s |
|
||||
sed -e '/TEST/{' \
|
||||
-e 's/^#[ ][ ]*TEST[ ]*//' \
|
||||
-e 's/^ //' \
|
||||
-e 'H' \
|
||||
-e 'd' \
|
||||
-e '}' \
|
||||
-e 's/.*//' \
|
||||
-e x \
|
||||
-e 's/\n/__LINEBREAK__/g' |
|
||||
sort |
|
||||
sed -e 's/__LINEBREAK__/\
|
||||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\
|
||||
/' \
|
||||
-e 's/__LINEBREAK__/\
|
||||
/g' |
|
||||
sed -e 's/^[ ][ ]*$//') > $t
|
||||
|
||||
f=../test/TESTS
|
||||
cmp $t $f > /dev/null 2>&1 ||
|
||||
(echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
|
5
dist/splint.rc
vendored
Normal file
5
dist/splint.rc
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
-namechecks
|
||||
+posixstrictlib
|
||||
+showallconjs
|
||||
+showscan
|
||||
+stats
|
74
dist/sqlconf
vendored
Executable file
74
dist/sqlconf
vendored
Executable file
|
@ -0,0 +1,74 @@
|
|||
#!/bin/sh -
|
||||
#
|
||||
# This is how I normally configure DBSQL when I'm doing daily work.
|
||||
#
|
||||
# Note that I'm usually using the latest copy of Mac OS/X for
|
||||
# devlelopment work, so some of this may be specific to that.
|
||||
#
|
||||
|
||||
[ -d build_unix ] && {
|
||||
echo 'You cannot build in the top-level directory.'
|
||||
exit 1
|
||||
}
|
||||
[ -d aclocal ] && {
|
||||
echo 'You cannot build in the dist directory.'
|
||||
exit 1
|
||||
}
|
||||
args=""
|
||||
#args="--disable-shared $args"
|
||||
#args="--disable-static $args"
|
||||
args="--enable-vacuum $args"
|
||||
#args="--enable-datetime $args"
|
||||
args="--enable-authentication $args"
|
||||
args="--enable-incore-databases $args"
|
||||
args="--enable-incore-temp-databases $args"
|
||||
args="--enable-debug $args"
|
||||
args="--enable-diagnostic $args"
|
||||
args="--enable-test $args"
|
||||
args="--enable-tcl $args"
|
||||
#args="--enable-sqlite-compat $args"
|
||||
args="--enable-soundex-sqlfn $args"
|
||||
#args="--with-tcl=/usr/lib/tcl-8.5.19/lib $args"
|
||||
#args="--with-berkeleydb=/usr/local/db-4.8.30 $args"
|
||||
#args="--with-db-uniquename=FOO $args"
|
||||
|
||||
# Mac OS/X enable:
|
||||
#args="LD_TWOLEVEL_NAMESPACE=1 LIBTSO_LIBS=-ltcl8.4 $args"
|
||||
|
||||
# On NixOS enable:
|
||||
CFLAGS="${NIX_CFLAGS_COMPILE} -O0 -g -DDEBUG"
|
||||
LDLAGS="${NIX_LDFLAGS} /home/gburd/src/libdb/build_unix/.libs"
|
||||
#args="--with-berkeleydb=$(pkg-config --variable=prefix db) $args"
|
||||
#args="--with-berkeleydb=/nix/store/mlhib3c2ra8bj36vhxmwqhyxph8a8sgf-db-4.8.30 $args"
|
||||
args="--with-berkeleydb=/home/gburd/opt $args"
|
||||
args="--with-tcl=$(pkg-config --variable=libdir tcl) $args"
|
||||
|
||||
echo "env $cppflags $ldflags $libs ../dist/configure $args"
|
||||
env $cppflags $ldflags $libs sh ../dist/configure -C $args
|
||||
|
||||
# (echo "break __db_loadme" &&
|
||||
# echo "break __db_err" &&
|
||||
# echo "define dd" &&
|
||||
# echo 'print __db_dump(dbp, "a", "/tmp/o")' &&
|
||||
# echo "end" &&
|
||||
# echo "define dc" &&
|
||||
# echo 'print __db_dump(dbc->dbp, "a", "/tmp/o")' &&
|
||||
# echo "end") > .gdbinit
|
||||
|
||||
# (echo "set environment LD_LIBRARY_PATH=.:.libs" &&
|
||||
# echo "dir ../src" &&
|
||||
# echo "dir ../src/dbsql" &&
|
||||
# echo "dir ../src/dbsql/rl/src" &&
|
||||
# echo "dir /usr/local/db/src/dist" &&
|
||||
# echo "path /usr/local/db/lib" &&
|
||||
# echo "path .") > .gdbinit
|
||||
|
||||
rm -f tags
|
||||
ln -s ../dist/tags tags
|
||||
mkdir -p .libs && true
|
||||
|
||||
exit 0
|
||||
|
||||
nix-build -E 'with import <nixpkgs> {}; enableDebugging db4'
|
||||
gdb -ix .gdbinit --tui build_unix/.libs/dbsql
|
||||
r --init ../test/smoke.sql smoke
|
83
dist/srcfiles.in
vendored
Normal file
83
dist/srcfiles.in
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
# DBSQL - A SQL database engine.
|
||||
#
|
||||
# Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
#
|
||||
# This library 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.
|
||||
#
|
||||
# There are special exceptions to the terms and conditions of the GPL as it
|
||||
# is applied to this software. View the full text of the exception in file
|
||||
# LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
#
|
||||
# This library 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.
|
||||
|
||||
|
||||
# This is an input file for the s_win32_dsp. It lists the source files in
|
||||
# the DBSQL tree and notes which are used to build the Win/32 library.
|
||||
#
|
||||
# Please keep this list sorted alphabetically!
|
||||
#
|
||||
# Each non-blank, non-comment line is of the form
|
||||
# filename module [ module ...]
|
||||
#
|
||||
# The possible modules, including the name of the project (.dsp) file:
|
||||
#
|
||||
# app=NAME Linked into application NAME.exe (db_NAME.dsp)
|
||||
# dynamic File is in the Windows DLL (db_dll.dsp)
|
||||
# static File is in the Windows static library (db_static.dsp)
|
||||
# java File is in the Windows Java DLL (db_java.dsp)
|
||||
# tcl File is in the Windows tcl DLL (db_tcl.dsp)
|
||||
# testutil File is used for Windows testing (db_test.dsp)
|
||||
|
||||
build_unix/lempar.c dynamic static
|
||||
build_unix/opcodes.c dynamic static
|
||||
build_unix/sql_parser.c dynamic static
|
||||
build_win32/dbkill.cpp testutil
|
||||
dist/splint.rc
|
||||
examples/binary_codec.c
|
||||
src/api.c dynamic static
|
||||
src/api_table.c dynamic static
|
||||
src/cg_attach.c dynamic static
|
||||
src/cg_auth.c dynamic static
|
||||
src/cg_build.c dynamic static
|
||||
src/cg_copy.c dynamic static
|
||||
src/cg_date.c dynamic static
|
||||
src/cg_delete.c dynamic static
|
||||
src/cg_expr.c dynamic static
|
||||
src/cg_insert.c dynamic static
|
||||
src/cg_pragma.c dynamic static
|
||||
src/cg_select.c dynamic static
|
||||
src/cg_trigger.c dynamic static
|
||||
src/cg_update.c dynamic static
|
||||
src/cg_vacuum.c dynamic static
|
||||
src/cg_where.c dynamic static
|
||||
src/clib/getopt.c app=dbsql
|
||||
src/clib/memcmp.c dynamic static
|
||||
src/clib/random.c dynamic static
|
||||
src/clib/snprintf.c dynamic static
|
||||
src/clib/strcasecmp.c dynamic static
|
||||
src/clib/strdup.c dynamic static
|
||||
src/clib/xvprintf.c dynamic static
|
||||
src/common/dbsql_alloc.c dynamic static
|
||||
src/common/dbsql_atof.c dynamic static
|
||||
src/common/dbsql_atoi.c dynamic static
|
||||
src/common/dbsql_err.c dynamic static
|
||||
src/common/hash.c dynamic static
|
||||
src/common/str.c dynamic static
|
||||
src/dbsql/dbsql.c app=dbsql
|
||||
src/dbsql_tclsh.c app=dbsql_tclsh
|
||||
src/lemon/lemon.c app=lemon
|
||||
src/lemon/lempar.c app=lemon
|
||||
src/os/os_jtime.c dynamic static
|
||||
src/os/os_sleep.c dynamic static
|
||||
src/safety.c dynamic static
|
||||
src/sm.c dynamic static
|
||||
src/sql_fns.c dynamic static
|
||||
src/sql_tokenize.c dynamic static
|
||||
src/vdbe.c dynamic static
|
||||
src/vdbe_method.c dynamic static
|
203
docs_src/dbsql.1
Normal file
203
docs_src/dbsql.1
Normal file
|
@ -0,0 +1,203 @@
|
|||
.\" Hey, EMACS: -*- nroff -*-
|
||||
.\" First parameter, NAME, should be all caps
|
||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||
.\" other parameters are allowed: see man(7), man(1)
|
||||
.TH DBSQL 1 "Mon Apr 15 23:49:17 2002"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
.\" Some roff macros, for reference:
|
||||
.\" .nh disable hyphenation
|
||||
.\" .hy enable hyphenation
|
||||
.\" .ad l left justify
|
||||
.\" .ad b justify to both left and right margins
|
||||
.\" .nf disable filling
|
||||
.\" .fi enable filling
|
||||
.\" .br insert line break
|
||||
.\" .sp <n> insert n+1 empty lines
|
||||
.\" for manpage-specific macros, see man(7)
|
||||
.SH NAME
|
||||
dbsql \- A command line interface for DBSQL
|
||||
.SH SYNOPSIS
|
||||
.B dbsql
|
||||
.RI [ options ] " filename " [ SQL ]
|
||||
.SS SUMMARY
|
||||
.PP
|
||||
dbsql is a terminal-based front-end to the DBSQL library. It enables
|
||||
you to type in queries interactively, issue them to DBSQL and see the
|
||||
results. Alternatively, you can specify SQL code on the command-line. In
|
||||
addition it provides a number of meta-commands.
|
||||
|
||||
.SH DESCRIPTION
|
||||
This manual page documents briefly the
|
||||
.B dbsql
|
||||
command.
|
||||
This manual page was written for the Debian GNU/Linux distribution
|
||||
because the original program does not have a manual page.
|
||||
.SS GETTING STARTED
|
||||
.PP
|
||||
To start the dbsql program, just type "dbsql" followed by the name
|
||||
the file that holds the DBSQL database. If the file does not exist, a
|
||||
new one is created automatically. The dbsql program will then prompt
|
||||
you to enter SQL. Type in SQL statements (terminated by a semicolon),
|
||||
press "Enter" and the SQL will be executed.
|
||||
|
||||
For example, to create a new DBSQL database named "ex1" with a single
|
||||
table named "tbl1", you might do this:
|
||||
.sp
|
||||
.nf
|
||||
$ dbsql ex1
|
||||
DBSQL version 2.0.0
|
||||
Enter ".help" for instructions
|
||||
dbsql> create table tbl1(one varchar(10), two smallint);
|
||||
dbsql> insert into tbl1 values('hello!',10);
|
||||
dbsql> insert into tbl1 values('goodbye', 20);
|
||||
dbsql> select * from tbl1;
|
||||
hello!|10
|
||||
goodbye|20
|
||||
dbsql>
|
||||
.sp
|
||||
.fi
|
||||
|
||||
.SS DBSQL META-COMMANDS
|
||||
.PP
|
||||
Most of the time, dbsql just reads lines of input and passes them on
|
||||
to the DBSQL library for execution. But if an input line begins with
|
||||
a dot ("."), then that line is intercepted and interpreted by the
|
||||
dbsql program itself. These "dot commands" are typically used to
|
||||
change the output format of queries, or to execute certain prepackaged
|
||||
query statements.
|
||||
|
||||
For a listing of the available dot commands, you can enter ".help" at
|
||||
any time. For example:
|
||||
.sp
|
||||
.nf
|
||||
.cc |
|
||||
dbsql> .help
|
||||
.dump ?TABLE? ... Dump the database in an text format
|
||||
.echo ON|OFF Turn command echo on or off
|
||||
.exit Exit this program
|
||||
.explain ON|OFF Turn output mode suitable for EXPLAIN on or off.
|
||||
"off" will revert to the output mode that was
|
||||
previously in effect
|
||||
.header(s) ON|OFF Turn display of headers on or off
|
||||
.help Show this message
|
||||
.indices TABLE Show names of all indices on TABLE
|
||||
.mode MODE Set mode to one of "line(s)", "column(s)",
|
||||
"insert", "list", or "html"
|
||||
.mode insert TABLE Generate SQL insert statements for TABLE
|
||||
.nullvalue STRING Print STRING instead of nothing for NULL data
|
||||
.output FILENAME Send output to FILENAME
|
||||
.output stdout Send output to the screen
|
||||
.prompt MAIN CONTINUE Replace the standard prompts
|
||||
"dbsql > " and " ...> "
|
||||
with the strings MAIN and CONTINUE
|
||||
CONTINUE is optional.
|
||||
.quit Exit this program
|
||||
.read FILENAME Execute SQL in FILENAME
|
||||
.reindex ?TABLE? Rebuild indices
|
||||
.schema ?TABLE? Show the CREATE statements
|
||||
.separator STRING Change separator string for "list" mode
|
||||
.show Show the current values for the following:
|
||||
.echo
|
||||
.explain
|
||||
.mode
|
||||
.nullvalue
|
||||
.output
|
||||
.separator
|
||||
.width
|
||||
.tables ?PATTERN? List names of tables matching a pattern
|
||||
.timeout MS Try opening locked tables for MS milliseconds
|
||||
.width NUM NUM ... Set column widths for "column" mode
|
||||
dbsql>
|
||||
|cc .
|
||||
.sp
|
||||
.fi
|
||||
|
||||
.SH OPTIONS
|
||||
The program has the following options:
|
||||
.TP
|
||||
.BI \-init\ file
|
||||
Read in and process 'file', which contains "dot commands".
|
||||
You can use this file to initialize display settings.
|
||||
.TP
|
||||
.B \-html
|
||||
Set output mode to HTML.
|
||||
.TP
|
||||
.B \-list
|
||||
Set output mode to 'list'.
|
||||
.TP
|
||||
.B \-line
|
||||
Set output mode to 'line'.
|
||||
.TP
|
||||
.B \-column
|
||||
Set output mode to 'column'.
|
||||
.TP
|
||||
.BI \-separator\ separator
|
||||
Specify which output field separator for 'list' mode to use.
|
||||
Default is '|'.
|
||||
.TP
|
||||
.BI \-nullvalue\ string
|
||||
When a null is encountered, print 'string'. Default is no string.
|
||||
.TP
|
||||
.B \-[no]header
|
||||
Turn headers on or off. Default is off.
|
||||
.TP
|
||||
.B \-echo
|
||||
Print commands before execution.
|
||||
|
||||
|
||||
.SH OUTPUT MODE
|
||||
The DBSQL program has different output modes, which define the way
|
||||
the output (from queries) is formatted.
|
||||
|
||||
In 'list' mode, which is the default, one record per line is output,
|
||||
each field separated by the separator specified with the
|
||||
\fB-separator\fP option or \fB.separator\fP command.
|
||||
|
||||
In 'line' mode, each column is output on its own line, records are
|
||||
separated by blank lines.
|
||||
|
||||
In HTML mode, an XHTML table is generated.
|
||||
|
||||
In 'column' mode, one record per line is output, aligned neatly in colums.
|
||||
|
||||
.SH INIT FILE
|
||||
dbsql can be initialized using resource files. These can be combined with
|
||||
command line arguments to set up dbsql exactly the way you want it.
|
||||
Initialization proceeds as follows:
|
||||
|
||||
o The defaults of
|
||||
|
||||
.sp
|
||||
.nf
|
||||
.cc |
|
||||
mode = LIST
|
||||
separator = "|"
|
||||
main prompt = "dbsql> "
|
||||
continue prompt = " ...> "
|
||||
|cc .
|
||||
.sp
|
||||
.fi
|
||||
|
||||
are established.
|
||||
|
||||
o If a file .dbsqlrc can be found in the user's home directory, it is
|
||||
read and processed. It should only contain "dot commands". If the
|
||||
file is not found or cannot be read, processing continues without
|
||||
notification.
|
||||
|
||||
o If a file is specified on the command line with the -init option, it
|
||||
is processed in the same manner as .dbsqlrc
|
||||
|
||||
o All other command line options are processed
|
||||
|
||||
o The database is opened and you are now ready to begin.
|
||||
|
||||
.SH SEE ALSO
|
||||
http://dbsql.org/
|
||||
.br
|
||||
The dbsql-doc package
|
||||
.SH AUTHOR
|
||||
This manual page was originally written by Andreas Rottmann
|
||||
<rotty@debian.org>, for the Debian GNU/Linux system (but may be used
|
||||
by others).
|
892
docs_src/lemon.html
Normal file
892
docs_src/lemon.html
Normal file
|
@ -0,0 +1,892 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>The Lemon Parser Generator</title>
|
||||
</head>
|
||||
<body bgcolor=white>
|
||||
<h1 align=center>The Lemon Parser Generator</h1>
|
||||
|
||||
<p>Lemon is an LALR(1) parser generator for C or C++.
|
||||
It does the same job as ``bison'' and ``yacc''.
|
||||
But lemon is not another bison or yacc clone. It
|
||||
uses a different grammar syntax which is designed to
|
||||
reduce the number of coding errors. Lemon also uses a more
|
||||
sophisticated parsing engine that is faster than yacc and
|
||||
bison and which is both reentrant and thread-safe.
|
||||
Furthermore, Lemon implements features that can be used
|
||||
to eliminate resource leaks, making is suitable for use
|
||||
in long-running programs such as graphical user interfaces
|
||||
or embedded controllers.</p>
|
||||
|
||||
<p>This document is an introduction to the Lemon
|
||||
parser generator.</p>
|
||||
|
||||
<h2>Theory of Operation</h2>
|
||||
|
||||
<p>The main goal of Lemon is to translate a context free grammar (CFG)
|
||||
for a particular language into C code that implements a parser for
|
||||
that language.
|
||||
The program has two inputs:
|
||||
<ul>
|
||||
<li>The grammar specification.
|
||||
<li>A parser template file.
|
||||
</ul>
|
||||
Typically, only the grammar specification is supplied by the programmer.
|
||||
Lemon comes with a default parser template which works fine for most
|
||||
applications. But the user is free to substitute a different parser
|
||||
template if desired.</p>
|
||||
|
||||
<p>Depending on command-line options, Lemon will generate between
|
||||
one and three files of outputs.
|
||||
<ul>
|
||||
<li>C code to implement the parser.
|
||||
<li>A header file defining an integer ID for each terminal symbol.
|
||||
<li>An information file that describes the states of the generated parser
|
||||
automaton.
|
||||
</ul>
|
||||
By default, all three of these output files are generated.
|
||||
The header file is suppressed if the ``-m'' command-line option is
|
||||
used and the report file is omitted when ``-q'' is selected.</p>
|
||||
|
||||
<p>The grammar specification file uses a ``.y'' suffix, by convention.
|
||||
In the examples used in this document, we'll assume the name of the
|
||||
grammar file is ``gram.y''. A typical use of Lemon would be the
|
||||
following command:
|
||||
<pre>
|
||||
lemon gram.y
|
||||
</pre>
|
||||
This command will generate three output files named ``gram.c'',
|
||||
``gram.h'' and ``gram.out''.
|
||||
The first is C code to implement the parser. The second
|
||||
is the header file that defines numerical values for all
|
||||
terminal symbols, and the last is the report that explains
|
||||
the states used by the parser automaton.</p>
|
||||
|
||||
<h3>Command Line Options</h3>
|
||||
|
||||
<p>The behavior of Lemon can be modified using command-line options.
|
||||
You can obtain a list of the available command-line options together
|
||||
with a brief explanation of what each does by typing
|
||||
<pre>
|
||||
lemon -?
|
||||
</pre>
|
||||
As of this writing, the following command-line options are supported:
|
||||
<ul>
|
||||
<li><tt>-b</tt>
|
||||
<li><tt>-c</tt>
|
||||
<li><tt>-g</tt>
|
||||
<li><tt>-m</tt>
|
||||
<li><tt>-q</tt>
|
||||
<li><tt>-s</tt>
|
||||
<li><tt>-x</tt>
|
||||
</ul>
|
||||
The ``-b'' option reduces the amount of text in the report file by
|
||||
printing only the basis of each parser state, rather than the full
|
||||
configuration.
|
||||
The ``-c'' option suppresses action table compression. Using -c
|
||||
will make the parser a little larger and slower but it will detect
|
||||
syntax errors sooner.
|
||||
The ``-g'' option causes no output files to be generated at all.
|
||||
Instead, the input grammar file is printed on standard output but
|
||||
with all comments, actions and other extraneous text deleted. This
|
||||
is a useful way to get a quick summary of a grammar.
|
||||
The ``-m'' option causes the output C source file to be compatible
|
||||
with the ``makeheaders'' program.
|
||||
Makeheaders is a program that automatically generates header files
|
||||
from C source code. When the ``-m'' option is used, the header
|
||||
file is not output since the makeheaders program will take care
|
||||
of generated all header files automatically.
|
||||
The ``-q'' option suppresses the report file.
|
||||
Using ``-s'' causes a brief summary of parser statistics to be
|
||||
printed. Like this:
|
||||
<pre>
|
||||
Parser statistics: 74 terminals, 70 nonterminals, 179 rules
|
||||
340 states, 2026 parser table entries, 0 conflicts
|
||||
</pre>
|
||||
Finally, the ``-x'' option causes Lemon to print its version number
|
||||
and then stops without attempting to read the grammar or generate a parser.</p>
|
||||
|
||||
<h3>The Parser Interface</h3>
|
||||
|
||||
<p>Lemon doesn't generate a complete, working program. It only generates
|
||||
a few subroutines that implement a parser. This section describes
|
||||
the interface to those subroutines. It is up to the programmer to
|
||||
call these subroutines in an appropriate way in order to produce a
|
||||
complete system.</p>
|
||||
|
||||
<p>Before a program begins using a Lemon-generated parser, the program
|
||||
must first create the parser.
|
||||
A new parser is created as follows:
|
||||
<pre>
|
||||
void *pParser = ParseAlloc( malloc );
|
||||
</pre>
|
||||
The ParseAlloc() routine allocates and initializes a new parser and
|
||||
returns a pointer to it.
|
||||
The actual data structure used to represent a parser is opaque --
|
||||
its internal structure is not visible or usable by the calling routine.
|
||||
For this reason, the ParseAlloc() routine returns a pointer to void
|
||||
rather than a pointer to some particular structure.
|
||||
The sole argument to the ParseAlloc() routine is a pointer to the
|
||||
subroutine used to allocate memory. Typically this means ``malloc()''.</p>
|
||||
|
||||
<p>After a program is finished using a parser, it can reclaim all
|
||||
memory allocated by that parser by calling
|
||||
<pre>
|
||||
ParseFree(pParser, free);
|
||||
</pre>
|
||||
The first argument is the same pointer returned by ParseAlloc(). The
|
||||
second argument is a pointer to the function used to release bulk
|
||||
memory back to the system.</p>
|
||||
|
||||
<p>After a parser has been allocated using ParseAlloc(), the programmer
|
||||
must supply the parser with a sequence of tokens (terminal symbols) to
|
||||
be parsed. This is accomplished by calling the following function
|
||||
once for each token:
|
||||
<pre>
|
||||
Parse(pParser, hTokenID, sTokenData, pArg);
|
||||
</pre>
|
||||
The first argument to the Parse() routine is the pointer returned by
|
||||
ParseAlloc().
|
||||
The second argument is a small positive integer that tells the parse the
|
||||
type of the next token in the data stream.
|
||||
There is one token type for each terminal symbol in the grammar.
|
||||
The gram.h file generated by Lemon contains #define statements that
|
||||
map symbolic terminal symbol names into appropriate integer values.
|
||||
(A value of 0 for the second argument is a special flag to the
|
||||
parser to indicate that the end of input has been reached.)
|
||||
The third argument is the value of the given token. By default,
|
||||
the type of the third argument is integer, but the grammar will
|
||||
usually redefine this type to be some kind of structure.
|
||||
Typically the second argument will be a broad category of tokens
|
||||
such as ``identifier'' or ``number'' and the third argument will
|
||||
be the name of the identifier or the value of the number.</p>
|
||||
|
||||
<p>The Parse() function may have either three or four arguments,
|
||||
depending on the grammar. If the grammar specification file request
|
||||
it, the Parse() function will have a fourth parameter that can be
|
||||
of any type chosen by the programmer. The parser doesn't do anything
|
||||
with this argument except to pass it through to action routines.
|
||||
This is a convenient mechanism for passing state information down
|
||||
to the action routines without having to use global variables.</p>
|
||||
|
||||
<p>A typical use of a Lemon parser might look something like the
|
||||
following:
|
||||
<pre>
|
||||
01 ParseTree *ParseFile(const char *zFilename){
|
||||
02 Tokenizer *pTokenizer;
|
||||
03 void *pParser;
|
||||
04 Token sToken;
|
||||
05 int hTokenId;
|
||||
06 ParserState sState;
|
||||
07
|
||||
08 pTokenizer = TokenizerCreate(zFilename);
|
||||
09 pParser = ParseAlloc( malloc );
|
||||
10 InitParserState(&sState);
|
||||
11 while( GetNextToken(pTokenizer, &hTokenId, &sToken) ){
|
||||
12 Parse(pParser, hTokenId, sToken, &sState);
|
||||
13 }
|
||||
14 Parse(pParser, 0, sToken, &sState);
|
||||
15 ParseFree(pParser, free );
|
||||
16 TokenizerFree(pTokenizer);
|
||||
17 return sState.treeRoot;
|
||||
18 }
|
||||
</pre>
|
||||
This example shows a user-written routine that parses a file of
|
||||
text and returns a pointer to the parse tree.
|
||||
(We've omitted all error-handling from this example to keep it
|
||||
simple.)
|
||||
We assume the existence of some kind of tokenizer which is created
|
||||
using TokenizerCreate() on line 8 and deleted by TokenizerFree()
|
||||
on line 16. The GetNextToken() function on line 11 retrieves the
|
||||
next token from the input file and puts its type in the
|
||||
integer variable hTokenId. The sToken variable is assumed to be
|
||||
some kind of structure that contains details about each token,
|
||||
such as its complete text, what line it occurs on, etc. </p>
|
||||
|
||||
<p>This example also assumes the existence of structure of type
|
||||
ParserState that holds state information about a particular parse.
|
||||
An instance of such a structure is created on line 6 and initialized
|
||||
on line 10. A pointer to this structure is passed into the Parse()
|
||||
routine as the optional 4th argument.
|
||||
The action routine specified by the grammar for the parser can use
|
||||
the ParserState structure to hold whatever information is useful and
|
||||
appropriate. In the example, we note that the treeRoot field of
|
||||
the ParserState structure is left pointing to the root of the parse
|
||||
tree.</p>
|
||||
|
||||
<p>The core of this example as it relates to Lemon is as follows:
|
||||
<pre>
|
||||
ParseFile(){
|
||||
pParser = ParseAlloc( malloc );
|
||||
while( GetNextToken(pTokenizer,&hTokenId, &sToken) ){
|
||||
Parse(pParser, hTokenId, sToken);
|
||||
}
|
||||
Parse(pParser, 0, sToken);
|
||||
ParseFree(pParser, free );
|
||||
}
|
||||
</pre>
|
||||
Basically, what a program has to do to use a Lemon-generated parser
|
||||
is first create the parser, then send it lots of tokens obtained by
|
||||
tokenizing an input source. When the end of input is reached, the
|
||||
Parse() routine should be called one last time with a token type
|
||||
of 0. This step is necessary to inform the parser that the end of
|
||||
input has been reached. Finally, we reclaim memory used by the
|
||||
parser by calling ParseFree().</p>
|
||||
|
||||
<p>There is one other interface routine that should be mentioned
|
||||
before we move on.
|
||||
The ParseTrace() function can be used to generate debugging output
|
||||
from the parser. A prototype for this routine is as follows:
|
||||
<pre>
|
||||
ParseTrace(FILE *stream, char *zPrefix);
|
||||
</pre>
|
||||
After this routine is called, a short (one-line) message is written
|
||||
to the designated output stream every time the parser changes states
|
||||
or calls an action routine. Each such message is prefaced using
|
||||
the text given by zPrefix. This debugging output can be turned off
|
||||
by calling ParseTrace() again with a first argument of NULL (0).</p>
|
||||
|
||||
<h3>Differences With YACC and BISON</h3>
|
||||
|
||||
<p>Programmers who have previously used the yacc or bison parser
|
||||
generator will notice several important differences between yacc and/or
|
||||
bison and Lemon.
|
||||
<ul>
|
||||
<li>In yacc and bison, the parser calls the tokenizer. In Lemon,
|
||||
the tokenizer calls the parser.
|
||||
<li>Lemon uses no global variables. Yacc and bison use global variables
|
||||
to pass information between the tokenizer and parser.
|
||||
<li>Lemon allows multiple parsers to be running simultaneously. Yacc
|
||||
and bison do not.
|
||||
</ul>
|
||||
These differences may cause some initial confusion for programmers
|
||||
with prior yacc and bison experience.
|
||||
But after years of experience using Lemon, I firmly
|
||||
believe that the Lemon way of doing things is better.</p>
|
||||
|
||||
<h2>Input File Syntax</h2>
|
||||
|
||||
<p>The main purpose of the grammar specification file for Lemon is
|
||||
to define the grammar for the parser. But the input file also
|
||||
specifies additional information Lemon requires to do its job.
|
||||
Most of the work in using Lemon is in writing an appropriate
|
||||
grammar file.</p>
|
||||
|
||||
<p>The grammar file for lemon is, for the most part, free format.
|
||||
It does not have sections or divisions like yacc or bison. Any
|
||||
declaration can occur at any point in the file.
|
||||
Lemon ignores whitespace (except where it is needed to separate
|
||||
tokens) and it honors the same commenting conventions as C and C++.</p>
|
||||
|
||||
<h3>Terminals and Nonterminals</h3>
|
||||
|
||||
<p>A terminal symbol (token) is any string of alphanumeric
|
||||
and underscore characters
|
||||
that begins with an upper case letter.
|
||||
A terminal can contain lower class letters after the first character,
|
||||
but the usual convention is to make terminals all upper case.
|
||||
A nonterminal, on the other hand, is any string of alphanumeric
|
||||
and underscore characters than begins with a lower case letter.
|
||||
Again, the usual convention is to make nonterminals use all lower
|
||||
case letters.</p>
|
||||
|
||||
<p>In Lemon, terminal and nonterminal symbols do not need to
|
||||
be declared or identified in a separate section of the grammar file.
|
||||
Lemon is able to generate a list of all terminals and nonterminals
|
||||
by examining the grammar rules, and it can always distinguish a
|
||||
terminal from a nonterminal by checking the case of the first
|
||||
character of the name.</p>
|
||||
|
||||
<p>Yacc and bison allow terminal symbols to have either alphanumeric
|
||||
names or to be individual characters included in single quotes, like
|
||||
this: ')' or '$'. Lemon does not allow this alternative form for
|
||||
terminal symbols. With Lemon, all symbols, terminals and nonterminals,
|
||||
must have alphanumeric names.</p>
|
||||
|
||||
<h3>Grammar Rules</h3>
|
||||
|
||||
<p>The main component of a Lemon grammar file is a sequence of grammar
|
||||
rules.
|
||||
Each grammar rule consists of a nonterminal symbol followed by
|
||||
the special symbol ``::='' and then a list of terminals and/or nonterminals.
|
||||
The rule is terminated by a period.
|
||||
The list of terminals and nonterminals on the right-hand side of the
|
||||
rule can be empty.
|
||||
Rules can occur in any order, except that the left-hand side of the
|
||||
first rule is assumed to be the start symbol for the grammar (unless
|
||||
specified otherwise using the <tt>%start</tt> directive described below.)
|
||||
A typical sequence of grammar rules might look something like this:
|
||||
<pre>
|
||||
expr ::= expr PLUS expr.
|
||||
expr ::= expr TIMES expr.
|
||||
expr ::= LPAREN expr RPAREN.
|
||||
expr ::= VALUE.
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>There is one non-terminal in this example, ``expr'', and five
|
||||
terminal symbols or tokens: ``PLUS'', ``TIMES'', ``LPAREN'',
|
||||
``RPAREN'' and ``VALUE''.</p>
|
||||
|
||||
<p>Like yacc and bison, Lemon allows the grammar to specify a block
|
||||
of C code that will be executed whenever a grammar rule is reduced
|
||||
by the parser.
|
||||
In Lemon, this action is specified by putting the C code (contained
|
||||
within curly braces <tt>{...}</tt>) immediately after the
|
||||
period that closes the rule.
|
||||
For example:
|
||||
<pre>
|
||||
expr ::= expr PLUS expr. { printf("Doing an addition...\n"); }
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>In order to be useful, grammar actions must normally be linked to
|
||||
their associated grammar rules.
|
||||
In yacc and bison, this is accomplished by embedding a ``$$'' in the
|
||||
action to stand for the value of the left-hand side of the rule and
|
||||
symbols ``$1'', ``$2'', and so forth to stand for the value of
|
||||
the terminal or nonterminal at position 1, 2 and so forth on the
|
||||
right-hand side of the rule.
|
||||
This idea is very powerful, but it is also very error-prone. The
|
||||
single most common source of errors in a yacc or bison grammar is
|
||||
to miscount the number of symbols on the right-hand side of a grammar
|
||||
rule and say ``$7'' when you really mean ``$8''.</p>
|
||||
|
||||
<p>Lemon avoids the need to count grammar symbols by assigning symbolic
|
||||
names to each symbol in a grammar rule and then using those symbolic
|
||||
names in the action.
|
||||
In yacc or bison, one would write this:
|
||||
<pre>
|
||||
expr -> expr PLUS expr { $$ = $1 + $3; };
|
||||
</pre>
|
||||
But in Lemon, the same rule becomes the following:
|
||||
<pre>
|
||||
expr(A) ::= expr(B) PLUS expr(C). { A = B+C; }
|
||||
</pre>
|
||||
In the Lemon rule, any symbol in parentheses after a grammar rule
|
||||
symbol becomes a place holder for that symbol in the grammar rule.
|
||||
This place holder can then be used in the associated C action to
|
||||
stand for the value of that symbol.<p>
|
||||
|
||||
<p>The Lemon notation for linking a grammar rule with its reduce
|
||||
action is superior to yacc/bison on several counts.
|
||||
First, as mentioned above, the Lemon method avoids the need to
|
||||
count grammar symbols.
|
||||
Secondly, if a terminal or nonterminal in a Lemon grammar rule
|
||||
includes a linking symbol in parentheses but that linking symbol
|
||||
is not actually used in the reduce action, then an error message
|
||||
is generated.
|
||||
For example, the rule
|
||||
<pre>
|
||||
expr(A) ::= expr(B) PLUS expr(C). { A = B; }
|
||||
</pre>
|
||||
will generate an error because the linking symbol ``C'' is used
|
||||
in the grammar rule but not in the reduce action.</p>
|
||||
|
||||
<p>The Lemon notation for linking grammar rules to reduce actions
|
||||
also facilitates the use of destructors for reclaiming memory
|
||||
allocated by the values of terminals and nonterminals on the
|
||||
right-hand side of a rule.</p>
|
||||
|
||||
<h3>Precedence Rules</h3>
|
||||
|
||||
<p>Lemon resolves parsing ambiguities in exactly the same way as
|
||||
yacc and bison. A shift-reduce conflict is resolved in favor
|
||||
of the shift, and a reduce-reduce conflict is resolved by reducing
|
||||
whichever rule comes first in the grammar file.</p>
|
||||
|
||||
<p>Just like in
|
||||
yacc and bison, Lemon allows a measure of control
|
||||
over the resolution of paring conflicts using precedence rules.
|
||||
A precedence value can be assigned to any terminal symbol
|
||||
using the %left, %right or %nonassoc directives. Terminal symbols
|
||||
mentioned in earlier directives have a lower precedence that
|
||||
terminal symbols mentioned in later directives. For example:</p>
|
||||
|
||||
<p><pre>
|
||||
%left AND.
|
||||
%left OR.
|
||||
%nonassoc EQ NE GT GE LT LE.
|
||||
%left PLUS MINUS.
|
||||
%left TIMES DIVIDE MOD.
|
||||
%right EXP NOT.
|
||||
</pre></p>
|
||||
|
||||
<p>In the preceding sequence of directives, the AND operator is
|
||||
defined to have the lowest precedence. The OR operator is one
|
||||
precedence level higher. And so forth. Hence, the grammar would
|
||||
attempt to group the ambiguous expression
|
||||
<pre>
|
||||
a AND b OR c
|
||||
</pre>
|
||||
like this
|
||||
<pre>
|
||||
a AND (b OR c).
|
||||
</pre>
|
||||
The associativity (left, right or nonassoc) is used to determine
|
||||
the grouping when the precedence is the same. AND is left-associative
|
||||
in our example, so
|
||||
<pre>
|
||||
a AND b AND c
|
||||
</pre>
|
||||
is parsed like this
|
||||
<pre>
|
||||
(a AND b) AND c.
|
||||
</pre>
|
||||
The EXP operator is right-associative, though, so
|
||||
<pre>
|
||||
a EXP b EXP c
|
||||
</pre>
|
||||
is parsed like this
|
||||
<pre>
|
||||
a EXP (b EXP c).
|
||||
</pre>
|
||||
The nonassoc precedence is used for non-associative operators.
|
||||
So
|
||||
<pre>
|
||||
a EQ b EQ c
|
||||
</pre>
|
||||
is an error.</p>
|
||||
|
||||
<p>The precedence of non-terminals is transferred to rules as follows:
|
||||
The precedence of a grammar rule is equal to the precedence of the
|
||||
left-most terminal symbol in the rule for which a precedence is
|
||||
defined. This is normally what you want, but in those cases where
|
||||
you want to precedence of a grammar rule to be something different,
|
||||
you can specify an alternative precedence symbol by putting the
|
||||
symbol in square braces after the period at the end of the rule and
|
||||
before any C-code. For example:</p>
|
||||
|
||||
<p><pre>
|
||||
expr = MINUS expr. [NOT]
|
||||
</pre></p>
|
||||
|
||||
<p>This rule has a precedence equal to that of the NOT symbol, not the
|
||||
MINUS symbol as would have been the case by default.</p>
|
||||
|
||||
<p>With the knowledge of how precedence is assigned to terminal
|
||||
symbols and individual
|
||||
grammar rules, we can now explain precisely how parsing conflicts
|
||||
are resolved in Lemon. Shift-reduce conflicts are resolved
|
||||
as follows:
|
||||
<ul>
|
||||
<li> If either the token to be shifted or the rule to be reduced
|
||||
lacks precedence information, then resolve in favor of the
|
||||
shift, but report a parsing conflict.
|
||||
<li> If the precedence of the token to be shifted is greater than
|
||||
the precedence of the rule to reduce, then resolve in favor
|
||||
of the shift. No parsing conflict is reported.
|
||||
<li> If the precedence of the token it be shifted is less than the
|
||||
precedence of the rule to reduce, then resolve in favor of the
|
||||
reduce action. No parsing conflict is reported.
|
||||
<li> If the precedences are the same and the shift token is
|
||||
right-associative, then resolve in favor of the shift.
|
||||
No parsing conflict is reported.
|
||||
<li> If the precedences are the same the the shift token is
|
||||
left-associative, then resolve in favor of the reduce.
|
||||
No parsing conflict is reported.
|
||||
<li> Otherwise, resolve the conflict by doing the shift and
|
||||
report the parsing conflict.
|
||||
</ul>
|
||||
Reduce-reduce conflicts are resolved this way:
|
||||
<ul>
|
||||
<li> If either reduce rule
|
||||
lacks precedence information, then resolve in favor of the
|
||||
rule that appears first in the grammar and report a parsing
|
||||
conflict.
|
||||
<li> If both rules have precedence and the precedence is different
|
||||
then resolve the dispute in favor of the rule with the highest
|
||||
precedence and do not report a conflict.
|
||||
<li> Otherwise, resolve the conflict by reducing by the rule that
|
||||
appears first in the grammar and report a parsing conflict.
|
||||
</ul>
|
||||
|
||||
<h3>Special Directives</h3>
|
||||
|
||||
<p>The input grammar to Lemon consists of grammar rules and special
|
||||
directives. We've described all the grammar rules, so now we'll
|
||||
talk about the special directives.</p>
|
||||
|
||||
<p>Directives in lemon can occur in any order. You can put them before
|
||||
the grammar rules, or after the grammar rules, or in the mist of the
|
||||
grammar rules. It doesn't matter. The relative order of
|
||||
directives used to assign precedence to terminals is important, but
|
||||
other than that, the order of directives in Lemon is arbitrary.</p>
|
||||
|
||||
<p>Lemon supports the following special directives:
|
||||
<ul>
|
||||
<li><tt>%code</tt>
|
||||
<li><tt>%default_destructor</tt>
|
||||
<li><tt>%default_type</tt>
|
||||
<li><tt>%destructor</tt>
|
||||
<li><tt>%extra_argument</tt>
|
||||
<li><tt>%include</tt>
|
||||
<li><tt>%left</tt>
|
||||
<li><tt>%name</tt>
|
||||
<li><tt>%nonassoc</tt>
|
||||
<li><tt>%parse_accept</tt>
|
||||
<li><tt>%parse_failure </tt>
|
||||
<li><tt>%right</tt>
|
||||
<li><tt>%stack_overflow</tt>
|
||||
<li><tt>%stack_size</tt>
|
||||
<li><tt>%start_symbol</tt>
|
||||
<li><tt>%syntax_error</tt>
|
||||
<li><tt>%token_destructor</tt>
|
||||
<li><tt>%token_prefix</tt>
|
||||
<li><tt>%token_type</tt>
|
||||
<li><tt>%type</tt>
|
||||
</ul>
|
||||
Each of these directives will be described separately in the
|
||||
following sections:</p>
|
||||
|
||||
<h4>The <tt>%code</tt> directive</h4>
|
||||
|
||||
<p>The %code directive is used to specify addition C/C++ code that
|
||||
is added to the end of the main output file. This is similar to
|
||||
the %include directive except that %include is inserted at the
|
||||
beginning of the main output file.</p>
|
||||
|
||||
<p>%code is typically used to include some action routines or perhaps
|
||||
a tokenizer as part of the output file.</p>
|
||||
|
||||
<h4>The <tt>%default_destructor</tt> directive</h4>
|
||||
|
||||
<p>The %default_destructor directive specifies a destructor to
|
||||
use for non-terminals that do not have their own destructor
|
||||
specified by a separate %destructor directive. See the documentation
|
||||
on the %destructor directive below for additional information.</p>
|
||||
|
||||
<p>In some grammers, many different non-terminal symbols have the
|
||||
same datatype and hence the same destructor. This directive is
|
||||
a convenience way to specify the same destructor for all those
|
||||
non-terminals using a single statement.</p>
|
||||
|
||||
<h4>The <tt>%default_type</tt> directive</h4>
|
||||
|
||||
<p>The %default_type directive specifies the datatype of non-terminal
|
||||
symbols that do no have their own datatype defined using a separate
|
||||
%type directive. See the documentation on %type below for addition
|
||||
information.</p>
|
||||
|
||||
<h4>The <tt>%destructor</tt> directive</h4>
|
||||
|
||||
<p>The %destructor directive is used to specify a destructor for
|
||||
a non-terminal symbol.
|
||||
(See also the %token_destructor directive which is used to
|
||||
specify a destructor for terminal symbols.)</p>
|
||||
|
||||
<p>A non-terminal's destructor is called to dispose of the
|
||||
non-terminal's value whenever the non-terminal is popped from
|
||||
the stack. This includes all of the following circumstances:
|
||||
<ul>
|
||||
<li> When a rule reduces and the value of a non-terminal on
|
||||
the right-hand side is not linked to C code.
|
||||
<li> When the stack is popped during error processing.
|
||||
<li> When the ParseFree() function runs.
|
||||
</ul>
|
||||
The destructor can do whatever it wants with the value of
|
||||
the non-terminal, but its design is to deallocate memory
|
||||
or other resources held by that non-terminal.</p>
|
||||
|
||||
<p>Consider an example:
|
||||
<pre>
|
||||
%type nt {void*}
|
||||
%destructor nt { free($$); }
|
||||
nt(A) ::= ID NUM. { A = malloc( 100 ); }
|
||||
</pre>
|
||||
This example is a bit contrived but it serves to illustrate how
|
||||
destructors work. The example shows a non-terminal named
|
||||
``nt'' that holds values of type ``void*''. When the rule for
|
||||
an ``nt'' reduces, it sets the value of the non-terminal to
|
||||
space obtained from malloc(). Later, when the nt non-terminal
|
||||
is popped from the stack, the destructor will fire and call
|
||||
free() on this malloced space, thus avoiding a memory leak.
|
||||
(Note that the symbol ``$$'' in the destructor code is replaced
|
||||
by the value of the non-terminal.)</p>
|
||||
|
||||
<p>It is important to note that the value of a non-terminal is passed
|
||||
to the destructor whenever the non-terminal is removed from the
|
||||
stack, unless the non-terminal is used in a C-code action. If
|
||||
the non-terminal is used by C-code, then it is assumed that the
|
||||
C-code will take care of destroying it if it should really
|
||||
be destroyed. More commonly, the value is used to build some
|
||||
larger structure and we don't want to destroy it, which is why
|
||||
the destructor is not called in this circumstance.</p>
|
||||
|
||||
<p>By appropriate use of destructors, it is possible to
|
||||
build a parser using Lemon that can be used within a long-running
|
||||
program, such as a GUI, that will not leak memory or other resources.
|
||||
To do the same using yacc or bison is much more difficult.</p>
|
||||
|
||||
<h4>The <tt>%extra_argument</tt> directive</h4>
|
||||
|
||||
The %extra_argument directive instructs Lemon to add a 4th parameter
|
||||
to the parameter list of the Parse() function it generates. Lemon
|
||||
doesn't do anything itself with this extra argument, but it does
|
||||
make the argument available to C-code action routines, destructors,
|
||||
and so forth. For example, if the grammar file contains:</p>
|
||||
|
||||
<p><pre>
|
||||
%extra_argument { MyStruct *pAbc }
|
||||
</pre></p>
|
||||
|
||||
<p>Then the Parse() function generated will have an 4th parameter
|
||||
of type ``MyStruct*'' and all action routines will have access to
|
||||
a variable named ``pAbc'' that is the value of the 4th parameter
|
||||
in the most recent call to Parse().</p>
|
||||
|
||||
<h4>The <tt>%include</tt> directive</h4>
|
||||
|
||||
<p>The %include directive specifies C code that is included at the
|
||||
top of the generated parser. You can include any text you want --
|
||||
the Lemon parser generator copies it blindly. If you have multiple
|
||||
%include directives in your grammar file the value of the last
|
||||
%include directive overwrites all the others.</p.
|
||||
|
||||
<p>The %include directive is very handy for getting some extra #include
|
||||
preprocessor statements at the beginning of the generated parser.
|
||||
For example:</p>
|
||||
|
||||
<p><pre>
|
||||
%include {#include <unistd.h>}
|
||||
</pre></p>
|
||||
|
||||
<p>This might be needed, for example, if some of the C actions in the
|
||||
grammar call functions that are prototyed in unistd.h.</p>
|
||||
|
||||
<h4>The <tt>%left</tt> directive</h4>
|
||||
|
||||
The %left directive is used (along with the %right and
|
||||
%nonassoc directives) to declare precedences of terminal
|
||||
symbols. Every terminal symbol whose name appears after
|
||||
a %left directive but before the next period (``.'') is
|
||||
given the same left-associative precedence value. Subsequent
|
||||
%left directives have higher precedence. For example:</p>
|
||||
|
||||
<p><pre>
|
||||
%left AND.
|
||||
%left OR.
|
||||
%nonassoc EQ NE GT GE LT LE.
|
||||
%left PLUS MINUS.
|
||||
%left TIMES DIVIDE MOD.
|
||||
%right EXP NOT.
|
||||
</pre></p>
|
||||
|
||||
<p>Note the period that terminates each %left, %right or %nonassoc
|
||||
directive.</p>
|
||||
|
||||
<p>LALR(1) grammars can get into a situation where they require
|
||||
a large amount of stack space if you make heavy use or right-associative
|
||||
operators. For this reason, it is recommended that you use %left
|
||||
rather than %right whenever possible.</p>
|
||||
|
||||
<h4>The <tt>%name</tt> directive</h4>
|
||||
|
||||
<p>By default, the functions generated by Lemon all begin with the
|
||||
five-character string ``Parse''. You can change this string to something
|
||||
different using the %name directive. For instance:</p>
|
||||
|
||||
<p><pre>
|
||||
%name Abcde
|
||||
</pre></p>
|
||||
|
||||
<p>Putting this directive in the grammar file will cause Lemon to generate
|
||||
functions named
|
||||
<ul>
|
||||
<li> AbcdeAlloc(),
|
||||
<li> AbcdeFree(),
|
||||
<li> AbcdeTrace(), and
|
||||
<li> Abcde().
|
||||
</ul>
|
||||
The %name directive allows you to generator two or more different
|
||||
parsers and link them all into the same executable.
|
||||
</p>
|
||||
|
||||
<h4>The <tt>%nonassoc</tt> directive</h4>
|
||||
|
||||
<p>This directive is used to assign non-associative precedence to
|
||||
one or more terminal symbols. See the section on precedence rules
|
||||
or on the %left directive for additional information.</p>
|
||||
|
||||
<h4>The <tt>%parse_accept</tt> directive</h4>
|
||||
|
||||
<p>The %parse_accept directive specifies a block of C code that is
|
||||
executed whenever the parser accepts its input string. To ``accept''
|
||||
an input string means that the parser was able to process all tokens
|
||||
without error.</p>
|
||||
|
||||
<p>For example:</p>
|
||||
|
||||
<p><pre>
|
||||
%parse_accept {
|
||||
printf("parsing complete!\n");
|
||||
}
|
||||
</pre></p>
|
||||
|
||||
|
||||
<h4>The <tt>%parse_failure</tt> directive</h4>
|
||||
|
||||
<p>The %parse_failure directive specifies a block of C code that
|
||||
is executed whenever the parser fails complete. This code is not
|
||||
executed until the parser has tried and failed to resolve an input
|
||||
error using is usual error recovery strategy. The routine is
|
||||
only invoked when parsing is unable to continue.</p>
|
||||
|
||||
<p><pre>
|
||||
%parse_failure {
|
||||
fprintf(stderr,"Giving up. Parser is hopelessly lost...\n");
|
||||
}
|
||||
</pre></p>
|
||||
|
||||
<h4>The <tt>%right</tt> directive</h4>
|
||||
|
||||
<p>This directive is used to assign right-associative precedence to
|
||||
one or more terminal symbols. See the section on precedence rules
|
||||
or on the %left directive for additional information.</p>
|
||||
|
||||
<h4>The <tt>%stack_overflow</tt> directive</h4>
|
||||
|
||||
<p>The %stack_overflow directive specifies a block of C code that
|
||||
is executed if the parser's internal stack ever overflows. Typically
|
||||
this just prints an error message. After a stack overflow, the parser
|
||||
will be unable to continue and must be reset.</p>
|
||||
|
||||
<p><pre>
|
||||
%stack_overflow {
|
||||
fprintf(stderr,"Giving up. Parser stack overflow\n");
|
||||
}
|
||||
</pre></p>
|
||||
|
||||
<p>You can help prevent parser stack overflows by avoiding the use
|
||||
of right recursion and right-precedence operators in your grammar.
|
||||
Use left recursion and and left-precedence operators instead, to
|
||||
encourage rules to reduce sooner and keep the stack size down.
|
||||
For example, do rules like this:
|
||||
<pre>
|
||||
list ::= list element. // left-recursion. Good!
|
||||
list ::= .
|
||||
</pre>
|
||||
Not like this:
|
||||
<pre>
|
||||
list ::= element list. // right-recursion. Bad!
|
||||
list ::= .
|
||||
</pre>
|
||||
|
||||
<h4>The <tt>%stack_size</tt> directive</h4>
|
||||
|
||||
<p>If stack overflow is a problem and you can't resolve the trouble
|
||||
by using left-recursion, then you might want to increase the size
|
||||
of the parser's stack using this directive. Put an positive integer
|
||||
after the %stack_size directive and Lemon will generate a parse
|
||||
with a stack of the requested size. The default value is 100.</p>
|
||||
|
||||
<p><pre>
|
||||
%stack_size 2000
|
||||
</pre></p>
|
||||
|
||||
<h4>The <tt>%start_symbol</tt> directive</h4>
|
||||
|
||||
<p>By default, the start-symbol for the grammar that Lemon generates
|
||||
is the first non-terminal that appears in the grammar file. But you
|
||||
can choose a different start-symbol using the %start_symbol directive.</p>
|
||||
|
||||
<p><pre>
|
||||
%start_symbol prog
|
||||
</pre></p>
|
||||
|
||||
<h4>The <tt>%token_destructor</tt> directive</h4>
|
||||
|
||||
<p>The %destructor directive assigns a destructor to a non-terminal
|
||||
symbol. (See the description of the %destructor directive above.)
|
||||
This directive does the same thing for all terminal symbols.</p>
|
||||
|
||||
<p>Unlike non-terminal symbols which may each have a different data type
|
||||
for their values, terminals all use the same data type (defined by
|
||||
the %token_type directive) and so they use a common destructor. Other
|
||||
than that, the token destructor works just like the non-terminal
|
||||
destructors.</p>
|
||||
|
||||
<h4>The <tt>%token_prefix</tt> directive</h4>
|
||||
|
||||
<p>Lemon generates #defines that assign small integer constants
|
||||
to each terminal symbol in the grammar. If desired, Lemon will
|
||||
add a prefix specified by this directive
|
||||
to each of the #defines it generates.
|
||||
So if the default output of Lemon looked like this:
|
||||
<pre>
|
||||
#define AND 1
|
||||
#define MINUS 2
|
||||
#define OR 3
|
||||
#define PLUS 4
|
||||
</pre>
|
||||
You can insert a statement into the grammar like this:
|
||||
<pre>
|
||||
%token_prefix TOKEN_
|
||||
</pre>
|
||||
to cause Lemon to produce these symbols instead:
|
||||
<pre>
|
||||
#define TOKEN_AND 1
|
||||
#define TOKEN_MINUS 2
|
||||
#define TOKEN_OR 3
|
||||
#define TOKEN_PLUS 4
|
||||
</pre>
|
||||
|
||||
<h4>The <tt>%token_type</tt> and <tt>%type</tt> directives</h4>
|
||||
|
||||
<p>These directives are used to specify the data types for values
|
||||
on the parser's stack associated with terminal and non-terminal
|
||||
symbols. The values of all terminal symbols must be of the same
|
||||
type. This turns out to be the same data type as the 3rd parameter
|
||||
to the Parse() function generated by Lemon. Typically, you will
|
||||
make the value of a terminal symbol by a pointer to some kind of
|
||||
token structure. Like this:</p>
|
||||
|
||||
<p><pre>
|
||||
%token_type {Token*}
|
||||
</pre></p>
|
||||
|
||||
<p>If the data type of terminals is not specified, the default value
|
||||
is ``int''.</p>
|
||||
|
||||
<p>Non-terminal symbols can each have their own data types. Typically
|
||||
the data type of a non-terminal is a pointer to the root of a parse-tree
|
||||
structure that contains all information about that non-terminal.
|
||||
For example:</p>
|
||||
|
||||
<p><pre>
|
||||
%type expr {Expr*}
|
||||
</pre></p>
|
||||
|
||||
<p>Each entry on the parser's stack is actually a union containing
|
||||
instances of all data types for every non-terminal and terminal symbol.
|
||||
Lemon will automatically use the correct element of this union depending
|
||||
on what the corresponding non-terminal or terminal symbol is. But
|
||||
the grammar designer should keep in mind that the size of the union
|
||||
will be the size of its largest element. So if you have a single
|
||||
non-terminal whose data type requires 1K of storage, then your 100
|
||||
entry parser stack will require 100K of heap space. If you are willing
|
||||
and able to pay that price, fine. You just need to know.</p>
|
||||
|
||||
<h3>Error Processing</h3>
|
||||
|
||||
<p>After extensive experimentation over several years, it has been
|
||||
discovered that the error recovery strategy used by yacc is about
|
||||
as good as it gets. And so that is what Lemon uses.</p>
|
||||
|
||||
<p>When a Lemon-generated parser encounters a syntax error, it
|
||||
first invokes the code specified by the %syntax_error directive, if
|
||||
any. It then enters its error recovery strategy. The error recovery
|
||||
strategy is to begin popping the parsers stack until it enters a
|
||||
state where it is permitted to shift a special non-terminal symbol
|
||||
named ``error''. It then shifts this non-terminal and continues
|
||||
parsing. But the %syntax_error routine will not be called again
|
||||
until at least three new tokens have been successfully shifted.</p>
|
||||
|
||||
<p>If the parser pops its stack until the stack is empty, and it still
|
||||
is unable to shift the error symbol, then the %parse_failed routine
|
||||
is invoked and the parser resets itself to its start state, ready
|
||||
to begin parsing a new file. This is what will happen at the very
|
||||
first syntax error, of course, if there are no instances of the
|
||||
``error'' non-terminal in your grammar.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
0
docs_src/m4/m4.links
Normal file
0
docs_src/m4/m4.links
Normal file
206
flake.lock
Normal file
206
flake.lock
Normal file
|
@ -0,0 +1,206 @@
|
|||
{
|
||||
"nodes": {
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1673956053,
|
||||
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1694529238,
|
||||
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_2": {
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1685518550,
|
||||
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"pre-commit-hooks",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1660459072,
|
||||
"narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-github-actions": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1693660503,
|
||||
"narHash": "sha256-B/g2V4v6gjirFmy+I5mwB2bCYc0l3j5scVfwgl6WOl8=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-github-actions",
|
||||
"rev": "bd5bdbb52350e145c526108f4ef192eb8e554fa0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-github-actions",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1697722682,
|
||||
"narHash": "sha256-PRhNRNxBEsf4hdpuGIGcRckyYGm5iGuI9P0UGzOmzEo=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "8e8f3e83b66a6a9a9e953e4a14b1a227b22a18d4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1685801374,
|
||||
"narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c37ca420157f4abc31e26f436c1145f8951ff373",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-23.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1689261696,
|
||||
"narHash": "sha256-LzfUtFs9MQRvIoQ3MfgSuipBVMXslMPH/vZ+nM40LkA=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "df1eee2aa65052a18121ed4971081576b25d6b5c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"pre-commit-hooks": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-utils": "flake-utils_2",
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1696846637,
|
||||
"narHash": "sha256-0hv4kbXxci2+pxhuXlVgftj/Jq79VSmtAyvfabCCtYk=",
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"rev": "42e1b6095ef80a51f79595d9951eb38e91c4e6ca",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nix-github-actions": "nix-github-actions",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"pre-commit-hooks": "pre-commit-hooks"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_2": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
104
flake.nix
Normal file
104
flake.nix
Normal file
|
@ -0,0 +1,104 @@
|
|||
{
|
||||
description = "The DBSQL library, a mixup of SQLite and Berkeley DB";
|
||||
|
||||
nixConfig = {
|
||||
bash-prompt = "\\[\\e[34;1m\\]nix ~ \\[\\e[0m\\]";
|
||||
};
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
inputs.pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix";
|
||||
inputs.nix-github-actions.url = "github:nix-community/nix-github-actions";
|
||||
inputs.nix-github-actions.inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
||||
outputs = { self, nixpkgs, flake-utils, pre-commit-hooks, nix-github-actions }:
|
||||
let
|
||||
inherit (nixpkgs) lib;
|
||||
officialRelease = false;
|
||||
|
||||
#version = "DBSQL ${DBSQL_VERSION}: (${versionSuffix})";
|
||||
version = "DBSQL 0.3.1: (${versionSuffix})";
|
||||
versionSuffix =
|
||||
if officialRelease
|
||||
then ""
|
||||
else "pre${builtins.substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101")}_${self.shortRev or "dirty"}";
|
||||
|
||||
supportedSystems = [ "x86_64-linux" ];
|
||||
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
|
||||
nixpkgsFor = forAllSystems (system: import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [ self.overlay ];
|
||||
});
|
||||
|
||||
in
|
||||
flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
|
||||
overlays = [
|
||||
|
||||
(final: prev: {
|
||||
dbsql = with final; stdenv.mkDerivation rec {
|
||||
inherit version;
|
||||
inherit system;
|
||||
pname = "dbsql";
|
||||
src = self;
|
||||
configureFlags = [
|
||||
"--host ${system}"
|
||||
];
|
||||
buildInputs = [
|
||||
(enableDebuging db4)
|
||||
glibc.out
|
||||
glibc.static
|
||||
tcl-8_5
|
||||
];
|
||||
nativeBuildInputs = [ autoreconfHook ];
|
||||
meta = {
|
||||
changelog = "https://git.burd.me/greg/dbsql/raw/branch/main/ChangeLog";
|
||||
downloadPage = "https://git.burd.me/greg/dbsql/releases";
|
||||
homepage = "https://github.com/gburd/dbsql";
|
||||
license = "https://github.com/gburd/dbsql/LICENSE";
|
||||
mainProgram = "dbsql";
|
||||
maintainers = [ "Greg Burd <greg@burd.me>" ];
|
||||
platforms = supportedSystems;
|
||||
};
|
||||
};
|
||||
})
|
||||
];
|
||||
|
||||
checks = {
|
||||
pre-commit-check = pre-commit-hooks.lib.${system}.run {
|
||||
src = ./.;
|
||||
hooks = {
|
||||
nixpkgs-fmt.enable = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
devShell = nixpkgs.legacyPackages.${system}.mkShell {
|
||||
inherit (self.checks.${system}.pre-commit-check) shellHook;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
in rec {
|
||||
packages = {
|
||||
inherit (pkgs) dbsql;
|
||||
|
||||
githubActions = nix-github-actions.lib.mkGithubMatrix {
|
||||
checks = nixpkgs.lib.getAttrs [ "x86_64-linux" "x86_64-darwin" ] self.packages;
|
||||
};
|
||||
};
|
||||
packages.default = self.packages.${system}.dbsql;
|
||||
packages.container = pkgs.callPackage ./container.nix { package = packages.default; };
|
||||
|
||||
apps.dbsql = flake-utils.lib.mkApp { drv = packages.default; };
|
||||
apps.${system}.default = apps.dbsql;
|
||||
|
||||
devShells.default = import ./shell.nix { inherit pkgs; };
|
||||
}
|
||||
);
|
||||
}
|
43
index.html
43
index.html
|
@ -1,43 +0,0 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<title>DBSQL by gburd</title>
|
||||
|
||||
<link rel="stylesheet" href="stylesheets/styles.css">
|
||||
<link rel="stylesheet" href="stylesheets/pygment_trac.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<header>
|
||||
<h1>DBSQL</h1>
|
||||
<p>A SQL database engine on top of Oracle Berkeley DB</p>
|
||||
|
||||
<p class="view"><a href="https://github.com/gburd/dbsql">View the Project on GitHub <small>gburd/dbsql</small></a></p>
|
||||
|
||||
|
||||
<ul>
|
||||
<li><a href="https://github.com/gburd/dbsql/zipball/master">Download <strong>ZIP File</strong></a></li>
|
||||
<li><a href="https://github.com/gburd/dbsql/tarball/master">Download <strong>TAR Ball</strong></a></li>
|
||||
<li><a href="https://github.com/gburd/dbsql">View On <strong>GitHub</strong></a></li>
|
||||
</ul>
|
||||
</header>
|
||||
<section>
|
||||
<h3>DB SQL</h3>
|
||||
|
||||
<p>This project isn't under active development. Years ago I set about to reuse the <a href="http://sqlite.org/">SQLite</a> source with Berkeley DB functioning as the storage manager. As I set about to do this I also completely changed the SQLite code, mostly in format but with some other changes. The project finished up when DBSQL was functional, but not fully debugged. I used this prototype to help justify the work to do much the same within the Berkeley DB group in Oracle. Berkeley DB now has a good integration with SQLite, so this project is defunct.</p>
|
||||
</section>
|
||||
<footer>
|
||||
<p>This project is maintained by <a href="https://github.com/gburd">gburd</a></p>
|
||||
<p><small>Hosted on GitHub Pages — Theme by <a href="https://github.com/orderedlist">orderedlist</a></small></p>
|
||||
</footer>
|
||||
</div>
|
||||
<script src="javascripts/scale.fix.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,17 +0,0 @@
|
|||
var metas = document.getElementsByTagName('meta');
|
||||
var i;
|
||||
if (navigator.userAgent.match(/iPhone/i)) {
|
||||
for (i=0; i<metas.length; i++) {
|
||||
if (metas[i].name == "viewport") {
|
||||
metas[i].content = "width=device-width, minimum-scale=1.0, maximum-scale=1.0";
|
||||
}
|
||||
}
|
||||
document.addEventListener("gesturestart", gestureStart, false);
|
||||
}
|
||||
function gestureStart() {
|
||||
for (i=0; i<metas.length; i++) {
|
||||
if (metas[i].name == "viewport") {
|
||||
metas[i].content = "width=device-width, minimum-scale=0.25, maximum-scale=1.6";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
{"note":"Don't delete this file! It's used internally to help with page regeneration.","tagline":"A SQL database engine on top of Oracle Berkeley DB","body":"### DB SQL\r\nThis project isn't under active development. Years ago I set about to reuse the [SQLite](http://sqlite.org/) source with Berkeley DB functioning as the storage manager. As I set about to do this I also completely changed the SQLite code, mostly in format but with some other changes. The project finished up when DBSQL was functional, but not fully debugged. I used this prototype to help justify the work to do much the same within the Berkeley DB group in Oracle. Berkeley DB now has a good integration with SQLite, so this project is defunct.","name":"DBSQL","google":""}
|
28
shell.nix
Normal file
28
shell.nix
Normal file
|
@ -0,0 +1,28 @@
|
|||
{ pkgs ? import <nixpkgs> {} }:
|
||||
pkgs.mkShell {
|
||||
|
||||
nativeBuildInputs = with pkgs.buildPackages; [
|
||||
act
|
||||
autoconf
|
||||
ed
|
||||
gcc
|
||||
gdb
|
||||
gettext
|
||||
libtool
|
||||
m4
|
||||
pkg-config
|
||||
perl
|
||||
ripgrep
|
||||
python3
|
||||
];
|
||||
|
||||
buildInputs = with pkgs; [
|
||||
# (enableDebuging db4)
|
||||
db4
|
||||
glibc.out
|
||||
glibc.static
|
||||
tcl-8_5
|
||||
];
|
||||
|
||||
DOCKER_BUILDKIT = 1;
|
||||
}
|
141
src/TODO
Normal file
141
src/TODO
Normal file
|
@ -0,0 +1,141 @@
|
|||
--- Things to fix before 1.0
|
||||
* search for TODO and fix in all files
|
||||
* review use of __os_malloc verses __os_umalloc
|
||||
* strcasecmp.c: what about UNICODE?
|
||||
* --enable-sqlite-compat create the sqlite compat api
|
||||
* --disable-statistics
|
||||
* command line tools
|
||||
* dbsql
|
||||
* --bcp bulk copy from file
|
||||
* integrate the new 4.3 unique id generation
|
||||
* replace NDEBUG with DIAGNOSTIC
|
||||
* ask about optimizations for MySQL, incorporate into DBSQL
|
||||
* modify types to be less ambiguous int -> u_int32_t
|
||||
* work bottom up, and top down knitting DB access patterns in
|
||||
* grep for 'return [0-9]+' and replace with #defines that make more sense
|
||||
* change all 'return XXX;' statements to be 'return (XXX);'
|
||||
* replace '(char*)0' with NULL or some such thing
|
||||
* look for and try to replace (void*) casts
|
||||
* move dbsql_get_encoding global into DBSQL->[get,set]_encoding()
|
||||
* rewrite error reporting, get rid of __str_urealloc and err_msgs
|
||||
* lint, lclint and splint checking
|
||||
* spell check comments, docs, etc - add standard spell.ok etc stuff
|
||||
* grep for "Malloc Failed", fix
|
||||
* replace home grown linked lists(src_list) with macro implementations of same
|
||||
* dbsql_create_env() should do the following as a default setup:
|
||||
To minimize the amount of space taken up by the log files,
|
||||
configure Berkeley DB to have small log files (see the
|
||||
DbEnv.set_lg_max method), do frequent checkpoints (see the
|
||||
DbEnv.txn_checkpoint method), and automatically remove log
|
||||
files (see the DB_LOG_AUTOREMOVE flag to the DbEnv.set_flags
|
||||
method). -- Keith
|
||||
* purify - memory leak/buffer overrun check
|
||||
* profile - gprof(1) - profile run, look for hot spots
|
||||
* produce and examine a code coverage report
|
||||
* fix places where I moved local scope vars to function scope vars (as I go)
|
||||
* consider using a DB_SEQ for 'int priorNewRowid; /* Last generated ROWID */'
|
||||
* what is the difference between DBSQL_STATUS_ERROR verses DBSQL_RUN_RECOVERY
|
||||
when should one be used over the other? check usage.
|
||||
* DBSQL->{sg}et_verbose
|
||||
* stats?
|
||||
* How will TRIGGERS work in a multi env setup or worse yet, when replicated?
|
||||
* add .describe [command] ('.describe select') to dbsql
|
||||
* add .edit [!n] to open $EDITOR on historical statement
|
||||
* examine the MySQL command line interface, add best features
|
||||
* TRUNCATE table [tablename]
|
||||
* use something similar to readline in shell (but not readline, its GPL)
|
||||
|
||||
--- 1.1
|
||||
* cxx
|
||||
* Java
|
||||
* JDBC type ???
|
||||
* make the data types user definable via codec functions
|
||||
* ASSOCIATE select_stmt WITH db_database_name [READ ONLY|READ WRITE]
|
||||
KEY 'printf format expression' VALUE AS 'printf format expression'
|
||||
* select @@IDENTITY
|
||||
* SEQUENCE http://otn.oracle.com/products/rdb/pdf/0307_sequences.pdf
|
||||
* XOpen CLI (==ODBC) implementation
|
||||
* --enable-regex-like (e.g. 'SELECT * from Person where name like /B(u|i|y)rd/;')
|
||||
|
||||
--- 2.0
|
||||
* note that cg_where.c has a WHERE clause limit of 100 search for wc_exprs[101]
|
||||
* note in cg_where.c that if the 33rd table of a join has an index it won't
|
||||
be found or used as the bitmask method uses an u_int_32, consider fixing this
|
||||
* LibSDB interface http://siag.nu/libsdb/
|
||||
* --enable-xml
|
||||
http://www.throwingbeans.org/tech/postgresql_and_xml.html
|
||||
http://weblog.infoworld.com/udell/2003/03/12.html#a637
|
||||
http://www.sqlxml.org/
|
||||
http://www.perfectxml.com/SQLXML.asp
|
||||
http://www.sqlxml.org/faqs.aspx?faq=103
|
||||
* 64bit clean http://www.treblig.org/articles/64bits.html
|
||||
* Create View INFORMATION_SCHEMA_TABLES as
|
||||
Select * from ( select 'main' as TABLE_CATALOG , 'sqlite' as TABLE_SCHEMA , tbl_name as TABLE_NAME , case when type = 'table' then 'BASE TABLE' when type = 'view' then 'VIEW' end as TABLE_TYPE, sql as TABLE_SOURCE from sqlite_master where type in('table','view') and tbl_name not like 'INFORMATION_SCHEMA_%' union select 'main' as TABLE_CATALOG , 'sqlite' as TABLE_SCHEMA , tbl_name as TABLE_NAME , case when type = 'table' then 'TEMPORARY TABLE' when type = 'view' then 'TEMPORARY VIEW' end as TABLE_TYPE, sql as TABLE_SOURCE from sqlite_temp_master where type in('table','view') and tbl_name not like 'INFORMATION_SCHEMA_%' ) BT order by TABLE_TYPE , TABLE_NAME
|
||||
|
||||
--- 3.0
|
||||
* --enable-full-text-searching
|
||||
CONTAINS full text index, stemming, etc.
|
||||
* server
|
||||
* replication
|
||||
* build in severial replication methods, TCP p2p, TCP broadcast,
|
||||
UDP broadcast, multicast
|
||||
* discovery
|
||||
* on mac, use rendevous
|
||||
* on UNIX use SLRP
|
||||
* use kqueues, /dev/poll, rt-signals etc - I think there is a lib that abstracts this
|
||||
|
||||
--- Debugging
|
||||
* build dbsql_sim - randomly exercises the system hoping to uncover bugs
|
||||
* build dbsql_perf - measures performance of things relase/release vs baseline
|
||||
* OSDB http://osdb.sourceforge.net/
|
||||
|
||||
--- Missing SQL92 features
|
||||
* TRUNCATE table [tablename]
|
||||
* ???
|
||||
|
||||
--- Competition
|
||||
* http://mindprod.com/jgloss/sql.html
|
||||
|
||||
--- Everything else...
|
||||
* look at the API of http://www.xtgsystems.com/linux/simdb/doc.php
|
||||
* http://www.sqlsummit.com/ODBCPORT.HTM
|
||||
* http://en.wikipedia.org/wiki/ODBC
|
||||
* dbExpress, is it some ODBC-like API
|
||||
* http://www.thinksql.co.uk/Main/Documents/Multiversion.html
|
||||
* http://www.rpbourret.com/xml/XMLDatabaseProds.htm
|
||||
* http://www.rpbourret.com/xml/XMLAndDatabases.htm
|
||||
|
||||
--- Google AdWords
|
||||
|
||||
MySQL, sql, sql92, sqlite, jet database, ms access, access, sql engine,
|
||||
|
||||
|
||||
--- References
|
||||
|
||||
http://www.wiscorp.com/SQLStandards.html
|
||||
http://www.ocelot.ca/nist.htm
|
||||
http://www.jcc.com/SQLPages/jccs_sql.htm
|
||||
http://www.tdan.com/i016hy01.htm
|
||||
http://www.mimer.com/news.asp?secId=176&itemId=10
|
||||
http://www.itl.nist.gov/div897/ctg/sql-testing/sqlman60.htm
|
||||
http://www.opengroup.org/public/tech/datam/sql.htm
|
||||
http://www.dwm.uni-hildesheim.de/homes/r_maximi/SQL1998/CLICK_ME_SECOND.html
|
||||
http://www.iam.unibe.ch/~scg/Archive/Software/FreeDB/FreeDB.list.html
|
||||
http://www.infres.enst.fr/naw-home/doc/srfsqlhtml_bnf.html
|
||||
http://www.ontko.com/~rayo/database.html
|
||||
http://www.ocelot.ca/sites.htm
|
||||
http://www.sqlcorner.com/
|
||||
http://www.codebox.8m.com/sql.htm
|
||||
http://sqlzoo.net/sql92.html
|
||||
http://www.opengroup.org/testing/testsuites/nistsql.htm
|
||||
http://ou800doc.caldera.com/SDK_netapi/CTOC-xtiN.intro.html
|
||||
http://cui.unige.ch/db-research/Enseignement/analyseinfo/SQL7/BNFindex.html
|
||||
http://cui.unige.ch/db-research/Enseignement/analyseinfo/SQL92/BNFindex.html
|
||||
http://cui.unige.ch/db-research/Enseignement/analyseinfo/PLSQL21/BNFindex.html
|
||||
http://wombat.doc.ic.ac.uk/foldoc/foldoc.cgi?relational+algebra
|
||||
http://support.openlinksw.com/support/mac-faq.html
|
||||
|
||||
@misc{ gukal-fast,
|
||||
author = "Sreenivas Gukal and Edward Omiecinski and Umakishore Ramachandran",
|
||||
title = "Fast Recovery in Transient-Versioned Databases",
|
||||
url = "citeseer.nj.nec.com/38354.html" }
|
270
src/api_table.c
Normal file
270
src/api_table.c
Normal file
|
@ -0,0 +1,270 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains the __api_get_table() and __api_free_table()
|
||||
* interface routines. These are just wrappers around the main
|
||||
* interface routine of DBSQL->exec().
|
||||
*
|
||||
* These routines are in a separate files so that they will not be linked
|
||||
* if they are not used.
|
||||
*/
|
||||
#include "dbsql_config.h"
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "dbsql_int.h"
|
||||
|
||||
/*
|
||||
* This structure is used to pass data from __get_table() through
|
||||
* to the user's callback function.
|
||||
*/
|
||||
typedef struct table_result {
|
||||
char **result;
|
||||
char *err_msgs;
|
||||
u_int32_t num_result;
|
||||
u_int32_t num_alloc;
|
||||
u_int32_t num_row;
|
||||
u_int32_t num_col;
|
||||
u_int32_t num_data;
|
||||
u_int32_t rc;
|
||||
} table_result_t;
|
||||
|
||||
/*
|
||||
* __get_table_cb --
|
||||
* This routine is called once for each row in the result table. Its job
|
||||
* is to fill in the table_result_t structure appropriately, allocating
|
||||
* new memory as necessary.
|
||||
*
|
||||
* STATIC: static int __get_table_cb __P((void *, int, char **, char **));
|
||||
*/
|
||||
static int
|
||||
__get_table_cb(void* arg, int ncol, char* *argv, char* *colv)
|
||||
{
|
||||
int rc;
|
||||
table_result_t *p = (table_result_t*)arg;
|
||||
int need;
|
||||
int i;
|
||||
char *z;
|
||||
|
||||
/*
|
||||
* Make sure there is enough space in p->result to hold everything
|
||||
* we need to remember from this invocation of the callback.
|
||||
*/
|
||||
if (p->num_row == 0 && argv != 0) {
|
||||
need = ncol * 2;
|
||||
} else {
|
||||
need = ncol;
|
||||
}
|
||||
if (p->num_data + need >= p->num_alloc) {
|
||||
p->num_alloc = (p->num_alloc * 2) + need + 1;
|
||||
rc = __dbsql_realloc(NULL, sizeof(char*) * p->num_alloc,
|
||||
&p->result);
|
||||
if (rc == ENOMEM) {
|
||||
p->rc = DBSQL_NOMEM;
|
||||
return DBSQL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is the first row, then generate an extra row containing
|
||||
* the names of all columns.
|
||||
*/
|
||||
if (p->num_row==0) {
|
||||
p->num_col = ncol;
|
||||
for (i = 0; i < ncol; i++) {
|
||||
if (colv[i] == 0) {
|
||||
z = 0;
|
||||
} else {
|
||||
int rc = __dbsql_malloc(NULL,
|
||||
strlen(colv[i]) + 1, &z);
|
||||
if (rc == ENOMEM) {
|
||||
p->rc = DBSQL_NOMEM;
|
||||
return DBSQL_ERROR;
|
||||
}
|
||||
strcpy(z, colv[i]);
|
||||
}
|
||||
p->result[p->num_data++] = z;
|
||||
}
|
||||
} else if (p->num_col != ncol) {
|
||||
__str_append(&p->err_msgs,
|
||||
"DBSQL->get_table() called with two or more "
|
||||
"incompatible queries", (char*)0);
|
||||
p->rc = DBSQL_ERROR;
|
||||
return DBSQL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy over the row data.
|
||||
*/
|
||||
if (argv != 0) {
|
||||
for (i = 0; i < ncol; i++) {
|
||||
if (argv[i] == 0) {
|
||||
z = 0;
|
||||
} else {
|
||||
if (__dbsql_malloc(NULL, strlen(argv[i]) + 1,
|
||||
&z) == ENOMEM) {
|
||||
p->rc = DBSQL_NOMEM;
|
||||
return DBSQL_ERROR;
|
||||
}
|
||||
strcpy(z, argv[i]);
|
||||
}
|
||||
p->result[p->num_data++] = z;
|
||||
}
|
||||
p->num_row++;
|
||||
}
|
||||
return DBSQL_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* __api_get_table --
|
||||
* Query the database. But instead of invoking a callback for each row,
|
||||
* __dbsql_malloc() space to hold the result and return the entire results
|
||||
* at the conclusion of the call.
|
||||
* The result that is written to ***results is held in memory obtained
|
||||
* from __dbsql_malloc(). But the caller cannot free this memory directly
|
||||
* Instead, the entire table should be passed to DBSQL->free_table() when
|
||||
* the calling procedure is finished using it.
|
||||
*
|
||||
* PUBLIC: int __api_get_table __P((DBSQL *, const char *, char ***, int *,
|
||||
* PUBLIC: int *, char **));
|
||||
*
|
||||
* dbp The database on which the SQL executes
|
||||
* sql The SQL to be executed
|
||||
* results Write the result table here
|
||||
* nrows Write the number of rows in the result here
|
||||
* ncols Write the number of columns of result here
|
||||
* err_msgs Write error messages here
|
||||
*/
|
||||
int
|
||||
__api_get_table(dbp, sql, results, nrows, ncols, err_msgs)
|
||||
DBSQL *dbp;
|
||||
const char *sql;
|
||||
char ***results;
|
||||
int *nrows;
|
||||
int *ncols;
|
||||
char **err_msgs;
|
||||
{
|
||||
int rc;
|
||||
table_result_t res;
|
||||
|
||||
DBSQL_ASSERT(results);
|
||||
DBSQL_ASSERT(ncols);
|
||||
DBSQL_ASSERT(nrows);
|
||||
|
||||
*results = 0;
|
||||
*ncols = 0;
|
||||
*nrows = 0;
|
||||
res.err_msgs = 0;
|
||||
res.num_result = 0;
|
||||
res.num_row = 0;
|
||||
res.num_col = 0;
|
||||
res.num_data = 1;
|
||||
res.num_alloc = 20;
|
||||
res.rc = DBSQL_SUCCESS;
|
||||
|
||||
if (__dbsql_calloc(dbp, res.num_alloc, sizeof(char*),
|
||||
&res.result) == ENOMEM)
|
||||
return DBSQL_NOMEM;
|
||||
rc = dbp->exec(dbp, sql, __get_table_cb, &res, err_msgs);
|
||||
if (rc == DBSQL_ABORT) {
|
||||
/* !!!
|
||||
* We set this here because we're about to call free_table, but we
|
||||
* have to set it again below because a realloc may have moved the
|
||||
* memory around
|
||||
*/
|
||||
res.result[0] = res.result[1] + res.num_data;
|
||||
dbp->free_table(&res.result[1]);
|
||||
if (res.err_msgs) {
|
||||
if(err_msgs) {
|
||||
__dbsql_ufree(dbp, *err_msgs);
|
||||
*err_msgs = res.err_msgs;
|
||||
__str_urealloc(err_msgs);
|
||||
} else {
|
||||
__dbsql_free(dbp, res.err_msgs);
|
||||
}
|
||||
}
|
||||
return res.rc;
|
||||
}
|
||||
__dbsql_free(dbp, res.err_msgs);
|
||||
if (rc != DBSQL_SUCCESS) {
|
||||
dbp->free_table(&res.result[1]);
|
||||
return rc;
|
||||
}
|
||||
if (res.num_alloc > res.num_data) {
|
||||
if(__dbsql_realloc(dbp, sizeof(char*) * (res.num_data + 1),
|
||||
&res.result) == ENOMEM) {
|
||||
dbp->free_table(&res.result[1]);
|
||||
return DBSQL_NOMEM;
|
||||
}
|
||||
res.num_alloc = res.num_data + 1;
|
||||
}
|
||||
/* !!!
|
||||
* free_table() will need to know when to stop freeing results. We use result[0]
|
||||
* as a pointer to the last allocated row to be free'd. The number of rows to
|
||||
* be free'd is 'result[0] - (&result[1])'.
|
||||
*/
|
||||
res.result[0] = res.result[1] + res.num_data;
|
||||
*results = &res.result[1];
|
||||
if (ncols)
|
||||
*ncols = res.num_col;
|
||||
if (nrows)
|
||||
*nrows = res.num_row;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* __api_free_table --
|
||||
* This routine frees the space the DBSQL->get_table() __dbsql_malloc'ed.
|
||||
* There are two things to be free'd, (a) each row (results[0..n]) and then (b) the
|
||||
* array 'results'. The number of rows to be free'd is 'result[-1] - (&result[0])'.
|
||||
*
|
||||
* PUBLIC: void __api_free_table __P((char **));
|
||||
*
|
||||
* result Result returned from from __api_get_table()
|
||||
*/
|
||||
void
|
||||
__api_free_table(char* *results)
|
||||
{
|
||||
char *last_result;
|
||||
|
||||
DBSQL_ASSERT(results);
|
||||
|
||||
/* If this test is false then the result set is empty, only free (b) */
|
||||
if (*(results - 1) != *results) {
|
||||
/* !!!
|
||||
* The address of the last results row is the value of the first element of
|
||||
* the results array we created in get_table() but recall that we passed
|
||||
* the address of the second element (&results[1]) to the user and so
|
||||
* we need to read the memory of what used to be 'results[0]' which is
|
||||
* now '*(results - 1)'.
|
||||
*/
|
||||
last_result = *(results - 1);
|
||||
while (*results <= last_result) {
|
||||
if (*results != NULL)
|
||||
__dbsql_ufree(NULL, *results);
|
||||
results++;
|
||||
}
|
||||
}
|
||||
__dbsql_ufree(NULL, results);
|
||||
}
|
381
src/cg_attach.c
Normal file
381
src/cg_attach.c
Normal file
|
@ -0,0 +1,381 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains C code routines that are called by the parser
|
||||
* to handle ATTACH and DETACH statements.
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
#include "dbsql_int.h"
|
||||
|
||||
/*
|
||||
* __attach --
|
||||
* This routine is called by the parser to process an ATTACH statement:
|
||||
*
|
||||
* ATTACH DATABASE filename AS dbname
|
||||
*
|
||||
* The 'file' and 'db' arguments are the tokens that define the
|
||||
* 'file' and 'db' in the ATTACH statement.
|
||||
*
|
||||
* PUBLIC: void __attach __P((parser_t *, token_t *, token_t *));
|
||||
*/
|
||||
void
|
||||
__attach(parser_t* parser, token_t* file, token_t* db)
|
||||
{
|
||||
int rc, i;
|
||||
dbsql_db_t *new;
|
||||
char *filename, *databasename;
|
||||
DBSQL *dbp;
|
||||
vdbe_t *v;
|
||||
|
||||
v = __parser_get_vdbe(parser);
|
||||
__vdbe_add_op(v, OP_Halt, 0, 0);
|
||||
if (parser->explain)
|
||||
return;
|
||||
dbp = parser->db;
|
||||
if (dbp->format_version < 1) {
|
||||
__error_msg(parser, "cannot attach auxiliary databases to an "
|
||||
"older format master database", 0);
|
||||
parser->rc = DBSQL_ERROR;
|
||||
return;
|
||||
}
|
||||
if (dbp->nDb >= (MAX_ATTACHED + 2)) {
|
||||
__error_msg(parser, "too many attached databases - max %d",
|
||||
MAX_ATTACHED);
|
||||
parser->rc = DBSQL_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
filename = 0;
|
||||
__str_nappend(&filename, file->z, file->n, NULL);
|
||||
if (filename == 0)
|
||||
return;
|
||||
__str_unquote(filename);
|
||||
#ifndef DBSQL_NO_AUTH
|
||||
if (__auth_check(parser, DBSQL_ATTACH, filename, 0, 0) !=
|
||||
DBSQL_SUCCESS) {
|
||||
__dbsql_free(dbp, filename);
|
||||
return;
|
||||
}
|
||||
#endif /* DBSQL_NO_AUTH */
|
||||
|
||||
databasename = 0;
|
||||
__str_nappend(&databasename, db->z, db->n, NULL);
|
||||
if (databasename == 0)
|
||||
return;
|
||||
__str_unquote(databasename);
|
||||
for (i = 0; i < dbp->nDb; i++) {
|
||||
if (dbp->aDb[i].zName && strcasecmp(
|
||||
dbp->aDb[i].zName, databasename) == 0) {
|
||||
__error_msg(parser, "database %z is already in use",
|
||||
databasename);
|
||||
parser->rc = DBSQL_ERROR;
|
||||
__dbsql_free(dbp, filename);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (__dbsql_realloc(dbp, (sizeof(dbp->aDb[0]) *
|
||||
(dbp->nDb + 1)), &dbp->aDb) == ENOMEM)
|
||||
return;
|
||||
new = &dbp->aDb[(dbp->nDb++)];
|
||||
memset(new, 0, sizeof(*new));
|
||||
if (__sqldb_init(new, dbp, filename, 0, 0, 1) != 0) {
|
||||
__error_msg(parser, "unable to open database: %s", filename);
|
||||
}
|
||||
new->zName = databasename;
|
||||
__dbsql_free(dbp, filename);
|
||||
dbp->flags &= ~DBSQL_Initialized;
|
||||
if (parser->nErr)
|
||||
return;
|
||||
if (rc == DBSQL_SUCCESS) {
|
||||
rc = __init_databases(parser->db, &parser->zErrMsg);
|
||||
}
|
||||
if (rc) {
|
||||
i = dbp->nDb - 1;
|
||||
DBSQL_ASSERT(i >= 2);
|
||||
if (dbp->aDb[i].pBt) {
|
||||
__sm_close_db(dbp->aDb[i].pBt);
|
||||
dbp->aDb[i].pBt = 0;
|
||||
}
|
||||
__reset_internal_schema(dbp, 0);
|
||||
parser->nErr++;
|
||||
parser->rc = DBSQL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* __detach --
|
||||
* This routine is called by the parser to process a DETACH statement:
|
||||
*
|
||||
* DETACH DATABASE db
|
||||
*
|
||||
* The db argument is the name of the database in the DETACH statement.
|
||||
*
|
||||
* PUBLIC: void __detach __P((parser_t *, token_t *));
|
||||
*/
|
||||
void
|
||||
__detach(parser_t* parser, token_t* db)
|
||||
{
|
||||
int i;
|
||||
DBSQL *dbp;
|
||||
vdbe_t *v = __parser_get_vdbe(parser);
|
||||
__vdbe_add_op(v, OP_Halt, 0, 0);
|
||||
if (parser->explain)
|
||||
return;
|
||||
dbp = parser->db;
|
||||
for (i = 0; i < dbp->nDb; i++) {
|
||||
if (dbp->aDb[i].pBt == 0 ||
|
||||
dbp->aDb[i].zName == 0)
|
||||
continue;
|
||||
if (strlen(dbp->aDb[i].zName) != db->n)
|
||||
continue;
|
||||
if (strncasecmp(dbp->aDb[i].zName, db->z, db->n) == 0)
|
||||
break;
|
||||
}
|
||||
if (i >= dbp->nDb) {
|
||||
__error_msg(parser, "no such database: %T", db);
|
||||
return;
|
||||
}
|
||||
if (i < 2) {
|
||||
__error_msg(parser, "cannot detach database %T", db);
|
||||
return;
|
||||
}
|
||||
#ifndef DBSQL_NO_AUTH
|
||||
if (__auth_check(parser, DBSQL_DETACH, dbp->aDb[i].zName, 0, 0) !=
|
||||
DBSQL_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
#endif /* DBSQL_NO_AUTH */
|
||||
__sm_close_db(dbp->aDb[i].pBt);
|
||||
dbp->aDb[i].pBt = 0;
|
||||
__dbsql_free(dbp, dbp->aDb[i].zName);
|
||||
__reset_internal_schema(dbp, i);
|
||||
dbp->nDb--;
|
||||
if (i < dbp->nDb) {
|
||||
dbp->aDb[i] = dbp->aDb[dbp->nDb];
|
||||
memset(&dbp->aDb[dbp->nDb], 0, sizeof(dbp->aDb[0]));
|
||||
__reset_internal_schema(dbp, i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* __ref_normalizer_ctx_init --
|
||||
* Initialize a ref_normalizer_ctx_t structure. This routine must be
|
||||
* called prior to passing the structure to one of the
|
||||
* __ref_normalize_XXX() routines below. The return value indicates
|
||||
* whether or not normalization is required. TRUE means we do need to
|
||||
* fix the database references, FALSE means we do not.
|
||||
*
|
||||
* PUBLIC: int __ref_normalizer_ctx_init __P((ref_normalizer_ctx_t *,
|
||||
* PUBLIC: parser_t *, int, const char *,
|
||||
* PUBLIC: const token_t *));
|
||||
*
|
||||
* normctx The normalizer to be initialized
|
||||
* parser Error messages will be written here
|
||||
* dbnum This is the database that must must be used
|
||||
* type "view", "trigger", or "index"
|
||||
* name Name of the view, trigger, or index
|
||||
*/
|
||||
int
|
||||
__ref_normalizer_ctx_init(normctx, parser, dbnum, type, name)
|
||||
ref_normalizer_ctx_t *normctx;
|
||||
parser_t *parser;
|
||||
int dbnum;
|
||||
const char *type;
|
||||
const token_t *name;
|
||||
{
|
||||
DBSQL *dbp;
|
||||
|
||||
if (dbnum < 0 || dbnum == 1)
|
||||
return 0;
|
||||
dbp = parser->db;
|
||||
DBSQL_ASSERT(dbp->nDb > dbnum);
|
||||
normctx->pParse = parser;
|
||||
normctx->zDb = dbp->aDb[dbnum].zName;
|
||||
normctx->zType = type;
|
||||
normctx->pName = name;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* __ref_normalize_src_list --
|
||||
* The following set of routines walk through the parse tree and assign
|
||||
* a specific database to all table references where the database name
|
||||
* was left unspecified in the original SQL statement. The normctx
|
||||
* structure must have been initialized by a prior call to
|
||||
* __ref_normalizer_ctx_init().
|
||||
*
|
||||
* These routines are used to make sure that an index, trigger, or
|
||||
* view in one database does not refer to objects in a different database.
|
||||
* (Exception: indices, triggers, and views in the TEMP database are
|
||||
* allowed to refer to anything.) If a reference is explicitly made
|
||||
* to an object in a different database, an error message is added to
|
||||
* parser->zErrMsg and these routines return non-zero. If everything
|
||||
* checks out, these routines return 0.
|
||||
*
|
||||
* PUBLIC: int __ref_normalize_src_list __P((ref_normalizer_ctx_t *,
|
||||
* PUBLIC: src_list_t *));
|
||||
*
|
||||
* normctx Context of the normalization
|
||||
* src_list The source list to check and modify
|
||||
*/
|
||||
int __ref_normalize_src_list(normctx, src_list)
|
||||
ref_normalizer_ctx_t *normctx;
|
||||
src_list_t *src_list;
|
||||
{
|
||||
int i;
|
||||
const char *db;
|
||||
DBSQL *dbp = normctx->pParse->db;
|
||||
|
||||
if (src_list == 0)
|
||||
return 0;
|
||||
db = normctx->zDb;
|
||||
for (i = 0; i < src_list->nSrc; i++) {
|
||||
if (src_list->a[i].zDatabase == 0) {
|
||||
__dbsql_strdup(dbp, db, &src_list->a[i].zDatabase);
|
||||
} else if (strcasecmp(src_list->a[i].zDatabase, db) != 0) {
|
||||
char *name;
|
||||
__dbsql_strndup(dbp, normctx->pName->z, &name,
|
||||
normctx->pName->n);
|
||||
__error_msg(normctx->pParse, "%s %z cannot reference "
|
||||
"objects in database %s", normctx->zType,
|
||||
name, src_list->a[i].zDatabase);
|
||||
return 1;
|
||||
}
|
||||
if (__ref_normalize_select(normctx, src_list->a[i].pSelect))
|
||||
return 1;
|
||||
if (__ref_normalize_expr(normctx, src_list->a[i].pOn))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* __ref_normalize_select --
|
||||
*
|
||||
* PUBLIC: int __ref_normalize_select __P((ref_normalizer_ctx_t *,
|
||||
* PUBLIC: select_t *));
|
||||
*
|
||||
* normctx Context of the normalization
|
||||
* select The SELECT statement to be fixed to one
|
||||
* database
|
||||
*/
|
||||
int
|
||||
__ref_normalize_select(ref_normalizer_ctx_t* normctx, select_t* select)
|
||||
{
|
||||
while (select) {
|
||||
if (__ref_normalize_expr_list(normctx, select->pEList)) {
|
||||
return 1;
|
||||
}
|
||||
if (__ref_normalize_src_list(normctx, select->pSrc)) {
|
||||
return 1;
|
||||
}
|
||||
if (__ref_normalize_expr(normctx, select->pWhere)) {
|
||||
return 1;
|
||||
}
|
||||
if (__ref_normalize_expr(normctx, select->pHaving)) {
|
||||
return 1;
|
||||
}
|
||||
select = select->pPrior;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* __ref_normalize_expr --
|
||||
*
|
||||
* PUBLIC: int __ref_normalize_expr __P((ref_normalizer_ctx_t *,
|
||||
* PUBLIC: expr_t *));
|
||||
*
|
||||
* normctx Context of the normalization
|
||||
* expr The expr_t to be fixed to one database
|
||||
*/
|
||||
int __ref_normalize_expr(normctx, expr)
|
||||
ref_normalizer_ctx_t *normctx;
|
||||
expr_t *expr;
|
||||
{
|
||||
while (expr) {
|
||||
if (__ref_normalize_select(normctx, expr->pSelect)) {
|
||||
return 1;
|
||||
}
|
||||
if (__ref_normalize_expr_list(normctx, expr->pList)) {
|
||||
return 1;
|
||||
}
|
||||
if (__ref_normalize_expr(normctx, expr->pRight)) {
|
||||
return 1;
|
||||
}
|
||||
expr = expr->pLeft;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* __ref_normalize_expr_list --
|
||||
*
|
||||
* PUBLIC: int __ref_normalize_expr_list __P((ref_normalizer_ctx_t *,
|
||||
* PUBLIC: expr_list_t *));
|
||||
*
|
||||
* normctx Context of the normalization
|
||||
* expr The expression to be fixed to one database
|
||||
*/
|
||||
int
|
||||
__ref_normalize_expr_list(ref_normalizer_ctx_t* normctx, expr_list_t* list)
|
||||
{
|
||||
int i;
|
||||
if (list == 0)
|
||||
return 0;
|
||||
for (i = 0; i < list->nExpr; i++) {
|
||||
if (__ref_normalize_expr(normctx, list->a[i].pExpr)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* __ref_normalize_trigger_step --
|
||||
*
|
||||
* PUBLIC: int __ref_normalize_trigger_step __P((ref_normalizer_ctx_t *,
|
||||
* PUBLIC: trigger_step_t *));
|
||||
*
|
||||
* normctx Context of the normalization
|
||||
* expr The trigger step to be fixed to one database
|
||||
*/
|
||||
int __ref_normalize_trigger_step(normctx, step)
|
||||
ref_normalizer_ctx_t *normctx;
|
||||
trigger_step_t *step;
|
||||
{
|
||||
while (step) {
|
||||
if (__ref_normalize_select(normctx, step->pSelect)) {
|
||||
return 1;
|
||||
}
|
||||
if (__ref_normalize_expr(normctx, step->pWhere)) {
|
||||
return 1;
|
||||
}
|
||||
if (__ref_normalize_expr_list(normctx, step->pExprList)) {
|
||||
return 1;
|
||||
}
|
||||
step = step->pNext;
|
||||
}
|
||||
return 0;
|
||||
}
|
275
src/cg_auth.c
Normal file
275
src/cg_auth.c
Normal file
|
@ -0,0 +1,275 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains code used to implement the __api_set_auth_callback()
|
||||
* API. This facility is an optional feature of the library. Embedded
|
||||
* systems that do not need this facility may omit it by reconfiguring
|
||||
* with '--disable-auth'. Then recompile the entire library.
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
#include "dbsql_int.h"
|
||||
|
||||
#ifndef DBSQL_OMIT_AUTHORIZATION
|
||||
|
||||
/*
|
||||
* Set or clear the access authorization function.
|
||||
* The access authorization function is be called during the compilation
|
||||
* phase to verify that the user has read and/or write access permission
|
||||
* on various fields of the database. The first argument to the auth
|
||||
* function is a copy of the 3rd argument to this routine. The second
|
||||
* argument to the auth function is one of these constants:
|
||||
*
|
||||
* DBSQL_COPY
|
||||
* DBSQL_CREATE_INDEX
|
||||
* DBSQL_CREATE_TABLE
|
||||
* DBSQL_CREATE_TEMP_INDEX
|
||||
* DBSQL_CREATE_TEMP_TABLE
|
||||
* DBSQL_CREATE_TEMP_TRIGGER
|
||||
* DBSQL_CREATE_TEMP_VIEW
|
||||
* DBSQL_CREATE_TRIGGER
|
||||
* DBSQL_CREATE_VIEW
|
||||
* DBSQL_DELETE
|
||||
* DBSQL_DROP_INDEX
|
||||
* DBSQL_DROP_TABLE
|
||||
* DBSQL_DROP_TEMP_INDEX
|
||||
* DBSQL_DROP_TEMP_TABLE
|
||||
* DBSQL_DROP_TEMP_TRIGGER
|
||||
* DBSQL_DROP_TEMP_VIEW
|
||||
* DBSQL_DROP_TRIGGER
|
||||
* DBSQL_DROP_VIEW
|
||||
* DBSQL_INSERT
|
||||
* DBSQL_PRAGMA
|
||||
* DBSQL_READ
|
||||
* DBSQL_SELECT
|
||||
* DBSQL_TRANSACTION
|
||||
* DBSQL_UPDATE
|
||||
*
|
||||
* The third and fourth arguments to the auth function are the name of
|
||||
* the table and the column that are being accessed. The auth function
|
||||
* should return either DBSQL_SUCCESS, DBSQL_DENY, or DBSQL_IGNORE. If
|
||||
* DBSQL_SUCCESS is returned, it means that access is allowed. DBSQL_DENY
|
||||
* means that the SQL statement will never-run - the dbsql_exec() call
|
||||
* will return with an error. DBSQL_IGNORE means that the SQL statement
|
||||
* should run but attempts to read the specified column will return NULL
|
||||
* and attempts to write the column will be ignored.
|
||||
*
|
||||
* Setting the auth function to NULL disables this hook. The default
|
||||
* setting of the auth function is NULL.
|
||||
*
|
||||
* PUBLIC: int __api_set_authorizer __P((DBSQL *,
|
||||
* PUBLIC: int (*auth)(void*,int,const char*, const char*,const char*,
|
||||
* PUBLIC: const char*), void *));
|
||||
*/
|
||||
int __api_set_authorizer(dbp, auth, arg)
|
||||
DBSQL *dbp;
|
||||
int (*auth)(void*,int,const char*,const char*,const char*,const char*);
|
||||
void *arg;
|
||||
{
|
||||
dbp->auth = auth;
|
||||
dbp->pAuthArg = arg;
|
||||
return DBSQL_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* __auth_bad_return_code --
|
||||
* Write an error message into pParse->zErrMsg that explains that the
|
||||
* user-supplied authorization function returned an illegal value.
|
||||
*
|
||||
* STATIC: static void __auth_bad_return_code __P((parser_t *, int));
|
||||
*/
|
||||
static void
|
||||
__auth_bad_return_code(parser_t* parser, int rc)
|
||||
{
|
||||
char buf[20];
|
||||
sprintf(buf, "(%d)", rc);
|
||||
__str_append(&parser->zErrMsg, "illegal return value ",
|
||||
buf, " from the authorization function - ",
|
||||
"should be DBSQL_SUCCESS, DBSQL_IGNORE, or DBSQL_DENY",
|
||||
(char*)0);
|
||||
parser->nErr++;
|
||||
parser->rc = DBSQL_MISUSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* __auth_read --
|
||||
* The 'expr' should be a TK_COLUMN expression. The table referred to
|
||||
* is in 'tab_list' or else it is the NEW or OLD table of a trigger.
|
||||
* Check to see if it is OK to read this particular column.
|
||||
*
|
||||
* If the auth function returns DBSQL_IGNORE, change the TK_COLUMN
|
||||
* instruction into a TK_NULL. If the auth function returns DBSQL_DENY,
|
||||
* then generate an error.
|
||||
*
|
||||
* PUBLIC: void __auth_read __P((parser_t *, expr_t *, src_list_t *));
|
||||
*
|
||||
* parser The parser context
|
||||
* expr The expression to check authorization on
|
||||
* tab_list All table that expr might refer to
|
||||
*/
|
||||
void
|
||||
__auth_read(parser_t* parser, expr_t* expr, src_list_t* tab_list)
|
||||
{
|
||||
int rc;
|
||||
DBSQL *dbp = parser->db;
|
||||
table_t *table; /* The table being read */
|
||||
const char *col; /* Name of the column of the table */
|
||||
int src; /* Index in tab_list->a[] of table being read */
|
||||
const char *databasename; /* Name of database being accessed */
|
||||
trigger_stack_t *stack; /* The stack of current triggers */
|
||||
|
||||
if (dbp->auth == 0)
|
||||
return;
|
||||
DBSQL_ASSERT(expr->op == TK_COLUMN);
|
||||
for (src = 0; src < tab_list->nSrc; src++) {
|
||||
if (expr->iTable == tab_list->a[src].iCursor)
|
||||
break;
|
||||
}
|
||||
if (src >= 0 && src < tab_list->nSrc) {
|
||||
table = tab_list->a[src].pTab;
|
||||
} else {
|
||||
/*
|
||||
* This must be an attempt to read the NEW or OLD pseudo-tables
|
||||
* of a trigger.
|
||||
*/
|
||||
stack = parser->trigStack;
|
||||
DBSQL_ASSERT(stack != 0);
|
||||
DBSQL_ASSERT(expr->iTable == stack->newIdx ||
|
||||
expr->iTable == stack->oldIdx);
|
||||
table = stack->pTab;
|
||||
}
|
||||
if (table == 0)
|
||||
return;
|
||||
if (expr->iColumn >= 0) {
|
||||
DBSQL_ASSERT(expr->iColumn < table->nCol);
|
||||
col = table->aCol[expr->iColumn].zName;
|
||||
} else if (table->iPKey >= 0) {
|
||||
DBSQL_ASSERT(table->iPKey < table->nCol);
|
||||
col = table->aCol[table->iPKey].zName;
|
||||
} else {
|
||||
col = "ROWID";
|
||||
}
|
||||
DBSQL_ASSERT(expr->iDb < dbp->nDb);
|
||||
databasename = dbp->aDb[expr->iDb].zName;
|
||||
rc = dbp->auth(dbp->pAuthArg, DBSQL_READ, table->zName,
|
||||
col, databasename, parser->zAuthContext);
|
||||
if (rc == DBSQL_IGNORE) {
|
||||
expr->op = TK_NULL;
|
||||
} else if (rc == DBSQL_DENY) {
|
||||
if (dbp->nDb > 2 || expr->iDb != 0) {
|
||||
__str_append(&parser->zErrMsg,"access to ",
|
||||
databasename, ".", table->zName, ".",
|
||||
col, " is prohibited", (char*)0);
|
||||
} else {
|
||||
__str_append(&parser->zErrMsg,"access to ",
|
||||
table->zName, ".", col, " is prohibited",
|
||||
(char*)0);
|
||||
}
|
||||
parser->nErr++;
|
||||
parser->rc = DBSQL_AUTH;
|
||||
} else if (rc != DBSQL_SUCCESS) {
|
||||
__auth_bad_return_code(parser, rc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* __auth_check --
|
||||
* Do an authorization check using the code and arguments given. Return
|
||||
* either DBSQL_SUCCESS (zero) or DBSQL_IGNORE or DBSQL_DENY. If
|
||||
* DBSQL_DENY is returned, then the error count and error message in
|
||||
* parser are modified appropriately.
|
||||
*
|
||||
* PUBLIC: int __auth_check __P((parser_t *, int, const char *, const char *,
|
||||
* PUBLIC: const char *));
|
||||
*/
|
||||
int
|
||||
__auth_check(parser, code, arg1, arg2, arg3)
|
||||
parser_t *parser;
|
||||
int code;
|
||||
const char *arg1;
|
||||
const char *arg2;
|
||||
const char *arg3;
|
||||
{
|
||||
int rc;
|
||||
DBSQL *dbp = parser->db;
|
||||
|
||||
if (dbp->auth == 0) {
|
||||
return DBSQL_SUCCESS;
|
||||
}
|
||||
rc = dbp->auth(dbp->pAuthArg, code, arg1, arg2, arg3,
|
||||
parser->zAuthContext);
|
||||
if (rc == DBSQL_DENY) {
|
||||
__str_append(&parser->zErrMsg, "not authorized",
|
||||
(char*)0);
|
||||
parser->rc = DBSQL_AUTH;
|
||||
parser->nErr++;
|
||||
} else if (rc != DBSQL_SUCCESS && rc != DBSQL_IGNORE) {
|
||||
rc = DBSQL_DENY;
|
||||
__auth_bad_return_code(parser, rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* __auth_context_push --
|
||||
* Push an authorization context. After this routine is called, the
|
||||
* arg3 argument to authorization callbacks will be context until
|
||||
* popped. Or if parser==0, this routine is a no-op.
|
||||
*
|
||||
* PUBLIC: void __auth_context_push __P((parser_t *, auth_context_t *,
|
||||
* PUBLIC: const char *));
|
||||
*/
|
||||
void __auth_context_push(parser, authctx, context)
|
||||
parser_t *parser;
|
||||
auth_context_t *authctx;
|
||||
const char *context;
|
||||
{
|
||||
authctx->pParse = parser;
|
||||
if (parser) {
|
||||
authctx->zAuthContext = parser->zAuthContext;
|
||||
parser->zAuthContext = context;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* __auth_context_pop --
|
||||
* Pop an authorization context that was previously pushed
|
||||
* by __auth_context_push.
|
||||
*
|
||||
* PUBLIC: void __auth_context_pop __P((auth_context_t *));
|
||||
*/
|
||||
void
|
||||
__auth_context_pop(auth_context_t* authctx)
|
||||
{
|
||||
if (authctx->pParse) {
|
||||
authctx->pParse->zAuthContext = authctx->zAuthContext;
|
||||
authctx->pParse = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* TODO what is the difference between DBSQL_OMIT_AUTHORIZATION and
|
||||
DBSQL_NO_AUTH? Which one should be used here? Setup a test case for this.*/
|
||||
|
||||
# define __auth_check(a,b,c,d,e) DBSQL_SUCCESS
|
||||
|
||||
#endif /* !defined(DBSQL_OMIT_AUTHORIZATION) */
|
2715
src/cg_build.c
Normal file
2715
src/cg_build.c
Normal file
File diff suppressed because it is too large
Load diff
150
src/cg_copy.c
Normal file
150
src/cg_copy.c
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This file contains code used to implement the COPY command.
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
#include "dbsql_int.h"
|
||||
|
||||
/*
|
||||
* __copy --
|
||||
* The COPY command is for compatibility with PostgreSQL and specificially
|
||||
* for the ability to read the output of pg_dump. The format is as
|
||||
* follows:
|
||||
*
|
||||
* COPY table FROM file [USING DELIMITERS string]
|
||||
*
|
||||
* "table" is an existing table name. We will read lines of code from
|
||||
* file to fill this table with data. File might be "stdin". The
|
||||
* optional delimiter string identifies the field separators. The
|
||||
* default is a tab.
|
||||
*
|
||||
* PUBLIC: void __copy __P((parser_t *, src_list_t *, token_t *,
|
||||
* PUBLIC: token_t *, int));
|
||||
*
|
||||
* parser The parser context
|
||||
* table_name The name of the table into which we will insert
|
||||
* filename The file from which to obtain information
|
||||
* delimiter Use this as the field delimiter
|
||||
* on_error What to do if a constraint fails
|
||||
*/
|
||||
void __copy(parser, table_name, filename, delimiter, on_error)
|
||||
parser_t *parser;
|
||||
src_list_t *table_name;
|
||||
token_t *filename;
|
||||
token_t *delimiter;
|
||||
int on_error;
|
||||
{
|
||||
table_t *table;
|
||||
int i;
|
||||
vdbe_t *v;
|
||||
int addr, end;
|
||||
index_t *index;
|
||||
char *file = 0;
|
||||
const char *db_name;
|
||||
DBSQL *db = parser->db;
|
||||
|
||||
if (parser->rc != DBSQL_SUCCESS)
|
||||
goto copy_cleanup;
|
||||
DBSQL_ASSERT(table_name->nSrc == 1);
|
||||
table = __src_list_lookup(parser, table_name);
|
||||
if (table==0 || __is_table_read_only(parser, table, 0))
|
||||
goto copy_cleanup;
|
||||
__dbsql_strndup(parser->db, filename->z, &file, filename->n);
|
||||
__str_unquote(file);
|
||||
DBSQL_ASSERT(table->iDb < db->nDb);
|
||||
db_name = db->aDb[table->iDb].zName;
|
||||
if (__auth_check(parser, DBSQL_INSERT, table->zName, 0, db_name) ||
|
||||
__auth_check(parser, DBSQL_COPY, table->zName, file, db_name)) {
|
||||
goto copy_cleanup;
|
||||
}
|
||||
v = __parser_get_vdbe(parser);
|
||||
if (v) {
|
||||
__vdbe_prepare_write(parser, 1, table->iDb);
|
||||
addr = __vdbe_add_op(v, OP_FileOpen, 0, 0);
|
||||
__vdbe_change_p3(v, addr, filename->z, filename->n);
|
||||
__vdbe_dequote_p3(v, addr);
|
||||
__vdbe_add_op(v, OP_Integer, table->iDb, 0);
|
||||
__vdbe_add_op(v, OP_OpenWrite, 0, table->tnum);
|
||||
__vdbe_change_p3(v, -1, table->zName, P3_STATIC);
|
||||
for(i = 1, index = table->pIndex; index;
|
||||
index=index->pNext, i++) {
|
||||
DBSQL_ASSERT(index->iDb == 1 || index->iDb == table->iDb);
|
||||
__vdbe_add_op(v, OP_Integer, index->iDb, 0);
|
||||
__vdbe_add_op(v, OP_OpenWrite, i, index->tnum);
|
||||
__vdbe_change_p3(v, -1, index->zName, P3_STATIC);
|
||||
}
|
||||
if (db->flags & DBSQL_CountRows) {
|
||||
/* Initialize the row count */
|
||||
__vdbe_add_op(v, OP_Integer, 0, 0);
|
||||
}
|
||||
end = __vdbe_make_label(v);
|
||||
addr = __vdbe_add_op(v, OP_FileRead, table->nCol, end);
|
||||
if (delimiter) {
|
||||
__vdbe_change_p3(v, addr, delimiter->z, delimiter->n);
|
||||
__vdbe_dequote_p3(v, addr);
|
||||
} else {
|
||||
__vdbe_change_p3(v, addr, "\t", 1);
|
||||
}
|
||||
if (table->iPKey >= 0) {
|
||||
__vdbe_add_op(v, OP_FileColumn, table->iPKey, 0);
|
||||
__vdbe_add_op(v, OP_MustBeInt, 0, 0);
|
||||
} else {
|
||||
__vdbe_add_op(v, OP_NewRecno, 0, 0);
|
||||
}
|
||||
for(i = 0; i < table->nCol; i++) {
|
||||
if (i == table->iPKey) {
|
||||
/*
|
||||
* The integer primary key column is filled
|
||||
* with NULL since its value is always pulled
|
||||
* from the record number.
|
||||
*/
|
||||
__vdbe_add_op(v, OP_String, 0, 0);
|
||||
} else {
|
||||
__vdbe_add_op(v, OP_FileColumn, i, 0);
|
||||
}
|
||||
}
|
||||
__generate_constraint_checks(parser, table, 0, 0,
|
||||
(table->iPKey >= 0), 0, on_error,
|
||||
addr);
|
||||
__complete_insertion(parser, table, 0, 0, 0, 0, -1);
|
||||
if ((db->flags & DBSQL_CountRows) != 0) {
|
||||
/* Increment row count */
|
||||
__vdbe_add_op(v, OP_AddImm, 1, 0);
|
||||
}
|
||||
__vdbe_add_op(v, OP_Goto, 0, addr);
|
||||
__vdbe_resolve_label(v, end);
|
||||
__vdbe_add_op(v, OP_Noop, 0, 0);
|
||||
__vdbe_conclude_write(parser);
|
||||
if (db->flags & DBSQL_CountRows) {
|
||||
__vdbe_add_op(v, OP_ColumnName, 0, 0);
|
||||
__vdbe_change_p3(v, -1, "rows inserted", P3_STATIC);
|
||||
__vdbe_add_op(v, OP_Callback, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
copy_cleanup:
|
||||
__src_list_delete(table_name);
|
||||
__dbsql_free(parser->db, file);
|
||||
return;
|
||||
}
|
1044
src/cg_date.c
Normal file
1044
src/cg_date.c
Normal file
File diff suppressed because it is too large
Load diff
491
src/cg_delete.c
Normal file
491
src/cg_delete.c
Normal file
|
@ -0,0 +1,491 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains C code routines that are called by the parser
|
||||
* to handle DELETE FROM statements.
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
|
||||
#include "dbsql_int.h"
|
||||
|
||||
/*
|
||||
* __src_list_lookup --
|
||||
* Look up every table that is named in 'src'. If any table is not found,
|
||||
* add an error message to parse->zErrMsg and return NULL. If all tables
|
||||
* are found, return a pointer to the last table.
|
||||
*
|
||||
* PUBLIC: table_t *__src_list_lookup __P((parser_t *, src_list_t *));
|
||||
*/
|
||||
table_t *
|
||||
__src_list_lookup(parser_t* parser, src_list_t* src)
|
||||
{
|
||||
table_t *table = 0;
|
||||
int i;
|
||||
for (i = 0; i < src->nSrc; i++) {
|
||||
const char *tb_name = src->a[i].zName;
|
||||
const char *db_name = src->a[i].zDatabase;
|
||||
table = __locate_table(parser, tb_name, db_name);
|
||||
src->a[i].pTab = table;
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
/*
|
||||
* __is_table_read_only --
|
||||
* Check to make sure the given table is writable. If it is not
|
||||
* writable, generate an error message and return 1. If it is
|
||||
* writable return 0;
|
||||
*
|
||||
* PUBLIC: int __is_table_read_only __P((parser_t *, table_t *, int));
|
||||
*/
|
||||
int
|
||||
__is_table_read_only(parser_t* parser, table_t* table, int views_ok)
|
||||
{
|
||||
if (table->readOnly) {
|
||||
__error_msg(parser, "table %s may not be modified",
|
||||
table->zName);
|
||||
return 1;
|
||||
}
|
||||
if (!views_ok && table->pSelect) {
|
||||
__error_msg(parser, "cannot modify %s because it is a view",
|
||||
table->zName);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* __delete_from --
|
||||
* Process a DELETE FROM statement.
|
||||
*
|
||||
* PUBLIC: void __delete_from __P((parser_t *, src_list_t *, expr_t *));
|
||||
*
|
||||
* parser The parser context
|
||||
* list The table from which we should delete things
|
||||
* where The WHERE clause. May be null.
|
||||
*/
|
||||
void __delete_from(parser, list, where)
|
||||
parser_t *parser;
|
||||
src_list_t *list;
|
||||
expr_t *where;
|
||||
{
|
||||
vdbe_t *v; /* The virtual database engine */
|
||||
table_t *table; /* The table from which records will be deleted */
|
||||
const char *name; /* Name of database holding 'table' */
|
||||
int end, addr; /* A couple addresses of generated code */
|
||||
int i; /* Loop counter */
|
||||
where_info_t *info; /* Information about the WHERE clause */
|
||||
index_t *idx; /* For looping over indices of the table */
|
||||
int cur; /* VDBE Cursor number for 'table' */
|
||||
DBSQL *dbp; /* Main database structure */
|
||||
int view; /* True if attempting to delete from a view */
|
||||
auth_context_t context;/* Authorization context */
|
||||
int row_triggers_exist = 0;/* True if any triggers exist */
|
||||
int before_triggers;/* True if there are BEFORE triggers */
|
||||
int after_triggers; /* True if there are AFTER triggers */
|
||||
int old_idx = -1; /* Cursor for the OLD table of AFTER triggers */
|
||||
|
||||
context.pParse = 0;
|
||||
if (parser->nErr || parser->rc == ENOMEM) {
|
||||
list = 0;
|
||||
goto delete_from_cleanup;
|
||||
}
|
||||
dbp = parser->db;
|
||||
DBSQL_ASSERT(list->nSrc == 1);
|
||||
|
||||
/*
|
||||
* Locate the table which we want to delete. This table has to be
|
||||
* put in an src_list_t structure because some of the subroutines we
|
||||
* will be calling are designed to work with multiple tables and expect
|
||||
* an src_list_t* parameter instead of just a table_t* parameter.
|
||||
*/
|
||||
table = __src_list_lookup(parser, list);
|
||||
if (table == 0)
|
||||
goto delete_from_cleanup;
|
||||
before_triggers = __triggers_exist(parser, table->pTrigger,
|
||||
TK_DELETE, TK_BEFORE, TK_ROW, 0);
|
||||
after_triggers = __triggers_exist(parser, table->pTrigger,
|
||||
TK_DELETE, TK_AFTER, TK_ROW, 0);
|
||||
row_triggers_exist = (before_triggers || after_triggers);
|
||||
view = (table->pSelect != 0);
|
||||
if (__is_table_read_only(parser, table, before_triggers)) {
|
||||
goto delete_from_cleanup;
|
||||
}
|
||||
DBSQL_ASSERT(table->iDb < dbp->nDb);
|
||||
name = dbp->aDb[table->iDb].zName;
|
||||
if (__auth_check(parser, DBSQL_DELETE, table->zName, 0, name)) {
|
||||
goto delete_from_cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* If pTab is really a view, make sure it has been initialized.
|
||||
*/
|
||||
if (view && __view_get_column_names(parser, table)) {
|
||||
goto delete_from_cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a cursor used to store the old.* data for a trigger.
|
||||
*/
|
||||
if (row_triggers_exist) {
|
||||
old_idx = parser->nTab++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolve the column names in all the expressions.
|
||||
*/
|
||||
DBSQL_ASSERT(list->nSrc == 1);
|
||||
cur = list->a[0].iCursor = parser->nTab++;
|
||||
if (where) {
|
||||
if (__expr_resolve_ids(parser, list, 0, where)) {
|
||||
goto delete_from_cleanup;
|
||||
}
|
||||
if (__expr_check(parser, where, 0, 0)) {
|
||||
goto delete_from_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the view context.
|
||||
*/
|
||||
if (view) {
|
||||
__auth_context_push(parser, &context, table->zName);
|
||||
}
|
||||
|
||||
/*
|
||||
* Begin generating code.
|
||||
*/
|
||||
v = __parser_get_vdbe(parser);
|
||||
if (v == 0) {
|
||||
goto delete_from_cleanup;
|
||||
}
|
||||
__vdbe_prepare_write(parser, row_triggers_exist, table->iDb);
|
||||
|
||||
/*
|
||||
* If we are trying to delete from a view, construct that view into
|
||||
* a temporary table.
|
||||
*/
|
||||
if (view) {
|
||||
select_t *vsel = __select_dup(table->pSelect);
|
||||
__select(parser, vsel, SRT_TempTable, cur, 0, 0, 0);
|
||||
__select_delete(vsel);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the counter of the number of rows deleted, if
|
||||
* we are counting rows.
|
||||
*/
|
||||
if (dbp->flags & DBSQL_CountRows) {
|
||||
__vdbe_add_op(v, OP_Integer, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Special case: A DELETE without a WHERE clause deletes everything.
|
||||
* It is easier just to erase the whole table. Note, however, that
|
||||
* this means that the row change count will be incorrect.
|
||||
*/
|
||||
if (where == 0 && !row_triggers_exist) {
|
||||
if (dbp->flags & DBSQL_CountRows) {
|
||||
/*
|
||||
* If counting rows deleted, just count the total
|
||||
* number of entries in the table.
|
||||
*/
|
||||
int end_of_loop = __vdbe_make_label(v);
|
||||
int addr;
|
||||
if (!view) {
|
||||
__vdbe_add_op(v, OP_Integer, table->iDb, 0);
|
||||
__vdbe_add_op(v, OP_OpenRead, cur,
|
||||
table->tnum);
|
||||
}
|
||||
__vdbe_add_op(v, OP_Rewind, cur,
|
||||
(__vdbe_current_addr(v) + 2));
|
||||
addr = __vdbe_add_op(v, OP_AddImm, 1, 0);
|
||||
__vdbe_add_op(v, OP_Next, cur, addr);
|
||||
__vdbe_resolve_label(v, end_of_loop);
|
||||
__vdbe_add_op(v, OP_Close, cur, 0);
|
||||
}
|
||||
if (!view) {
|
||||
__vdbe_add_op(v, OP_Clear, table->tnum, table->iDb);
|
||||
for (idx = table->pIndex; idx; idx = idx->pNext) {
|
||||
__vdbe_add_op(v, OP_Clear, idx->tnum,
|
||||
idx->iDb);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* The usual case: There is a WHERE clause so we have to
|
||||
* scan through the table and pick which records to delete.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Begin the database scan.
|
||||
*/
|
||||
info = __where_begin(parser, list, where, 1, 0);
|
||||
if (info == 0)
|
||||
goto delete_from_cleanup;
|
||||
|
||||
/*
|
||||
* Remember the key of every item to be deleted.
|
||||
*/
|
||||
__vdbe_add_op(v, OP_ListWrite, 0, 0);
|
||||
if (dbp->flags & DBSQL_CountRows) {
|
||||
__vdbe_add_op(v, OP_AddImm, 1, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* End the database scan loop.
|
||||
*/
|
||||
__where_end(info);
|
||||
|
||||
/*
|
||||
* Open the pseudo-table used to store OLD if there are
|
||||
* triggers.
|
||||
*/
|
||||
if (row_triggers_exist) {
|
||||
__vdbe_add_op(v, OP_OpenPseudo, old_idx, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete every item whose key was written to the list
|
||||
* during the database scan. We have to delete items
|
||||
* after the scan is complete because deleting an item
|
||||
* can change the scan order.
|
||||
*/
|
||||
__vdbe_add_op(v, OP_ListRewind, 0, 0);
|
||||
end = __vdbe_make_label(v);
|
||||
|
||||
/*
|
||||
* This is the beginning of the delete loop when there are
|
||||
* row triggers.
|
||||
*/
|
||||
if (row_triggers_exist) {
|
||||
addr = __vdbe_add_op(v, OP_ListRead, 0, end);
|
||||
__vdbe_add_op(v, OP_Dup, 0, 0);
|
||||
if (!view) {
|
||||
__vdbe_add_op(v, OP_Integer, table->iDb, 0);
|
||||
__vdbe_add_op(v, OP_OpenRead, cur,
|
||||
table->tnum);
|
||||
}
|
||||
__vdbe_add_op(v, OP_MoveTo, cur, 0);
|
||||
__vdbe_add_op(v, OP_Recno, cur, 0);
|
||||
__vdbe_add_op(v, OP_RowData, cur, 0);
|
||||
__vdbe_add_op(v, OP_PutIntKey, old_idx, 0);
|
||||
if (!view) {
|
||||
__vdbe_add_op(v, OP_Close, cur, 0);
|
||||
}
|
||||
__code_row_trigger(parser, TK_DELETE, 0, TK_BEFORE,
|
||||
table, -1, old_idx,
|
||||
((parser->trigStack) ?
|
||||
parser->trigStack->orconf :
|
||||
OE_Default), addr);
|
||||
}
|
||||
|
||||
if (!view) {
|
||||
/*
|
||||
* Open cursors for the table we are deleting from
|
||||
* and all its indices. If there are row triggers,
|
||||
* this happens inside the OP_ListRead loop because
|
||||
* the cursor have to all be closed before the trigger
|
||||
* fires. If there are no row triggers, the cursors
|
||||
* are opened only once on the outside the loop.
|
||||
*/
|
||||
parser->nTab = cur + 1;
|
||||
__vdbe_add_op(v, OP_Integer, table->iDb, 0);
|
||||
__vdbe_add_op(v, OP_OpenWrite, cur, table->tnum);
|
||||
for (i = 1, idx = table->pIndex; idx;
|
||||
i++, idx = idx->pNext) {
|
||||
__vdbe_add_op(v, OP_Integer, idx->iDb, 0);
|
||||
__vdbe_add_op(v, OP_OpenWrite, parser->nTab++,
|
||||
idx->tnum);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the beginning of the delete loop when
|
||||
* there are no row triggers.
|
||||
*/
|
||||
if (!row_triggers_exist) {
|
||||
addr = __vdbe_add_op(v, OP_ListRead, 0, end);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete the row.
|
||||
*/
|
||||
__generate_row_delete(dbp, v, table, cur,
|
||||
(parser->trigStack == 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are row triggers, close all cursors then invoke
|
||||
* the AFTER triggers.
|
||||
*/
|
||||
if (row_triggers_exist) {
|
||||
if (!view) {
|
||||
for(i = 1, idx = table->pIndex; idx;
|
||||
i++, idx = idx->pNext) {
|
||||
__vdbe_add_op(v, OP_Close, cur + i,
|
||||
idx->tnum);
|
||||
}
|
||||
__vdbe_add_op(v, OP_Close, cur, 0);
|
||||
}
|
||||
__code_row_trigger(parser, TK_DELETE, 0, TK_AFTER,
|
||||
table, -1, old_idx,
|
||||
((parser->trigStack) ?
|
||||
parser->trigStack->orconf :
|
||||
OE_Default), addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* End of the delete loop.
|
||||
*/
|
||||
__vdbe_add_op(v, OP_Goto, 0, addr);
|
||||
__vdbe_resolve_label(v, end);
|
||||
__vdbe_add_op(v, OP_ListReset, 0, 0);
|
||||
|
||||
/*
|
||||
* Close the cursors after the loop if there are no row
|
||||
* triggers.
|
||||
*/
|
||||
if (!row_triggers_exist) {
|
||||
for (i = 1, idx = table->pIndex; idx;
|
||||
i++, idx = idx->pNext) {
|
||||
__vdbe_add_op(v, OP_Close, cur + i, idx->tnum);
|
||||
}
|
||||
__vdbe_add_op(v, OP_Close, cur, 0);
|
||||
parser->nTab = cur;
|
||||
}
|
||||
}
|
||||
__vdbe_conclude_write(parser);
|
||||
|
||||
/*
|
||||
* Return the number of rows that were deleted.
|
||||
*/
|
||||
if (dbp->flags & DBSQL_CountRows) {
|
||||
__vdbe_add_op(v, OP_ColumnName, 0, 0);
|
||||
__vdbe_change_p3(v, -1, "rows deleted", P3_STATIC);
|
||||
__vdbe_add_op(v, OP_Callback, 1, 0);
|
||||
}
|
||||
|
||||
delete_from_cleanup:
|
||||
__auth_context_pop(&context);
|
||||
__src_list_delete(list);
|
||||
__expr_delete(where);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* __generate_row_delete --
|
||||
* This routine generates VDBE code that causes a single row of a
|
||||
* single table to be deleted.
|
||||
*
|
||||
* The VDBE must be in a particular state when this routine is called.
|
||||
* These are the requirements:
|
||||
*
|
||||
* 1. A read/write cursor pointing to 'table', the table containing
|
||||
* the row to be deleted, must be opened as cursor number "base".
|
||||
*
|
||||
* 2. Read/write cursors for all indices of pTab must be open as
|
||||
* cursor number base+i for the i-th index.
|
||||
*
|
||||
* 3. The record number of the row to be deleted must be on the top
|
||||
* of the stack.
|
||||
*
|
||||
* This routine pops the top of the stack to remove the record number
|
||||
* and then generates code to remove both the table record and all index
|
||||
* entries that point to that record.
|
||||
*
|
||||
* PUBLIC: void __generate_row_delete __P((DBSQL *, vdbe_t *, table_t *,
|
||||
* PUBLIC: int, int));
|
||||
*
|
||||
* dbp The database containing the index
|
||||
* v Generate code into this VDBE
|
||||
* table Table containing the row to be deleted
|
||||
* cur Cursor number for the table
|
||||
* count Increment the row change counter
|
||||
*/
|
||||
void __generate_row_delete(dbp, v, table, cur, count)
|
||||
DBSQL *dbp;
|
||||
vdbe_t *v;
|
||||
table_t *table;
|
||||
int cur;
|
||||
int count;
|
||||
{
|
||||
int addr;
|
||||
addr = __vdbe_add_op(v, OP_NotExists, cur, 0);
|
||||
__generate_row_index_delete(dbp, v, table, cur, 0);
|
||||
__vdbe_add_op(v, OP_Delete, cur, count);
|
||||
__vdbe_change_p2(v, addr, __vdbe_current_addr(v));
|
||||
}
|
||||
|
||||
/*
|
||||
* __generate_row_index_delete --
|
||||
* This routine generates VDBE code that causes the deletion of all
|
||||
* index entries associated with a single row of a single table.
|
||||
*
|
||||
* The VDBE must be in a particular state when this routine is called.
|
||||
* These are the requirements:
|
||||
*
|
||||
* 1. A read/write cursor pointing to 'table', the table containing
|
||||
* the row to be deleted, must be opened as cursor number 'cur'.
|
||||
*
|
||||
* 2. Read/write cursors for all indices of 'table' must be open as
|
||||
* cursor number cur+i for the i-th index.
|
||||
*
|
||||
* 3. The 'cur' cursor must be pointing to the row that is to be
|
||||
* deleted.
|
||||
*
|
||||
* PUBLIC: void __generate_row_index_delete __P((DBSQL *, vdbe_t *,
|
||||
* PUBLIC: table_t *, int, char *));
|
||||
*
|
||||
* dbp The database containing the index
|
||||
* v Generate code into this VDBE
|
||||
* table Table containing the row to be deleted
|
||||
* cur Cursor number for the table
|
||||
* idx_used Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0
|
||||
*/
|
||||
void __generate_row_index_delete(dbp, v, table, cur, idx_used)
|
||||
DBSQL *dbp;
|
||||
vdbe_t *v;
|
||||
table_t *table;
|
||||
int cur;
|
||||
char *idx_used;
|
||||
{
|
||||
int i;
|
||||
index_t *idx;
|
||||
|
||||
for (i = 1, idx = table->pIndex; idx; i++, idx = idx->pNext) {
|
||||
int j;
|
||||
if (idx_used != 0 && idx_used[i-1] == 0)
|
||||
continue;
|
||||
__vdbe_add_op(v, OP_Recno, cur, 0);
|
||||
for (j = 0; j < idx->nColumn; j++) {
|
||||
int n = idx->aiColumn[j];
|
||||
if (n == table->iPKey) {
|
||||
__vdbe_add_op(v, OP_Dup, j, 0);
|
||||
} else {
|
||||
__vdbe_add_op(v, OP_Column, cur, n);
|
||||
}
|
||||
}
|
||||
__vdbe_add_op(v, OP_MakeIdxKey, idx->nColumn, 0);
|
||||
__add_idx_key_type(v, idx);
|
||||
__vdbe_add_op(v, OP_IdxDelete, cur + i, 0);
|
||||
}
|
||||
}
|
1934
src/cg_expr.c
Normal file
1934
src/cg_expr.c
Normal file
File diff suppressed because it is too large
Load diff
1068
src/cg_insert.c
Normal file
1068
src/cg_insert.c
Normal file
File diff suppressed because it is too large
Load diff
387
src/cg_pragma.c
Normal file
387
src/cg_pragma.c
Normal file
|
@ -0,0 +1,387 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains code used to implement the PRAGMA command.
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <ctype.h>
|
||||
#endif
|
||||
|
||||
#include "dbsql_int.h"
|
||||
|
||||
/*
|
||||
* __get_boolean --
|
||||
* Interpret the given string as a boolean value.
|
||||
*
|
||||
* STATIC: static int __get_boolean __P((char *));
|
||||
*/
|
||||
static int
|
||||
__get_boolean(char* z)
|
||||
{
|
||||
static char *true[] = { "yes", "on", "true" };
|
||||
int i;
|
||||
if (z[0] == 0)
|
||||
return 0;
|
||||
if (isdigit(z[0]) || (z[0]=='-' && isdigit(z[1]))) {
|
||||
return atoi(z);
|
||||
}
|
||||
for(i = 0; i < sizeof(true) / sizeof(true[0]); i++) {
|
||||
if (strcasecmp(z, true[i]) == 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* __get_safety_level --
|
||||
* Interpret the given string as a safety level. Return 0 for OFF,
|
||||
* 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or
|
||||
* unrecognized string argument.
|
||||
*
|
||||
* Note that the values returned are one less that the values that
|
||||
* should be passed into __sm_set_safety_level(). This is done
|
||||
* to support legacy SQL code. The safety level used to be boolean
|
||||
* and older scripts may have used numbers 0 for OFF and 1 for ON.
|
||||
*
|
||||
* STATIC: static int __get_safety_level __P((char *));
|
||||
*/
|
||||
static int
|
||||
__get_safety_level(char* z)
|
||||
{
|
||||
static const struct {
|
||||
const char *word;
|
||||
int val;
|
||||
} key[] = {
|
||||
{ "no", 0 },
|
||||
{ "off", 0 },
|
||||
{ "false", 0 },
|
||||
{ "yes", 1 },
|
||||
{ "on", 1 },
|
||||
{ "true", 1 },
|
||||
{ "full", 2 },
|
||||
};
|
||||
int i;
|
||||
if (z[0] == 0)
|
||||
return 1;
|
||||
if (isdigit(z[0]) || (z[0] == '-' && isdigit(z[1]))) {
|
||||
return atoi(z);
|
||||
}
|
||||
for (i = 0; i < sizeof(key)/sizeof(key[0]); i++) {
|
||||
if (strcasecmp(z,key[i].word) == 0)
|
||||
return key[i].val;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* __pragma --
|
||||
* Process a pragma statement.
|
||||
*
|
||||
* Pragmas are of this form:
|
||||
*
|
||||
* PRAGMA id = value
|
||||
*
|
||||
* The identifier might also be a string. The value is a string, and
|
||||
* identifier, or a number. If 'minus_p' is true, then the value is
|
||||
* a number that was preceded by a minus sign.
|
||||
*
|
||||
* PUBLIC: void __pragma __P((parser_t *, token_t *, token_t *, int));
|
||||
*/
|
||||
void
|
||||
__pragma(parser_t* parser, token_t* left, token_t* right, int minus_p)
|
||||
{
|
||||
char *left_name = 0;
|
||||
char *right_name = 0;
|
||||
DBSQL *dbp = parser->db;
|
||||
vdbe_t *v = __parser_get_vdbe(parser);
|
||||
if (v == 0)
|
||||
return;
|
||||
|
||||
__dbsql_strndup(dbp, left->z, &left_name, left->n);
|
||||
__str_unquote(left_name);
|
||||
if (minus_p) {
|
||||
right_name = 0;
|
||||
__str_nappend(&right_name, "-", 1, right->z, right->n, NULL);
|
||||
} else {
|
||||
__dbsql_strndup(dbp, right->z, &right_name, right->n);
|
||||
__str_unquote(right_name);
|
||||
}
|
||||
if (__auth_check(parser, DBSQL_PRAGMA, left_name, right_name, NULL)) {
|
||||
__dbsql_free(dbp, left_name);
|
||||
__dbsql_free(dbp, right_name);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* PRAGMA trigger_overhead_test
|
||||
*/
|
||||
if (strcasecmp(left_name, "trigger_overhead_test") == 0) {
|
||||
if (__get_boolean(right_name)) {
|
||||
always_code_trigger_setup = 1;
|
||||
} else {
|
||||
always_code_trigger_setup = 0;
|
||||
}
|
||||
} else
|
||||
/*
|
||||
* PRAGMA vdbe_trace
|
||||
*/
|
||||
if (strcasecmp(left_name, "vdbe_trace") == 0) {
|
||||
if (__get_boolean(right_name)) {
|
||||
dbp->flags |= DBSQL_VdbeTrace;
|
||||
} else {
|
||||
dbp->flags &= ~DBSQL_VdbeTrace;
|
||||
}
|
||||
} else
|
||||
/*
|
||||
* PRAGMA full_column_names
|
||||
*/
|
||||
if (strcasecmp(left_name, "full_column_names") == 0) {
|
||||
if (__get_boolean(right_name)) {
|
||||
dbp->flags |= DBSQL_FullColNames;
|
||||
} else {
|
||||
dbp->flags &= ~DBSQL_FullColNames;
|
||||
}
|
||||
} else
|
||||
/*
|
||||
* PRAGMA show_datatypes
|
||||
*/
|
||||
if (strcasecmp(left_name, "show_datatypes") == 0) {
|
||||
if( __get_boolean(right_name)) {
|
||||
dbp->flags |= DBSQL_ReportTypes;
|
||||
} else {
|
||||
dbp->flags &= ~DBSQL_ReportTypes;
|
||||
}
|
||||
} else
|
||||
/*
|
||||
* PRAGMA count_changes
|
||||
*/
|
||||
if (strcasecmp(left_name, "count_changes") == 0) {
|
||||
if (__get_boolean(right_name)) {
|
||||
dbp->flags |= DBSQL_CountRows;
|
||||
} else {
|
||||
dbp->flags &= ~DBSQL_CountRows;
|
||||
}
|
||||
} else
|
||||
/*
|
||||
* PRAGMA empty_result_callbacks
|
||||
*/
|
||||
if (strcasecmp(left_name, "empty_result_callbacks") == 0) {
|
||||
if ( __get_boolean(right_name)) {
|
||||
dbp->flags |= DBSQL_NullCallback;
|
||||
} else {
|
||||
dbp->flags &= ~DBSQL_NullCallback;
|
||||
}
|
||||
} else
|
||||
/*
|
||||
* PRAGMA table_info
|
||||
*/
|
||||
if (strcasecmp(left_name, "table_info") == 0) {
|
||||
table_t *table;
|
||||
table = __find_table(dbp, right_name, 0);
|
||||
if (table) {
|
||||
static vdbe_op_t table_info_preface[] = {
|
||||
{ OP_ColumnName, 0, 0, "cid"},
|
||||
{ OP_ColumnName, 1, 0, "name"},
|
||||
{ OP_ColumnName, 2, 0, "type"},
|
||||
{ OP_ColumnName, 3, 0, "notnull"},
|
||||
{ OP_ColumnName, 4, 0, "dflt_value"},
|
||||
{ OP_ColumnName, 5, 0, "pk"},
|
||||
};
|
||||
int i;
|
||||
__vdbe_add_op_list(v, ARRAY_SIZE(table_info_preface),
|
||||
table_info_preface);
|
||||
__view_get_column_names(parser, table);
|
||||
for (i = 0; i < table->nCol; i++) {
|
||||
__vdbe_add_op(v, OP_Integer, i, 0);
|
||||
__vdbe_add_op(v, OP_String, 0, 0);
|
||||
__vdbe_change_p3(v, -1, table->aCol[i].zName,
|
||||
P3_STATIC);
|
||||
__vdbe_add_op(v, OP_String, 0, 0);
|
||||
__vdbe_change_p3(v, -1,
|
||||
table->aCol[i].zType ?
|
||||
table->aCol[i].zType :
|
||||
"numeric", P3_STATIC);
|
||||
__vdbe_add_op(v, OP_Integer,
|
||||
table->aCol[i].notNull, 0);
|
||||
__vdbe_add_op(v, OP_String, 0, 0);
|
||||
__vdbe_change_p3(v, -1, table->aCol[i].zDflt,
|
||||
P3_STATIC);
|
||||
__vdbe_add_op(v, OP_Integer,
|
||||
table->aCol[i].isPrimKey, 0);
|
||||
__vdbe_add_op(v, OP_Callback, 6, 0);
|
||||
}
|
||||
}
|
||||
} else
|
||||
/*
|
||||
* PRAGMA index_info
|
||||
*/
|
||||
if (strcasecmp(left_name, "index_info") == 0) {
|
||||
index_t *index;
|
||||
table_t *table;
|
||||
index = __find_index(dbp, right_name, 0);
|
||||
if (index) {
|
||||
static vdbe_op_t table_info_preface[] = {
|
||||
{ OP_ColumnName, 0, 0, "seqno"},
|
||||
{ OP_ColumnName, 1, 0, "cid"},
|
||||
{ OP_ColumnName, 2, 0, "name"},
|
||||
};
|
||||
int i;
|
||||
table = index->pTable;
|
||||
__vdbe_add_op_list(v, ARRAY_SIZE(table_info_preface),
|
||||
table_info_preface);
|
||||
for (i = 0; i < index->nColumn; i++) {
|
||||
int cnum = index->aiColumn[i];
|
||||
__vdbe_add_op(v, OP_Integer, i, 0);
|
||||
__vdbe_add_op(v, OP_Integer, cnum, 0);
|
||||
__vdbe_add_op(v, OP_String, 0, 0);
|
||||
DBSQL_ASSERT(table->nCol > cnum);
|
||||
__vdbe_change_p3(v, -1,
|
||||
table->aCol[cnum].zName,
|
||||
P3_STATIC);
|
||||
__vdbe_add_op(v, OP_Callback, 3, 0);
|
||||
}
|
||||
}
|
||||
} else
|
||||
/*
|
||||
* PRAGMA index_list
|
||||
*/
|
||||
if (strcasecmp(left_name, "index_list") == 0) {
|
||||
index_t *index;
|
||||
table_t *table;
|
||||
table = __find_table(dbp, right_name, 0);
|
||||
if (table) {
|
||||
v = __parser_get_vdbe(parser);
|
||||
index = table->pIndex;
|
||||
}
|
||||
if (table && index) {
|
||||
int i = 0;
|
||||
static vdbe_op_t index_list_preface[] = {
|
||||
{ OP_ColumnName, 0, 0, "seq"},
|
||||
{ OP_ColumnName, 1, 0, "name"},
|
||||
{ OP_ColumnName, 2, 0, "unique"},
|
||||
};
|
||||
|
||||
__vdbe_add_op_list(v, ARRAY_SIZE(index_list_preface),
|
||||
index_list_preface);
|
||||
while(index) {
|
||||
__vdbe_add_op(v, OP_Integer, i, 0);
|
||||
__vdbe_add_op(v, OP_String, 0, 0);
|
||||
__vdbe_change_p3(v, -1, index->zName,
|
||||
P3_STATIC);
|
||||
__vdbe_add_op(v, OP_Integer,
|
||||
index->onError != OE_None, 0);
|
||||
__vdbe_add_op(v, OP_Callback, 3, 0);
|
||||
++i;
|
||||
index = index->pNext;
|
||||
}
|
||||
}
|
||||
} else
|
||||
/*
|
||||
* PRAGMA foreign_key_list
|
||||
*/
|
||||
if (strcasecmp(left_name, "foreign_key_list") == 0) {
|
||||
foreign_key_t *fk;
|
||||
table_t *table;
|
||||
table = __find_table(dbp, right_name, 0);
|
||||
if (table) {
|
||||
v = __parser_get_vdbe(parser);
|
||||
fk = table->pFKey;
|
||||
}
|
||||
if (table && fk) {
|
||||
int i = 0;
|
||||
static vdbe_op_t index_list_preface[] = {
|
||||
{ OP_ColumnName, 0, 0, "id"},
|
||||
{ OP_ColumnName, 1, 0, "seq"},
|
||||
{ OP_ColumnName, 2, 0, "table"},
|
||||
{ OP_ColumnName, 3, 0, "from"},
|
||||
{ OP_ColumnName, 4, 0, "to"},
|
||||
};
|
||||
|
||||
__vdbe_add_op_list(v, ARRAY_SIZE(index_list_preface),
|
||||
index_list_preface);
|
||||
while(fk) {
|
||||
int j;
|
||||
for (j = 0; j < fk->nCol; j++) {
|
||||
__vdbe_add_op(v, OP_Integer, i, 0);
|
||||
__vdbe_add_op(v, OP_Integer, j, 0);
|
||||
__vdbe_add_op(v, OP_String, 0, 0);
|
||||
__vdbe_change_p3(v, -1, fk->zTo,
|
||||
P3_STATIC);
|
||||
__vdbe_add_op(v, OP_String, 0, 0);
|
||||
__vdbe_change_p3(v, -1,
|
||||
table->aCol[fk->aCol[j].iFrom].zName,
|
||||
P3_STATIC);
|
||||
__vdbe_add_op(v, OP_String, 0, 0);
|
||||
__vdbe_change_p3(v, -1,
|
||||
fk->aCol[j].zCol, P3_STATIC);
|
||||
__vdbe_add_op(v, OP_Callback, 5, 0);
|
||||
}
|
||||
++i;
|
||||
fk = fk->pNextFrom;
|
||||
}
|
||||
}
|
||||
} else
|
||||
/*
|
||||
* PRAGMA database_list
|
||||
*/
|
||||
if (strcasecmp(left_name, "database_list") == 0) {
|
||||
int i;
|
||||
static vdbe_op_t index_list_preface[] = {
|
||||
{ OP_ColumnName, 0, 0, "seq"},
|
||||
{ OP_ColumnName, 1, 0, "name"},
|
||||
{ OP_ColumnName, 2, 0, "file"},
|
||||
};
|
||||
|
||||
__vdbe_add_op_list(v, ARRAY_SIZE(index_list_preface),
|
||||
index_list_preface);
|
||||
for (i = 0; i < dbp->nDb; i++) {
|
||||
if (dbp->aDb[i].pBt == 0)
|
||||
continue;
|
||||
DBSQL_ASSERT(dbp->aDb[i].zName != 0);
|
||||
__vdbe_add_op(v, OP_Integer, i, 0);
|
||||
__vdbe_add_op(v, OP_String, 0, 0);
|
||||
__vdbe_change_p3(v, -1, dbp->aDb[i].zName, P3_STATIC);
|
||||
__vdbe_add_op(v, OP_String, 0, 0);
|
||||
__vdbe_change_p3(v, -1,
|
||||
__sm_get_database_name(dbp->aDb[i].pBt), P3_STATIC);
|
||||
__vdbe_add_op(v, OP_Callback, 3, 0);
|
||||
}
|
||||
} else
|
||||
#ifndef NDEBUG
|
||||
/*
|
||||
* PRAGMA parser_trace
|
||||
*/
|
||||
if (strcasecmp(left_name, "parser_trace") == 0) {
|
||||
extern void __sql_parser_trace(FILE*, char *);
|
||||
if (__get_boolean(right_name)) {
|
||||
__sql_parser_trace(stdout, "parser: ");
|
||||
} else {
|
||||
__sql_parser_trace(0, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else {}
|
||||
__dbsql_free(dbp, left_name);
|
||||
__dbsql_free(dbp, right_name);
|
||||
}
|
2911
src/cg_select.c
Normal file
2911
src/cg_select.c
Normal file
File diff suppressed because it is too large
Load diff
952
src/cg_trigger.c
Normal file
952
src/cg_trigger.c
Normal file
|
@ -0,0 +1,952 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
#include "dbsql_int.h"
|
||||
|
||||
/*
|
||||
* __vdbe_delete_trigger_step --
|
||||
* Delete a linked list of TriggerStep structures.
|
||||
*
|
||||
* PUBLIC: void __vdbe_delete_trigger_step __P((trigger_step_t *));
|
||||
*/
|
||||
void
|
||||
__vdbe_delete_trigger_step(trigger_step_t* ts)
|
||||
{
|
||||
while(ts) {
|
||||
trigger_step_t * tmp = ts;
|
||||
ts = ts->pNext;
|
||||
|
||||
if (tmp->target.dyn)
|
||||
__dbsql_free(NULL, (char *)tmp->target.z);
|
||||
__expr_delete(tmp->pWhere);
|
||||
__expr_list_delete(tmp->pExprList);
|
||||
__select_delete(tmp->pSelect);
|
||||
__id_list_delete(tmp->pIdList);
|
||||
|
||||
__dbsql_free(NULL, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* __begin_trigger --
|
||||
* This is called by the parser when it sees a CREATE TRIGGER statement
|
||||
* up to the point of the BEGIN before the trigger actions. A trigger_t
|
||||
* structure is generated based on the information available and stored
|
||||
* in parser->pNewTrigger. After the trigger actions have been parsed,
|
||||
* the __finish_trigger() function is called to complete the trigger
|
||||
* construction process.
|
||||
*
|
||||
* PUBLIC: void __begin_trigger __P((parser_t *, token_t *, int, int,
|
||||
* PUBLIC: id_list_t *, src_list_t *, int, expr_t *, int));
|
||||
*
|
||||
* parser The parse context of the CREATE TRIGGER
|
||||
* statement
|
||||
* trigger The trigger of the trigger
|
||||
* tr_tm One of TK_BEFORE, TK_AFTER, TK_INSTEAD
|
||||
* op One of TK_INSERT, TK_UPDATE, TK_DELETE
|
||||
* columns Column list if this is an UPDATE OF trigger
|
||||
* tab_name The table name of the table/view for this
|
||||
* trigger
|
||||
* foreach One of TK_ROW or TK_STATEMENT
|
||||
* when_clause WHEN clause
|
||||
* temp_p True if the TEMPORARY keyword is present
|
||||
*/
|
||||
void
|
||||
__begin_trigger(parser, trigger, tr_tm, op, columns, tab_name, foreach,
|
||||
when_clause, temp_p)
|
||||
parser_t *parser;
|
||||
token_t *trigger;
|
||||
int tr_tm;
|
||||
int op;
|
||||
id_list_t *columns;
|
||||
src_list_t *tab_name;
|
||||
int foreach;
|
||||
expr_t *when_clause;
|
||||
int temp_p;
|
||||
{
|
||||
trigger_t *nt;
|
||||
table_t *table;
|
||||
ref_normalizer_ctx_t normctx;
|
||||
DBSQL *dbp = parser->db;
|
||||
char *name = 0; /* Name of the trigger */
|
||||
int db_idx; /* When database to store the trigger in */
|
||||
|
||||
/*
|
||||
* Check that:
|
||||
* 1. The trigger name does not already exist.
|
||||
* 2. The table (or view) does exist in the same database as the
|
||||
* trigger.
|
||||
* 3. That we are not trying to create a trigger on either the
|
||||
* master or master temp tables.
|
||||
* 4. That we are not trying to create an INSTEAD OF trigger on a
|
||||
* table.
|
||||
* 5. That we are not trying to create a BEFORE or AFTER trigger on
|
||||
* a view.
|
||||
*/
|
||||
if (parser->rc == ENOMEM)
|
||||
goto trigger_cleanup;
|
||||
DBSQL_ASSERT(tab_name->nSrc == 1);
|
||||
if (parser->initFlag &&
|
||||
__ref_normalizer_ctx_init(&normctx, parser, parser->iDb,
|
||||
"trigger", trigger) &&
|
||||
__ref_normalize_src_list(&normctx, tab_name)) {
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
table = __src_list_lookup(parser, tab_name);
|
||||
if (!table) {
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
db_idx = (temp_p ? 1 : table->iDb);
|
||||
if (db_idx >= 2 && !parser->initFlag) {
|
||||
__error_msg(parser, "triggers may not be added to auxiliary "
|
||||
"database %s", dbp->aDb[table->iDb].zName);
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
|
||||
__dbsql_strndup(dbp, trigger->z, &name, trigger->n);
|
||||
__str_unquote(name);
|
||||
if( __hash_find(&(dbp->aDb[db_idx].trigHash), name,trigger->n+1) ){
|
||||
__error_msg(parser, "trigger %T already exists", trigger);
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
if (strncasecmp(table->zName, MASTER_NAME,
|
||||
strlen(MASTER_NAME)) == 0) {
|
||||
__error_msg(parser, "cannot create trigger on system table");
|
||||
parser->nErr++;
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
if (strncasecmp(table->zName, TEMP_MASTER_NAME,
|
||||
strlen(TEMP_MASTER_NAME)) == 0) {
|
||||
__error_msg(parser, "cannot create trigger on system table");
|
||||
parser->nErr++;
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
if (table->pSelect && tr_tm != TK_INSTEAD) {
|
||||
__error_msg(parser, "cannot create %s trigger on view: %S",
|
||||
((tr_tm == TK_BEFORE) ? "BEFORE" : "AFTER"),
|
||||
tab_name, 0);
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
if (!table->pSelect && tr_tm == TK_INSTEAD) {
|
||||
__error_msg(parser, "cannot create INSTEAD OF"
|
||||
" trigger on table: %S", tab_name, 0);
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
#ifndef DBSQL_NO_AUTH
|
||||
{
|
||||
int code = DBSQL_CREATE_TRIGGER;
|
||||
const char *db = dbp->aDb[table->iDb].zName;
|
||||
const char *db_trig = temp_p ? dbp->aDb[1].zName : db;
|
||||
if (table->iDb == 1 || temp_p)
|
||||
code = DBSQL_CREATE_TEMP_TRIGGER;
|
||||
if (__auth_check(parser, code, name, table->zName, db_trig)) {
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
if (__auth_check(parser, DBSQL_INSERT,
|
||||
SCHEMA_TABLE(table->iDb), 0, db)) {
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* INSTEAD OF triggers can only appear on views and BEGIN triggers
|
||||
* cannot appear on views. So we might as well translate every
|
||||
* INSTEAD OF trigger into a BEFORE trigger. It simplifies code
|
||||
* elsewhere.
|
||||
*/
|
||||
if (tr_tm == TK_INSTEAD) {
|
||||
tr_tm = TK_BEFORE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build the Trigger object.
|
||||
*/
|
||||
__dbsql_calloc(dbp, 1, sizeof(trigger_t), &nt);
|
||||
if (nt == 0)
|
||||
goto trigger_cleanup;
|
||||
nt->name = name;
|
||||
name = 0;
|
||||
if (__dbsql_strdup(dbp, tab_name->a[0].zName, &nt->table) == ENOMEM)
|
||||
goto trigger_cleanup;
|
||||
nt->iDb = db_idx;
|
||||
nt->iTabDb = table->iDb;
|
||||
nt->op = op;
|
||||
nt->tr_tm = tr_tm;
|
||||
nt->pWhen = __expr_dup(when_clause);
|
||||
nt->pColumns = __id_list_dup(columns);
|
||||
nt->foreach = foreach;
|
||||
__token_copy(&nt->nameToken,trigger);
|
||||
DBSQL_ASSERT( parser->pNewTrigger==0 );
|
||||
parser->pNewTrigger = nt;
|
||||
|
||||
trigger_cleanup:
|
||||
__dbsql_free(dbp, name);
|
||||
__src_list_delete(tab_name);
|
||||
__id_list_delete(columns);
|
||||
__expr_delete(when_clause);
|
||||
}
|
||||
|
||||
/*
|
||||
* __finish_trigger --
|
||||
* This routine is called after all of the trigger actions have been
|
||||
* parsed in order to complete the process of building the trigger.
|
||||
*
|
||||
* PUBLIC: void __finish_trigger __P((parser_t *, trigger_step_t *,
|
||||
* PUBLIC: token_t *));
|
||||
*
|
||||
* parser The parse context of the CREATE TRIGGER
|
||||
* statement
|
||||
* steplist The triggered program
|
||||
* all Token that describes the complete
|
||||
* CREATE TRIGGER
|
||||
*/
|
||||
void
|
||||
__finish_trigger(parser_t* parser, trigger_step_t* steplist, token_t* all)
|
||||
{
|
||||
ref_normalizer_ctx_t normctx;
|
||||
trigger_t *nt = 0; /* The trigger whose construction is finishing up */
|
||||
DBSQL *dbp = parser->db;
|
||||
|
||||
if (parser->nErr || parser->pNewTrigger == 0)
|
||||
goto triggerfinish_cleanup;
|
||||
nt = parser->pNewTrigger;
|
||||
parser->pNewTrigger = 0;
|
||||
nt->step_list = steplist;
|
||||
while(steplist) {
|
||||
steplist->pTrig = nt;
|
||||
steplist = steplist->pNext;
|
||||
}
|
||||
if (__ref_normalizer_ctx_init(&normctx, parser, nt->iDb,
|
||||
"trigger", &nt->nameToken) &&
|
||||
__ref_normalize_trigger_step(&normctx, nt->step_list)) {
|
||||
goto triggerfinish_cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* if we are not initializing, and this trigger is not on a TEMP
|
||||
* table, build the master entry.
|
||||
*/
|
||||
if (!parser->initFlag) {
|
||||
static vdbe_op_t insert_trig[] = {
|
||||
{ OP_NewRecno, 0, 0, 0 },
|
||||
{ OP_String, 0, 0, "trigger" },
|
||||
{ OP_String, 0, 0, 0 }, /* 2: trigger name */
|
||||
{ OP_String, 0, 0, 0 }, /* 3: table name */
|
||||
{ OP_Integer, 0, 0, 0 },
|
||||
{ OP_String, 0, 0, 0 }, /* 5: SQL */
|
||||
{ OP_MakeRecord, 5, 0, 0 },
|
||||
{ OP_PutIntKey, 0, 0, 0 },
|
||||
};
|
||||
int addr;
|
||||
vdbe_t *v;
|
||||
|
||||
/*
|
||||
* Make an entry in the master table.
|
||||
*/
|
||||
v = __parser_get_vdbe(parser);
|
||||
if (v == 0)
|
||||
goto triggerfinish_cleanup;
|
||||
__vdbe_prepare_write(parser, 0, 0);
|
||||
__open_master_table(v, nt->iDb);
|
||||
addr = __vdbe_add_op_list(v, ARRAY_SIZE(insert_trig),
|
||||
insert_trig);
|
||||
__vdbe_change_p3(v, (addr + 2), nt->name, 0);
|
||||
__vdbe_change_p3(v, (addr + 3), nt->table, 0);
|
||||
__vdbe_change_p3(v, (addr + 5), all->z, all->n);
|
||||
if (nt->iDb == 0) {
|
||||
__change_schema_signature(dbp, v);
|
||||
}
|
||||
__vdbe_add_op(v, OP_Close, 0, 0);
|
||||
__vdbe_conclude_write(parser);
|
||||
}
|
||||
|
||||
if (!parser->explain) {
|
||||
table_t *table;
|
||||
__hash_insert(&dbp->aDb[nt->iDb].trigHash,
|
||||
nt->name, (strlen(nt->name) + 1), nt);
|
||||
table = __locate_table(parser, nt->table,
|
||||
dbp->aDb[nt->iTabDb].zName);
|
||||
DBSQL_ASSERT(table != 0);
|
||||
nt->pNext = table->pTrigger;
|
||||
table->pTrigger = nt;
|
||||
nt = 0;
|
||||
}
|
||||
|
||||
triggerfinish_cleanup:
|
||||
__vdbe_delete_trigger(nt);
|
||||
__vdbe_delete_trigger(parser->pNewTrigger);
|
||||
parser->pNewTrigger = 0;
|
||||
__vdbe_delete_trigger_step(steplist);
|
||||
}
|
||||
|
||||
/*
|
||||
* __persist_trigger_step --
|
||||
* Make a copy of all components of the given trigger step. This has
|
||||
* the effect of copying all expr_t.token.z values into memory obtained
|
||||
* from __dbsql_calloc(). As initially created, the expr_t.token.z values
|
||||
* all point to the input string that was fed to the parser. But that
|
||||
* string is ephemeral - it will go away as soon as the dbsql_exec()
|
||||
* call that started the parser exits. This routine makes a persistent
|
||||
* copy of all the Expr.token.z strings so that the trigger_step_t
|
||||
* structure will be valid even after the dbsql_exec() call returns.
|
||||
*
|
||||
* STATIC: static void __persist_trigger_step __P((trigger_step_t *));
|
||||
*/
|
||||
static void
|
||||
__persist_trigger_step(trigger_step_t* ts)
|
||||
{
|
||||
if (ts->target.z) {
|
||||
__dbsql_strndup(NULL, ts->target.z, &ts->target.z, ts->target.n);
|
||||
ts->target.dyn = 1;
|
||||
}
|
||||
if (ts->pSelect) {
|
||||
select_t *new = __select_dup(ts->pSelect);
|
||||
__select_delete(ts->pSelect);
|
||||
ts->pSelect = new;
|
||||
}
|
||||
if( ts->pWhere ){
|
||||
expr_t *new = __expr_dup(ts->pWhere);
|
||||
__expr_delete(ts->pWhere);
|
||||
ts->pWhere = new;
|
||||
}
|
||||
if (ts->pExprList) {
|
||||
expr_list_t *new = __expr_list_dup(ts->pExprList);
|
||||
__expr_list_delete(ts->pExprList);
|
||||
ts->pExprList = new;
|
||||
}
|
||||
if (ts->pIdList) {
|
||||
id_list_t *new = __id_list_dup(ts->pIdList);
|
||||
__id_list_delete(ts->pIdList);
|
||||
ts->pIdList = new;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* __trigger_select_step --
|
||||
* Turn a SELECT statement (that the 'select' parameter points to) into
|
||||
* a trigger step. Return a pointer to a trigger_step_t structure.
|
||||
*
|
||||
* The parser calls this routine when it finds a SELECT statement in
|
||||
* body of a TRIGGER.
|
||||
*
|
||||
* PUBLIC: trigger_step_t * __trigger_select_step __P((select_t *));
|
||||
*/
|
||||
trigger_step_t *
|
||||
__trigger_select_step(select_t* select)
|
||||
{
|
||||
trigger_step_t *ts;
|
||||
|
||||
if (__dbsql_calloc(NULL, 1, sizeof(trigger_step_t), &ts) == ENOMEM)
|
||||
return 0;
|
||||
|
||||
ts->op = TK_SELECT;
|
||||
ts->pSelect = select;
|
||||
ts->orconf = OE_Default;
|
||||
__persist_trigger_step(ts);
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
/*
|
||||
* __trigger_insert_step --
|
||||
* Build a trigger step out of an INSERT statement. Return a pointer
|
||||
* to the new trigger step.
|
||||
*
|
||||
* The parser calls this routine when it sees an INSERT inside the
|
||||
* body of a trigger.
|
||||
*
|
||||
* PUBLIC: trigger_step_t *__trigger_insert_step __P((token_t *, id_list_t *,
|
||||
* PUBLIC: expr_list_t *, select_t *, int));
|
||||
*
|
||||
* tab_name Name of the table into which we insert
|
||||
* column List of columns in tab_name to insert into
|
||||
* elist The VALUE clause: a list of values to be
|
||||
* inserted
|
||||
* select A SELECT statement that supplies values
|
||||
* orconf The conflict algorithm (OE_Abort, OE_Replace,
|
||||
* etc.)
|
||||
*/
|
||||
trigger_step_t *
|
||||
__trigger_insert_step(token_t* tab_name, id_list_t* column, expr_list_t* elist, select_t* select, int orconf)
|
||||
{
|
||||
trigger_step_t *ts;
|
||||
|
||||
if (__dbsql_calloc(NULL, 1, sizeof(trigger_step_t), &ts) == ENOMEM)
|
||||
return 0;
|
||||
|
||||
DBSQL_ASSERT(elist == 0 || select == 0);
|
||||
DBSQL_ASSERT(elist != 0 || select != 0);
|
||||
|
||||
ts->op = TK_INSERT;
|
||||
ts->pSelect = select;
|
||||
ts->target = *tab_name;
|
||||
ts->pIdList = column;
|
||||
ts->pExprList = elist;
|
||||
ts->orconf = orconf;
|
||||
__persist_trigger_step(ts);
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
/*
|
||||
* __trigger_update_step --
|
||||
* Construct a trigger step that implements an UPDATE statement and return
|
||||
* a pointer to that trigger step. The parser calls this routine when it
|
||||
* sees an UPDATE statement inside the body of a CREATE TRIGGER.
|
||||
*
|
||||
* PUBLIC: trigger_step_t *__trigger_update_step __P((token_t *, expr_list_t *,
|
||||
* PUBLIC: expr_t *, int));
|
||||
*
|
||||
* tab_name Name of the table to be updated
|
||||
* elist The SET clause: list of column and new values
|
||||
* where_clause The WHERE clause
|
||||
* orconf The conflict algorithm. (OE_Abort, OE_Ignore,
|
||||
* etc)
|
||||
*/
|
||||
trigger_step_t *
|
||||
__trigger_update_step(token_t* tab_name, expr_list_t* elist, expr_t* where_clause, int orconf)
|
||||
{
|
||||
trigger_step_t *ts;
|
||||
|
||||
if (__dbsql_calloc(NULL, 1, sizeof(trigger_step_t), &ts) == ENOMEM)
|
||||
return 0;
|
||||
|
||||
ts->op = TK_UPDATE;
|
||||
ts->target = *tab_name;
|
||||
ts->pExprList = elist;
|
||||
ts->pWhere = where_clause;
|
||||
ts->orconf = orconf;
|
||||
__persist_trigger_step(ts);
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
/*
|
||||
* __trigger_delete_step --
|
||||
* Construct a trigger step that implements a DELETE statement and return
|
||||
* a pointer to that trigger step. The parser calls this routine when it
|
||||
* sees a DELETE statement inside the body of a CREATE TRIGGER.
|
||||
*
|
||||
* PUBLIC: trigger_step_t *__trigger_delete_step __P((token_t *, expr_t *));
|
||||
*/
|
||||
trigger_step_t *
|
||||
__trigger_delete_step(token_t* tab_name, expr_t* where_clause)
|
||||
{
|
||||
trigger_step_t *ts;
|
||||
|
||||
if (__dbsql_calloc(NULL, 1, sizeof(trigger_step_t), &ts) == ENOMEM)
|
||||
return 0;
|
||||
|
||||
ts->op = TK_DELETE;
|
||||
ts->target = *tab_name;
|
||||
ts->pWhere = where_clause;
|
||||
ts->orconf = OE_Default;
|
||||
__persist_trigger_step(ts);
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
/*
|
||||
* __vdbe_delete_trigger --
|
||||
* Recursively delete a trigger_t structure
|
||||
*
|
||||
* PUBLIC: void __vdbe_delete_trigger __P((trigger_t *));
|
||||
*/
|
||||
void
|
||||
__vdbe_delete_trigger(trigger_t* trigger)
|
||||
{
|
||||
if (trigger == 0)
|
||||
return;
|
||||
__vdbe_delete_trigger_step(trigger->step_list);
|
||||
__dbsql_free(NULL, trigger->name);
|
||||
__dbsql_free(NULL, trigger->table);
|
||||
__expr_delete(trigger->pWhen);
|
||||
__id_list_delete(trigger->pColumns);
|
||||
if (trigger->nameToken.dyn)
|
||||
__dbsql_free(NULL, (char*)trigger->nameToken.z);
|
||||
__dbsql_free(NULL, trigger);
|
||||
}
|
||||
|
||||
/*
|
||||
* __drop_trigger --
|
||||
* This function is called to drop a trigger from the database schema.
|
||||
*
|
||||
* This may be called directly from the parser and therefore identifies
|
||||
* the trigger by name. The __drop_trigger_ptr() routine does the
|
||||
* same job as this routine except it take a spointer to the trigger
|
||||
* instead of the trigger name.
|
||||
*
|
||||
* Note that this function does not delete the trigger entirely. Instead
|
||||
* it removes it from the internal schema and places it in the trigDrop
|
||||
* hash table. This is so that the trigger can be restored into the
|
||||
* database schema if the transaction is rolled back.
|
||||
*
|
||||
* PUBLIC: void __drop_trigger __P((parser_t *, src_list_t *));
|
||||
*/
|
||||
void
|
||||
__drop_trigger(parser_t* parser, src_list_t* trig_list)
|
||||
{
|
||||
int i;
|
||||
trigger_t *trigger;
|
||||
const char *db_name;
|
||||
const char *trig_name;
|
||||
int name_len;
|
||||
DBSQL *dbp = parser->db;
|
||||
|
||||
if (parser->rc == ENOMEM)
|
||||
goto err;
|
||||
DBSQL_ASSERT(trig_list->nSrc == 1);
|
||||
db_name = trig_list->a[0].zDatabase;
|
||||
trig_name = trig_list->a[0].zName;
|
||||
name_len = strlen(trig_name);
|
||||
for (i = 0; i < dbp->nDb; i++) {
|
||||
int j = (i < 2) ? (i ^ 1) : i; /* Search TEMP before MAIN. */
|
||||
if (db_name &&
|
||||
strcasecmp(dbp->aDb[j].zName, db_name))
|
||||
continue;
|
||||
trigger = __hash_find(&(dbp->aDb[j].trigHash), trig_name,
|
||||
(name_len + 1));
|
||||
if (trigger)
|
||||
break;
|
||||
}
|
||||
if (!trigger) {
|
||||
__error_msg(parser, "no such trigger: %S", trig_list, 0);
|
||||
goto err;
|
||||
}
|
||||
__drop_trigger_ptr(parser, trigger, 0);
|
||||
|
||||
err:
|
||||
__src_list_delete(trig_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* __drop_trigger_ptr --
|
||||
* Drop a trigger given a pointer to that trigger. If nested is false,
|
||||
* then also generate code to remove the trigger from the DBSQL_MASTER
|
||||
* table.
|
||||
*
|
||||
* PUBLIC: void __drop_trigger_ptr __P((parser_t *, trigger_t *, int));
|
||||
*/
|
||||
void
|
||||
__drop_trigger_ptr(parser_t* parser, trigger_t* trigger, int nested)
|
||||
{
|
||||
table_t *table;
|
||||
vdbe_t *v;
|
||||
DBSQL *dbp = parser->db;
|
||||
|
||||
DBSQL_ASSERT(trigger->iDb < dbp->nDb);
|
||||
if (trigger->iDb >= 2) {
|
||||
__error_msg(parser, "triggers may not be removed from "
|
||||
"auxiliary database %s",
|
||||
dbp->aDb[trigger->iDb].zName);
|
||||
return;
|
||||
}
|
||||
table = __find_table(dbp, trigger->table,
|
||||
dbp->aDb[trigger->iTabDb].zName);
|
||||
DBSQL_ASSERT(table);
|
||||
DBSQL_ASSERT(table->iDb == trigger->iDb || trigger->iDb == 1);
|
||||
#ifndef DBSQL_NO_AUTH
|
||||
{
|
||||
int code = DBSQL_DROP_TRIGGER;
|
||||
const char *db = dbp->aDb[trigger->iDb].zName;
|
||||
const char *tab = SCHEMA_TABLE(trigger->iDb);
|
||||
if (trigger->iDb)
|
||||
code = DBSQL_DROP_TEMP_TRIGGER;
|
||||
if (__auth_check(parser, code, trigger->name,
|
||||
table->zName, db) ||
|
||||
__auth_check(parser, DBSQL_DELETE, tab, 0, db)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Generate code to destroy the database record of the trigger.
|
||||
*/
|
||||
if (table != 0 && !nested && (v = __parser_get_vdbe(parser)) != 0) {
|
||||
int base;
|
||||
static vdbe_op_t drop_trigger[] = {
|
||||
{ OP_Rewind, 0, ADDR(9), 0},
|
||||
{ OP_String, 0, 0, 0}, /* 1 */
|
||||
{ OP_Column, 0, 1, 0},
|
||||
{ OP_Ne, 0, ADDR(8), 0},
|
||||
{ OP_String, 0, 0, "trigger"},
|
||||
{ OP_Column, 0, 0, 0},
|
||||
{ OP_Ne, 0, ADDR(8), 0},
|
||||
{ OP_Delete, 0, 0, 0},
|
||||
{ OP_Next, 0, ADDR(1), 0}, /* 8 */
|
||||
};
|
||||
|
||||
__vdbe_prepare_write(parser, 0, 0);
|
||||
__open_master_table(v, trigger->iDb);
|
||||
base = __vdbe_add_op_list(v, ARRAY_SIZE(drop_trigger),
|
||||
drop_trigger);
|
||||
__vdbe_change_p3(v, base+1, trigger->name, 0);
|
||||
if (trigger->iDb == 0) {
|
||||
__change_schema_signature(dbp, v);
|
||||
}
|
||||
__vdbe_add_op(v, OP_Close, 0, 0);
|
||||
__vdbe_conclude_write(parser);
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is not an "explain", then delete the trigger structure.
|
||||
*/
|
||||
if (!parser->explain) {
|
||||
const char *name = trigger->name;
|
||||
int len = strlen(name);
|
||||
if (table->pTrigger == trigger) {
|
||||
table->pTrigger = trigger->pNext;
|
||||
} else {
|
||||
trigger_t *cc = table->pTrigger;
|
||||
while(cc) {
|
||||
if (cc->pNext == trigger) {
|
||||
cc->pNext = cc->pNext->pNext;
|
||||
break;
|
||||
}
|
||||
cc = cc->pNext;
|
||||
}
|
||||
DBSQL_ASSERT(cc);
|
||||
}
|
||||
__hash_insert(&(dbp->aDb[trigger->iDb].trigHash), name,
|
||||
(len + 1), 0);
|
||||
__vdbe_delete_trigger(trigger);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* __check_column_overlap --
|
||||
* 'elist' is the SET clause of an UPDATE statement. Each entry
|
||||
* in 'elist' is of the format <id>=<expr>. If any of the entries
|
||||
* in 'elist' have an <id> which matches an identifier in 'id_list',
|
||||
* then return TRUE. If 'id_list'==NULL, then it is considered a
|
||||
* wildcard that matches anything. Likewise if elist==NULL then
|
||||
* it matches anything so always return true. Return false only
|
||||
* if there is no match.
|
||||
*
|
||||
* STATIC: static int __check_column_overlap __P((id_list_t *, expr_list_t *));
|
||||
*/
|
||||
static int
|
||||
__check_column_overlap(id_list_t* id_list, expr_list_t* elist)
|
||||
{
|
||||
int e;
|
||||
if (!id_list || !elist)
|
||||
return 1;
|
||||
for (e = 0; e < elist->nExpr; e++) {
|
||||
if (__id_list_index(id_list, elist->a[e].zName) >= 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* A global variable that is TRUE if we should always set up temp tables for
|
||||
* for triggers, even if there are no triggers to code. This is used to test
|
||||
* how much overhead the triggers algorithm is causing.
|
||||
*
|
||||
* This flag can be set or cleared using the "trigger_overhead_test" pragma.
|
||||
* The pragma is not documented since it is not really part of the public
|
||||
* interface, just the test procedure.
|
||||
*/
|
||||
int always_code_trigger_setup = 0; /* TODO, remove this global, place it
|
||||
in the environment. */
|
||||
|
||||
/*
|
||||
* __triggers_exist --
|
||||
* Returns true if a trigger matching op, tr_tm and foreach that is NOT
|
||||
* already on the parser_t objects trigger-stack (to prevent recursive
|
||||
* trigger firing) is found in the list specified as trigger.
|
||||
*
|
||||
* PUBLIC: int __triggers_exist __P((parser_t *, trigger_t *, int, int, int,
|
||||
* PUBLIC: expr_list_t *));
|
||||
*
|
||||
* parser Used to check for recursive triggers
|
||||
* trigger A list of triggers associated with a table
|
||||
* op One of TK_DELETE, TK_INSERT, TK_UPDATE
|
||||
* tr_tm One of TK_BEFORE, TK_AFTER
|
||||
* foreach One of TK_ROW or TK_STATEMENT
|
||||
* changes Columns that change in an UPDATE statement
|
||||
*/
|
||||
int __triggers_exist(parser, trigger, op, tr_tm, foreach, changes)
|
||||
parser_t *parser;
|
||||
trigger_t *trigger;
|
||||
int op;
|
||||
int tr_tm;
|
||||
int foreach;
|
||||
expr_list_t *changes;
|
||||
{
|
||||
trigger_t * trig_cursor;
|
||||
|
||||
if (always_code_trigger_setup) {
|
||||
return 1;
|
||||
}
|
||||
trig_cursor = trigger;
|
||||
while (trig_cursor) {
|
||||
if (trig_cursor->op == op &&
|
||||
trig_cursor->tr_tm == tr_tm &&
|
||||
trig_cursor->foreach == foreach &&
|
||||
__check_column_overlap(trig_cursor->pColumns, changes)) {
|
||||
trigger_stack_t *ss;
|
||||
ss = parser->trigStack;
|
||||
while (ss && ss->pTrigger != trigger) {
|
||||
ss = ss->pNext;
|
||||
}
|
||||
if (!ss)
|
||||
return 1;
|
||||
}
|
||||
trig_cursor = trig_cursor->pNext;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* __target_src_list --
|
||||
* Convert the pStep->target token into a src_list_t and return a pointer
|
||||
* to that src_list_t.
|
||||
*
|
||||
* This routine adds a specific database name, if needed, to the target
|
||||
* when forming the src_list_t. This prevents a trigger in one database
|
||||
* from referring to a target in another database. An exception is when
|
||||
* the trigger is in TEMP in which case it can refer to any other database
|
||||
* it wants.
|
||||
*
|
||||
* STATIC: static src_list_t *__target_src_list __P((parser_t *,
|
||||
* STATIC: trigger_step_t *));
|
||||
*
|
||||
* parser The parsing context
|
||||
* step The trigger containing the target token
|
||||
*/
|
||||
static src_list_t *targetSrcList(parser, step)
|
||||
parser_t *parser;
|
||||
trigger_step_t *step;
|
||||
{
|
||||
token_t db; /* Dummy database name token */
|
||||
int db_idx; /* Index of the database to use */
|
||||
src_list_t *src; /* SrcList to be returned */
|
||||
|
||||
db_idx = step->pTrig->iDb;
|
||||
if (db_idx == 0 || db_idx >= 2) {
|
||||
DBSQL_ASSERT(db_idx < parser->db->nDb);
|
||||
db.z = parser->db->aDb[db_idx].zName;
|
||||
db.n = strlen(db.z);
|
||||
src = __src_list_append(0, &db, &step->target);
|
||||
} else {
|
||||
src = __src_list_append(0, &step->target, 0);
|
||||
}
|
||||
return src;
|
||||
}
|
||||
|
||||
/*
|
||||
* __code_trigger_prigram --
|
||||
* Generate VDBE code for zero or more statements inside the body of a
|
||||
* trigger.
|
||||
*
|
||||
* STATIC: static int __code_trigger_prigram __P(());
|
||||
*
|
||||
* parser The parser context
|
||||
* steplist List of statements inside the trigger body
|
||||
* orconfin Conflict algorithm. (OE_Abort, etc)
|
||||
*/
|
||||
static int
|
||||
__code_trigger_program(parser_t* parser, trigger_step_t* steplist, int orconfin)
|
||||
{
|
||||
int orconf;
|
||||
trigger_step_t * ts = steplist;
|
||||
|
||||
while (ts) {
|
||||
int saveNTab = parser->nTab;
|
||||
orconf = (orconfin == OE_Default)?ts->orconf:orconfin;
|
||||
parser->trigStack->orconf = orconf;
|
||||
switch(ts->op) {
|
||||
case TK_SELECT: {
|
||||
select_t * ss = __select_dup(ts->pSelect);
|
||||
DBSQL_ASSERT(ss);
|
||||
DBSQL_ASSERT(ss->pSrc);
|
||||
__select(parser, ss, SRT_Discard, 0, 0, 0, 0);
|
||||
__select_delete(ss);
|
||||
break;
|
||||
}
|
||||
case TK_UPDATE: {
|
||||
src_list_t *src;
|
||||
src = targetSrcList(parser, ts);
|
||||
__vdbe_add_op(parser->pVdbe, OP_ListPush, 0, 0);
|
||||
__update(parser, src,
|
||||
__expr_list_dup(ts->pExprList),
|
||||
__expr_dup(ts->pWhere), orconf);
|
||||
__vdbe_add_op(parser->pVdbe, OP_ListPop, 0, 0);
|
||||
break;
|
||||
}
|
||||
case TK_INSERT: {
|
||||
src_list_t *src;
|
||||
src = targetSrcList(parser, ts);
|
||||
__insert(parser, src,
|
||||
__expr_list_dup(ts->pExprList),
|
||||
__select_dup(ts->pSelect),
|
||||
__id_list_dup(ts->pIdList), orconf);
|
||||
break;
|
||||
}
|
||||
case TK_DELETE: {
|
||||
src_list_t *src;
|
||||
__vdbe_add_op(parser->pVdbe, OP_ListPush, 0, 0);
|
||||
src = targetSrcList(parser, ts);
|
||||
__delete_from(parser, src, __expr_dup(ts->pWhere));
|
||||
__vdbe_add_op(parser->pVdbe, OP_ListPop, 0, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
DBSQL_ASSERT(0);
|
||||
}
|
||||
parser->nTab = saveNTab;
|
||||
ts = ts->pNext;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* __code_row_trigger --
|
||||
* This is called to code FOR EACH ROW triggers.
|
||||
*
|
||||
* When the code that this function generates is executed, the following
|
||||
* must be true:
|
||||
*
|
||||
* 1. No cursors may be open in the main database. (But newIdx and oldIdx
|
||||
* can be indices of cursors in temporary tables. See below.)
|
||||
*
|
||||
* 2. If the triggers being coded are ON INSERT or ON UPDATE triggers,
|
||||
* then a temporary vdbe cursor (index newIdx) must be open and
|
||||
* pointing at a row containing values to be substituted for new.*
|
||||
* expressions in the trigger program(s).
|
||||
*
|
||||
* 3. If the triggers being coded are ON DELETE or ON UPDATE triggers,
|
||||
* then a temporary vdbe cursor (index oldIdx) must be open and
|
||||
* pointing at a row containing values to be substituted for old.*
|
||||
* expressions in the trigger program(s).
|
||||
*
|
||||
* PUBLIC: int __code_row_trigger __P(());
|
||||
*
|
||||
* parser Parser context
|
||||
* op One of TK_UPDATE, TK_INSERT, TK_DELETE
|
||||
* changes Changes list for any UPDATE OF triggers
|
||||
* tr_tm One of TK_BEFORE, TK_AFTER
|
||||
* table The table to code triggers from
|
||||
* new_idx The indice of the "new" row to access
|
||||
* old_idx The indice of the "old" row to access
|
||||
* orconf ON CONFLICT policy
|
||||
* ignore_jump Instruction to jump to for RAISE(IGNORE)
|
||||
*/
|
||||
int __code_row_trigger(parser, op, changes, tr_tm, table, new_idx, old_idx,
|
||||
orconf, ignore_jump)
|
||||
parser_t *parser;
|
||||
int op;
|
||||
expr_list_t *changes;
|
||||
int tr_tm;
|
||||
table_t *table;
|
||||
int new_idx;
|
||||
int old_idx;
|
||||
int orconf;
|
||||
int ignore_jump;
|
||||
{
|
||||
trigger_t * trigger;
|
||||
trigger_stack_t * trig_stack;
|
||||
DBSQL *dbp = parser->db;
|
||||
|
||||
DBSQL_ASSERT(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
|
||||
DBSQL_ASSERT(tr_tm == TK_BEFORE || tr_tm == TK_AFTER );
|
||||
|
||||
DBSQL_ASSERT(new_idx != -1 || old_idx != -1);
|
||||
|
||||
trigger = table->pTrigger;
|
||||
while(trigger) {
|
||||
int fire_this = 0;
|
||||
|
||||
/*
|
||||
* Determine whether we should code this trigger.
|
||||
*/
|
||||
if (trigger->op == op && trigger->tr_tm == tr_tm &&
|
||||
trigger->foreach == TK_ROW) {
|
||||
fire_this = 1;
|
||||
trig_stack = parser->trigStack;
|
||||
while(trig_stack) {
|
||||
if (trig_stack->pTrigger == trigger) {
|
||||
fire_this = 0;
|
||||
}
|
||||
trig_stack = trig_stack->pNext;
|
||||
}
|
||||
if (op == TK_UPDATE && trigger->pColumns &&
|
||||
!__check_column_overlap(trigger->pColumns,
|
||||
changes)) {
|
||||
fire_this = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (fire_this && __dbsql_calloc(dbp, 1,sizeof(trigger_stack_t),
|
||||
&trig_stack) != ENOMEM) {
|
||||
int end_trigger;
|
||||
src_list_t dummy_tab_list;
|
||||
expr_t * when_expr;
|
||||
auth_context_t authctx;
|
||||
|
||||
dummy_tab_list.nSrc = 0;
|
||||
|
||||
/*
|
||||
* Push an entry on to the trigger stack.
|
||||
*/
|
||||
trig_stack->pTrigger = trigger;
|
||||
trig_stack->newIdx = new_idx;
|
||||
trig_stack->oldIdx = old_idx;
|
||||
trig_stack->pTab = table;
|
||||
trig_stack->pNext = parser->trigStack;
|
||||
trig_stack->ignoreJump = ignore_jump;
|
||||
parser->trigStack = trig_stack;
|
||||
__auth_context_push(parser, &authctx, trigger->name);
|
||||
|
||||
/*
|
||||
* Code the WHEN clause.
|
||||
*/
|
||||
end_trigger = __vdbe_make_label(parser->pVdbe);
|
||||
when_expr = __expr_dup(trigger->pWhen);
|
||||
if (__expr_resolve_ids(parser, &dummy_tab_list, 0,
|
||||
when_expr)) {
|
||||
parser->trigStack = parser->trigStack->pNext;
|
||||
__dbsql_free(dbp, trig_stack);
|
||||
__expr_delete(when_expr);
|
||||
return 1;
|
||||
}
|
||||
__expr_if_false(parser, when_expr, end_trigger, 1);
|
||||
__expr_delete(when_expr);
|
||||
|
||||
__code_trigger_program(parser, trigger->step_list,
|
||||
orconf);
|
||||
|
||||
/*
|
||||
* Pop the entry off the trigger stack.
|
||||
*/
|
||||
parser->trigStack = parser->trigStack->pNext;
|
||||
__auth_context_pop(&authctx);
|
||||
__dbsql_free(dbp, trig_stack);
|
||||
|
||||
__vdbe_resolve_label(parser->pVdbe, end_trigger);
|
||||
}
|
||||
trigger = trigger->pNext;
|
||||
}
|
||||
return 0;
|
||||
}
|
527
src/cg_update.c
Normal file
527
src/cg_update.c
Normal file
|
@ -0,0 +1,527 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains routines that handle UPDATE statements.
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
#include "dbsql_int.h"
|
||||
|
||||
/*
|
||||
* __update --
|
||||
* Process an UPDATE statement.
|
||||
*
|
||||
* UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
|
||||
* \_______/ \________/ \______/ \________________/
|
||||
* on_error tab_list changes where
|
||||
*
|
||||
* PUBLIC: void __update __P((parser_t *, src_list_t *, expr_list_t *,
|
||||
* PUBLIC: expr_t *, int));
|
||||
*
|
||||
* parser The parser context
|
||||
* tab_list The table in which we should change things
|
||||
* changes Things to be changed
|
||||
* where The WHERE clause. May be null
|
||||
* on_error How to handle constraint errors
|
||||
*/
|
||||
void __update(parser, tab_list, changes, where, on_error)
|
||||
parser_t *parser;
|
||||
src_list_t *tab_list;
|
||||
expr_list_t *changes;
|
||||
expr_t *where;
|
||||
int on_error;
|
||||
{
|
||||
int rc;
|
||||
int i, j; /* Loop counters */
|
||||
table_t *table; /* The table to be updated */
|
||||
int addr; /* VDBE instruction address of the start of
|
||||
the loop */
|
||||
where_info_t *winfo; /* Information about the WHERE clause */
|
||||
vdbe_t *v; /* The virtual database engine */
|
||||
index_t *idx; /* For looping over indices */
|
||||
int num_idx; /* Number of indices that need updating */
|
||||
int total_num_idx; /* Total number of indices */
|
||||
int cur; /* VDBE Cursor number of table */
|
||||
DBSQL *dbp; /* The database structure */
|
||||
index_t **indices = 0;/* An array of indices that need updating too */
|
||||
char *idx_used = 0; /* idx_used[i]==1 if the i-th index is used */
|
||||
int *xref = 0; /* xref[i] is the index in changes->a[] of the
|
||||
an expression for the i-th column of the
|
||||
table. xref[i]==-1 if the i-th column is not
|
||||
changed. */
|
||||
int recno_will_change_p;/* True if the record number is being changed*/
|
||||
expr_t *recno; /* Expression defining the new record number */
|
||||
int open_all_p; /* True if all indices need to be opened */
|
||||
int is_view_p; /* Trying to update a view */
|
||||
auth_context_t auth; /* The authorization context */
|
||||
|
||||
int before_triggers; /* True if there are any BEFORE triggers */
|
||||
int after_triggers; /* True if there are any AFTER triggers */
|
||||
int row_triggers_exist = 0;/* True if any row triggers exist */
|
||||
|
||||
int new_idx = -1;/* index of trigger "new" temp table */
|
||||
int old_idx = -1;/* index of trigger "old" temp table */
|
||||
select_t *view;
|
||||
|
||||
auth.pParse = 0;
|
||||
if (parser->nErr || parser->rc == ENOMEM)
|
||||
goto update_cleanup;
|
||||
dbp = parser->db;
|
||||
DBSQL_ASSERT(tab_list->nSrc == 1);
|
||||
|
||||
/*
|
||||
* Locate the table which we want to update.
|
||||
*/
|
||||
table = __src_list_lookup(parser, tab_list);
|
||||
if (table == 0)
|
||||
goto update_cleanup;
|
||||
before_triggers = __triggers_exist(parser, table->pTrigger,
|
||||
TK_UPDATE, TK_BEFORE, TK_ROW,
|
||||
changes);
|
||||
after_triggers = __triggers_exist(parser, table->pTrigger,
|
||||
TK_UPDATE, TK_AFTER, TK_ROW,
|
||||
changes);
|
||||
row_triggers_exist = before_triggers || after_triggers;
|
||||
is_view_p = (table->pSelect != 0);
|
||||
if (__is_table_read_only(parser, table, before_triggers)) {
|
||||
goto update_cleanup;
|
||||
}
|
||||
if (is_view_p) {
|
||||
if (__view_get_column_names(parser, table)) {
|
||||
goto update_cleanup;
|
||||
}
|
||||
}
|
||||
if (__dbsql_calloc(dbp, table->nCol, sizeof(int), &xref) == ENOMEM)
|
||||
goto update_cleanup;
|
||||
for (i = 0; i < table->nCol; i++) {
|
||||
xref[i] = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are FOR EACH ROW triggers, allocate cursors for the
|
||||
* special OLD and NEW tables.
|
||||
*/
|
||||
if (row_triggers_exist) {
|
||||
new_idx = parser->nTab++;
|
||||
old_idx = parser->nTab++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a cursors for the main database table and for all indices.
|
||||
* The index cursors might not be used, but if they are used they
|
||||
* need to occur right after the database cursor. So go ahead and
|
||||
* allocate enough space, just in case.
|
||||
*/
|
||||
tab_list->a[0].iCursor = cur = parser->nTab++;
|
||||
for (idx = table->pIndex; idx; idx = idx->pNext) {
|
||||
parser->nTab++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolve the column names in all the expressions of the
|
||||
* of the UPDATE statement. Also find the column index
|
||||
* for each column to be updated in the changes array. For each
|
||||
* column to be updated, make sure we have authorization to change
|
||||
* that column.
|
||||
*/
|
||||
recno_will_change_p = 0;
|
||||
for (i = 0; i < changes->nExpr; i++) {
|
||||
if (__expr_resolve_ids(parser, tab_list, 0,
|
||||
changes->a[i].pExpr)) {
|
||||
goto update_cleanup;
|
||||
}
|
||||
if (__expr_check(parser, changes->a[i].pExpr, 0, 0)) {
|
||||
goto update_cleanup;
|
||||
}
|
||||
for (j = 0; j < table->nCol; j++) {
|
||||
if (strcasecmp(table->aCol[j].zName,
|
||||
changes->a[i].zName) == 0) {
|
||||
if (j == table->iPKey) {
|
||||
recno_will_change_p = 1;
|
||||
recno = changes->a[i].pExpr;
|
||||
}
|
||||
xref[j] = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j >= table->nCol) {
|
||||
if (__is_row_id(changes->a[i].zName)) {
|
||||
recno_will_change_p = 1;
|
||||
recno = changes->a[i].pExpr;
|
||||
} else {
|
||||
__error_msg(parser, "no such column: %s",
|
||||
changes->a[i].zName);
|
||||
goto update_cleanup;
|
||||
}
|
||||
}
|
||||
#ifndef DBSQL_NO_AUTH
|
||||
rc = __auth_check(parser, DBSQL_UPDATE, table->zName,
|
||||
table->aCol[j].zName,
|
||||
dbp->aDb[table->iDb].zName);
|
||||
if (rc == DBSQL_DENY) {
|
||||
goto update_cleanup;
|
||||
} else if (rc == DBSQL_IGNORE) {
|
||||
xref[j] = -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate memory for the array indices[] and fill it with pointers
|
||||
* to every index that needs to be updated. Indices only need
|
||||
* updating if their key includes one of the columns named in changes
|
||||
* or if the record number of the original table entry is changing.
|
||||
*/
|
||||
for (num_idx = total_num_idx = 0, idx = table->pIndex;
|
||||
idx; idx = idx->pNext, total_num_idx++) {
|
||||
if (recno_will_change_p) {
|
||||
i = 0;
|
||||
} else {
|
||||
for (i = 0; i < idx->nColumn; i++) {
|
||||
if (xref[idx->aiColumn[i]] >= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < idx->nColumn)
|
||||
num_idx++;
|
||||
}
|
||||
if (total_num_idx > 0) { /* TODO, is this the right amt to alloc? */
|
||||
if (__dbsql_calloc(dbp, num_idx + total_num_idx,
|
||||
sizeof(index_t *), &indices) == ENOMEM)
|
||||
goto update_cleanup;
|
||||
idx_used = (char*)&indices[num_idx];
|
||||
}
|
||||
for (num_idx = j = 0, idx = table->pIndex; idx; idx = idx->pNext, j++){
|
||||
if (recno_will_change_p) {
|
||||
i = 0;
|
||||
} else {
|
||||
for (i = 0; i < idx->nColumn; i++) {
|
||||
if (xref[idx->aiColumn[i]] >= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < idx->nColumn) {
|
||||
indices[num_idx++] = idx;
|
||||
idx_used[j] = 1;
|
||||
} else {
|
||||
idx_used[j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolve the column names in all the expressions in the
|
||||
* WHERE clause.
|
||||
*/
|
||||
if (where) {
|
||||
if (__expr_resolve_ids(parser, tab_list, 0, where)) {
|
||||
goto update_cleanup;
|
||||
}
|
||||
if (__expr_check(parser, where, 0, 0)) {
|
||||
goto update_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the view context.
|
||||
*/
|
||||
if (is_view_p) {
|
||||
__auth_context_push(parser, &auth, table->zName);
|
||||
}
|
||||
|
||||
/*
|
||||
* Begin generating code.
|
||||
*/
|
||||
v = __parser_get_vdbe(parser);
|
||||
if (v == 0)
|
||||
goto update_cleanup;
|
||||
__vdbe_prepare_write(parser, 1, table->iDb);
|
||||
|
||||
/*
|
||||
* If we are trying to update a view, construct that view into
|
||||
* a temporary table.
|
||||
*/
|
||||
if (is_view_p) {
|
||||
view = __select_dup(table->pSelect);
|
||||
__select(parser, view, SRT_TempTable, cur, 0, 0, 0);
|
||||
__select_delete(view);
|
||||
}
|
||||
|
||||
/*
|
||||
* Begin the database scan.
|
||||
*/
|
||||
winfo = __where_begin(parser, tab_list, where, 1, 0);
|
||||
if (winfo == 0)
|
||||
goto update_cleanup;
|
||||
|
||||
/*
|
||||
* Remember the index of every item to be updated.
|
||||
*/
|
||||
__vdbe_add_op(v, OP_ListWrite, 0, 0);
|
||||
|
||||
/*
|
||||
* End the database scan loop.
|
||||
*/
|
||||
__where_end(winfo);
|
||||
|
||||
/*
|
||||
* Initialize the count of updated rows.
|
||||
*/
|
||||
if (dbp->flags & DBSQL_CountRows && !parser->trigStack) {
|
||||
__vdbe_add_op(v, OP_Integer, 0, 0);
|
||||
}
|
||||
|
||||
if (row_triggers_exist) {
|
||||
/*
|
||||
* Create pseudo-tables for NEW and OLD
|
||||
*/
|
||||
__vdbe_add_op(v, OP_OpenPseudo, old_idx, 0);
|
||||
__vdbe_add_op(v, OP_OpenPseudo, new_idx, 0);
|
||||
|
||||
/*
|
||||
* The top of the update loop for when there are triggers.
|
||||
*/
|
||||
__vdbe_add_op(v, OP_ListRewind, 0, 0);
|
||||
addr = __vdbe_add_op(v, OP_ListRead, 0, 0);
|
||||
__vdbe_add_op(v, OP_Dup, 0, 0);
|
||||
|
||||
/*
|
||||
* Open a cursor and make it point to the record that is
|
||||
* being updated.
|
||||
*/
|
||||
__vdbe_add_op(v, OP_Dup, 0, 0);
|
||||
if(!is_view_p) {
|
||||
__vdbe_add_op(v, OP_Integer, table->iDb, 0);
|
||||
__vdbe_add_op(v, OP_OpenRead, cur, table->tnum);
|
||||
}
|
||||
__vdbe_add_op(v, OP_MoveTo, cur, 0);
|
||||
|
||||
/*
|
||||
* Generate the OLD table.
|
||||
*/
|
||||
__vdbe_add_op(v, OP_Recno, cur, 0);
|
||||
__vdbe_add_op(v, OP_RowData, cur, 0);
|
||||
__vdbe_add_op(v, OP_PutIntKey, old_idx, 0);
|
||||
|
||||
/*
|
||||
* Generate the NEW table.
|
||||
*/
|
||||
if (recno_will_change_p) {
|
||||
__expr_code(parser, recno);
|
||||
} else {
|
||||
__vdbe_add_op(v, OP_Recno, cur, 0);
|
||||
}
|
||||
for(i = 0; i < table->nCol; i++) {
|
||||
if (i == table->iPKey) {
|
||||
__vdbe_add_op(v, OP_String, 0, 0);
|
||||
continue;
|
||||
}
|
||||
j = xref[i];
|
||||
if (j < 0) {
|
||||
__vdbe_add_op(v, OP_Column, cur, i);
|
||||
}else{
|
||||
__expr_code(parser, changes->a[j].pExpr);
|
||||
}
|
||||
}
|
||||
__vdbe_add_op(v, OP_MakeRecord, table->nCol, 0);
|
||||
__vdbe_add_op(v, OP_PutIntKey, new_idx, 0);
|
||||
if (!is_view_p) {
|
||||
__vdbe_add_op(v, OP_Close, cur, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fire the BEFORE and INSTEAD OF triggers.
|
||||
*/
|
||||
if (__code_row_trigger(parser, TK_UPDATE, changes,
|
||||
TK_BEFORE, table, new_idx, old_idx,
|
||||
on_error, addr)) {
|
||||
goto update_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_view_p) {
|
||||
/*
|
||||
* Open every index that needs updating. Note that if any
|
||||
* index could potentially invoke a REPLACE conflict resolution
|
||||
* action, then we need to open all indices because we might
|
||||
* need to be deleting some records.
|
||||
*/
|
||||
__vdbe_add_op(v, OP_Integer, table->iDb, 0);
|
||||
__vdbe_add_op(v, OP_OpenWrite, cur, table->tnum);
|
||||
if (on_error == OE_Replace) {
|
||||
open_all_p = 1;
|
||||
} else {
|
||||
open_all_p = 0;
|
||||
for (idx = table->pIndex; idx; idx = idx->pNext) {
|
||||
if (idx->onError == OE_Replace) {
|
||||
open_all_p = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(i = 0, idx = table->pIndex; idx; idx = idx->pNext, i++) {
|
||||
if (open_all_p || idx_used[i]) {
|
||||
__vdbe_add_op(v, OP_Integer, idx->iDb, 0);
|
||||
__vdbe_add_op(v, OP_OpenWrite, (cur + i + 1),
|
||||
idx->tnum);
|
||||
DBSQL_ASSERT(parser->nTab > (cur + i + 1));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop over every record that needs updating. We have to load
|
||||
* the old data for each record to be updated because some
|
||||
* columns might not change and we will need to copy the old
|
||||
* value. Also, the old data is needed to delete the old index
|
||||
* entires. So make the cursor point at the old record.
|
||||
*/
|
||||
if (!row_triggers_exist) {
|
||||
__vdbe_add_op(v, OP_ListRewind, 0, 0);
|
||||
addr = __vdbe_add_op(v, OP_ListRead, 0, 0);
|
||||
__vdbe_add_op(v, OP_Dup, 0, 0);
|
||||
}
|
||||
__vdbe_add_op(v, OP_NotExists, cur, addr);
|
||||
|
||||
/*
|
||||
* If the record number will change, push the record number
|
||||
* as it will be after the update. (The old record number is
|
||||
* currently on top of the stack.)
|
||||
*/
|
||||
if (recno_will_change_p) {
|
||||
__expr_code(parser, recno);
|
||||
__vdbe_add_op(v, OP_MustBeInt, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute new data for this record.
|
||||
*/
|
||||
for (i = 0; i < table->nCol; i++) {
|
||||
if (i == table->iPKey) {
|
||||
__vdbe_add_op(v, OP_String, 0, 0);
|
||||
continue;
|
||||
}
|
||||
j = xref[i];
|
||||
if (j < 0) {
|
||||
__vdbe_add_op(v, OP_Column, cur, i);
|
||||
} else {
|
||||
__expr_code(parser, changes->a[j].pExpr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Do constraint checks.
|
||||
*/
|
||||
__generate_constraint_checks(parser, table, cur, idx_used,
|
||||
recno_will_change_p, 1, on_error,
|
||||
addr);
|
||||
|
||||
/*
|
||||
* Delete the old indices for the current record.
|
||||
*/
|
||||
__generate_row_index_delete(dbp, v, table, cur, idx_used);
|
||||
|
||||
/*
|
||||
* If changing the record number, delete the old record.
|
||||
*/
|
||||
if (recno_will_change_p) {
|
||||
__vdbe_add_op(v, OP_Delete, cur, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the new index entries and the new record.
|
||||
*/
|
||||
__complete_insertion(parser, table, cur, idx_used,
|
||||
recno_will_change_p, 1, -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Increment the row counter.
|
||||
*/
|
||||
if (dbp->flags & DBSQL_CountRows && !parser->trigStack) {
|
||||
__vdbe_add_op(v, OP_AddImm, 1, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are triggers, close all the cursors after each iteration
|
||||
* through the loop. The fire the after triggers.
|
||||
*/
|
||||
if (row_triggers_exist) {
|
||||
if (!is_view_p) {
|
||||
for(i = 0, idx = table->pIndex; idx;
|
||||
idx = idx->pNext, i++) {
|
||||
if (open_all_p || idx_used[i]) {
|
||||
__vdbe_add_op(v, OP_Close,
|
||||
(cur + i + 1), 0);
|
||||
}
|
||||
}
|
||||
__vdbe_add_op(v, OP_Close, cur, 0);
|
||||
parser->nTab = cur;
|
||||
}
|
||||
if (__code_row_trigger(parser, TK_UPDATE, changes,
|
||||
TK_AFTER, table, new_idx, old_idx,
|
||||
on_error, addr)) {
|
||||
goto update_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Repeat the above with the next record to be updated, until
|
||||
* all record selected by the WHERE clause have been updated.
|
||||
*/
|
||||
__vdbe_add_op(v, OP_Goto, 0, addr);
|
||||
__vdbe_change_p2(v, addr, __vdbe_current_addr(v));
|
||||
__vdbe_add_op(v, OP_ListReset, 0, 0);
|
||||
|
||||
/*
|
||||
* Close all tables if there were no FOR EACH ROW triggers.
|
||||
*/
|
||||
if (!row_triggers_exist) {
|
||||
for (i = 0, idx = table->pIndex; idx; idx = idx->pNext, i++) {
|
||||
if (open_all_p || idx_used[i]) {
|
||||
__vdbe_add_op(v, OP_Close, (cur + i + 1), 0);
|
||||
}
|
||||
}
|
||||
__vdbe_add_op(v, OP_Close, cur, 0);
|
||||
parser->nTab = cur;
|
||||
} else {
|
||||
__vdbe_add_op(v, OP_Close, new_idx, 0);
|
||||
__vdbe_add_op(v, OP_Close, old_idx, 0);
|
||||
}
|
||||
|
||||
__vdbe_conclude_write(parser);
|
||||
|
||||
/*
|
||||
* Return the number of rows that were changed.
|
||||
*/
|
||||
if (dbp->flags & DBSQL_CountRows && !parser->trigStack) {
|
||||
__vdbe_add_op(v, OP_ColumnName, 0, 0);
|
||||
__vdbe_change_p3(v, -1, "rows updated", P3_STATIC);
|
||||
__vdbe_add_op(v, OP_Callback, 1, 0);
|
||||
}
|
||||
|
||||
update_cleanup:
|
||||
__auth_context_pop(&auth);
|
||||
__dbsql_free(NULL, indices);
|
||||
__dbsql_free(NULL, xref);
|
||||
__src_list_delete(tab_list);
|
||||
__expr_list_delete(changes);
|
||||
__expr_delete(where);
|
||||
return;
|
||||
}
|
76
src/cg_vacuum.c
Normal file
76
src/cg_vacuum.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains code used to implement the VACUUM command.
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
#include "dbsql_int.h"
|
||||
|
||||
#if !defined(DBSQL_OMIT_VACUUM) || DBSQL_OMIT_VACUUM
|
||||
|
||||
/*
|
||||
* __vacuum --
|
||||
* The non-standard VACUUM command is used to clean up the database,
|
||||
* collapse free space, etc. It is modelled after the VACUUM command
|
||||
* in PostgreSQL.
|
||||
*
|
||||
* PUBLIC: void __vacuum __P((parser_t *, token_t *));
|
||||
*/
|
||||
void
|
||||
__vacuum(parser_t* parser, token_t* tab_name)
|
||||
{
|
||||
vdbe_t *v = __parser_get_vdbe(parser);
|
||||
__vdbe_add_op(v, OP_Vacuum, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* __execute_vacuum --
|
||||
* This routine implements the OP_Vacuum opcode of the VDBE. It works
|
||||
* by running through each database asking each to reclaim space.
|
||||
*
|
||||
* PUBLIC: int __execute_vacuum __P((char **, DBSQL *));
|
||||
*/
|
||||
int
|
||||
__execute_vacuum(char* *err_msgs, DBSQL* dbp)
|
||||
{
|
||||
return DBSQL_SUCCESS; /* NOTE: When DB implements compaction (someday)
|
||||
then this will be the place to invoke the
|
||||
__sm_compact() function. For now, its
|
||||
a no-op. */
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* __execute_vacuum --
|
||||
* A no-op.
|
||||
*
|
||||
* PUBLIC: int __execute_vacuum __P((char **, DBSQL *));
|
||||
*/
|
||||
int
|
||||
__execute_vacuum(char* *err_msgs, DBSQL* dbp)
|
||||
{
|
||||
return DBSQL_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
1435
src/cg_where.c
Normal file
1435
src/cg_where.c
Normal file
File diff suppressed because it is too large
Load diff
209
src/clib/getopt.c
Normal file
209
src/clib/getopt.c
Normal file
|
@ -0,0 +1,209 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Redistributions in any form must be accompanied by information on
|
||||
* how to obtain complete source code for the DB software and any
|
||||
* accompanying software that uses the DB software. The source code
|
||||
* must either be included in the distribution or be available for no
|
||||
* more than the cost of distribution plus a nominal fee, and must be
|
||||
* freely redistributable under reasonable conditions. For an
|
||||
* executable file, complete source code means the source code for all
|
||||
* modules it contains. It does not include source code for modules or
|
||||
* files that typically accompany the major components of the operating
|
||||
* system on which the executable file runs.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ORACLE CORPORATION ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
||||
* NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL ORACLE CORPORATION
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995
|
||||
*The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1995, 1996
|
||||
*The President and Fellows of Harvard University. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "dbsql_int.h"
|
||||
|
||||
int __dbsql_getopt_reset; /* global reset for VxWorks. */
|
||||
|
||||
int opterr = 1, /* if error message should be printed */
|
||||
optind = 1, /* index into parent argv vector */
|
||||
optopt, /* character checked for validity */
|
||||
optreset; /* reset getopt */
|
||||
char *optarg; /* argument associated with option */
|
||||
|
||||
#undef BADCH
|
||||
#define BADCH (int)'?'
|
||||
#undef BADARG
|
||||
#define BADARG (int)':'
|
||||
#undef EMSG
|
||||
#define EMSG ""
|
||||
|
||||
/*
|
||||
* getopt --
|
||||
* Parse argc/argv argument vector.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_GETOPT
|
||||
* PUBLIC: int getopt __P((int, char * const *, const char *));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
int
|
||||
getopt(nargc, nargv, ostr)
|
||||
int nargc;
|
||||
char * const *nargv;
|
||||
const char *ostr;
|
||||
{
|
||||
static char *progname;
|
||||
static char *place = EMSG; /* option letter processing */
|
||||
char *oli; /* option letter list index */
|
||||
|
||||
/*
|
||||
* VxWorks needs to be able to repeatedly call getopt from multiple
|
||||
* programs within its global name space.
|
||||
*/
|
||||
if (__dbsql_getopt_reset) {
|
||||
__dbsql_getopt_reset = 0;
|
||||
|
||||
opterr = optind = 1;
|
||||
optopt = optreset = 0;
|
||||
optarg = NULL;
|
||||
progname = NULL;
|
||||
place = EMSG;
|
||||
}
|
||||
if (!progname) {
|
||||
if ((progname = __os_rpath(*nargv)) == NULL)
|
||||
progname = *nargv;
|
||||
else
|
||||
++progname;
|
||||
}
|
||||
|
||||
if (optreset || !*place) { /* update scanning pointer */
|
||||
optreset = 0;
|
||||
if (optind >= nargc || *(place = nargv[optind]) != '-') {
|
||||
place = EMSG;
|
||||
return (EOF);
|
||||
}
|
||||
if (place[1] && *++place == '-') { /* found "--" */
|
||||
++optind;
|
||||
place = EMSG;
|
||||
return (EOF);
|
||||
}
|
||||
} /* option letter okay? */
|
||||
if ((optopt = (int)*place++) == (int)':' ||
|
||||
!(oli = strchr(ostr, optopt))) {
|
||||
/*
|
||||
* if the user didn't specify '-' as an option,
|
||||
* assume it means EOF.
|
||||
*/
|
||||
if (optopt == (int)'-')
|
||||
return (EOF);
|
||||
if (!*place)
|
||||
++optind;
|
||||
if (opterr && *ostr != ':')
|
||||
(void)fprintf(stderr,
|
||||
"%s: illegal option -- %c\n", progname, optopt);
|
||||
return (BADCH);
|
||||
}
|
||||
if (*++oli != ':') { /* don't need argument */
|
||||
optarg = NULL;
|
||||
if (!*place)
|
||||
++optind;
|
||||
}
|
||||
else { /* need an argument */
|
||||
if (*place) /* no white space */
|
||||
optarg = place;
|
||||
else if (nargc <= ++optind) { /* no arg */
|
||||
place = EMSG;
|
||||
if (*ostr == ':')
|
||||
return (BADARG);
|
||||
if (opterr)
|
||||
(void)fprintf(stderr,
|
||||
"%s: option requires an argument -- %c\n",
|
||||
progname, optopt);
|
||||
return (BADCH);
|
||||
}
|
||||
else /* white space */
|
||||
optarg = nargv[optind];
|
||||
place = EMSG;
|
||||
++optind;
|
||||
}
|
||||
return (optopt); /* dump back option letter */
|
||||
}
|
124
src/clib/memcmp.c
Normal file
124
src/clib/memcmp.c
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Redistributions in any form must be accompanied by information on
|
||||
* how to obtain complete source code for the DB software and any
|
||||
* accompanying software that uses the DB software. The source code
|
||||
* must either be included in the distribution or be available for no
|
||||
* more than the cost of distribution plus a nominal fee, and must be
|
||||
* freely redistributable under reasonable conditions. For an
|
||||
* executable file, complete source code means the source code for all
|
||||
* modules it contains. It does not include source code for modules or
|
||||
* files that typically accompany the major components of the operating
|
||||
* system on which the executable file runs.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ORACLE CORPORATION ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
||||
* NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL ORACLE CORPORATION
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995
|
||||
*The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1995, 1996
|
||||
*The President and Fellows of Harvard University. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* memcmp --
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_MEMCMP
|
||||
* PUBLIC: int memcmp __P((const void *, const void *, size_t));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
#ifndef HAVE_MEMCMP
|
||||
int
|
||||
memcmp(s1, s2, n)
|
||||
char *s1, *s2;
|
||||
size_t n;
|
||||
{
|
||||
if (n != 0) {
|
||||
unsigned char *p1 = (unsigned char *)s1,
|
||||
*p2 = (unsigned char *)s2;
|
||||
do {
|
||||
if (*p1++ != *p2++)
|
||||
return (*--p1 - *--p2);
|
||||
} while (--n != 0);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
238
src/clib/random.c
Normal file
238
src/clib/random.c
Normal file
|
@ -0,0 +1,238 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Redistributions in any form must be accompanied by information on
|
||||
* how to obtain complete source code for the DB software and any
|
||||
* accompanying software that uses the DB software. The source code
|
||||
* must either be included in the distribution or be available for no
|
||||
* more than the cost of distribution plus a nominal fee, and must be
|
||||
* freely redistributable under reasonable conditions. For an
|
||||
* executable file, complete source code means the source code for all
|
||||
* modules it contains. It does not include source code for modules or
|
||||
* files that typically accompany the major components of the operating
|
||||
* system on which the executable file runs.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ORACLE CORPORATION ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
||||
* NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL ORACLE CORPORATION
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995
|
||||
*The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1995, 1996
|
||||
*The President and Fellows of Harvard University. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "dbsql_int.h"
|
||||
|
||||
#define SEED_SZ 256
|
||||
|
||||
/*
|
||||
* __rng_seed --
|
||||
* Produce a sutable seed for our random number generator. In
|
||||
* this case that means using the current time. The seed is
|
||||
* written to a char[SEED_SZ] buffer passed by the caller.
|
||||
* Note that when testing its useful to generate the same pattern
|
||||
* of random numbers. We accomplish that by initializing the contents
|
||||
* of 'buf' to '\0' when CONFIG_TEST is defined. In this way, tests
|
||||
* are repeatable.
|
||||
*/
|
||||
#ifndef HAVE_SRAND48_R
|
||||
void
|
||||
__rng_seed(char* buf)
|
||||
{
|
||||
u_int32_t pid;
|
||||
double jt;
|
||||
u_int32_t i;
|
||||
|
||||
memset(buf, 0, SEED_SZ);
|
||||
#ifdef CONFIG_TEST
|
||||
return;
|
||||
#else
|
||||
__os_id(NULL, &pid, NULL);
|
||||
__os_jtime(&jt);
|
||||
for (i = 0; i < SEED_SZ; i++) {
|
||||
if (i % 2)
|
||||
buf[i] = (char)(pid & 0xf);
|
||||
else
|
||||
buf[i] = (char)((u_int32_t)jt & 0xf);
|
||||
}
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* srand48_r --
|
||||
* Seed the random number generator before use.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_SRAND48_R
|
||||
* PUBLIC: int srand48_r __P((struct drand48_data *));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
#ifndef HAVE_SRAND48_R
|
||||
int
|
||||
srand48_r(buffer)
|
||||
struct drand48_data *buffer;
|
||||
{
|
||||
int i;
|
||||
char k[SEED_SZ];
|
||||
buffer->j = 0;
|
||||
buffer->i = 0;
|
||||
__rng_seed(k);
|
||||
for(i = 0; i < 256; i++) {
|
||||
buffer->s[i] = i;
|
||||
}
|
||||
for(i = 0; i < 256; i++) {
|
||||
int t;
|
||||
buffer->j = (buffer->j + buffer->s[i] + k[i]) & 0xff;
|
||||
t = buffer->s[buffer->j];
|
||||
buffer->s[buffer->j] = buffer->s[i];
|
||||
buffer->s[i] = t;
|
||||
}
|
||||
buffer->init_p = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* lrand48_r --
|
||||
* A re-entrant version of a random number generator. This
|
||||
* random number generator is based on the RC4 algorithm.
|
||||
*
|
||||
* STATIC: #ifndef HAVE_LRAND48_R
|
||||
* STATIC: int lrand48_r __P((struct drand48_data *, double *));
|
||||
* STATIC: #endif
|
||||
*/
|
||||
#ifndef HAVE_LRAND48_R
|
||||
static int
|
||||
lrand48_r(buffer, result)
|
||||
struct drand48_data *buffer;
|
||||
double *result;
|
||||
{
|
||||
/* TODO: am I sure there isn't a race in here? */
|
||||
int t;
|
||||
buffer->i = (buffer->i + 1) & 0xff;
|
||||
buffer->j = (buffer->j + buffer->s[buffer->i]) & 0xff;
|
||||
t = buffer->s[buffer->i];
|
||||
buffer->s[buffer->i] = buffer->s[buffer->j];
|
||||
buffer->s[buffer->j] = t;
|
||||
t = buffer->s[buffer->i] + buffer->s[buffer->j];
|
||||
*result = buffer->s[t & 0xff];
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* rand8_r --
|
||||
*
|
||||
* PUBLIC: int rand8_r __P((struct drand48_data *, u_int8_t *));
|
||||
*/
|
||||
int
|
||||
rand8_r(buffer, result)
|
||||
struct drand48_data *buffer;
|
||||
u_int8_t *result;
|
||||
{
|
||||
long int i;
|
||||
int rc = lrand48_r(buffer, &i);
|
||||
*result = i & 0xf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* rand32_r --
|
||||
*
|
||||
* PUBLIC: int rand32_r __P((struct drand48_data *, u_int32_t *));
|
||||
*/
|
||||
int
|
||||
rand32_r(buffer, result)
|
||||
struct drand48_data *buffer;
|
||||
u_int32_t *result;
|
||||
{
|
||||
int rc, i;
|
||||
long int r, s;
|
||||
rc = lrand48_r(buffer, &r);
|
||||
for(i = 1; i < 4; i++) {
|
||||
rc = lrand48_r(buffer, &s);
|
||||
r = (r << 8) + s;
|
||||
}
|
||||
*result = r;
|
||||
return rc;
|
||||
}
|
||||
|
157
src/clib/snprintf.c
Normal file
157
src/clib/snprintf.c
Normal file
|
@ -0,0 +1,157 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Redistributions in any form must be accompanied by information on
|
||||
* how to obtain complete source code for the DB software and any
|
||||
* accompanying software that uses the DB software. The source code
|
||||
* must either be included in the distribution or be available for no
|
||||
* more than the cost of distribution plus a nominal fee, and must be
|
||||
* freely redistributable under reasonable conditions. For an
|
||||
* executable file, complete source code means the source code for all
|
||||
* modules it contains. It does not include source code for modules or
|
||||
* files that typically accompany the major components of the operating
|
||||
* system on which the executable file runs.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ORACLE CORPORATION ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
||||
* NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL ORACLE CORPORATION
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995
|
||||
*The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1995, 1996
|
||||
*The President and Fellows of Harvard University. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "dbsql_int.h"
|
||||
|
||||
/*
|
||||
* snprintf --
|
||||
* Bounded version of sprintf.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_SNPRINTF
|
||||
* PUBLIC: int snprintf __P((char *, size_t, const char *, ...));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
#ifndef HAVE_SNPRINTF
|
||||
int
|
||||
#ifdef STDC_HEADERS
|
||||
snprintf(char *str, size_t n, const char *fmt, ...)
|
||||
#else
|
||||
snprintf(str, n, fmt, va_alist)
|
||||
char *str;
|
||||
size_t n;
|
||||
const char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
static int ret_charpnt = -1;
|
||||
va_list ap;
|
||||
int len;
|
||||
|
||||
COMPQUIET(n, 0);
|
||||
|
||||
/*
|
||||
* Some old versions of sprintf return a pointer to the first argument
|
||||
* instead of a character count. Assume the return value of snprintf,
|
||||
* vsprintf, etc. will be the same as sprintf, and check the easy one.
|
||||
*
|
||||
* We do this test at run-time because it's not a test we can do in a
|
||||
* cross-compilation environment.
|
||||
*/
|
||||
if (ret_charpnt == -1) {
|
||||
char buf[10];
|
||||
|
||||
ret_charpnt =
|
||||
(int)sprintf(buf, "123") != 3 ||
|
||||
(int)sprintf(buf, "123456789") != 9 ||
|
||||
(int)sprintf(buf, "1234") != 4;
|
||||
}
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
len = vsprintf(str, fmt, ap);
|
||||
va_end(ap);
|
||||
return (ret_charpnt ? (int)strlen(str) : len);
|
||||
}
|
||||
#endif
|
151
src/clib/strcasecmp.c
Normal file
151
src/clib/strcasecmp.c
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1987, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This array is designed for mapping upper and lower case letter
|
||||
* together for a case independent comparison. The mappings are
|
||||
* based upon ascii character sequences.
|
||||
*/
|
||||
static const unsigned char charmap[] = {
|
||||
'\000', '\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',
|
||||
'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
|
||||
'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
|
||||
'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
|
||||
'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
|
||||
'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
|
||||
'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
|
||||
'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
|
||||
'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
|
||||
'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
|
||||
'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
|
||||
'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
|
||||
'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
|
||||
'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
|
||||
'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
|
||||
'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
|
||||
'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
|
||||
'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
|
||||
'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
|
||||
'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
|
||||
'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
|
||||
'\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
|
||||
'\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
|
||||
'\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
|
||||
'\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
|
||||
'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
|
||||
'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
|
||||
'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
|
||||
'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377'
|
||||
};
|
||||
|
||||
/*
|
||||
* strcasecmp --
|
||||
* Do strcmp(3) in a case-insensitive manner.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_STRCASECMP
|
||||
* PUBLIC: int strcasecmp __P((const char *, const char *));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
#ifndef HAVE_STRCASECMP
|
||||
int
|
||||
strcasecmp(s1, s2)
|
||||
const char *s1, *s2;
|
||||
{
|
||||
register const unsigned char *cm = charmap,
|
||||
*us1 = (const unsigned char *)s1,
|
||||
*us2 = (const unsigned char *)s2;
|
||||
|
||||
while (cm[*us1] == cm[*us2++])
|
||||
if (*us1++ == '\0')
|
||||
return (0);
|
||||
return (cm[*us1] - cm[*--us2]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* strncasecmp --
|
||||
* Do strncmp(3) in a case-insensitive manner.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_STRNCASECMP
|
||||
* PUBLIC: int strncasecmp __P((const char *, const char *, size_t));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
#ifndef HAVE_STRNCASECMP
|
||||
int
|
||||
strncasecmp(s1, s2, n)
|
||||
const char *s1, *s2;
|
||||
register size_t n;
|
||||
{
|
||||
if (n != 0) {
|
||||
register const unsigned char *cm = charmap,
|
||||
*us1 = (const unsigned char *)s1,
|
||||
*us2 = (const unsigned char *)s2;
|
||||
|
||||
do {
|
||||
if (cm[*us1] != cm[*us2++])
|
||||
return (cm[*us1] - cm[*--us2]);
|
||||
if (*us1++ == '\0')
|
||||
break;
|
||||
} while (--n != 0);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
108
src/clib/strdup.c
Normal file
108
src/clib/strdup.c
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1988, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* strdup --
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_STRDUP
|
||||
* PUBLIC: char *strdup __P((const char *));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
#ifndef HAVE_STRDUP
|
||||
char *
|
||||
strdup(str)
|
||||
const char *str;
|
||||
{
|
||||
size_t len;
|
||||
char *copy;
|
||||
|
||||
len = strlen(str) + 1;
|
||||
if (!(copy = malloc((u_int)len)))
|
||||
return (NULL);
|
||||
memcpy(copy, str, len);
|
||||
return (copy);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* strndup --
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_STRNDUP
|
||||
* PUBLIC: char *strndup __P((const char *, size_t));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
#ifndef HAVE_STRNDUP
|
||||
char *
|
||||
strndup(str, len)
|
||||
const char *str;
|
||||
size_t len;
|
||||
{
|
||||
char *copy;
|
||||
|
||||
if (len > strlen(str))
|
||||
len = strlen(str);
|
||||
if (!(copy = malloc((u_int)len + 1)))
|
||||
return (NULL);
|
||||
memcpy(copy, str, len + 1);
|
||||
return (copy);
|
||||
}
|
||||
#endif
|
836
src/clib/xvprintf.c
Normal file
836
src/clib/xvprintf.c
Normal file
|
@ -0,0 +1,836 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following is an printf with some extra features (as well as some
|
||||
* missing features). A few extensions to the formatting notation are
|
||||
* supported:
|
||||
* * The "=" flag (similar to "-") causes the output to be
|
||||
* be centered in the appropriately sized field.
|
||||
*
|
||||
* * The %b field outputs an integer in binary notation.
|
||||
*
|
||||
* * The %c field now accepts a precision. The character output
|
||||
* is repeated by the number of times the precision specifies.
|
||||
*
|
||||
* * The %' field works like %c, but takes as its character the
|
||||
* next character of the format string, instead of the next
|
||||
* argument. For example, printf("%.78'-") prints 78 minus
|
||||
* signs, the same as printf("%.78c",'-').
|
||||
*
|
||||
* When compiled using GCC on a SPARC, this version of printf is
|
||||
* faster than the library printf for SUN OS 4.1. Also, all functions
|
||||
* are fully reentrant.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
#include "dbsql_int.h"
|
||||
|
||||
/*
|
||||
* Conversion types fall into various categories as defined by the
|
||||
* following enumeration.
|
||||
*/
|
||||
#define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */
|
||||
#define etFLOAT 2 /* Floating point. %f */
|
||||
#define etEXP 3 /* Exponentional notation. %e and %E */
|
||||
#define etGENERIC 4 /* Floating or exponential, depending on exponent. %g*/
|
||||
#define etSIZE 5 /* Return number of characters processed so far. %n */
|
||||
#define etSTRING 6 /* Strings. %s */
|
||||
#define etDYNSTRING 7 /* Dynamically allocated strings. %z */
|
||||
#define etPERCENT 8 /* Percent symbol. %% */
|
||||
#define etCHARX 9 /* Characters. %c */
|
||||
#define etERROR 10 /* Used to indicate no such conversion type */
|
||||
/* The rest are extensions, not normally found in printf() */
|
||||
#define etCHARLIT 11 /* Literal characters. %' */
|
||||
#define etSQLESCAPE 12 /* Strings with '\'' doubled. %q */
|
||||
#define etSQLESCAPE2 13 /* Strings with '\'' doubled and enclosed in '',
|
||||
NULL pointers replaced by SQL NULL. %Q */
|
||||
|
||||
/*
|
||||
* Each builtin conversion character (ex: the 'd' in "%d") is described
|
||||
* by an instance of the following structure
|
||||
*/
|
||||
typedef struct et_info {
|
||||
char fmttype; /* The format field code letter */
|
||||
u_int8_t base; /* The base for radix conversion */
|
||||
u_int8_t flags; /* One or more of FLAG_ constants below */
|
||||
#define FLAG_SIGNED 1 /* True if the value to convert is signed */
|
||||
#define FLAG_INTERN 2 /* True if for internal use only */
|
||||
u_int8_t type; /* Conversion paradigm */
|
||||
char *charset; /* The character set for conversion */
|
||||
char *prefix; /* Prefix on non-zero values in alt format */
|
||||
} et_info_t;
|
||||
|
||||
/*
|
||||
* The following table is searched linearly, so it is good to put the
|
||||
* most frequently used conversion types first.
|
||||
*/
|
||||
static et_info_t fmtinfo[] = {
|
||||
{ 'd', 10, 1, etRADIX, "0123456789", 0 },
|
||||
{ 's', 0, 0, etSTRING, 0, 0 },
|
||||
{ 'z', 0, 2, etDYNSTRING, 0, 0 },
|
||||
{ 'q', 0, 0, etSQLESCAPE, 0, 0 },
|
||||
{ 'Q', 0, 0, etSQLESCAPE2, 0, 0 },
|
||||
{ 'c', 0, 0, etCHARX, 0, 0 },
|
||||
{ 'o', 8, 0, etRADIX, "01234567", "0" },
|
||||
{ 'u', 10, 0, etRADIX, "0123456789", 0 },
|
||||
{ 'x', 16, 0, etRADIX, "0123456789abcdef", "x0" },
|
||||
{ 'X', 16, 0, etRADIX, "0123456789ABCDEF", "X0" },
|
||||
{ 'f', 0, 1, etFLOAT, 0, 0 },
|
||||
{ 'e', 0, 1, etEXP, "e", 0 },
|
||||
{ 'E', 0, 1, etEXP, "E", 0 },
|
||||
{ 'g', 0, 1, etGENERIC, "e", 0 },
|
||||
{ 'G', 0, 1, etGENERIC, "E", 0 },
|
||||
{ 'i', 10, 1, etRADIX, "0123456789", 0 },
|
||||
{ 'n', 0, 0, etSIZE, 0, 0 },
|
||||
{ '%', 0, 0, etPERCENT, 0, 0 },
|
||||
{ 'p', 10, 0, etRADIX, "0123456789", 0 },
|
||||
};
|
||||
#define etNINFO (sizeof(fmtinfo) / sizeof(fmtinfo[0]))
|
||||
|
||||
/*
|
||||
* If NOFLOATINGPOINT is defined, then none of the floating point
|
||||
* conversions will work.
|
||||
*/
|
||||
#ifndef etNOFLOATINGPOINT
|
||||
/*
|
||||
* et_get_digit --
|
||||
* "*val" is a double such that 0.1 <= *val < 10.0
|
||||
* Return the ascii code for the leading digit of *val, then
|
||||
* multiply "*val" by 10.0 to renormalize.
|
||||
*
|
||||
* Example:
|
||||
* input: *val = 3.14159
|
||||
* output: *val = 1.4159 function return = '3'
|
||||
*
|
||||
* The counter *cnt is incremented each time. After counter exceeds
|
||||
* 16 (the number of significant digits in a 64-bit float) '0' is
|
||||
* always returned.
|
||||
*/
|
||||
static int
|
||||
et_getdigit(long_double_t* val, int* cnt)
|
||||
{
|
||||
int digit;
|
||||
long_double_t d;
|
||||
if ((*cnt)++ >= 16 )
|
||||
return '0';
|
||||
digit = (int)*val;
|
||||
d = digit;
|
||||
digit += '0';
|
||||
*val = (*val - d) * 10.0;
|
||||
return digit;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define etBUFSIZE 1024 /* Size of the output buffer */
|
||||
|
||||
/*
|
||||
* __et_printf --
|
||||
* The root printf-like program used by all variations implemented herein.
|
||||
*
|
||||
* INPUTS:
|
||||
* func This is a pointer to a function taking three arguments
|
||||
* 1. A pointer to anything. Same as the "arg" parameter.
|
||||
* 2. A pointer to the list of characters to be output
|
||||
* (Note, this list is NOT null terminated.)
|
||||
* 3. An integer number of characters to be output.
|
||||
* (Note: This number might be zero.)
|
||||
*
|
||||
* arg This is the pointer to anything which will be passed as the
|
||||
* first argument to "func". Use it for whatever you like.
|
||||
*
|
||||
* fmt This is the format string, as in the usual print.
|
||||
*
|
||||
* ap This is a pointer to a list of arguments. Same as in
|
||||
* vfprint.
|
||||
*
|
||||
* OUTPUTS:
|
||||
* The return value is the total number of characters sent to
|
||||
* the function "func". Returns -1 on a error.
|
||||
*
|
||||
* NOTE: The order in which automatic variables are declared below
|
||||
* seems to make a big difference in determining how fast this function
|
||||
* runs.
|
||||
*/
|
||||
static int
|
||||
__et_printf(dbp, func, arg, fmt, ap)
|
||||
DBSQL *dbp;
|
||||
void (*func)(void*,char*,int);
|
||||
void *arg;
|
||||
const char *fmt;
|
||||
va_list ap;
|
||||
{
|
||||
int c; /* Next character in the format string */
|
||||
char *bufpt; /* Pointer to the conversion buffer */
|
||||
int precision; /* Precision of the current field */
|
||||
int length; /* Length of the field */
|
||||
int idx; /* A general purpose loop counter */
|
||||
int count; /* Total number of characters output */
|
||||
int width; /* Width of the current field */
|
||||
u_int8_t flag_leftjustify; /* True if "-" flag is present */
|
||||
u_int8_t flag_plussign; /* True if "+" flag is present */
|
||||
u_int8_t flag_blanksign; /* True if " " flag is present */
|
||||
u_int8_t flag_alternateform; /* True if "#" flag is present */
|
||||
u_int8_t flag_zeropad; /* True if field width constant starts
|
||||
with zero */
|
||||
u_int8_t flag_long; /* True if "l" flag is present */
|
||||
unsigned long longvalue; /* Value for integer types */
|
||||
long_double_t realvalue; /* Value for real types */
|
||||
et_info_t *infop; /* Pointer to the appropriate info
|
||||
structure */
|
||||
char buf[etBUFSIZE]; /* Conversion buffer */
|
||||
char prefix; /* Prefix character. "+" or "-" or " " or
|
||||
'\0'. */
|
||||
u_int8_t errorflag = 0; /* True if an error is encountered */
|
||||
u_int8_t xtype; /* Conversion paradigm */
|
||||
char *extra; /* Extra memory used for etTCLESCAPE
|
||||
conversions */
|
||||
static char spaces[] =
|
||||
" "
|
||||
" ";
|
||||
#define etSPACESIZE (sizeof(spaces)-1)
|
||||
#ifndef etNOFLOATINGPOINT
|
||||
int exp; /* exponent of real numbers */
|
||||
double rounder; /* Used for rounding floating point values*/
|
||||
u_int8_t flag_dp; /* True if decimal point should be shown */
|
||||
u_int8_t flag_rtz; /* True if trailing zeros should be
|
||||
removed */
|
||||
u_int8_t flag_exp; /* True to force display of the exponent */
|
||||
int nsd; /* Number of significant digits returned */
|
||||
#endif
|
||||
|
||||
count = length = 0;
|
||||
bufpt = 0;
|
||||
for(; (c = (*fmt)) != 0; ++fmt) {
|
||||
if (c != '%') {
|
||||
int amt;
|
||||
bufpt = (char *)fmt;
|
||||
amt = 1;
|
||||
while((c = (*++fmt)) != '%' && c != 0)
|
||||
amt++;
|
||||
(*func)(arg, bufpt, amt);
|
||||
count += amt;
|
||||
if (c == 0)
|
||||
break;
|
||||
}
|
||||
if ((c = (*++fmt)) == 0) {
|
||||
errorflag = 1;
|
||||
(*func)(arg, "%", 1);
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
/* Find out what flags are present. */
|
||||
flag_leftjustify = flag_plussign = flag_blanksign =
|
||||
flag_alternateform = flag_zeropad = 0;
|
||||
do {
|
||||
switch(c) {
|
||||
case '-': flag_leftjustify = 1; c = 0; break;
|
||||
case '+': flag_plussign = 1; c = 0; break;
|
||||
case ' ': flag_blanksign = 1; c = 0; break;
|
||||
case '#': flag_alternateform = 1; c = 0; break;
|
||||
case '0': flag_zeropad = 1; c = 0; break;
|
||||
default: break;
|
||||
}
|
||||
} while(c == 0 && (c = (*++fmt)) != 0);
|
||||
/* Get the field width. */
|
||||
width = 0;
|
||||
if (c == '*') {
|
||||
width = va_arg(ap, int);
|
||||
if (width < 0) {
|
||||
flag_leftjustify = 1;
|
||||
width = -width;
|
||||
}
|
||||
c = *++fmt;
|
||||
} else {
|
||||
while(c >= '0' && c <= '9') {
|
||||
width = (width * 10) + c - '0';
|
||||
c = *++fmt;
|
||||
}
|
||||
}
|
||||
if (width > etBUFSIZE - 10) {
|
||||
width = etBUFSIZE - 10;
|
||||
}
|
||||
/* Get the precision. */
|
||||
if (c == '.') {
|
||||
precision = 0;
|
||||
c = *++fmt;
|
||||
if (c == '*') {
|
||||
precision = va_arg(ap,int);
|
||||
#ifndef etCOMPATIBILITY
|
||||
/* This is sensible, but SUN OS 4.1 doesn't
|
||||
do it. */
|
||||
if (precision < 0)
|
||||
precision = -precision;
|
||||
#endif
|
||||
c = *++fmt;
|
||||
} else {
|
||||
while(c >= '0' && c <= '9') {
|
||||
precision = (precision * 10) + c - '0';
|
||||
c = *++fmt;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Limit the precision to prevent overflowing buf[]
|
||||
* during conversion
|
||||
*/
|
||||
if (precision > etBUFSIZE - 40)
|
||||
precision = etBUFSIZE - 40;
|
||||
} else {
|
||||
precision = -1;
|
||||
}
|
||||
/* Get the conversion type modifier. */
|
||||
if (c == 'l') {
|
||||
flag_long = 1;
|
||||
c = *++fmt;
|
||||
} else {
|
||||
flag_long = 0;
|
||||
}
|
||||
/* Fetch the info entry for the field. */
|
||||
infop = 0;
|
||||
xtype = etERROR;
|
||||
for(idx = 0; idx < etNINFO; idx++) {
|
||||
if (c == fmtinfo[idx].fmttype) {
|
||||
infop = &fmtinfo[idx];
|
||||
xtype = infop->type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
extra = 0;
|
||||
|
||||
/*
|
||||
* At this point, variables are initialized as follows:
|
||||
*
|
||||
* flag_alternateform TRUE if a '#' is present.
|
||||
* flag_plussign TRUE if a '+' is present.
|
||||
* flag_leftjustify TRUE if a '-' is present or
|
||||
* if the field width was
|
||||
* negative.
|
||||
* flag_zeropad TRUE if the width began
|
||||
* with 0.
|
||||
* flag_long TRUE if the letter 'l' (ell)
|
||||
* prefixed the conversion
|
||||
* character.
|
||||
* flag_blanksign TRUE if a ' ' is present.
|
||||
* width The specified field width.
|
||||
* This is always non-negative.
|
||||
* Zero is the default.
|
||||
* precision The specified precision. The
|
||||
* default is -1.
|
||||
* xtype The class of the conversion.
|
||||
* infop Pointer to the appropriate
|
||||
* info struct.
|
||||
*/
|
||||
switch(xtype) {
|
||||
case etRADIX:
|
||||
if (flag_long) {
|
||||
longvalue = va_arg(ap, long);
|
||||
} else{
|
||||
longvalue = va_arg(ap, int);
|
||||
}
|
||||
#ifdef etCOMPATIBILITY
|
||||
/*
|
||||
* For the format %#x, the value zero is printed "0"
|
||||
* not "0x0". I think this is stupid.
|
||||
*/
|
||||
if (longvalue == 0)
|
||||
flag_alternateform = 0;
|
||||
#else
|
||||
/*
|
||||
* More sensible: turn off the prefix for octal
|
||||
* (to prevent "00"), but leave the prefix for hex.
|
||||
*/
|
||||
if (longvalue == 0 && infop->base == 8)
|
||||
flag_alternateform = 0;
|
||||
#endif
|
||||
if (infop->flags & FLAG_SIGNED) {
|
||||
if (*(long *)&longvalue < 0) {
|
||||
longvalue = -*(long *)&longvalue;
|
||||
prefix = '-';
|
||||
} else if (flag_plussign) {
|
||||
prefix = '+';
|
||||
} else if (flag_blanksign) {
|
||||
prefix = ' ';
|
||||
} else {
|
||||
prefix = 0;
|
||||
}
|
||||
} else {
|
||||
prefix = 0;
|
||||
}
|
||||
if (flag_zeropad && precision < width - (prefix != 0)){
|
||||
precision = width - (prefix != 0);
|
||||
}
|
||||
bufpt = &buf[etBUFSIZE];
|
||||
{
|
||||
register char *cset;
|
||||
register int base;
|
||||
cset = infop->charset;
|
||||
base = infop->base;
|
||||
do { /* Convert to ascii */
|
||||
*(--bufpt) = cset[longvalue % base];
|
||||
longvalue = longvalue / base;
|
||||
} while(longvalue > 0);
|
||||
}
|
||||
length = &buf[etBUFSIZE] - bufpt;
|
||||
for(idx = precision - length; idx > 0; idx--) {
|
||||
*(--bufpt) = '0'; /* Zero pad */
|
||||
}
|
||||
if (prefix)
|
||||
*(--bufpt) = prefix; /* Add sign */
|
||||
if (flag_alternateform && infop->prefix) {
|
||||
/* Add "0" or "0x" */
|
||||
char *pre, x;
|
||||
pre = infop->prefix;
|
||||
if (*bufpt != pre[0]) {
|
||||
for(pre = infop->prefix;
|
||||
(x = (*pre)) != 0; pre++) {
|
||||
*(--bufpt) = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
length = &buf[etBUFSIZE] - bufpt;
|
||||
break;
|
||||
case etFLOAT:
|
||||
case etEXP:
|
||||
case etGENERIC:
|
||||
realvalue = va_arg(ap, double);
|
||||
#ifndef etNOFLOATINGPOINT
|
||||
if (precision < 0)
|
||||
precision = 6; /* Set default precision */
|
||||
if (precision > etBUFSIZE - 10)
|
||||
precision = etBUFSIZE - 10;
|
||||
if (realvalue < 0.0) {
|
||||
realvalue = -realvalue;
|
||||
prefix = '-';
|
||||
} else {
|
||||
if (flag_plussign)
|
||||
prefix = '+';
|
||||
else if (flag_blanksign)
|
||||
prefix = ' ';
|
||||
else
|
||||
prefix = 0;
|
||||
}
|
||||
if (infop->type == etGENERIC && precision > 0)
|
||||
precision--;
|
||||
rounder = 0.0;
|
||||
#ifdef COMPATIBILITY
|
||||
/*
|
||||
* Rounding works like BSD when the constant 0.4999 is
|
||||
* used. Wierd!
|
||||
*/
|
||||
for(idx = precision, rounder = 0.4999; idx > 0;
|
||||
idx--, rounder *= 0.1);
|
||||
#else
|
||||
/*
|
||||
* It makes more sense to use 0.5
|
||||
*/
|
||||
for(idx = precision, rounder = 0.5; idx > 0;
|
||||
idx--, rounder *= 0.1);
|
||||
#endif
|
||||
if (infop->type == etFLOAT)
|
||||
realvalue += rounder;
|
||||
/*
|
||||
* Normalize realvalue to within
|
||||
* 10.0 > realvalue >= 1.0
|
||||
*/
|
||||
exp = 0;
|
||||
if (realvalue > 0.0) {
|
||||
int k = 0;
|
||||
while(realvalue >= 1e8 && k++ < 100) {
|
||||
realvalue *= 1e-8;
|
||||
exp+=8;
|
||||
}
|
||||
while(realvalue >= 10.0 && k++ < 100) {
|
||||
realvalue *= 0.1;
|
||||
exp++;
|
||||
}
|
||||
while(realvalue < 1e-8 && k++ < 100) {
|
||||
realvalue *= 1e8;
|
||||
exp-=8;
|
||||
}
|
||||
while(realvalue < 1.0 && k++ < 100) {
|
||||
realvalue *= 10.0;
|
||||
exp--;
|
||||
}
|
||||
if (k >= 100) {
|
||||
bufpt = "NaN";
|
||||
length = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bufpt = buf;
|
||||
/*
|
||||
* If the field type is etGENERIC, then convert to
|
||||
* either etEXP or etFLOAT, as appropriate.
|
||||
*/
|
||||
flag_exp = (xtype == etEXP);
|
||||
if (xtype != etFLOAT) {
|
||||
realvalue += rounder;
|
||||
if (realvalue >= 10.0) {
|
||||
realvalue *= 0.1;
|
||||
exp++;
|
||||
}
|
||||
}
|
||||
if (xtype == etGENERIC) {
|
||||
flag_rtz = !flag_alternateform;
|
||||
if (exp<-4 || exp > precision) {
|
||||
xtype = etEXP;
|
||||
} else {
|
||||
precision = precision - exp;
|
||||
xtype = etFLOAT;
|
||||
}
|
||||
} else {
|
||||
flag_rtz = 0;
|
||||
}
|
||||
/*
|
||||
* The "exp+precision" test causes output to be of
|
||||
* type etEXP if the precision is too large to fit
|
||||
* in buf[].
|
||||
*/
|
||||
nsd = 0;
|
||||
if (xtype == etFLOAT &&
|
||||
exp + precision < etBUFSIZE - 30) {
|
||||
flag_dp =(precision > 0 || flag_alternateform);
|
||||
if (prefix) {
|
||||
*(bufpt++) = prefix; /* Sign */
|
||||
}
|
||||
if (exp < 0) {
|
||||
*(bufpt++) = '0'; /* Digits before
|
||||
"." */
|
||||
} else {
|
||||
for(; exp >= 0; exp--) {
|
||||
*(bufpt++) =
|
||||
et_getdigit(&realvalue,
|
||||
&nsd);
|
||||
}
|
||||
}
|
||||
if (flag_dp) {
|
||||
*(bufpt++) = '.';/* The decimal point*/
|
||||
}
|
||||
for(exp++; exp < 0 && precision > 0;
|
||||
precision--, exp++) {
|
||||
*(bufpt++) = '0';
|
||||
}
|
||||
while((precision--) > 0) {
|
||||
*(bufpt++) = et_getdigit(&realvalue,
|
||||
&nsd);
|
||||
}
|
||||
*(bufpt--) = 0; /* Null terminate */
|
||||
if (flag_rtz && flag_dp) {
|
||||
/* Remove trailing zeros and "." */
|
||||
while( bufpt >= buf && *bufpt == '0') {
|
||||
*(bufpt--) = 0;
|
||||
}
|
||||
if (bufpt >= buf && *bufpt == '.' ) {
|
||||
*(bufpt--) = 0;
|
||||
}
|
||||
}
|
||||
bufpt++; /* point to next free slot */
|
||||
} else { /* etEXP or etGENERIC */
|
||||
flag_dp = (precision>0 || flag_alternateform);
|
||||
if (prefix) {
|
||||
*(bufpt++) = prefix; /* Sign */
|
||||
}
|
||||
/* First digit */
|
||||
*(bufpt++) = et_getdigit(&realvalue,&nsd);
|
||||
if (flag_dp) {
|
||||
*(bufpt++) = '.'; /* Decimal point */
|
||||
}
|
||||
while((precision--) > 0) {
|
||||
*(bufpt++) = et_getdigit(&realvalue,
|
||||
&nsd);
|
||||
}
|
||||
bufpt--; /* point to last digit */
|
||||
if (flag_rtz && flag_dp) {
|
||||
/* Remove tail zeros */
|
||||
while(bufpt >= buf && *bufpt == '0') {
|
||||
*(bufpt--) = 0;
|
||||
}
|
||||
if (bufpt >= buf && *bufpt == '.' ) {
|
||||
*(bufpt--) = 0;
|
||||
}
|
||||
}
|
||||
bufpt++; /* point to next free slot */
|
||||
if (exp || flag_exp) {
|
||||
*(bufpt++) = infop->charset[0];
|
||||
if (exp < 0) { /* sign of exp */
|
||||
*(bufpt++) = '-';
|
||||
exp = -exp;
|
||||
} else {
|
||||
*(bufpt++) = '+';
|
||||
}
|
||||
if (exp >= 100) {
|
||||
/* 100's digit */
|
||||
*(bufpt++) = (exp/100) + '0';
|
||||
exp %= 100;
|
||||
}
|
||||
/* 10's digit */
|
||||
*(bufpt++) = exp/10+'0';
|
||||
/* 1's digit */
|
||||
*(bufpt++) = exp%10+'0';
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The converted number is in buf[] and zero
|
||||
* terminated. Output it. Note that the number is
|
||||
* in the usual order, not reversed as with integer
|
||||
* conversions.
|
||||
*/
|
||||
length = bufpt - buf;
|
||||
bufpt = buf;
|
||||
|
||||
/*
|
||||
* Special Case: Add leading zeros if the
|
||||
* flag_zeropad flag is set and we are not left
|
||||
* justified.
|
||||
*/
|
||||
if (flag_zeropad && !flag_leftjustify &&
|
||||
length < width) {
|
||||
int i;
|
||||
int nPad = width - length;
|
||||
for(i = width; i >= nPad; i--) {
|
||||
bufpt[i] = bufpt[i - nPad];
|
||||
}
|
||||
i = (prefix != 0);
|
||||
while(nPad--)
|
||||
bufpt[i++] = '0';
|
||||
length = width;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case etSIZE:
|
||||
*(va_arg(ap,int*)) = count;
|
||||
length = width = 0;
|
||||
break;
|
||||
case etPERCENT:
|
||||
buf[0] = '%';
|
||||
bufpt = buf;
|
||||
length = 1;
|
||||
break;
|
||||
case etCHARLIT: /* FALLTHROUGH */
|
||||
case etCHARX:
|
||||
c = buf[0] = (xtype == etCHARX ?
|
||||
va_arg(ap, int) : *++fmt);
|
||||
if (precision >= 0) {
|
||||
for(idx = 1; idx < precision; idx++) {
|
||||
buf[idx] = c;
|
||||
}
|
||||
length = precision;
|
||||
} else {
|
||||
length = 1;
|
||||
}
|
||||
bufpt = buf;
|
||||
break;
|
||||
case etSTRING:
|
||||
case etDYNSTRING:
|
||||
bufpt = va_arg(ap, char*);
|
||||
if (bufpt == 0) {
|
||||
bufpt = "";
|
||||
} else if (xtype == etDYNSTRING) {
|
||||
extra = bufpt;
|
||||
}
|
||||
length = strlen(bufpt);
|
||||
if (precision >= 0 && precision < length ) {
|
||||
length = precision;
|
||||
}
|
||||
break;
|
||||
case etSQLESCAPE: /* FALLTHROUGH */
|
||||
case etSQLESCAPE2:
|
||||
{
|
||||
int i, j, n, c, isnull;
|
||||
char *arg = va_arg(ap,char*);
|
||||
isnull = (arg == 0);
|
||||
if( isnull ) arg = (xtype == etSQLESCAPE2 ?
|
||||
"NULL" : "(NULL)");
|
||||
for(i = n = 0; (c = arg[i]) != 0; i++) {
|
||||
if (c == '\'')
|
||||
n++;
|
||||
}
|
||||
n += i + 1 + ((!isnull && xtype == etSQLESCAPE2) ?
|
||||
2 : 0);
|
||||
if (n > etBUFSIZE) {
|
||||
if (__dbsql_calloc(dbp, 1, n, extra) == ENOMEM)
|
||||
return -1;
|
||||
bufpt = extra;
|
||||
} else {
|
||||
bufpt = buf;
|
||||
}
|
||||
j = 0;
|
||||
if (!isnull && xtype == etSQLESCAPE2)
|
||||
bufpt[j++] = '\'';
|
||||
for(i = 0; (c = arg[i]) != 0; i++) {
|
||||
bufpt[j++] = c;
|
||||
if (c == '\'')
|
||||
bufpt[j++] = c;
|
||||
}
|
||||
if (!isnull && xtype == etSQLESCAPE2)
|
||||
bufpt[j++] = '\'';
|
||||
bufpt[j] = 0;
|
||||
length = j;
|
||||
if (precision >= 0 && precision < length)
|
||||
length = precision;
|
||||
}
|
||||
break;
|
||||
case etERROR:
|
||||
buf[0] = '%';
|
||||
buf[1] = c;
|
||||
errorflag = 0;
|
||||
idx = 1 + (c != 0);
|
||||
(*func)(arg, "%", idx);
|
||||
count += idx;
|
||||
if (c == 0)
|
||||
fmt--;
|
||||
break;
|
||||
} /* End switch over the format type */
|
||||
/*
|
||||
* The text of the conversion is pointed to by "bufpt" and is
|
||||
* "length" characters long. The field width is "width". Do
|
||||
* the output.
|
||||
*/
|
||||
if (!flag_leftjustify) {
|
||||
register int nspace;
|
||||
nspace = width - length;
|
||||
if (nspace > 0) {
|
||||
count += nspace;
|
||||
while(nspace >= etSPACESIZE) {
|
||||
(*func)(arg, spaces, etSPACESIZE);
|
||||
nspace -= etSPACESIZE;
|
||||
}
|
||||
if (nspace > 0)
|
||||
(*func)(arg, spaces, nspace);
|
||||
}
|
||||
}
|
||||
if (length > 0) {
|
||||
(*func)(arg, bufpt, length);
|
||||
count += length;
|
||||
}
|
||||
if (flag_leftjustify) {
|
||||
register int nspace;
|
||||
nspace = width - length;
|
||||
if (nspace > 0) {
|
||||
count += nspace;
|
||||
while(nspace >= etSPACESIZE) {
|
||||
(*func)(arg, spaces, etSPACESIZE);
|
||||
nspace -= etSPACESIZE;
|
||||
}
|
||||
if (nspace > 0)
|
||||
(*func)(arg, spaces, nspace);
|
||||
}
|
||||
}
|
||||
if (extra) {
|
||||
if (xtype == etDYNSTRING) {
|
||||
__dbsql_free(dbp, extra); /* TODO which free? */
|
||||
} else {
|
||||
__dbsql_free(dbp, extra);
|
||||
}
|
||||
}
|
||||
} /* End for loop over the format string */
|
||||
return errorflag ? -1 : count;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* __mout --
|
||||
* This function implements the callback from vxprintf.
|
||||
* This routine add nNewChar characters of text in zNewText to
|
||||
* the sgMprintf structure pointed to by "arg".
|
||||
*
|
||||
* STATIC: static void mout __P((void *, char *, int));
|
||||
*/
|
||||
static void
|
||||
__mout(void* arg, char* zNewText, int nNewChar)
|
||||
{
|
||||
xvprintf_t *pM = (xvprintf_t*)arg;
|
||||
if (pM->len + nNewChar + 1 > pM->amt) {
|
||||
pM->amt = pM->len + (nNewChar * 2) + 1;
|
||||
if (pM->text == pM->base) {
|
||||
__dbsql_calloc(NULL, 1, pM->amt, &pM->text);
|
||||
if (pM->text && pM->len)
|
||||
memcpy(pM->text, pM->base, pM->len);
|
||||
} else {
|
||||
|
||||
if (__dbsql_realloc(NULL, pM->amt, &pM->text) == ENOMEM) {
|
||||
__dbsql_free(NULL, pM->text);
|
||||
pM->len = 0;
|
||||
pM->amt = 0;
|
||||
pM->text = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pM->text) {
|
||||
memcpy(&pM->text[pM->len], zNewText, nNewChar);
|
||||
pM->len += nNewChar;
|
||||
pM->text[pM->len] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* xvprintf --
|
||||
*
|
||||
* PUBLIC: char *xvprintf __P((DBSQL *, const char *, va_list));
|
||||
*/
|
||||
char *
|
||||
xvprintf(dbp, fmt, ap)
|
||||
DBSQL *dbp;
|
||||
const char *fmt;
|
||||
va_list ap;
|
||||
{
|
||||
xvprintf_t s;
|
||||
char *new;
|
||||
char buf[200];
|
||||
|
||||
s.len = 0;
|
||||
s.text = buf;
|
||||
s.amt = sizeof(buf);
|
||||
s.base = buf;
|
||||
__et_printf(dbp, __mout, &s, fmt, ap);
|
||||
s.text[s.len] = 0;
|
||||
__dbsql_malloc(dbp, s.len + 1, &new);
|
||||
if (new)
|
||||
strcpy(new, s.text);
|
||||
if (s.text != s.base)
|
||||
__dbsql_free(dbp, s.text);
|
||||
return new;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TEST
|
||||
/*
|
||||
* xprintf --
|
||||
*
|
||||
* PUBLIC: char *xprintf __P((DBSQL *, const char *, ...));
|
||||
*/
|
||||
char *
|
||||
#ifdef STDC_HEADERS
|
||||
xprintf(DBSQL *dbp, const char *fmt, ...)
|
||||
#else
|
||||
xprintf(dbp, fmt, va_alist)
|
||||
DBSQL *dbp;
|
||||
const char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
char *result;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
result = xvprintf(dbp, fmt, ap);
|
||||
va_end(ap);
|
||||
return result;
|
||||
}
|
||||
#endif
|
163
src/common/dbsql_alloc.c
Normal file
163
src/common/dbsql_alloc.c
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
#include "dbsql.h"
|
||||
#include "dbsql_config.h"
|
||||
#include "db_int.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/*
|
||||
* __dbsql_umalloc --
|
||||
* A malloc(3) function that will use use the _os_umalloc call of DB
|
||||
* to obtain memory.
|
||||
*
|
||||
* PUBLIC: int __dbsql_umalloc __P((DBSQL *, size_t, void *));
|
||||
*/
|
||||
int
|
||||
__dbsql_umalloc(DBSQL* dbp, size_t size, void* storep)
|
||||
{
|
||||
return (__os_umalloc((dbp ? dbp->dbenv : NULL), size, storep));
|
||||
}
|
||||
|
||||
/*
|
||||
* __dbsql_urealloc --
|
||||
* realloc(3) counterpart to __dbsql_umalloc.
|
||||
*
|
||||
* PUBLIC: int __dbsql_urealloc __P((DBSQL *, size_t, void *));
|
||||
*/
|
||||
int
|
||||
__dbsql_urealloc(DBSQL* dbp, size_t size, void* storep)
|
||||
{
|
||||
return (__os_urealloc((dbp ? dbp->dbenv : NULL), size, storep));
|
||||
}
|
||||
|
||||
/*
|
||||
* __dbsql_ufree --
|
||||
* free(3) counterpart to __dbsql_umalloc.
|
||||
*
|
||||
* PUBLIC: void __dbsql_ufree __P((DBSQL *, void *));
|
||||
*/
|
||||
void
|
||||
__dbsql_ufree(DBSQL* dbp, void* ptr)
|
||||
{
|
||||
__os_ufree((dbp ? dbp->dbenv : NULL), ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* __dbsql_strdup --
|
||||
* The __dbsql_strdup(3) function for DBSQL.
|
||||
*
|
||||
* PUBLIC: int __dbsql_strdup __P((DBSQL *, const char *, void *));
|
||||
*/
|
||||
int
|
||||
__dbsql_strdup(dbp, str, storep)
|
||||
DBSQL *dbp;
|
||||
const char *str;
|
||||
void *storep;
|
||||
{
|
||||
return (__os_strdup((dbp ? dbp->dbenv : NULL), str, storep));
|
||||
}
|
||||
|
||||
/*
|
||||
* __dbsql_strndup --
|
||||
* The __dbsql_strndup(3) function for DBSQL.
|
||||
*
|
||||
* PUBLIC: int __dbsql_strndup __P((DBSQL *, const char *, void *, size_t));
|
||||
*/
|
||||
int
|
||||
__dbsql_strndup(dbp, str, storep, len)
|
||||
DBSQL *dbp;
|
||||
const char *str;
|
||||
void *storep;
|
||||
size_t len;
|
||||
{
|
||||
size_t size;
|
||||
int ret;
|
||||
void *p;
|
||||
DB_ENV *dbenv = (dbp->dbenv ? NULL : dbp->dbenv);
|
||||
|
||||
*(void **)storep = NULL;
|
||||
|
||||
if (len > strlen(str))
|
||||
size = strlen(str);
|
||||
else
|
||||
size = len;
|
||||
if ((ret = __os_calloc(dbenv, 1, size + 1, &p)) != 0)
|
||||
return (ret);
|
||||
|
||||
memcpy(p, str, size);
|
||||
|
||||
*(void **)storep = p;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __dbsql_calloc --
|
||||
* The calloc(3) function for DBSQL.
|
||||
*
|
||||
* PUBLIC: int __dbsql_calloc __P((DBSQL *, size_t, size_t, void *));
|
||||
*/
|
||||
int
|
||||
__dbsql_calloc(dbp, num, size, storep)
|
||||
DBSQL *dbp;
|
||||
size_t num, size;
|
||||
void *storep;
|
||||
{
|
||||
return (__os_calloc((dbp ? dbp->dbenv : NULL), num, size,
|
||||
storep));
|
||||
}
|
||||
|
||||
/*
|
||||
* __dbsql_malloc --
|
||||
* The malloc(3) function for DBSQL.
|
||||
*
|
||||
* PUBLIC: int __dbsql_malloc __P((DBSQL *, size_t, void *));
|
||||
*/
|
||||
int
|
||||
__dbsql_malloc(DBSQL* dbp, size_t size, void* storep)
|
||||
{
|
||||
return (__os_malloc((dbp ? dbp->dbenv : NULL), size, storep));
|
||||
}
|
||||
|
||||
/*
|
||||
* __dbsql_realloc --
|
||||
* The realloc(3) function for DBSQL.
|
||||
*
|
||||
* PUBLIC: int __dbsql_realloc __P((DBSQL *, size_t, void *));
|
||||
*/
|
||||
int
|
||||
__dbsql_realloc(DBSQL* dbp, size_t size, void* storep)
|
||||
{
|
||||
return (__os_realloc((dbp ? dbp->dbenv : NULL), size, storep));
|
||||
}
|
||||
|
||||
/*
|
||||
* __dbsql_free --
|
||||
* The free(3) function for DBSQL.
|
||||
*
|
||||
* PUBLIC: void __dbsql_free __P((DBSQL *, void *));
|
||||
*/
|
||||
void
|
||||
__dbsql_free(DBSQL* dbp, void* ptr)
|
||||
{
|
||||
__os_free((dbp ? dbp->dbenv : NULL), ptr);
|
||||
}
|
105
src/common/dbsql_atof.c
Normal file
105
src/common/dbsql_atof.c
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
#include "dbsql_int.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
* __dbsql_atof --
|
||||
* The string z[] is an ascii representation of a real number.
|
||||
* Convert this string to a double.
|
||||
*
|
||||
* This routine assumes that z[] really is a valid number. If it
|
||||
* is not, the result is undefined.
|
||||
*
|
||||
* This routine is used instead of the library atof() function because
|
||||
* the library atof() might want to use "," as the decimal point instead
|
||||
* of "." depending on how locale is set. But that would cause problems
|
||||
* for SQL. So this routine always uses "." regardless of locale.
|
||||
*
|
||||
* PUBLIC: double __dbsql_atof __P((const char *));
|
||||
*/
|
||||
double
|
||||
__dbsql_atof(z)
|
||||
const char *z;
|
||||
{
|
||||
int sign = 1;
|
||||
long_double_t v1 = 0.0;
|
||||
if (*z == '-') {
|
||||
sign = -1;
|
||||
z++;
|
||||
} else if (*z == '+') {
|
||||
z++;
|
||||
}
|
||||
while(isdigit(*z)) {
|
||||
v1 = v1 * 10.0 + (*z - '0');
|
||||
z++;
|
||||
}
|
||||
if (*z == '.') {
|
||||
long_double_t divisor = 1.0;
|
||||
z++;
|
||||
while(isdigit(*z)) {
|
||||
v1 = v1 * 10.0 + (*z - '0');
|
||||
divisor *= 10.0;
|
||||
z++;
|
||||
}
|
||||
v1 /= divisor;
|
||||
}
|
||||
if (*z == 'e' || *z == 'E') {
|
||||
int esign = 1;
|
||||
int eval = 0;
|
||||
long_double_t scale = 1.0;
|
||||
z++;
|
||||
if (*z == '-') {
|
||||
esign = -1;
|
||||
z++;
|
||||
} else if (*z == '+') {
|
||||
z++;
|
||||
}
|
||||
while(isdigit(*z)) {
|
||||
eval = eval * 10 + *z - '0';
|
||||
z++;
|
||||
}
|
||||
while(eval >= 64) {
|
||||
scale *= 1.0e+64;
|
||||
eval -= 64;
|
||||
}
|
||||
while(eval >= 16) {
|
||||
scale *= 1.0e+16;
|
||||
eval -= 16;
|
||||
}
|
||||
while(eval >= 4) {
|
||||
scale *= 1.0e+4;
|
||||
eval -= 4;
|
||||
}
|
||||
while(eval >= 1) {
|
||||
scale *= 1.0e+1;
|
||||
eval -= 1;
|
||||
}
|
||||
if (esign < 0) {
|
||||
v1 /= scale;
|
||||
} else {
|
||||
v1 *= scale;
|
||||
}
|
||||
}
|
||||
return sign < 0 ? -v1 : v1;
|
||||
}
|
58
src/common/dbsql_atoi.c
Normal file
58
src/common/dbsql_atoi.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
#include "dbsql_int.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
* __dbsql_atoi --
|
||||
* Return TRUE if 'str' is a 32-bit signed integer and write
|
||||
* the value of the integer into '*num'. If 'str' is not an integer
|
||||
* or is an integer that is too large to be expressed with just 32
|
||||
* bits, then return false.
|
||||
*
|
||||
* PUBLIC: int __dbsql_atoi __P((const char *, int *));
|
||||
*/
|
||||
int
|
||||
__dbsql_atoi(str, num)
|
||||
const char *str;
|
||||
int *num;
|
||||
{
|
||||
int v = 0;
|
||||
int neg;
|
||||
int i, c;
|
||||
if (*str == '-') {
|
||||
neg = 1;
|
||||
str++;
|
||||
} else if (*str == '+') {
|
||||
neg = 0;
|
||||
str++;
|
||||
} else {
|
||||
neg = 0;
|
||||
}
|
||||
for (i = 0; (c = str[i]) >= '0' && c <= '9'; i++) {
|
||||
v = (v * 10) + c - '0';
|
||||
}
|
||||
*num = neg ? -v : v;
|
||||
return (c == 0 && i > 0 &&
|
||||
(i < 10 || (i == 10 && memcmp(str,"2147483647", 10) <= 0)));
|
||||
}
|
461
src/common/dbsql_err.c
Normal file
461
src/common/dbsql_err.c
Normal file
|
@ -0,0 +1,461 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h> /* Declare STDERR_FILENO. */
|
||||
#endif
|
||||
|
||||
#include "dbsql_int.h"
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
/*
|
||||
* __dbsql_assert --
|
||||
* Error when an assertion fails. Only checked if #DIAGNOSTIC defined.
|
||||
*
|
||||
* PUBLIC: #ifdef DIAGNOSTIC
|
||||
* PUBLIC: void __dbsql_assert __P((const char *, const char *, int));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
void
|
||||
__dbsql_assert(failedexpr, file, line)
|
||||
const char *failedexpr, *file;
|
||||
int line;
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"__dbsql_assert: \"%s\" failed: file \"%s\", line %d\n",
|
||||
failedexpr, file, line);
|
||||
(void)fflush(stderr);
|
||||
|
||||
/* We want a stack trace of how this could possibly happen. */
|
||||
abort();
|
||||
|
||||
/* NOTREACHED */
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* __dbsql_panic_msg --
|
||||
* Just report that someone else paniced.
|
||||
*
|
||||
* PUBLIC: int __dbsql_panic_msg __P((DBSQL *));
|
||||
*/
|
||||
int
|
||||
__dbsql_panic_msg(DBSQL* dbp)
|
||||
{
|
||||
__dbsql_err(dbp, "PANIC: fatal database error detected; run recovery");
|
||||
|
||||
if (dbp && dbp->dbsql_paniccall != NULL)
|
||||
dbp->dbsql_paniccall(dbp, DB_RUNRECOVERY);
|
||||
|
||||
return (DB_RUNRECOVERY);
|
||||
}
|
||||
|
||||
/*
|
||||
* __dbsql_panic --
|
||||
* Lock out the database due to unrecoverable error.
|
||||
*
|
||||
* PUBLIC: int __dbsql_panic __P((DBSQL *, int));
|
||||
*/
|
||||
int
|
||||
__dbsql_panic(DBSQL* dbp, int errval)
|
||||
{
|
||||
if (dbp != NULL) {
|
||||
PANIC_SET(dbp, 1);
|
||||
|
||||
__dbsql_err(dbp, "PANIC: %s", dbsql_strerror(errval));
|
||||
|
||||
if (dbp->dbsql_paniccall != NULL)
|
||||
dbp->dbsql_paniccall(dbp, errval);
|
||||
}
|
||||
|
||||
#if defined(DIAGNOSTIC) && !defined(CONFIG_TEST)
|
||||
/*
|
||||
* We want a stack trace of how this could possibly happen.
|
||||
*
|
||||
* Don't drop core if it's the test suite -- it's reasonable for the
|
||||
* test suite to check to make sure that DBSQL_RUNRECOVERY is returned
|
||||
* under certain conditions.
|
||||
*/
|
||||
abort();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Chaos reigns within.
|
||||
* Reflect, repent, and reboot.
|
||||
* Order shall return.
|
||||
*/
|
||||
return (DBSQL_RUNRECOVERY);
|
||||
}
|
||||
|
||||
/*
|
||||
* dbsql_strerror --
|
||||
* ANSI C strerror(3) for DBSQL.
|
||||
*
|
||||
* EXTERN: char *dbsql_strerror __P((int));
|
||||
*/
|
||||
char *
|
||||
dbsql_strerror(int error)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (error == 0)
|
||||
return ("Successful return: 0");
|
||||
if (error > 0) {
|
||||
if ((p = strerror(error)) != NULL)
|
||||
return (p);
|
||||
goto unknown_err;
|
||||
}
|
||||
if (error <= -30999 && error >= -30800) {
|
||||
if ((p = db_strerror(error)) != NULL)
|
||||
return (p);
|
||||
goto unknown_err;
|
||||
}
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* The Tcl API requires that some of these return strings be compared
|
||||
* against strings stored in application scripts. So, any of these
|
||||
* errors that do not invariably result in a Tcl exception may not be
|
||||
* altered.
|
||||
*/
|
||||
switch (error) {
|
||||
case DBSQL_ERROR:
|
||||
return ("DBSQL_ERROR: SQL logic error or missing database");
|
||||
case DBSQL_INTERNAL:
|
||||
return ("DBSQL_INTERNAL: Internal implementation flaw");
|
||||
case DBSQL_PERM:
|
||||
return ("DBSQL_PERM: Access denied due to permissions.");
|
||||
case DBSQL_ABORT:
|
||||
return ("DBSQL_ABORT: Callback requested query abort");
|
||||
case DBSQL_BUSY:
|
||||
return ("DBSQL_BUSY: Database is locked");
|
||||
case DBSQL_LOCKED:
|
||||
return ("DBSQL_LOCKED: Database table is locked");
|
||||
case DBSQL_NOMEM:
|
||||
return ("DBSQL_NOMEM: Unable to allocate additional memory.");
|
||||
case DBSQL_READONLY:
|
||||
return
|
||||
("DBSQL_READONLY: Attempt to write a readonly database");
|
||||
case DBSQL_INTERRUPTED:
|
||||
return ("DBSQL_INTERRUPTED: Interrupted during processing");
|
||||
case DBSQL_IOERR:
|
||||
return ("DBSQL_IOERROR: Disk I/O error");
|
||||
case DBSQL_NOTFOUND:
|
||||
return ("DBSQL_NOTFOUND: Table or record not found");
|
||||
case DBSQL_FULL:
|
||||
return ("DBSQL_FULL: Database is full");
|
||||
case DBSQL_CANTOPEN:
|
||||
return ("DBSQL_CANTOPEN: Unable to open database file");
|
||||
case DBSQL_PROTOCOL:
|
||||
return ("DBSQL_PROTOCOL: Database locking protocol failure");
|
||||
case DBSQL_EMPTY:
|
||||
return ("DBSQL_EMPTY: Table contains no data");
|
||||
case DBSQL_SCHEMA:
|
||||
return ("DBSQL_SCHEMA: Database schema has changed");
|
||||
case DBSQL_CONSTRAINT:
|
||||
return ("DBSQL_CONSTRAINT: Constraint failed");
|
||||
case DBSQL_MISMATCH:
|
||||
return ("DBSQL_MISMATCH: Datatype mismatch");
|
||||
case DBSQL_MISUSE:
|
||||
return
|
||||
("DBSQL_MISUSE: Library routine called out of sequence");
|
||||
case DBSQL_AUTH:
|
||||
return ("DBSQL_AUTH: Authorization denied");
|
||||
case DBSQL_FORMAT:
|
||||
return ("DBSQL_FORMAT: Auxiliary database format error");
|
||||
case DBSQL_RANGE:
|
||||
return ("DBSQL_RANGE: Bind index out of range");
|
||||
case DBSQL_CORRUPT:
|
||||
return ("DBSQL_CORRUPT: Data record is malformed");
|
||||
case DBSQL_RUNRECOVERY:
|
||||
return (
|
||||
"DBSQL_RUNRECOVERY: Shutdown and run recovery on the database environment.");
|
||||
case DBSQL_INVALID_NAME:
|
||||
return (
|
||||
"DBSQL_INVALID_NAME: Empty or invalid file name supplied");
|
||||
}
|
||||
|
||||
unknown_err: {
|
||||
/*
|
||||
* !!!
|
||||
* Room for a 64-bit number + slop. This buffer is only used
|
||||
* if we're given an unknown error, which should never happen.
|
||||
* Note, however, we're no longer thread-safe if it does.
|
||||
*/
|
||||
static char ebuf[40];
|
||||
|
||||
(void)snprintf(ebuf, sizeof(ebuf), "Unknown error: %d", error);
|
||||
return (ebuf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* __dbsql_err --
|
||||
* Standard DBSQL error routine. The same as errx, except we don't write
|
||||
* to stderr if no output mechanism was specified.
|
||||
*
|
||||
* PUBLIC: void __dbsql_err __P((const DBSQL *, const char *, ...))
|
||||
* PUBLIC: __attribute__ ((__format__ (__printf__, 2, 3)));
|
||||
*/
|
||||
void
|
||||
#ifdef STDC_HEADERS
|
||||
__dbsql_err(const DBSQL *dbp, const char *fmt, ...)
|
||||
#else
|
||||
__dbsql_err(dbp, fmt, va_alist)
|
||||
const DBSQL *dbp;
|
||||
const char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
DBSQL_REAL_ERR(dbp, 0, 0, 0, fmt);
|
||||
}
|
||||
|
||||
#ifndef HAVE_VSNPRINTF
|
||||
#define OVERFLOW_ERROR "internal buffer overflow, process aborted\n"
|
||||
#ifndef STDERR_FILENO
|
||||
#define STDERR_FILENO 2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* __dbsql_errcall --
|
||||
* Do the error message work for callback functions.
|
||||
*
|
||||
* PUBLIC: void __dbsql_errcall __P((const DBSQL *, int, int, const char *,
|
||||
* PUBLIC: va_list));
|
||||
*/
|
||||
void
|
||||
__dbsql_errcall(dbp, error, error_set, fmt, ap)
|
||||
const DBSQL *dbp;
|
||||
int error, error_set;
|
||||
const char *fmt;
|
||||
va_list ap;
|
||||
{
|
||||
char *p;
|
||||
char errbuf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
|
||||
|
||||
p = errbuf;
|
||||
if (fmt != NULL)
|
||||
p += vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
|
||||
if (error_set)
|
||||
p += snprintf(p,
|
||||
sizeof(errbuf) - (size_t)(p - errbuf), ": %s",
|
||||
dbsql_strerror(error));
|
||||
#ifndef HAVE_VSNPRINTF
|
||||
/*
|
||||
* !!!
|
||||
* We're potentially manipulating strings handed us by the application,
|
||||
* and on systems without a real snprintf() the sprintf() calls could
|
||||
* have overflowed the buffer. We can't do anything about it now, but
|
||||
* we don't want to return control to the application, we might have
|
||||
* overwritten the stack with a Trojan horse. We're not trying to do
|
||||
* anything recoverable here because systems without snprintf support
|
||||
* are pretty rare anymore.
|
||||
*/
|
||||
if ((size_t)(p - errbuf) > sizeof(errbuf)) {
|
||||
IGNORE_RESULT(write(
|
||||
STDERR_FILENO, OVERFLOW_ERROR, sizeof(OVERFLOW_ERROR) - 1));
|
||||
abort();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
#endif
|
||||
dbp->dbsql_errcall(dbp->dbsql_errpfx, errbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* __dbsql_errfile --
|
||||
* Do the error message work for FILE *s.
|
||||
*
|
||||
* PUBLIC: void __dbsql_errfile
|
||||
* PUBLIC: __P((const DBSQL *, int, int, const char *, va_list));
|
||||
*/
|
||||
void
|
||||
__dbsql_errfile(dbp, error, error_set, fmt, ap)
|
||||
const DBSQL *dbp;
|
||||
int error, error_set;
|
||||
const char *fmt;
|
||||
va_list ap;
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp = dbp == NULL ||
|
||||
dbp->dbsql_errfile == NULL ? stderr : dbp->dbsql_errfile;
|
||||
|
||||
if (dbp != NULL && dbp->dbsql_errpfx != NULL)
|
||||
(void)fprintf(fp, "%s: ", dbp->dbsql_errpfx);
|
||||
if (fmt != NULL) {
|
||||
(void)vfprintf(fp, fmt, ap);
|
||||
if (error_set)
|
||||
(void)fprintf(fp, ": ");
|
||||
}
|
||||
if (error_set)
|
||||
(void)fprintf(fp, "%s", dbsql_strerror(error));
|
||||
(void)fprintf(fp, "\n");
|
||||
(void)fflush(fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* __error_msg --
|
||||
* Add an error message to pParse->zErrMsg and increment pParse->nErr.
|
||||
* The following formatting characters are allowed:
|
||||
*
|
||||
* %s Insert a string
|
||||
* %z A string that should be freed after use
|
||||
* %d Insert an integer
|
||||
* %T Insert a token
|
||||
* %S Insert the first element of a SrcList
|
||||
*
|
||||
* PUBLIC: void __error_msg __P((parser_t *, const char *, ...));
|
||||
*/
|
||||
void
|
||||
#ifdef STDC_HEADERS
|
||||
__error_msg(parser_t *parser, const char *fmt, ...)
|
||||
#else
|
||||
__error_msg(parser, fmt, va_alist)
|
||||
parser_t parser;
|
||||
const char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
int len;
|
||||
int i, j;
|
||||
char *z;
|
||||
static char null[] = "NULL";
|
||||
|
||||
parser->nErr++;
|
||||
len = 1 + strlen(fmt);
|
||||
va_start(ap, fmt);
|
||||
for(i = 0; fmt[i]; i++) {
|
||||
if (fmt[i] != '%' || fmt[i + 1] == 0)
|
||||
continue;
|
||||
i++;
|
||||
switch(fmt[i]) {
|
||||
case 'd': {
|
||||
(void)va_arg(ap, int);
|
||||
len += 20;
|
||||
break;
|
||||
}
|
||||
case 'z': /* FALLTHROUGH */
|
||||
case 's': {
|
||||
char *z2 = va_arg(ap, char*);
|
||||
if (z2 == 0)
|
||||
z2 = null;
|
||||
len += strlen(z2);
|
||||
break;
|
||||
}
|
||||
case 'T': {
|
||||
token_t *p = va_arg(ap, token_t*);
|
||||
len += p->n;
|
||||
break;
|
||||
}
|
||||
case 'S': {
|
||||
src_list_t *p = va_arg(ap, src_list_t*);
|
||||
int k = va_arg(ap, int);
|
||||
DBSQL_ASSERT(p->nSrc > k && k >= 0);
|
||||
len += strlen(p->a[k].zName);
|
||||
if (p->a[k].zDatabase && p->a[k].zDatabase[0]) {
|
||||
len += strlen(p->a[k].zDatabase) + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
len++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
__dbsql_calloc(parser->db, 1, len, &z);
|
||||
if (z == 0)
|
||||
return;
|
||||
__dbsql_free(parser->db, parser->zErrMsg);
|
||||
parser->zErrMsg = z;
|
||||
va_start(ap, fmt);
|
||||
for(i = j = 0; fmt[i]; i++) {
|
||||
if (fmt[i] != '%' || fmt[i + 1] == 0)
|
||||
continue;
|
||||
if (i > j) {
|
||||
memcpy(z, &fmt[j], i - j);
|
||||
z += i - j;
|
||||
}
|
||||
j = i + 2;
|
||||
i++;
|
||||
switch(fmt[i]) {
|
||||
case 'd': {
|
||||
int x = va_arg(ap, int);
|
||||
sprintf(z, "%d", x);
|
||||
z += strlen(z);
|
||||
break;
|
||||
}
|
||||
case 'z': /* FALLTHROUGH */
|
||||
case 's': {
|
||||
int len;
|
||||
char *z2 = va_arg(ap, char*);
|
||||
if (z2 == 0)
|
||||
z2 = null;
|
||||
len = strlen(z2);
|
||||
memcpy(z, z2, len);
|
||||
z += len;
|
||||
if (fmt[i] == 'z' && z2 != null) {
|
||||
__dbsql_free(NULL, z2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'T': {
|
||||
token_t *p = va_arg(ap, token_t*);
|
||||
memcpy(z, p->z, p->n);
|
||||
z += p->n;
|
||||
break;
|
||||
}
|
||||
case 'S': {
|
||||
int len;
|
||||
src_list_t *p = va_arg(ap, src_list_t*);
|
||||
int k = va_arg(ap, int);
|
||||
assert(p->nSrc > k && k >= 0);
|
||||
if (p->a[k].zDatabase && p->a[k].zDatabase[0]) {
|
||||
len = strlen(p->a[k].zDatabase);
|
||||
memcpy(z, p->a[k].zDatabase, len);
|
||||
z += len;
|
||||
*(z++) = '.';
|
||||
}
|
||||
len = strlen(p->a[k].zName);
|
||||
memcpy(z, p->a[k].zName, len);
|
||||
z += len;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
*(z++) = fmt[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
if (i > j) {
|
||||
memcpy(z, &fmt[j], i - j);
|
||||
z += i - j;
|
||||
}
|
||||
DBSQL_ASSERT((z - parser->zErrMsg) < len);
|
||||
*z = 0;
|
||||
}
|
101
src/common/dbsql_fop.c
Normal file
101
src/common/dbsql_fop.c
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
#include "dbsql_int.h"
|
||||
#include "db_int.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
/*
|
||||
* __dbsql_exists --
|
||||
* Returns if file exists using the __os_exists call of DB.
|
||||
*
|
||||
* PUBLIC: int __dbsql_exists __P((DBSQL *, const char *, int *));
|
||||
*/
|
||||
int
|
||||
__dbsql_exists(dbp, path, isdirp)
|
||||
DBSQL *dbp;
|
||||
const char *path;
|
||||
int *isdirp;
|
||||
{
|
||||
return (__os_exists((dbp ? dbp->dbenv : NULL), path, isdirp));
|
||||
}
|
||||
|
||||
/*
|
||||
* __dbsql_mkdir --
|
||||
* Create a directory using the __os_mkdir call of DB.
|
||||
*
|
||||
* PUBLIC: int __dbsql_mkdir __P((DBSQL *, const char *, int));
|
||||
*/
|
||||
int
|
||||
__dbsql_mkdir(dbp, path, mode)
|
||||
DBSQL *dbp;
|
||||
const char *path;
|
||||
int mode;
|
||||
{
|
||||
return (__os_mkdir((dbp ? dbp->dbenv : NULL), path, mode));
|
||||
}
|
||||
|
||||
/*
|
||||
* __dbsql_omode --
|
||||
* Convert a file mode from a string to an int.
|
||||
*
|
||||
* PUBLIC: int __dbsql_omode __P((DBSQL *, const char *));
|
||||
*/
|
||||
int
|
||||
__dbsql_omode(dbp, mode)
|
||||
DBSQL *dbp;
|
||||
const char *mode;
|
||||
{
|
||||
u_int t;
|
||||
int ret;
|
||||
|
||||
|
||||
#define __SETMODE(offset, valid_ch, mask) { \
|
||||
if (mode[offset] == (valid_ch)) \
|
||||
t |= (mask); \
|
||||
else if (mode[offset] != '-') \
|
||||
goto format_err; \
|
||||
}
|
||||
t = 0;
|
||||
__SETMODE(0, 'r', S_IRUSR);
|
||||
__SETMODE(1, 'w', S_IWUSR);
|
||||
__SETMODE(2, 'x', S_IXUSR);
|
||||
__SETMODE(3, 'r', S_IRGRP);
|
||||
__SETMODE(4, 'w', S_IWGRP);
|
||||
__SETMODE(5, 'x', S_IXGRP);
|
||||
__SETMODE(6, 'r', S_IROTH);
|
||||
__SETMODE(7, 'w', S_IWOTH);
|
||||
__SETMODE(8, 'x', S_IXOTH);
|
||||
if (mode[9] != '\0' || t == 0) {
|
||||
/*
|
||||
* We disallow modes of 0 -- we use 0 to decide the application
|
||||
* never configured intermediate directory permissions, and we
|
||||
* shouldn't create intermediate directories. Besides, setting
|
||||
* the permissions to 0 makes no sense.
|
||||
*/
|
||||
|
||||
format_err: __dbsql_err(dbp, "illegal mode \"%s\"", mode);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
582
src/common/hash.c
Normal file
582
src/common/hash.c
Normal file
|
@ -0,0 +1,582 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Redistributions in any form must be accompanied by information on
|
||||
* how to obtain complete source code for the DB software and any
|
||||
* accompanying software that uses the DB software. The source code
|
||||
* must either be included in the distribution or be available for no
|
||||
* more than the cost of distribution plus a nominal fee, and must be
|
||||
* freely redistributable under reasonable conditions. For an
|
||||
* executable file, complete source code means the source code for all
|
||||
* modules it contains. It does not include source code for modules or
|
||||
* files that typically accompany the major components of the operating
|
||||
* system on which the executable file runs.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ORACLE CORPORATION ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
||||
* NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL ORACLE CORPORATION
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995
|
||||
*The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1995, 1996
|
||||
*The President and Fellows of Harvard University. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Basic hash-tables.
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
#include "dbsql_int.h"
|
||||
|
||||
/*
|
||||
* __hash_init --
|
||||
* Turn bulk memory into a hash table object by initializing the
|
||||
* fields of the hash_t structure.
|
||||
*
|
||||
* 'this' is a pointer to the hash table that is to be initialized.
|
||||
* 'class' is one of the constants DBSQL_HASH_INT, DBSQL_HASH_POINTER,
|
||||
* DBSQL_HASH_BINARY, or DBSQL_HASH_STRING. The value of 'class'
|
||||
* determines what kind of key the hash table will use. 'copy_key_p' is
|
||||
* true if the hash table should make its own private copy of keys and
|
||||
* false if it should just use the supplied pointer. 'copy_key_p' only
|
||||
* makes sense for DBSQL_HASH_STRING and DBSQL_HASH_BINARY and is ignored
|
||||
* for other key classes.
|
||||
*
|
||||
* PUBLIC: void __hash_init __P((hash_t *, int, int));
|
||||
*/
|
||||
void
|
||||
__hash_init(hash_t* this, int class, int copy_key_p)
|
||||
{
|
||||
DBSQL_ASSERT(this != 0);
|
||||
DBSQL_ASSERT(class >= DBSQL_HASH_INT && class <= DBSQL_HASH_BINARY);
|
||||
this->keyClass = class;
|
||||
this->copyKey = copy_key_p &&
|
||||
(class==DBSQL_HASH_STRING || class==DBSQL_HASH_BINARY);
|
||||
this->first = 0;
|
||||
this->count = 0;
|
||||
this->htsize = 0;
|
||||
this->ht = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* __hash_clear --
|
||||
* Remove all entries from a hash table. Reclaim all memory.
|
||||
* Call this routine to delete a hash table or to reset a hash table
|
||||
* to the empty state.
|
||||
*
|
||||
* PUBLIC: void __hash_clear __P((hash_t *));
|
||||
*/
|
||||
void
|
||||
__hash_clear(hash_t* this)
|
||||
{
|
||||
hash_ele_t *elem;
|
||||
DBSQL_ASSERT(this != 0);
|
||||
elem = this->first;
|
||||
this->first = 0;
|
||||
if( this->ht )
|
||||
__dbsql_free(NULL, this->ht);
|
||||
this->ht = 0;
|
||||
this->htsize = 0;
|
||||
while(elem) {
|
||||
hash_ele_t *next_elem = elem->next;
|
||||
if( this->copyKey && elem->pKey ){
|
||||
__dbsql_free(NULL, elem->pKey);
|
||||
}
|
||||
__dbsql_free(NULL, elem);
|
||||
elem = next_elem;
|
||||
}
|
||||
this->count = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* __int_hash --
|
||||
* Hash and comparison functions when the mode is DBSQL_HASH_INT
|
||||
*
|
||||
* STATIC: static int __int_hash __P((const void *, int));
|
||||
*/
|
||||
static int
|
||||
__int_hash(key, len)
|
||||
const void *key;
|
||||
int len;
|
||||
{
|
||||
return len ^ (len << 8) ^ (len >> 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* __int_cmp --
|
||||
*
|
||||
* STATIC: static int __h_int_cmp __P((const void *, int, const void *, int));
|
||||
*/
|
||||
static int
|
||||
__h_int_cmp(k1, n1, k2, n2)
|
||||
const void *k1;
|
||||
int n1;
|
||||
const void *k2;
|
||||
int n2;
|
||||
{
|
||||
return n2 - n1;
|
||||
}
|
||||
|
||||
/*
|
||||
* __str_hash --
|
||||
* Hash and comparison functions when the mode is DBSQL_HASH_STRING
|
||||
*
|
||||
* STATIC: static int __str_hash
|
||||
*/
|
||||
static int
|
||||
__str_hash(key, len)
|
||||
const void *key;
|
||||
int len;
|
||||
{
|
||||
return __hash_ignore_case((const char*)key, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* __str_cmp --
|
||||
*
|
||||
* STATIC: static int __h_str_cmp __P((const void *, int, const void *, int));
|
||||
*/
|
||||
static int
|
||||
__h_str_cmp(k1, n1, k2, n2)
|
||||
const void *k1;
|
||||
int n1;
|
||||
const void *k2;
|
||||
int n2;
|
||||
{
|
||||
if (n1 != n2)
|
||||
return (n2 - n1);
|
||||
return strncasecmp((const char*)k1, (const char*)k2, n1);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bin_hash --
|
||||
* Hash and comparison functions when the mode is DBSQL_HASH_BINARY
|
||||
*
|
||||
* STATIC: static int __bin_hash __((const void *, int));
|
||||
*/
|
||||
static int
|
||||
__bin_hash(key, len)
|
||||
const void *key;
|
||||
int len;
|
||||
{
|
||||
int h = 0;
|
||||
const char *z = (const char *)key;
|
||||
while(len-- > 0) {
|
||||
h = (h << 3) ^ h ^ * (z++);
|
||||
}
|
||||
return h & 0x7fffffff;
|
||||
}
|
||||
|
||||
/*
|
||||
* __bin_cmp --
|
||||
*
|
||||
* STATIC: static int __h_bin_cmp __P((const void *, int, const void *, int));
|
||||
*/
|
||||
static int
|
||||
__h_bin_cmp(k1, n1, k2, n2)
|
||||
const void *k1;
|
||||
int n1;
|
||||
const void *k2;
|
||||
int n2;
|
||||
{
|
||||
if (n1 != n2)
|
||||
return (n2 - n1);
|
||||
return memcmp(k1, k2, n1);
|
||||
}
|
||||
|
||||
/*
|
||||
* __hash_fn --
|
||||
* Return a pointer to the appropriate hash function given the key class.
|
||||
*
|
||||
* The C syntax in this function definition may be unfamilar to some
|
||||
* programmers, so we provide the following additional explanation:
|
||||
*
|
||||
* The name of the function is '__hash_fn'. The function takes a
|
||||
* single parameter 'class'. The return value of __hash_fn()
|
||||
* is a pointer to another function. Specifically, the return value
|
||||
* of __hash_fn() is a pointer to a function that takes two parameters
|
||||
* with types "const void*" and "int" and returns an "int".
|
||||
*/
|
||||
static int
|
||||
(*__hash_fn(int class))(const void*, int)
|
||||
{
|
||||
switch(class) {
|
||||
case DBSQL_HASH_INT:
|
||||
return &__int_hash;
|
||||
case DBSQL_HASH_STRING:
|
||||
return &__str_hash;
|
||||
case DBSQL_HASH_BINARY:
|
||||
return &__bin_hash;;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* __cmp_fn --
|
||||
* Return a pointer to the appropriate hash function given the key class.
|
||||
*
|
||||
* For help in interpreted the obscure C code in the function definition,
|
||||
* see the header comment on the previous function.
|
||||
*/
|
||||
static int
|
||||
(*__cmp_fn(int class))(const void*, int, const void*, int)
|
||||
{
|
||||
switch(class) {
|
||||
case DBSQL_HASH_INT:
|
||||
return &__h_int_cmp;
|
||||
case DBSQL_HASH_STRING:
|
||||
return &__h_str_cmp;
|
||||
case DBSQL_HASH_BINARY:
|
||||
return &__h_bin_cmp;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* __rehash --
|
||||
* Resize the hash table so that it cantains 'new_size' buckets.
|
||||
* 'new_size' must be a power of 2. The hash table might fail
|
||||
* to resize if __dbsql_calloc() fails.
|
||||
*
|
||||
* STATIC: static void __rehash __P((hash_t *, int));
|
||||
*/
|
||||
static void
|
||||
__rehash(hash_t* this, int new_size)
|
||||
{
|
||||
struct _ht *new_ht; /* The new hash table */
|
||||
hash_ele_t *elem, *next_elem; /* For looping over existing elements */
|
||||
hash_ele_t *x; /* Element being copied to new hash
|
||||
table */
|
||||
int (*hash)(const void*,int); /* The hash function */
|
||||
|
||||
DBSQL_ASSERT((new_size & (new_size - 1)) == 0);
|
||||
if (__dbsql_calloc(NULL, new_size, sizeof(struct _ht), &new_ht) == ENOMEM)
|
||||
return;
|
||||
if (this->ht)
|
||||
__dbsql_free(NULL, this->ht);
|
||||
this->ht = new_ht;
|
||||
this->htsize = new_size;
|
||||
hash = __hash_fn(this->keyClass);
|
||||
for (elem = this->first, this->first = 0; elem; elem = next_elem) {
|
||||
int h = (*hash)(elem->pKey, elem->nKey) & (new_size - 1);
|
||||
next_elem = elem->next;
|
||||
x = new_ht[h].chain;
|
||||
if (x) {
|
||||
elem->next = x;
|
||||
elem->prev = x->prev;
|
||||
if (x->prev)
|
||||
x->prev->next = elem;
|
||||
else
|
||||
this->first = elem;
|
||||
x->prev = elem;
|
||||
} else {
|
||||
elem->next = this->first;
|
||||
if (this->first)
|
||||
this->first->prev = elem;
|
||||
elem->prev = 0;
|
||||
this->first = elem;
|
||||
}
|
||||
new_ht[h].chain = elem;
|
||||
new_ht[h].count++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* __hash_search --
|
||||
* This function locates an element in an hash table that matches
|
||||
* the given key. The hash for this key has already been computed
|
||||
* and is passed as the 4th parameter.
|
||||
*
|
||||
* STATIC: static hash_ele_t * __hash_search __P((const hast_t *, const void *,
|
||||
* STATIC: int, int));
|
||||
*
|
||||
* this The hash_t to be searched
|
||||
* key The the object of our search
|
||||
* len The size of the key
|
||||
* h The hash value for this key
|
||||
*/
|
||||
static hash_ele_t *__hash_search(this, key, len, h)
|
||||
const hash_t *this;
|
||||
const void *key;
|
||||
int len;
|
||||
int h;
|
||||
{
|
||||
hash_ele_t *elem;
|
||||
int count;
|
||||
int (*cmp)(const void*, int, const void*, int);
|
||||
|
||||
if (this->ht) {
|
||||
elem = this->ht[h].chain;
|
||||
count = this->ht[h].count;
|
||||
cmp = __cmp_fn(this->keyClass);
|
||||
while (count-- && elem) {
|
||||
if ((*cmp)(elem->pKey, elem->nKey, key, len) == 0) {
|
||||
return elem;
|
||||
}
|
||||
elem = elem->next;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* __hash_remove --
|
||||
* Remove a single entry from the hash table given a pointer to that
|
||||
* element and a hash on the element's key.
|
||||
*
|
||||
* STATIC: static void __hash_remove __P((hash_t *, hash_ele_t *, int));
|
||||
*
|
||||
* this The hash_t to be searched
|
||||
* elem The element to be removed
|
||||
* h The hash value for this key
|
||||
*/
|
||||
static void __hash_remove(this, elem, h)
|
||||
hash_t *this;
|
||||
hash_ele_t* elem;
|
||||
int h;
|
||||
{
|
||||
if (elem->prev) {
|
||||
elem->prev->next = elem->next;
|
||||
} else {
|
||||
this->first = elem->next;
|
||||
}
|
||||
if (elem->next) {
|
||||
elem->next->prev = elem->prev;
|
||||
}
|
||||
if (this->ht[h].chain == elem) {
|
||||
this->ht[h].chain = elem->next;
|
||||
}
|
||||
this->ht[h].count--;
|
||||
if (this->ht[h].count <= 0) {
|
||||
this->ht[h].chain = 0;
|
||||
}
|
||||
if (this->copyKey && elem->pKey) {
|
||||
__dbsql_free(NULL, elem->pKey);
|
||||
}
|
||||
__dbsql_free(NULL, elem);
|
||||
this->count--;
|
||||
}
|
||||
|
||||
/*
|
||||
* __hash_find --
|
||||
* Attempt to locate an element of the hash table this with a key
|
||||
* that matches 'key', 'len'. Return the data for this element if it is
|
||||
* found, or NULL if there is no match.
|
||||
*
|
||||
* PUBLIC: void *__hash_find __P((const hash_t *, const void *, int));
|
||||
*/
|
||||
void *__hash_find(this, key, len)
|
||||
const hash_t *this;
|
||||
const void *key;
|
||||
int len;
|
||||
{
|
||||
int h;
|
||||
hash_ele_t *elem;
|
||||
int (*hash)(const void*, int);
|
||||
|
||||
if (this == 0 || this->ht == 0)
|
||||
return 0;
|
||||
hash = __hash_fn(this->keyClass);
|
||||
DBSQL_ASSERT(hash != 0);
|
||||
h = (*hash)(key, len);
|
||||
DBSQL_ASSERT((this->htsize & (this->htsize - 1)) == 0);
|
||||
elem = __hash_search(this, key, len, h & (this->htsize - 1));
|
||||
return (elem ? elem->data : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __hash_insert --
|
||||
* Insert an element into the hash table this. The key is 'key', 'len'
|
||||
* and the data is 'data'.
|
||||
*
|
||||
* If no element exists with a matching key, then a new
|
||||
* element is created. A copy of the key is made if the copy_key_p
|
||||
* flag is set. NULL is returned.
|
||||
*
|
||||
* If another element already exists with the same key, then the
|
||||
* new data replaces the old data and the old data is returned.
|
||||
* The key is not copied in this instance. If a __dbsql_malloc fails,
|
||||
* then the new data is returned and the hash table is unchanged.
|
||||
*
|
||||
* If the 'data' parameter to this function is NULL, then the
|
||||
* element corresponding to 'key' is removed from the hash table.
|
||||
*
|
||||
* PUBLIC: void *__hash_insert __P((hash_t *, const void *, int, void *));
|
||||
*/
|
||||
void *
|
||||
__hash_insert(this, key, len, data)
|
||||
hash_t *this;
|
||||
const void *key;
|
||||
int len;
|
||||
void *data;
|
||||
{
|
||||
int hraw; /* Raw hash value of the key */
|
||||
int h; /* the hash of the key modulo hash table size */
|
||||
hash_ele_t *elem; /* Used to loop thru the element list */
|
||||
hash_ele_t *new_elem; /* New element added to the pH */
|
||||
int (*hash)(const void*,int); /* The hash function */
|
||||
|
||||
DBSQL_ASSERT(this != 0);
|
||||
hash = __hash_fn(this->keyClass);
|
||||
DBSQL_ASSERT(hash != 0);
|
||||
hraw = (*hash)(key, len);
|
||||
DBSQL_ASSERT((this->htsize & (this->htsize - 1)) == 0);
|
||||
h = hraw & (this->htsize - 1);
|
||||
elem = __hash_search(this, key, len, h);
|
||||
if (elem) {
|
||||
void *old_data = elem->data;
|
||||
if (data == 0) {
|
||||
__hash_remove(this, elem, h);
|
||||
} else {
|
||||
elem->data = data;
|
||||
}
|
||||
return old_data;
|
||||
}
|
||||
if (data == 0)
|
||||
return 0;
|
||||
if (__dbsql_calloc(NULL, 1, sizeof(hash_ele_t), &new_elem) == ENOMEM)
|
||||
return data;
|
||||
if (this->copyKey && key != 0) {
|
||||
if (__dbsql_calloc(NULL, 1, len, &new_elem->pKey) == ENOMEM) {
|
||||
__dbsql_free(NULL, new_elem);
|
||||
return data;
|
||||
}
|
||||
memcpy((void*)new_elem->pKey, key, len);
|
||||
} else {
|
||||
new_elem->pKey = (void*)key;
|
||||
}
|
||||
new_elem->nKey = len;
|
||||
this->count++;
|
||||
if (this->htsize == 0)
|
||||
__rehash(this, 8);
|
||||
if (this->htsize == 0) {
|
||||
this->count = 0;
|
||||
__dbsql_free(NULL, new_elem);
|
||||
return data;
|
||||
}
|
||||
if (this->count > this->htsize) {
|
||||
__rehash(this, this->htsize * 2);
|
||||
}
|
||||
DBSQL_ASSERT((this->htsize & (this->htsize - 1)) == 0);
|
||||
h = hraw & (this->htsize - 1);
|
||||
elem = this->ht[h].chain;
|
||||
if (elem) {
|
||||
new_elem->next = elem;
|
||||
new_elem->prev = elem->prev;
|
||||
if (elem->prev) {
|
||||
elem->prev->next = new_elem;
|
||||
} else {
|
||||
this->first = new_elem;
|
||||
}
|
||||
elem->prev = new_elem;
|
||||
} else {
|
||||
new_elem->next = this->first;
|
||||
new_elem->prev = 0;
|
||||
if (this->first) {
|
||||
this->first->prev = new_elem;
|
||||
}
|
||||
this->first = new_elem;
|
||||
}
|
||||
this->ht[h].count++;
|
||||
this->ht[h].chain = new_elem;
|
||||
new_elem->data = data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* __hash_ignore_case --
|
||||
* This function computes a hash on the name of a keyword.
|
||||
* Case is not significant.
|
||||
*
|
||||
* PUBLIC: int __hash_ignore_case __P((const char *, int));
|
||||
*/
|
||||
int
|
||||
__hash_ignore_case(z, n)
|
||||
const char *z;
|
||||
int n;
|
||||
{
|
||||
int h = 0;
|
||||
if (n <= 0)
|
||||
n = strlen(z);
|
||||
while(n > 0) {
|
||||
h = (h<<3) ^ h ^ __str_upper_to_lower[(unsigned char) * z++];
|
||||
n--;
|
||||
}
|
||||
return h & 0x7fffffff;
|
||||
}
|
876
src/common/str.c
Normal file
876
src/common/str.c
Normal file
|
@ -0,0 +1,876 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Redistributions in any form must be accompanied by information on
|
||||
* how to obtain complete source code for the DB software and any
|
||||
* accompanying software that uses the DB software. The source code
|
||||
* must either be included in the distribution or be available for no
|
||||
* more than the cost of distribution plus a nominal fee, and must be
|
||||
* freely redistributable under reasonable conditions. For an
|
||||
* executable file, complete source code means the source code for all
|
||||
* modules it contains. It does not include source code for modules or
|
||||
* files that typically accompany the major components of the operating
|
||||
* system on which the executable file runs.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ORACLE CORPORATION ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
||||
* NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL ORACLE CORPORATION
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1995, 1996
|
||||
* The President and Fellows of Harvard University. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
#include "dbsql_int.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
unsigned char __str_upper_to_lower[] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
|
||||
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
|
||||
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
|
||||
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
|
||||
104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
|
||||
122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,
|
||||
108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
|
||||
126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
|
||||
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
|
||||
162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
|
||||
180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
|
||||
198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
|
||||
216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
|
||||
234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
|
||||
252,253,254,255
|
||||
};
|
||||
|
||||
/*
|
||||
* __str_append --
|
||||
* Create a string from the 2nd and subsequent arguments (up
|
||||
* to the first NULL argument), store the string in memory
|
||||
* obtained from __dbsql_calloc() and make the pointer indicated
|
||||
* by the 1st argument point to that string. The 1st argument
|
||||
* must either be NULL or point to memory obtained from
|
||||
* __dbsql_calloc().
|
||||
*
|
||||
* PUBLIC: void __str_append __P((char **, const char *, ...));
|
||||
*/
|
||||
void
|
||||
#ifdef STDC_HEADERS
|
||||
__str_append(char **result, const char *fmt, ...)
|
||||
#else
|
||||
__str_append(result, fmt, va_alist)
|
||||
char **result;
|
||||
const char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
size_t len;
|
||||
const char *tmp;
|
||||
char *r;
|
||||
|
||||
if (result == 0)
|
||||
return;
|
||||
len = strlen(fmt) + 1;
|
||||
va_start(ap, fmt);
|
||||
while((tmp = va_arg(ap, const char*)) != NULL) {
|
||||
len += strlen(tmp);
|
||||
}
|
||||
va_end(ap);
|
||||
__dbsql_free(NULL, *result);
|
||||
if (__dbsql_calloc(NULL, 1, len, &r) == ENOMEM)
|
||||
return;
|
||||
*result = r;
|
||||
strcpy(r, fmt);
|
||||
r += strlen(r);
|
||||
va_start(ap, fmt);
|
||||
while((tmp = va_arg(ap, const char*)) != NULL) {
|
||||
strcpy(r, tmp);
|
||||
r += strlen(r);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* __str_nappend --
|
||||
* Works like __str_append, but each string is now followed by
|
||||
* a length integer which specifies how much of the source string
|
||||
* to copy (in bytes). -1 means use the whole string. The 1st
|
||||
* argument must either be NULL or point to memory obtained from
|
||||
* __dbsql_calloc().
|
||||
*
|
||||
* PUBLIC: void __str_nappend __P((char **, ...));
|
||||
*/
|
||||
void
|
||||
#ifdef STDC_HEADERS
|
||||
__str_nappend(char **result, ...)
|
||||
#else
|
||||
__str_nappend(result, va_alist)
|
||||
char **result;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
size_t len;
|
||||
const char *tmp;
|
||||
char *r;
|
||||
unsigned long n;
|
||||
|
||||
if (result == 0)
|
||||
return;
|
||||
len = 0;
|
||||
va_start(ap, result);
|
||||
while((tmp = va_arg(ap, const char*)) != NULL) {
|
||||
n = va_arg(ap, int);
|
||||
if (n <= 0)
|
||||
n = strlen(tmp);
|
||||
len += (size_t)n;
|
||||
}
|
||||
va_end(ap);
|
||||
__dbsql_free(NULL, *result);
|
||||
if (__dbsql_calloc(NULL, 1, len + 1, &r) == ENOMEM)
|
||||
return;
|
||||
*result = r;
|
||||
va_start(ap, result);
|
||||
while((tmp = va_arg(ap, const char*)) != NULL) {
|
||||
n = va_arg(ap, int);
|
||||
if (n <= 0)
|
||||
n = strlen(tmp);
|
||||
strncpy(r, tmp, n);
|
||||
r += n;
|
||||
}
|
||||
*r = 0;
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* __str_unquote --
|
||||
* Convert an SQL-style quoted string into a normal string by removing
|
||||
* the quote characters. The conversion is done in-place. If the
|
||||
* input does not begin with a quote character, then this routine
|
||||
* is a no-op. Quotes can be of the form "'a-b-c'" or the MS-Access style
|
||||
* brackets around identifiers such as: "[a-b-c]". In both cases the
|
||||
* result is "a-b-c".
|
||||
*
|
||||
* PUBLIC: void __str_unquote __P((char *));
|
||||
*/
|
||||
void
|
||||
__str_unquote(char* z)
|
||||
{
|
||||
char quote;
|
||||
int i, j;
|
||||
|
||||
if (z == NULL)
|
||||
return;
|
||||
quote = z[0];
|
||||
switch(quote) {
|
||||
case '\'': break;
|
||||
case '"': break;
|
||||
case '[': quote = ']'; break;
|
||||
default: return;
|
||||
}
|
||||
for(i = 1, j = 0; z[i]; i++) {
|
||||
if (z[i] == quote) {
|
||||
if (z[i + 1] == quote) {
|
||||
z[j++] = quote;
|
||||
i++;
|
||||
} else {
|
||||
z[j++] = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
z[j++] = z[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* __str_urealloc --
|
||||
* Make a duplicate of a string into memory obtained from
|
||||
* __dbsql_umalloc() Free the original string using __dbsql_free().
|
||||
* This routine is called on all strings that are passed outside
|
||||
* the library. That way clients can free the string using
|
||||
* __dbsql_ufree() rather than having to call __dbsql_free().
|
||||
*
|
||||
* PUBLIC: int __str_urealloc __P((char **));
|
||||
*/
|
||||
int
|
||||
__str_urealloc(char* *pz)
|
||||
{
|
||||
int rc = DBSQL_SUCCESS;
|
||||
char *new;
|
||||
|
||||
if (pz == 0 || *pz == NULL)
|
||||
return rc;
|
||||
|
||||
if (__dbsql_umalloc(NULL, strlen(*pz) + 1, &new) == ENOMEM) {
|
||||
rc = ENOMEM;
|
||||
__dbsql_free(NULL, *pz);
|
||||
*pz = 0;
|
||||
}
|
||||
strcpy(new, *pz);
|
||||
__dbsql_free(NULL, *pz);
|
||||
*pz = new;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* __str_is_numeric --
|
||||
* Return TRUE if z is a pure numeric string. Return FALSE if the
|
||||
* string contains any character which is not part of a number.
|
||||
* An empty string is considered non-numeric.
|
||||
*
|
||||
* PUBLIC: int __str_is_numeric __P((const char *));
|
||||
*/
|
||||
int
|
||||
__str_is_numeric(const char *z)
|
||||
{
|
||||
if (*z == '-' || *z == '+')
|
||||
z++;
|
||||
if (!isdigit(*z)) {
|
||||
return 0;
|
||||
}
|
||||
z++;
|
||||
while(isdigit(*z)) {
|
||||
z++;
|
||||
}
|
||||
if (*z == '.') {
|
||||
z++;
|
||||
if (!isdigit(*z))
|
||||
return 0;
|
||||
while(isdigit(*z)) {
|
||||
z++;
|
||||
}
|
||||
}
|
||||
if (*z == 'e' || *z == 'E') {
|
||||
z++;
|
||||
if (*z == '+' || *z == '-')
|
||||
z++;
|
||||
if (!isdigit(*z))
|
||||
return 0;
|
||||
while(isdigit(*z)) {
|
||||
z++;
|
||||
}
|
||||
}
|
||||
return (*z == '\0');
|
||||
}
|
||||
|
||||
#ifdef DBSQL_UTF8_ENCODING
|
||||
|
||||
/*
|
||||
* Convert the UTF-8 character to which z points into a 31-bit
|
||||
* UCS character. This only works right if z points to a well-formed
|
||||
* UTF-8 string.
|
||||
*/
|
||||
static int __utf8_to_int(const unsigned char *z) {
|
||||
int c;
|
||||
static const int init_val[] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
|
||||
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
|
||||
45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
|
||||
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
|
||||
75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
|
||||
90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
|
||||
105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
|
||||
120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
|
||||
135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
|
||||
150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
|
||||
165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
|
||||
180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 0, 1, 2,
|
||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
|
||||
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0,
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 0, 1, 254,
|
||||
255,
|
||||
};
|
||||
c = init_val[*(z++)];
|
||||
while((0xc0 & *z) == 0x80) {
|
||||
c = (c<<6) | (0x3f & *(z++));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* X is a pointer to the first byte of a UTF-8 character. Increment
|
||||
* X so that it points to the next character. This only works right
|
||||
* if X points to a well-formed UTF-8 string.
|
||||
*/
|
||||
#define __next_char(X) while((0xc0 & *++(X)) == 0x80) {}
|
||||
#define __char_val(X) __utf8_to_int(X)
|
||||
|
||||
#else /* !defined(DBSQL_UTF8_ENCODING) */
|
||||
/*
|
||||
* For iso8859 encoding, the next character is just the next byte.
|
||||
*/
|
||||
#define __next_char(X) (++(X));
|
||||
#define __char_val(X) ((int)*(X))
|
||||
|
||||
#endif /* defined(DBSQL_UTF8_ENCODING) */
|
||||
|
||||
/*
|
||||
* __str_glob_cmp --
|
||||
* Compare two UTF-8 strings for equality where the first string can
|
||||
* potentially be a "glob" expression. Return true (1) if they
|
||||
* are the same and false (0) if they are different.
|
||||
*
|
||||
* Globbing rules:
|
||||
*
|
||||
* '*' Matches any sequence of zero or more characters.
|
||||
*
|
||||
* '?' Matches exactly one character.
|
||||
*
|
||||
* [...] Matches one character from the enclosed list of
|
||||
* characters.
|
||||
*
|
||||
* [^...] Matches one character not in the enclosed list.
|
||||
*
|
||||
* With the [...] and [^...] matching, a ']' character can be included
|
||||
* in the list by making it the first character after '[' or '^'. A
|
||||
* range of characters can be specified using '-'. Example:
|
||||
* "[a-z]" matches any single lower-case letter. To match a '-', make
|
||||
* it the last character in the list.
|
||||
*
|
||||
* This routine is usually quick, but can be N**2 in the worst case.
|
||||
*
|
||||
* Hints: to match '*' or '?', put them in "[]". Like this:
|
||||
*
|
||||
* abc[*]xyz Matches "abc*xyz" only
|
||||
*
|
||||
* PUBLIC: int __str_glob_cmp __P((const unsigned char *,
|
||||
* PUBLIC: const unsigned char *));
|
||||
*/
|
||||
int
|
||||
__str_glob_cmp(const unsigned char *pattern, const unsigned char *string)
|
||||
{
|
||||
unsigned char c, c2;
|
||||
int invert;
|
||||
int seen;
|
||||
|
||||
while((c = *pattern) != 0) {
|
||||
switch(c) {
|
||||
case '*':
|
||||
while((c = pattern[1]) == '*' || c == '?') {
|
||||
if (c == '?') {
|
||||
if (*string == 0)
|
||||
return 0;
|
||||
__next_char(string);
|
||||
}
|
||||
pattern++;
|
||||
}
|
||||
if (c == 0)
|
||||
return 1;
|
||||
if (c == '[') {
|
||||
while(*string &&
|
||||
__str_glob_cmp(&pattern[1],
|
||||
string) == 0) {
|
||||
__next_char(string);
|
||||
}
|
||||
return (*string != 0);
|
||||
} else {
|
||||
while((c2 = *string) != 0) {
|
||||
while(c2 != 0 && c2 != c) {
|
||||
c2 = *++string;
|
||||
}
|
||||
if (c2 == 0)
|
||||
return 0;
|
||||
if (__str_glob_cmp(&pattern[1],
|
||||
string))
|
||||
return 1;
|
||||
__next_char(string);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case '?': {
|
||||
if (*string == 0)
|
||||
return 0;
|
||||
__next_char(string);
|
||||
pattern++;
|
||||
break;
|
||||
}
|
||||
case '[': {
|
||||
int prior_c = 0;
|
||||
seen = 0;
|
||||
invert = 0;
|
||||
c = __char_val(string);
|
||||
if (c == 0)
|
||||
return 0;
|
||||
c2 = *++pattern;
|
||||
if (c2 == '^') {
|
||||
invert = 1;
|
||||
c2 = *++pattern;
|
||||
}
|
||||
if (c2 == ']') {
|
||||
if (c == ']')
|
||||
seen = 1;
|
||||
c2 = *++pattern;
|
||||
}
|
||||
while((c2 = __char_val(pattern)) != 0 && c2 != ']') {
|
||||
if (c2 == '-' && pattern[1] != ']' &&
|
||||
pattern[1] != 0 && prior_c > 0) {
|
||||
pattern++;
|
||||
c2 = __char_val(pattern);
|
||||
if (c >= prior_c && c <= c2)
|
||||
seen = 1;
|
||||
prior_c = 0;
|
||||
} else if (c == c2) {
|
||||
seen = 1;
|
||||
prior_c = c2;
|
||||
} else {
|
||||
prior_c = c2;
|
||||
}
|
||||
__next_char(pattern);
|
||||
}
|
||||
if (c2 == 0 || (seen ^ invert) == 0)
|
||||
return 0;
|
||||
__next_char(string);
|
||||
pattern++;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (c != *string )
|
||||
return 0;
|
||||
pattern++;
|
||||
string++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (*string == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __str_like_cmp --
|
||||
* Compare two UTF-8 strings for equality using the "LIKE" operator of
|
||||
* SQL. The '%' character matches any sequence of 0 or more
|
||||
* characters and '_' matches any single character. Case is
|
||||
* not significant. This routine is just an adaptation of the
|
||||
* __str_glob_cmp() routine above.
|
||||
*
|
||||
* PUBLIC: int __str_like_cmp __P((const unsigned char *,
|
||||
* PUBLIC: const unsigned char *));
|
||||
*/
|
||||
int
|
||||
__str_like_cmp(const unsigned char *pattern, const unsigned char *string)
|
||||
{
|
||||
register int c;
|
||||
int c2;
|
||||
|
||||
while((c = __str_upper_to_lower[*pattern]) != 0) {
|
||||
switch(c) {
|
||||
case '%': {
|
||||
while((c = pattern[1]) == '%' || c == '_') {
|
||||
if (c == '_') {
|
||||
if (*string == 0)
|
||||
return 0;
|
||||
__next_char(string);
|
||||
}
|
||||
pattern++;
|
||||
}
|
||||
if (c == 0)
|
||||
return 1;
|
||||
c = __str_upper_to_lower[c];
|
||||
while((c2 = __str_upper_to_lower[*string]) != 0) {
|
||||
while(c2 != 0 && c2 != c) {
|
||||
c2 = __str_upper_to_lower[*++string];
|
||||
}
|
||||
if (c2 == 0)
|
||||
return 0;
|
||||
if (__str_like_cmp(&pattern[1], string))
|
||||
return 1;
|
||||
__next_char(string);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case '_': {
|
||||
if (*string == 0)
|
||||
return 0;
|
||||
__next_char(string);
|
||||
pattern++;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (c != __str_upper_to_lower[*string])
|
||||
return 0;
|
||||
pattern++;
|
||||
string++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (*string == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __str_numeric_cmp --
|
||||
* This comparison routine is what we use for comparison operations
|
||||
* between numeric values in an SQL expression. "Numeric" is a little
|
||||
* bit misleading here. What we mean is that the strings have a
|
||||
* type of "numeric" from the point of view of SQL. The strings
|
||||
* do not necessarily contain numbers. They could contain text.
|
||||
*
|
||||
* If the input strings both look like actual numbers then they
|
||||
* compare in numerical order. Numerical strings are always less
|
||||
* than non-numeric strings so if one input string looks like a
|
||||
* number and the other does not, then the one that looks like
|
||||
* a number is the smaller. Non-numeric strings compare in
|
||||
* lexigraphical order (the same order as strcmp()).
|
||||
*
|
||||
* PUBLIC: int __str_numeric_cmp __P((const char *, const char *));
|
||||
*/
|
||||
int
|
||||
__str_numeric_cmp(const char *left, const char *right)
|
||||
{
|
||||
int result;
|
||||
int left_is_num, right_is_num;
|
||||
|
||||
if (left == 0) {
|
||||
return -1;
|
||||
} else if (right == 0) {
|
||||
return 1;
|
||||
}
|
||||
left_is_num = __str_is_numeric(left);
|
||||
right_is_num = __str_is_numeric(right);
|
||||
if (left_is_num) {
|
||||
if (!right_is_num) {
|
||||
result = -1;
|
||||
} else {
|
||||
double rl, rr;
|
||||
rl = __dbsql_atof(left);
|
||||
rr = __dbsql_atof(right);
|
||||
if (rl < rr){
|
||||
result = -1;
|
||||
} else if (rl > rr) {
|
||||
result = +1;
|
||||
} else {
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
} else if (right_is_num) {
|
||||
result = +1;
|
||||
} else {
|
||||
result = strcmp(left, right);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* __str_int_in32b --
|
||||
* The string 'num' represents an integer. There might be some other
|
||||
* information following the integer too, but that part is ignored.
|
||||
* If the integer that the prefix of 'num' represents will fit in a
|
||||
* 32-bit signed integer, return TRUE. Otherwise return FALSE.
|
||||
*
|
||||
* This routine returns FALSE for the string -2147483648 even though that
|
||||
* that number will, in theory fit in a 32-bit integer. But positive
|
||||
* 2147483648 will not fit in 32 bits. So it seems safer to return
|
||||
* false.
|
||||
*
|
||||
* PUBLIC: int __str_int_in32b __P((const char *));
|
||||
*/
|
||||
int
|
||||
__str_int_in32b(const char *num)
|
||||
{
|
||||
int i = 0;
|
||||
char c;
|
||||
if (*num == '-' || *num == '+')
|
||||
num++;
|
||||
while ((c = num[i]) >= '0' && c <= '9') {
|
||||
i++;
|
||||
}
|
||||
return (i < 10 || (i == 10 && memcmp(num, "2147483647", 10) <= 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* Some powers of 64. These constants are needed in the
|
||||
* __str_real_as_sortable() routine below.
|
||||
*/
|
||||
#define _64e3 (64.0 * 64.0 * 64.0)
|
||||
#define _64e4 (64.0 * 64.0 * 64.0 * 64.0)
|
||||
#define _64e15 (_64e3 * _64e4 * _64e4 * _64e4)
|
||||
#define _64e16 (_64e4 * _64e4 * _64e4 * _64e4)
|
||||
#define _64e63 (_64e15 * _64e16 * _64e16 * _64e16)
|
||||
#define _64e64 (_64e16 * _64e16 * _64e16 * _64e16)
|
||||
|
||||
/*
|
||||
* __str_real_as_sortable --
|
||||
* The following procedure converts a double-precision floating point
|
||||
* number into a string. The resulting string has the property that
|
||||
* two such strings comparied using strcmp() or memcmp() will give the
|
||||
* same results as a numeric comparison of the original floating point
|
||||
* numbers.
|
||||
*
|
||||
* This routine is used to generate database keys from floating point
|
||||
* numbers such that the keys sort in the same order as the original
|
||||
* floating point numbers even though the keys are compared using
|
||||
* memcmp().
|
||||
*
|
||||
* The calling function should have allocated at least 14 characters
|
||||
* of space for the buffer z[].
|
||||
*
|
||||
* PUBLIC: void __str_real_as_sortable __P((double, char *));
|
||||
*/
|
||||
void
|
||||
__str_real_as_sortable(double r, char* z)
|
||||
{
|
||||
int neg;
|
||||
int exp;
|
||||
int cnt = 0;
|
||||
|
||||
/*
|
||||
* This array maps integers between 0 and 63 into base-64 digits.
|
||||
* The digits must be chosen such at their ASCII codes are increasing.
|
||||
* This means we can not use the traditional base-64 digit set.
|
||||
*/
|
||||
static const char digit[] =
|
||||
"0123456789"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"|~";
|
||||
if (r < 0.0) {
|
||||
neg = 1;
|
||||
r = -r;
|
||||
*z++ = '-';
|
||||
} else {
|
||||
neg = 0;
|
||||
*z++ = '0';
|
||||
}
|
||||
exp = 0;
|
||||
|
||||
if (r == 0.0) {
|
||||
exp = -1024;
|
||||
} else if (r < (0.5 / 64.0)) {
|
||||
while(r < 0.5 / _64e64 && exp > -961) {
|
||||
r *= _64e64;
|
||||
exp -= 64;
|
||||
}
|
||||
while(r < 0.5 / _64e16 && exp > -1009) {
|
||||
r *= _64e16;
|
||||
exp -= 16;
|
||||
}
|
||||
while(r < 0.5 / _64e4 && exp > -1021) {
|
||||
r *= _64e4;
|
||||
exp -= 4;
|
||||
}
|
||||
while(r < 0.5 / 64.0 && exp > -1024) {
|
||||
r *= 64.0;
|
||||
exp -= 1;
|
||||
}
|
||||
} else if (r >= 0.5) {
|
||||
while(r >= 0.5 * _64e63 && exp < 960) {
|
||||
r *= 1.0 / _64e64;
|
||||
exp += 64;
|
||||
}
|
||||
while(r >= 0.5 * _64e15 && exp < 1008) {
|
||||
r *= 1.0 / _64e16;
|
||||
exp += 16;
|
||||
}
|
||||
while(r >= 0.5 * _64e3 && exp < 1020) {
|
||||
r *= 1.0 / _64e4;
|
||||
exp += 4;
|
||||
}
|
||||
while(r >= 0.5 && exp < 1023) {
|
||||
r *= 1.0/64.0;
|
||||
exp += 1;
|
||||
}
|
||||
}
|
||||
if (neg) {
|
||||
exp = -exp;
|
||||
r = -r;
|
||||
}
|
||||
exp += 1024;
|
||||
r += 0.5;
|
||||
if (exp < 0)
|
||||
return;
|
||||
if (exp >= 2048 || r >= 1.0) {
|
||||
strcpy(z, "~~~~~~~~~~~~");
|
||||
return;
|
||||
}
|
||||
*z++ = digit[(exp >> 6) & 0x3f];
|
||||
*z++ = digit[exp & 0x3f];
|
||||
while(r > 0.0 && cnt < 10) {
|
||||
int d;
|
||||
r *= 64.0;
|
||||
d = (int)r;
|
||||
DBSQL_ASSERT(d >= 0 && d < 64);
|
||||
*z++ = digit[d & 0x3f];
|
||||
r -= d;
|
||||
cnt++;
|
||||
}
|
||||
*z = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* __str_cmp --
|
||||
* This routine is used for sorting. Each key is a list of one or more
|
||||
* null-terminated elements. The list is terminated by two nulls in
|
||||
* a row. For example, the following text is a key with three elements
|
||||
*
|
||||
* Aone\000Dtwo\000Athree\000\000
|
||||
*
|
||||
* All elements begin with one of the characters "+-AD" and end with
|
||||
* "\000" with zero or more text elements in between. Except, NULL
|
||||
* elements consist of the special two-character sequence "N\000".
|
||||
*
|
||||
* Both arguments will have the same number of elements. This routine
|
||||
* returns negative, zero, or positive if the first argument is less
|
||||
* than, equal to, or greater than the first. (Result is a-b).
|
||||
*
|
||||
* Each element begins with one of the characters "+", "-", "A", "D".
|
||||
* This character determines the sort order and collating sequence:
|
||||
*
|
||||
* + Sort numerically in ascending order
|
||||
* - Sort numerically in descending order
|
||||
* A Sort as strings in ascending order
|
||||
* D Sort as strings in descending order.
|
||||
*
|
||||
* For the "+" and "-" sorting, pure numeric strings (strings for which
|
||||
* the __str_is_numeric() function above returns TRUE) always compare
|
||||
* less than strings that are not pure numerics. Non-numeric strings
|
||||
* compare in memcmp() order. This is the same sort order as the
|
||||
* __str_numeric_cmp() function above generates.
|
||||
*
|
||||
* Elements that begin with 'A' or 'D' compare in memcmp() order
|
||||
* regardless of whether or not they look like a number.
|
||||
*
|
||||
* Note that the sort order imposed by the rules above is the same
|
||||
* from the ordering defined by the "<", "<=", ">", and ">=" operators
|
||||
* of expressions and for indices.
|
||||
*
|
||||
* PUBLIC: int __str_cmp __P((const char *, const char *));
|
||||
*/
|
||||
int
|
||||
__str_cmp(const char *a, const char *b)
|
||||
{
|
||||
unsigned char dir = 0, res = 0;
|
||||
int a_numeric_p, b_numeric_p;
|
||||
|
||||
while(res == 0 && *a && *b) {
|
||||
if (a[0] == 'N' || b[0] == 'N') {
|
||||
if (a[0] == b[0]) {
|
||||
a += 2;
|
||||
b += 2;
|
||||
continue;
|
||||
}
|
||||
if (a[0] == 'N') {
|
||||
dir = b[0];
|
||||
res = -1;
|
||||
} else {
|
||||
dir = a[0];
|
||||
res = +1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
DBSQL_ASSERT(a[0] == b[0]);
|
||||
if ((dir = a[0]) == 'A' || a[0] == 'D') {
|
||||
res = strcmp(&a[1], &b[1]);
|
||||
if (res)
|
||||
break;
|
||||
} else {
|
||||
a_numeric_p = __str_is_numeric(&a[1]);
|
||||
b_numeric_p = __str_is_numeric(&b[1]);
|
||||
if (a_numeric_p) {
|
||||
double rA, rB;
|
||||
if (!b_numeric_p) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
rA = __dbsql_atof(&a[1]);
|
||||
rB = __dbsql_atof(&b[1]);
|
||||
if (rA < rB) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (rA > rB) {
|
||||
res = +1;
|
||||
break;
|
||||
}
|
||||
} else if (b_numeric_p) {
|
||||
res = +1;
|
||||
break;
|
||||
} else {
|
||||
res = strcmp(&a[1], &b[1]);
|
||||
if (res)
|
||||
break;
|
||||
}
|
||||
}
|
||||
a += strlen(&a[1]) + 2;
|
||||
b += strlen(&b[1]) + 2;
|
||||
}
|
||||
if (dir == '-' || dir == 'D')
|
||||
res = -res;
|
||||
return res;
|
||||
}
|
429
src/dbsql.in
Normal file
429
src/dbsql.in
Normal file
|
@ -0,0 +1,429 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
#ifndef _DBSQL_H_
|
||||
#define _DBSQL_H_
|
||||
|
||||
#ifndef __NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h> /* Needed for drand48 */
|
||||
#include <stdarg.h> /* Needed for the definition of va_list */
|
||||
|
||||
@inttypes_h_decl@
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include <db.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@DB_CONST@
|
||||
@DB_PROTO1@
|
||||
@DB_PROTO2@
|
||||
|
||||
/*
|
||||
* DBSQL version information.
|
||||
*/
|
||||
#define DBSQL_VERSION_MAJOR @DBSQL_VERSION_MAJOR@
|
||||
#define DBSQL_VERSION_MINOR @DBSQL_VERSION_MINOR@
|
||||
#define DBSQL_VERSION_PATCH @DBSQL_VERSION_PATCH@
|
||||
#define DBSQL_VERSION_STRING @DBSQL_VERSION_STRING@
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* DBSQL uses specifically sized types. If they're not provided by
|
||||
* the system, typedef them here.
|
||||
*
|
||||
* We protect them against multiple inclusion using __BIT_TYPES_DEFINED__,
|
||||
* as does BIND and Kerberos, since we don't know for sure what #include
|
||||
* files the user is using.
|
||||
*
|
||||
* !!!
|
||||
* We also provide the standard u_int, u_long etc., if they're not provided
|
||||
* by the system.
|
||||
*/
|
||||
#ifndef __BIT_TYPES_DEFINED__
|
||||
#define __BIT_TYPES_DEFINED__
|
||||
@u_int8_decl@
|
||||
@int16_decl@
|
||||
@u_int16_decl@
|
||||
@int32_decl@
|
||||
@u_int32_decl@
|
||||
#endif
|
||||
|
||||
@u_char_decl@
|
||||
@u_short_decl@
|
||||
@u_int_decl@
|
||||
@u_long_decl@
|
||||
@ssize_t_decl@
|
||||
@long_double_decl@
|
||||
|
||||
/*
|
||||
* Forward structure declarations, so we can declare pointers and
|
||||
* applications can get type checking.
|
||||
*/
|
||||
struct __dbsql; typedef struct __dbsql DBSQL;
|
||||
struct __dbsql_func; typedef struct __dbsql_func dbsql_func_t;
|
||||
struct __dbsql_stmt; typedef struct __dbsql_vm dbsql_stmt_t;
|
||||
struct __dbsql_db; typedef struct __dbsql_db dbsql_db_t;
|
||||
struct __dbsql_value; typedef struct __dbsql_value dbsql_value_t;
|
||||
typedef int (*dbsql_callback)(void *, int, char **, char **);
|
||||
|
||||
/*
|
||||
* Name of the master database table. The master database table
|
||||
* is a special table that holds the names and attributes of all
|
||||
* user tables and indices.
|
||||
*/
|
||||
#define MASTER_NAME "master"
|
||||
#define TEMP_MASTER_NAME "temp_master"
|
||||
|
||||
/*
|
||||
* If the following macro is set to 1, then NULL values are considered
|
||||
* distinct for the SELECT DISTINCT statement and for UNION or EXCEPT
|
||||
* compound queries. No other SQL database engine (among those tested)
|
||||
* works this way except for OCELOT. But the SQL92 spec implies that
|
||||
* this is how things should work.
|
||||
*
|
||||
* If the following macro is set to 0, then NULLs are indistinct for
|
||||
* SELECT DISTINCT and for UNION.
|
||||
*/
|
||||
#define NULL_ALWAYS_DISTINCT 0
|
||||
|
||||
/*
|
||||
* If the following macro is set to 1, then NULL values are considered
|
||||
* distinct when determining whether or not two entries are the same
|
||||
* in a UNIQUE index. This is the way PostgreSQL, Oracle, DB2, MySQL,
|
||||
* OCELOT, and Firebird all work. The SQL92 spec explicitly says this
|
||||
* is the way things are suppose to work.
|
||||
*
|
||||
* If the following macro is set to 0, the NULLs are indistinct for
|
||||
* a UNIQUE index. In this mode, you can only have a single NULL entry
|
||||
* for a column declared UNIQUE. This is the way Informix and SQL Server
|
||||
* work.
|
||||
*/
|
||||
#define NULL_DISTINCT_FOR_UNIQUE 1
|
||||
|
||||
/*
|
||||
* The name of the schema tables.
|
||||
*/
|
||||
#define SCHEMA_TABLE(x) (x?TEMP_MASTER_NAME:MASTER_NAME)
|
||||
|
||||
/*
|
||||
* Character Encoding:
|
||||
* DBSQL supports the major character encodings.
|
||||
* - ASCII (American Standard Code for Information Interchange)
|
||||
* - UTF-8 (8-bit UCS/Unicode Transformation Format)
|
||||
* - UTF-16 (16-bit UCS/Unicode Transformation Format)
|
||||
* - ISO-8859-1 (The IANA registered the character map ISO_8859-1:1987)
|
||||
*
|
||||
* The following constant holds one of two strings, "UTF-8" or "iso8859",
|
||||
* depending on which character encoding the library expects to see.
|
||||
* The character encoding makes a difference for the LIKE and GLOB
|
||||
* operators and for the LENGTH() and SUBSTR() functions.
|
||||
*/
|
||||
extern const char dbsql_encoding[];
|
||||
|
||||
#define DBSQL_ASCII_ENCODED 1
|
||||
#define DBSQL_UTF8_ENCODED 2
|
||||
#define DBSQL_UTF16_ENCODED 3
|
||||
#define DBSQL_ISO8859_ENCODED 4
|
||||
|
||||
/*
|
||||
* The DBSQL_UTF8_ENCODING macro is defined if the library expects to see
|
||||
* UTF-8 encoded data. The DBSQL_ISO8859_ENCODING macro is defined if the
|
||||
* iso8859 encoding should be used.
|
||||
*/
|
||||
#define DBSQL_@ENCODING@_ENCODING 1
|
||||
|
||||
|
||||
/* DBSQL (user visible) successful return code. */
|
||||
#define DBSQL_SUCCESS 0
|
||||
|
||||
/*
|
||||
* DBSQL (user visible) error return codes.
|
||||
*
|
||||
* !!!
|
||||
* We don't want our error returns to conflict with other packages where
|
||||
* possible, so pick a base error value that's hopefully not common. We
|
||||
* document that we own the error name space from -50,800 to -50,999.
|
||||
*/
|
||||
/* DBSQL (public) error return codes. */
|
||||
#define DBSQL_ERROR (-50999)/* SQL error or missing database */
|
||||
#define DBSQL_INTERNAL (-50998)/* An internal logic error */
|
||||
#define DBSQL_PERM (-50997)/* Access permission denied */
|
||||
#define DBSQL_ABORT (-50996)/* Callback routine requested an abort */
|
||||
#define DBSQL_BUSY (-50995)/* The database file is locked */
|
||||
#define DBSQL_LOCKED (-50994)/* A table in the database is locked */
|
||||
#define DBSQL_NOMEM (-50993)/* A call to allocate memory failed */
|
||||
#define DBSQL_READONLY (-50992)/* Attempt to write a readonly database */
|
||||
#define DBSQL_INTERRUPTED (-50991)/* Operation terminated by interrupt() */
|
||||
#define DBSQL_IOERR (-50990)/* Some kind of disk I/O error occurred */
|
||||
#define DBSQL_FULL (-50989)/* Failed because database is full */
|
||||
#define DBSQL_CANTOPEN (-50988)/* Unable to open the database file */
|
||||
#define DBSQL_PROTOCOL (-50987)/* Database lock protocol error */
|
||||
#define DBSQL_SCHEMA (-50986)/* The database schema changed */
|
||||
#define DBSQL_CONSTRAINT (-50985)/* Abort due to constraint violation */
|
||||
#define DBSQL_MISMATCH (-50984)/* Data type mismatch */
|
||||
#define DBSQL_MISUSE (-50983)/* Library used incorrectly */
|
||||
#define DBSQL_AUTH (-50982)/* Authorization denied */
|
||||
#define DBSQL_FORMAT (-50981)/* Auxiliary database format error */
|
||||
#define DBSQL_RANGE (-50980)/* 2nd parameter to bind() out of range */
|
||||
#define DBSQL_ROW (-50979)/* step() has another row ready */
|
||||
#define DBSQL_DONE (-50978)/* step() has finished executing */
|
||||
#define DBSQL_CORRUPT (-50977)/* The data record is malformed */
|
||||
#define DBSQL_RUNRECOVERY (-50976)/* Database environment requires recovery */
|
||||
#define DBSQL_INVALID_NAME (-50975)/* Empty or invalid file name supplied */
|
||||
|
||||
/* DBSQL (private) error return codes. */
|
||||
#define DBSQL_NOTFOUND (-50801)/* Table or record not found */
|
||||
#define DBSQL_EMPTY (-50800)/* Database table is empty */
|
||||
|
||||
/*
|
||||
* SQL Database Environment handle.
|
||||
*/
|
||||
struct __dbsql {
|
||||
void *app_private; /* For use by the application. */
|
||||
|
||||
/* Basic API functions. */
|
||||
const char *(*encoding)(void);
|
||||
int (*open) __P((DBSQL *, const char *, int, char **));
|
||||
int (*close) __P((DBSQL *));
|
||||
int (*rowid) __P((DBSQL *));
|
||||
int (*last_change_count) __P((DBSQL *));
|
||||
int (*total_change_count) __P((DBSQL *));
|
||||
void (*interrupt) __P((DBSQL *));
|
||||
void (*set_errcall) __P((DBSQL *, void (*)(const char *, char *)));
|
||||
void (*set_errfile) __P((DBSQL *, FILE *));
|
||||
void (*get_errfile) __P((DBSQL *, FILE **));
|
||||
void (*set_errpfx) __P((DBSQL *, const char *));
|
||||
void (*get_errpfx) __P((DBSQL *, const char **));
|
||||
DB_ENV *(*get_dbenv) __P((DBSQL *));
|
||||
|
||||
/* Callback access functions. */
|
||||
void *(*set_tracecall) __P((DBSQL *, void(*)(void *, const char *),\
|
||||
void *));
|
||||
#ifndef DBSQL_NO_PROGRESS
|
||||
void (*set_progresscall) __P((DBSQL *, int, int(*)(void*), void*));
|
||||
#endif
|
||||
void *(*set_commitcall) __P((DBSQL *, int(*)(void*), void*));
|
||||
void (*set_busycall) __P((DBSQL *, int(*)(DBSQL *, void *, const char *, int),\
|
||||
void *));
|
||||
void (*set_timeout) __P((DBSQL *, int ms));
|
||||
|
||||
int (*get_table) __P((DBSQL *, const char *, char ***, int *,\
|
||||
int *, char **));
|
||||
void (*free_table) __P((char **));
|
||||
int (*exec_printf) __P((DBSQL *, const char *, dbsql_callback,\
|
||||
void *, char **, ...));
|
||||
int (*exec_vprintf) __P((DBSQL *, const char *, dbsql_callback,\
|
||||
void *, char **, va_list ap));
|
||||
int (*exec_table_printf) __P((DBSQL *, const char *, char ***,\
|
||||
int *, int *, char **, ...));
|
||||
int (*exec_table_vprintf) __P((DBSQL *, const char *, char ***,\
|
||||
int *, int *, char **, va_list));
|
||||
int (*exec) __P((DBSQL *, const char *, dbsql_callback, void *,\
|
||||
char **));
|
||||
|
||||
int (*step) __P((dbsql_stmt_t *, int *, const char ***,\
|
||||
const char ***));
|
||||
|
||||
int (*create_function) __P((DBSQL *, const char *, int, int, void *,\
|
||||
void (*)(dbsql_func_t *, int, const char**), \
|
||||
void (*)(dbsql_func_t *, int, const char**), \
|
||||
void (*)(dbsql_func_t *)));
|
||||
int (*func_return_type) __P((DBSQL *, const char *, int));
|
||||
#define DBSQL_NUMERIC (-1)
|
||||
#define DBSQL_TEXT (-2)
|
||||
#define DBSQL_ARGS (-3)
|
||||
|
||||
int (*set_authorizer) __P((DBSQL *, int (*)(void *, int, const char *,\
|
||||
const char *, const char *,\
|
||||
const char *), void *));
|
||||
|
||||
/*
|
||||
* The return value of the authorization function should be one of the
|
||||
* following constants:
|
||||
*
|
||||
define DBSQL_SUCCESS 0 Allow access (This is actually defined above) */
|
||||
#define DBSQL_DENY 1 /* Abort the SQL statement with an error */
|
||||
#define DBSQL_IGNORE 2 /* Don't allow access, but don't generate an error */
|
||||
|
||||
/*
|
||||
* The second parameter to the access authorization function above will
|
||||
* be one of the values below. These values signify what kind of operation
|
||||
* is to be authorized. The 3rd and 4th parameters to the authorization
|
||||
* function will be parameters or NULL depending on which of the following
|
||||
* codes is used as the second parameter. The 5th parameter is the name
|
||||
* of the database ("main", "temp", etc.) if applicable. The 6th parameter
|
||||
* is the name of the inner-most trigger or view that is responsible for
|
||||
* the access attempt or NULL if this access attempt is directly from
|
||||
* input SQL code.
|
||||
* Arg-3 Arg-4
|
||||
*/
|
||||
#define DBSQL_COPY 0 /* Table Name File Name */
|
||||
#define DBSQL_CREATE_INDEX 1 /* Index Name Table Name */
|
||||
#define DBSQL_CREATE_TABLE 2 /* Table Name NULL */
|
||||
#define DBSQL_CREATE_TEMP_INDEX 3 /* Index Name Table Name */
|
||||
#define DBSQL_CREATE_TEMP_TABLE 4 /* Table Name NULL */
|
||||
#define DBSQL_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */
|
||||
#define DBSQL_CREATE_TEMP_VIEW 6 /* View Name NULL */
|
||||
#define DBSQL_CREATE_TRIGGER 7 /* Trigger Name Table Name */
|
||||
#define DBSQL_CREATE_VIEW 8 /* View Name NULL */
|
||||
#define DBSQL_DELETE 9 /* Table Name NULL */
|
||||
#define DBSQL_DROP_INDEX 10 /* Index Name Table Name */
|
||||
#define DBSQL_DROP_TABLE 11 /* Table Name NULL */
|
||||
#define DBSQL_DROP_TEMP_INDEX 12 /* Index Name Table Name */
|
||||
#define DBSQL_DROP_TEMP_TABLE 13 /* Table Name NULL */
|
||||
#define DBSQL_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */
|
||||
#define DBSQL_DROP_TEMP_VIEW 15 /* View Name NULL */
|
||||
#define DBSQL_DROP_TRIGGER 16 /* Trigger Name Table Name */
|
||||
#define DBSQL_DROP_VIEW 17 /* View Name NULL */
|
||||
#define DBSQL_INSERT 18 /* Table Name NULL */
|
||||
#define DBSQL_PRAGMA 19 /* Pragma Name 1st arg or NULL */
|
||||
#define DBSQL_READ 20 /* Table Name Column Name */
|
||||
#define DBSQL_SELECT 21 /* NULL NULL */
|
||||
#define DBSQL_TRANSACTION 22 /* NULL NULL */
|
||||
#define DBSQL_UPDATE 23 /* Table Name Column Name */
|
||||
#define DBSQL_ATTACH 24 /* Filename NULL */
|
||||
#define DBSQL_DETACH 25 /* Database Name NULL */
|
||||
|
||||
/* Non-callback access functions. */
|
||||
int (*prepare) __P((DBSQL *, const char *, const char **,\
|
||||
dbsql_stmt_t **, char **));
|
||||
int (*finalize) __P((dbsql_stmt_t *, char **));
|
||||
int (*reset) __P((dbsql_stmt_t *, char **));
|
||||
int (*bind) __P((dbsql_stmt_t *, int, const char *, int, int));
|
||||
|
||||
/*
|
||||
* From here on out, fields are internal and subject to change.
|
||||
*/
|
||||
DB_ENV *dbenv; /* The Berkeley DB Environment */
|
||||
int txn_flags;
|
||||
void (*dbsql_errcall)(const char *, char *); /* Error callback */
|
||||
FILE *dbsql_errfile; /* The error file */
|
||||
char *dbsql_errpfx; /* The error prefix string */
|
||||
void (*dbsql_paniccall)(DBSQL *, int); /* The panic callback */
|
||||
int panic; /* If non-zero, shut down the application */
|
||||
dbsql_db_t *aDb; /* One for each open SQL database + 2 */
|
||||
int nDb; /* Number of open dbsql_db_t's open */
|
||||
int flags; /* Flags, see below */
|
||||
#define DBSQL_VdbeTrace 0x00000001 /* True to trace VDBE execution */
|
||||
#define DBSQL_Initialized 0x00000002 /* True after initialization */
|
||||
#define DBSQL_Interrupt 0x00000004 /* Cancel current operation */
|
||||
#define DBSQL_InTrans 0x00000008 /* True if in a transaction */
|
||||
#define DBSQL_InternChanges 0x00000010 /* Uncommitted Hash table changes */
|
||||
#define DBSQL_FullColNames 0x00000020 /* Show full column names on SELECT */
|
||||
#define DBSQL_CountRows 0x00000040 /* Count rows changed by INSERT,
|
||||
DELETE, or UPDATE and return
|
||||
the count using a callback. */
|
||||
#define DBSQL_NullCallback 0x00000080 /* Invoke the callback once if the
|
||||
result set is empty */
|
||||
#define DBSQL_ReportTypes 0x00000200 /* Include information on datatypes
|
||||
in 4th argument of callback */
|
||||
#define DBSQL_DurableTemp 0x00000400 /* Back temp databases on disk. */
|
||||
#define DBSQL_Threaded 0x00000800 /* Set when we're expected to be
|
||||
thread safe. */
|
||||
u_int8_t want_to_close; /* Close after all VDBEs are deallocated */
|
||||
u_int32_t next_sig; /* Next value of aDb[0].schema_sig */
|
||||
int nTable; /* Number of tables in the database */
|
||||
void *pBusyArg; /* 1st Argument to the busy callback */
|
||||
int (*xBusyCallback)(DBSQL *, void *, const char*, int);
|
||||
void *pCommitArg; /* Argument to xCommitCallback() */
|
||||
int (*xCommitCallback)(void*);/* Invoked at every commit. */
|
||||
void *fns; /* All functions that can be in SQL exprs */
|
||||
int lastRowid; /* ROWID of most recent insert */
|
||||
int priorNewRowid; /* Last generated ROWID */
|
||||
int onError; /* Default conflict algorithm */
|
||||
int magic; /* Magic number to detect library misuse */
|
||||
#define DBSQL_STATUS_OPEN 0xa029a697 /* Database is open */
|
||||
#define DBSQL_STATUS_CLOSED 0x9f3c2d33 /* Database is closed */
|
||||
#define DBSQL_STATUS_BUSY 0xf03b7906 /* Database currently in use */
|
||||
#define DBSQL_STATUS_ERROR 0xb5357930 /* An DBSQL_MISUSE error occurred */
|
||||
u_int32_t _num_last_changes; /* Number of rows changed */
|
||||
u_int32_t _num_total_changes; /* Total number of rows changed */
|
||||
struct vdbe *pVdbe; /* List of active virtual machines */
|
||||
void (*xTrace)(void*,const char*); /* Trace function */
|
||||
void *pTraceArg; /* Argument to the trace function */
|
||||
#ifndef DBSQL_NO_AUTH /* Access authorization functions */
|
||||
int (*auth)(void*,int,const char*,const char*,const char*,const char*);
|
||||
void *pAuthArg; /* 1st argument to the access auth function */
|
||||
#endif
|
||||
#ifndef DBSQL_NO_PROGRESS
|
||||
int (*xProgress)(void *);/* The progress callback */
|
||||
void *pProgressArg; /* Argument to the progress callback */
|
||||
int nProgressOps; /* Number of opcodes for progress callback */
|
||||
#endif
|
||||
u_int32_t format_version;/* The version of the representation */
|
||||
};
|
||||
|
||||
#define DBSQL_THREAD 0x00001 /* When set the library is thread
|
||||
safe. */
|
||||
#define DBSQL_DURABLE_TEMP 0x00002 /* Store temp data on disk rather
|
||||
than in memory */
|
||||
|
||||
int dbsql_create_env __P((DBSQL **, const char *, const char *, int, u_int32_t));
|
||||
int dbsql_create __P((DBSQL **, DB_ENV *, u_int32_t));
|
||||
int dbsql_complete_stmt __P((const char *));
|
||||
char *dbsql_strerror __P((int));
|
||||
const char * dbsql_version __P((int *, int *, int *));
|
||||
|
||||
void dbsql_set_result_null __P((dbsql_func_t *));
|
||||
char *dbsql_set_result_string __P((dbsql_func_t *, const char *, int));
|
||||
void dbsql_set_result_int __P((dbsql_func_t *, int));
|
||||
void dbsql_set_result_int64 __P((dbsql_func_t *, int64_t));
|
||||
void dbsql_set_result_blob __P((dbsql_func_t *, const void *, size_t,\
|
||||
void(*)(void*)));
|
||||
void dbsql_set_result_varchar __P((dbsql_func_t *, const char *, size_t,\
|
||||
void(*)(void*)));
|
||||
void dbsql_set_result_double __P((dbsql_func_t *, double));
|
||||
void dbsql_set_result_error __P((dbsql_func_t *, const char *, int));
|
||||
void *dbsql_user_data __P((dbsql_func_t *));
|
||||
void *dbsql_aggregate_context __P((dbsql_func_t *, int));
|
||||
int dbsql_aggregate_count __P((dbsql_func_t *));
|
||||
|
||||
/*
|
||||
* The fifth parameter to dbsql_set_result_blob(), and
|
||||
* dbsql_set_result_varchar() is a destructor used to dispose of the BLOB
|
||||
* or text after DBSQL has finished with it. If the fifth argument is the
|
||||
* special value DBSQL_STATIC, then the library assumes that the information
|
||||
* is in static, unmanaged space and does not need to be freed. If the fifth
|
||||
* argument has the value DBSQL_TRANSIENT, then DBSQL makes its own private
|
||||
* copy of the data.
|
||||
*/
|
||||
#define DBSQL_STATIC ((void(*)(void *))0)
|
||||
#define DBSQL_TRANSIENT ((void(*)(void *))-1)
|
||||
|
||||
/*
|
||||
* Values are stored in the database in one of the following fundamental
|
||||
* types. TODO
|
||||
*/
|
||||
#define DBSQL_INTEGER 1
|
||||
#define DBSQL_FLOAT 2
|
||||
#define DBSQL_VARCHAR 3
|
||||
#define DBSQL_BLOB 4
|
||||
#define DBSQL_NULL 5
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !_DBSQL_H_ */
|
1497
src/dbsql/dbsql.c
Normal file
1497
src/dbsql/dbsql.c
Normal file
File diff suppressed because it is too large
Load diff
99
src/dbsql_tclsh.c
Normal file
99
src/dbsql_tclsh.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A TCL Shell for testing DBSQL.
|
||||
*/
|
||||
|
||||
#include "dbsql_config.h"
|
||||
#include "dbsql_int.h"
|
||||
#include "tcl.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static char main_loop[] =
|
||||
"set line {}\n"
|
||||
"while {![eof stdin]} {\n"
|
||||
"if {$line!=\"\"} {\n"
|
||||
"puts -nonewline \"> \"\n"
|
||||
"} else {\n"
|
||||
"puts -nonewline \"% \"\n"
|
||||
"}\n"
|
||||
"flush stdout\n"
|
||||
"append line [gets stdin]\n"
|
||||
"if {[info complete $line]} {\n"
|
||||
"if {[catch {uplevel #0 $line} result]} {\n"
|
||||
"puts stderr \"Error: $result\"\n"
|
||||
"} elseif {$result!=\"\"} {\n"
|
||||
"puts $result\n"
|
||||
"}\n"
|
||||
"set line {}\n"
|
||||
"} else {\n"
|
||||
"append line \\n\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
;
|
||||
|
||||
/*
|
||||
* main --
|
||||
*/
|
||||
int
|
||||
main(int argc, char* *argv)
|
||||
{
|
||||
int i;
|
||||
const char *info;
|
||||
Tcl_Interp *interp;
|
||||
Tcl_FindExecutable(argv[0]);
|
||||
interp = Tcl_CreateInterp();
|
||||
dbsql_init_tcl_interface(interp);
|
||||
#ifdef CONFIG_TEST
|
||||
extern int Sqlitetest1_Init(Tcl_Interp*);
|
||||
extern int Sqlitetest2_Init(Tcl_Interp*);
|
||||
extern int Sqlitetest3_Init(Tcl_Interp*);
|
||||
extern int Sqlitetest4_Init(Tcl_Interp*);
|
||||
extern int Md5_Init(Tcl_Interp*);
|
||||
Sqlitetest1_Init(interp);
|
||||
Sqlitetest2_Init(interp);
|
||||
Sqlitetest3_Init(interp);
|
||||
Sqlitetest4_Init(interp);
|
||||
Md5_Init(interp);
|
||||
#endif
|
||||
if (argc >= 2) {
|
||||
Tcl_SetVar(interp, "argv0", argv[1], TCL_GLOBAL_ONLY);
|
||||
Tcl_SetVar(interp, "argv", "", TCL_GLOBAL_ONLY);
|
||||
for (i = 2; i < argc; i++) {
|
||||
Tcl_SetVar(interp, "argv", argv[i],
|
||||
TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT |
|
||||
TCL_APPEND_VALUE);
|
||||
}
|
||||
if (Tcl_EvalFile(interp, argv[1]) != TCL_OK) {
|
||||
info = Tcl_GetVar(interp, "errorInfo",
|
||||
TCL_GLOBAL_ONLY);
|
||||
if (info == 0)
|
||||
info = interp->result;
|
||||
fprintf(stderr, "%s: %s\n", *argv, info);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
Tcl_GlobalEval(interp, main_loop);
|
||||
}
|
||||
return 0;
|
||||
}
|
41
src/inc/clib_ext.h
Normal file
41
src/inc/clib_ext.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/* DO NOT EDIT: automatically built by dist/s_include. */
|
||||
#ifndef _clib_ext_h_
|
||||
#define _clib_ext_h_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETOPT
|
||||
int getopt __P((int, char * const *, const char *));
|
||||
#endif
|
||||
#ifndef HAVE_MEMCMP
|
||||
int memcmp __P((const void *, const void *, size_t));
|
||||
#endif
|
||||
#ifndef HAVE_SRAND48_R
|
||||
int srand48_r __P((struct drand48_data *));
|
||||
#endif
|
||||
int rand8_r __P((struct drand48_data *, u_int8_t *));
|
||||
int rand32_r __P((struct drand48_data *, u_int32_t *));
|
||||
#ifndef HAVE_SNPRINTF
|
||||
int snprintf __P((char *, size_t, const char *, ...));
|
||||
#endif
|
||||
#ifndef HAVE_STRCASECMP
|
||||
int strcasecmp __P((const char *, const char *));
|
||||
#endif
|
||||
#ifndef HAVE_STRNCASECMP
|
||||
int strncasecmp __P((const char *, const char *, size_t));
|
||||
#endif
|
||||
#ifndef HAVE_STRDUP
|
||||
char *strdup __P((const char *));
|
||||
#endif
|
||||
#ifndef HAVE_STRNDUP
|
||||
char *strndup __P((const char *, size_t));
|
||||
#endif
|
||||
char *xvprintf __P((DBSQL *, const char *, va_list));
|
||||
char *xprintf __P((DBSQL *, const char *, ...));
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* !_clib_ext_h_ */
|
52
src/inc/common_ext.h
Normal file
52
src/inc/common_ext.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/* DO NOT EDIT: automatically built by dist/s_include. */
|
||||
#ifndef _common_ext_h_
|
||||
#define _common_ext_h_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int __dbsql_umalloc __P((DBSQL *, size_t, void *));
|
||||
int __dbsql_urealloc __P((DBSQL *, size_t, void *));
|
||||
void __dbsql_ufree __P((DBSQL *, void *));
|
||||
int __dbsql_strdup __P((DBSQL *, const char *, void *));
|
||||
int __dbsql_strndup __P((DBSQL *, const char *, void *, size_t));
|
||||
int __dbsql_calloc __P((DBSQL *, size_t, size_t, void *));
|
||||
int __dbsql_malloc __P((DBSQL *, size_t, void *));
|
||||
int __dbsql_realloc __P((DBSQL *, size_t, void *));
|
||||
void __dbsql_free __P((DBSQL *, void *));
|
||||
double __dbsql_atof __P((const char *));
|
||||
int __dbsql_atoi __P((const char *, int *));
|
||||
#ifdef DIAGNOSTIC
|
||||
void __dbsql_assert __P((const char *, const char *, int));
|
||||
#endif
|
||||
int __dbsql_panic_msg __P((DBSQL *));
|
||||
int __dbsql_panic __P((DBSQL *, int));
|
||||
void __dbsql_err __P((const DBSQL *, const char *, ...)) __attribute__ ((__format__ (__printf__, 2, 3)));
|
||||
void __dbsql_errcall __P((const DBSQL *, int, int, const char *, va_list));
|
||||
void __dbsql_errfile __P((const DBSQL *, int, int, const char *, va_list));
|
||||
void __error_msg __P((parser_t *, const char *, ...));
|
||||
int __dbsql_exists __P((DBSQL *, const char *, int *));
|
||||
int __dbsql_mkdir __P((DBSQL *, const char *, int));
|
||||
int __dbsql_omode __P((DBSQL *, const char *));
|
||||
void __hash_init __P((hash_t *, int, int));
|
||||
void __hash_clear __P((hash_t *));
|
||||
void *__hash_find __P((const hash_t *, const void *, int));
|
||||
void *__hash_insert __P((hash_t *, const void *, int, void *));
|
||||
int __hash_ignore_case __P((const char *, int));
|
||||
void __str_append __P((char **, const char *, ...));
|
||||
void __str_nappend __P((char **, ...));
|
||||
void __str_unquote __P((char *));
|
||||
int __str_urealloc __P((char **));
|
||||
int __str_is_numeric __P((const char *));
|
||||
int __str_glob_cmp __P((const unsigned char *, const unsigned char *));
|
||||
int __str_like_cmp __P((const unsigned char *, const unsigned char *));
|
||||
int __str_numeric_cmp __P((const char *, const char *));
|
||||
int __str_int_in32b __P((const char *));
|
||||
void __str_real_as_sortable __P((double, char *));
|
||||
int __str_cmp __P((const char *, const char *));
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* !_common_ext_h_ */
|
54
src/inc/db_int.h
Normal file
54
src/inc/db_int.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
#ifndef _DB_INT_H_
|
||||
#define _DB_INT_H_
|
||||
|
||||
/*
|
||||
* These are function prototypes to non-public API parts of DB we use
|
||||
* in DBSQL. DB may have been compiled with --uniquename, so we have
|
||||
* to manage that here. We also have to smooth out differences from
|
||||
* version to version here as internal API is bound to change.
|
||||
*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int __db_omode__DB_UNIQUE_NAME__ __P((const char *));
|
||||
extern int __os_calloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, size_t, void *));
|
||||
extern int __os_exists__DB_UNIQUE_NAME__ __P((DB_ENV *, const char *, int *));
|
||||
extern int __os_get_errno__DB_UNIQUE_NAME__ __P((void));
|
||||
extern int __os_id__DB_UNIQUE_NAME__ __P((DB_ENV *, pid_t *, db_threadid_t*));
|
||||
extern int __os_malloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, void *));
|
||||
extern int __os_mkdir__DB_UNIQUE_NAME__ __P((DB_ENV *, const char *, int));
|
||||
extern int __os_realloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, void *));
|
||||
extern int __os_strdup__DB_UNIQUE_NAME__ __P((DB_ENV *, const char *, void *));
|
||||
extern int __os_umalloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, void *));
|
||||
extern int __os_urealloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, void *));
|
||||
extern void *__ua_memcpy__DB_UNIQUE_NAME__ __P((void *, const void *, size_t));
|
||||
extern void __os_free__DB_UNIQUE_NAME__ __P((DB_ENV *, void *));
|
||||
extern void __os_set_errno__DB_UNIQUE_NAME__ __P((int));
|
||||
extern void __os_ufree__DB_UNIQUE_NAME__ __P((DB_ENV *, void *));
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* !_DB_INT_H_ */
|
201
src/inc/dbsql_ext.h
Normal file
201
src/inc/dbsql_ext.h
Normal file
|
@ -0,0 +1,201 @@
|
|||
/* DO NOT EDIT: automatically built by dist/s_include. */
|
||||
#ifndef _dbsql_ext_h_
|
||||
#define _dbsql_ext_h_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int __init_databases __P((DBSQL *, char**));
|
||||
int __sqldb_init __P((dbsql_db_t *, DBSQL *, const char *, int, int, int));
|
||||
void __api_interrupt __P((DBSQL *));
|
||||
int __api_get_table __P((DBSQL *, const char *, char ***, int *, int *, char **));
|
||||
void __api_free_table __P((char **));
|
||||
void __attach __P((parser_t *, token_t *, token_t *));
|
||||
void __detach __P((parser_t *, token_t *));
|
||||
int __ref_normalizer_ctx_init __P((ref_normalizer_ctx_t *, parser_t *, int, const char *, const token_t *));
|
||||
int __ref_normalize_src_list __P((ref_normalizer_ctx_t *, src_list_t *));
|
||||
int __ref_normalize_select __P((ref_normalizer_ctx_t *, select_t *));
|
||||
int __ref_normalize_expr __P((ref_normalizer_ctx_t *, expr_t *));
|
||||
int __ref_normalize_expr_list __P((ref_normalizer_ctx_t *, expr_list_t *));
|
||||
int __ref_normalize_trigger_step __P((ref_normalizer_ctx_t *, trigger_step_t *));
|
||||
int __api_set_authorizer __P((DBSQL *, int (*auth)(void*,int,const char*, const char*,const char*, const char*), void *));
|
||||
void __auth_read __P((parser_t *, expr_t *, src_list_t *));
|
||||
int __auth_check __P((parser_t *, int, const char *, const char *, const char *));
|
||||
void __auth_context_push __P((parser_t *, auth_context_t *, const char *));
|
||||
void __auth_context_pop __P((auth_context_t *));
|
||||
void __parse_begin __P((parser_t *, int));
|
||||
void __parse_exec __P((parser_t *));
|
||||
table_t *__find_table __P((DBSQL *, const char *, const char *));
|
||||
table_t *__locate_table __P((parser_t *, const char *, const char *));
|
||||
index_t *__find_index __P((DBSQL *, const char *, const char *));
|
||||
void __unlink_and_delete_index __P((DBSQL *, index_t *));
|
||||
void __reset_internal_schema __P((DBSQL *, int));
|
||||
void __rollback_internal_changes __P((DBSQL *));
|
||||
void __commit_internal_changes __P((DBSQL *));
|
||||
void __vdbe_delete_table __P((DBSQL *, table_t *));
|
||||
char *__table_name_from_token __P((token_t *));
|
||||
void __open_master_table __P((vdbe_t *, int));
|
||||
void __start_table __P((parser_t *, token_t *, token_t *, int, int));
|
||||
void __add_column __P((parser_t *, token_t *));
|
||||
void __add_not_null __P((parser_t *, int));
|
||||
void __add_column_type __P((parser_t *, token_t *, token_t *));
|
||||
void __add_default_value __P((parser_t *, token_t *, int));
|
||||
void __add_primary_key __P((parser_t *, id_list_t *, int));
|
||||
int __collate_type __P((const char *, int));
|
||||
void __add_collate_type __P((parser_t *, int));
|
||||
void __change_schema_signature __P((DBSQL *, vdbe_t *));
|
||||
void __ending_create_table_paren __P((parser_t *, token_t *, select_t *));
|
||||
void __create_view __P((parser_t *, token_t *, token_t *, select_t *, int));
|
||||
int __view_get_column_names __P((parser_t *, table_t *));
|
||||
table_t *__table_from_token __P((parser_t *, token_t *));
|
||||
void __drop_table __P((parser_t *, token_t *name, int));
|
||||
void __add_idx_key_type __P((vdbe_t *, index_t *));
|
||||
void __create_foreign_key __P((parser_t *, id_list_t *, token_t *, id_list_t *, int));
|
||||
void __defer_foreign_key __P((parser_t *, int));
|
||||
void __create_index __P((parser_t *, token_t *, src_list_t *, id_list_t *, int, token_t *, token_t *));
|
||||
void __drop_index __P((parser_t *, src_list_t *));
|
||||
id_list_t *__id_list_append __P((id_list_t *, token_t *));
|
||||
src_list_t *__src_list_append __P((src_list_t *, token_t *, token_t *));
|
||||
void __src_list_assign_cursors __P((parser_t *, src_list_t *));
|
||||
void __src_list_add_alias __P((src_list_t *, token_t *));
|
||||
void __id_list_delete __P((id_list_t *));
|
||||
int __id_list_index __P((id_list_t *, const char *));
|
||||
void __src_list_delete __P((src_list_t *));
|
||||
void __dbsql_txn_begin __P((parser_t *, int));
|
||||
void __dbsql_txn_commit __P((parser_t *));
|
||||
void __dbsql_txn_abort __P((parser_t *));
|
||||
void __code_verify_schema __P((parser_t *, int));
|
||||
void __vdbe_prepare_write __P((parser_t*, int, int));
|
||||
void __vdbe_conclude_write __P((parser_t *));
|
||||
void __copy __P((parser_t *, src_list_t *, token_t *, token_t *, int));
|
||||
void __register_datetime_funcs __P((DBSQL *));
|
||||
table_t *__src_list_lookup __P((parser_t *, src_list_t *));
|
||||
int __is_table_read_only __P((parser_t *, table_t *, int));
|
||||
void __delete_from __P((parser_t *, src_list_t *, expr_t *));
|
||||
void __generate_row_delete __P((DBSQL *, vdbe_t *, table_t *, int, int));
|
||||
void __generate_row_index_delete __P((DBSQL *, vdbe_t *, table_t *, int, char *));
|
||||
expr_t *__expr __P((int, expr_t *, expr_t *, token_t *));
|
||||
void __expr_span __P((expr_t *, token_t *, token_t *));
|
||||
expr_t *__expr_function __P((expr_list_t *, token_t *));
|
||||
void __expr_delete __P((expr_t *));
|
||||
expr_t *__expr_dup __P((expr_t *));
|
||||
void __token_copy __P((token_t *, token_t *));
|
||||
expr_list_t *__expr_list_dup __P((expr_list_t *));
|
||||
src_list_t *__src_list_dup __P((src_list_t *));
|
||||
id_list_t *__id_list_dup __P((id_list_t *));
|
||||
select_t *__select_dup __P((select_t *));
|
||||
expr_list_t *__expr_list_append __P((expr_list_t *, expr_t *, token_t *));
|
||||
void __expr_list_delete __P((expr_list_t *));
|
||||
int __expr_is_constant __P((expr_t *));
|
||||
int __expr_is_integer __P((expr_t *, int *));
|
||||
int __is_row_id __P((const char *));
|
||||
int __expr_resolve_ids __P((parser_t *, src_list_t *, expr_list_t *, expr_t *));
|
||||
int __expr_check __P((parser_t *, expr_t *, int, int *));
|
||||
int __expr_type __P((expr_t *));
|
||||
void __expr_code __P((parser_t *, expr_t *));
|
||||
void __expr_if_false __P((parser_t *, expr_t *, int, int));
|
||||
int __expr_compare __P((expr_t *, expr_t *));
|
||||
int __expr_analyze_aggregates __P((parser_t *, expr_t *));
|
||||
func_def_t *__find_function __P((DBSQL *, const char *, int, int, int));
|
||||
void __insert __P((parser_t *, src_list_t *, expr_list_t *, select_t *, id_list_t *, int));
|
||||
void __generate_constraint_checks __P((parser_t *, table_t *, int, char *, int, int, int, int));
|
||||
void __complete_insertion __P((parser_t *, table_t *, int, char *, int, int, int));
|
||||
void __pragma __P((parser_t *, token_t *, token_t *, int));
|
||||
select_t *__select_new __P((expr_list_t *, src_list_t *, expr_t *, expr_list_t *, expr_t *, expr_list_t *, int, int, int));
|
||||
int __join_type __P((parser_t *, token_t *, token_t *, token_t *));
|
||||
void __select_delete __P((select_t *));
|
||||
void __add_key_type __P((vdbe_t *, expr_list_t *));
|
||||
void __select_unbind __P((select_t *));
|
||||
vdbe_t *__parser_get_vdbe __P((parser_t *));
|
||||
int __select __P((parser_t *, select_t *, int, int, select_t *, int, int *));
|
||||
table_t *__select_result_set __P((parser_t *, char *, select_t *));
|
||||
void __vdbe_delete_trigger_step __P((trigger_step_t *));
|
||||
void __begin_trigger __P((parser_t *, token_t *, int, int, id_list_t *, src_list_t *, int, expr_t *, int));
|
||||
void __finish_trigger __P((parser_t *, trigger_step_t *, token_t *));
|
||||
trigger_step_t * __trigger_select_step __P((select_t *));
|
||||
trigger_step_t *__trigger_insert_step __P((token_t *, id_list_t *, expr_list_t *, select_t *, int));
|
||||
trigger_step_t *__trigger_update_step __P((token_t *, expr_list_t *, expr_t *, int));
|
||||
trigger_step_t *__trigger_delete_step __P((token_t *, expr_t *));
|
||||
void __vdbe_delete_trigger __P((trigger_t *));
|
||||
void __drop_trigger __P((parser_t *, src_list_t *));
|
||||
void __drop_trigger_ptr __P((parser_t *, trigger_t *, int));
|
||||
int __triggers_exist __P((parser_t *, trigger_t *, int, int, int, expr_list_t *));
|
||||
int __code_row_trigger __P(());
|
||||
void __update __P((parser_t *, src_list_t *, expr_list_t *, expr_t *, int));
|
||||
void __vacuum __P((parser_t *, token_t *));
|
||||
int __execute_vacuum __P((char **, DBSQL *));
|
||||
int __execute_vacuum __P((char **, DBSQL *));
|
||||
where_info_t *__where_begin __P((parser_t *, src_list_t *, expr_t *, int, expr_list_t **));
|
||||
void __where_end __P((where_info_t *));
|
||||
int __safety_on __P((DBSQL *));
|
||||
int __safety_off __P((DBSQL *));
|
||||
int __safety_check __P((DBSQL *));
|
||||
int __sm_bt_compare __P((DB *, const DBT *, const DBT *));
|
||||
int __sm_create __P((DBSQL *, const char *, int, int, sm_t **));
|
||||
int __sm_close_db __P((sm_t *));
|
||||
int __sm_checkpoint __P((sm_t *));
|
||||
char *__sm_get_database_name __P((sm_t *));
|
||||
int __sm_begin_txn __P((sm_t *));
|
||||
int __sm_commit_txn __P((sm_t *));
|
||||
int __sm_abort_txn __P((sm_t *));
|
||||
int __sm_cursor __P((sm_t *, int, int, sm_cursor_t **));
|
||||
int __sm_close_cursor __P((sm_cursor_t *));
|
||||
int __sm_moveto __P((sm_cursor_t *, const void *, int, int *));
|
||||
int __sm_next __P((sm_cursor_t *, int *));
|
||||
int __sm_prev __P((sm_cursor_t *, int *));
|
||||
int __sm_key_size __P((sm_cursor_t *, int *));
|
||||
int __sm_data_size __P((sm_cursor_t *, int *));
|
||||
int __sm_key_compare __P((sm_cursor_t *, const void *, int, int, int *));
|
||||
size_t __sm_key __P((sm_cursor_t *, size_t, size_t, const void *));
|
||||
size_t __sm_data __P((sm_cursor_t *, size_t, size_t, char *));
|
||||
int __sm_first __P((sm_cursor_t *, int *));
|
||||
int __sm_last __P((sm_cursor_t *, int *));
|
||||
int __sm_insert __P((sm_cursor_t *, const void *, int, const void *, int));
|
||||
int __sm_delete __P((sm_cursor_t *));
|
||||
int __sm_drop_table __P((sm_t *, int));
|
||||
int __sm_clear_table __P((sm_t *, int));
|
||||
int __sm_open_table __P((sm_t *, int *));
|
||||
int __sm_create_table __P((sm_t *, int *));
|
||||
int __sm_create_index __P((sm_t *, int *));
|
||||
int __sm_set_format_version __P((sm_t *, int, u_int32_t));
|
||||
int __sm_get_format_version __P((sm_t *, u_int32_t *));
|
||||
int __sm_set_schema_sig __P((sm_t *, u_int32_t));
|
||||
int __sm_get_schema_sig __P((sm_t *, u_int32_t *));
|
||||
void __register_builtin_funcs __P((DBSQL *));
|
||||
int __get_keyword_code __P((const char *, int));
|
||||
int __run_sql_parser __P((parser_t *, const char *, char **));
|
||||
int __api_step __P((dbsql_stmt_t *, int *, const char ***, const char ***));
|
||||
int __vdbe_exec __P((vdbe_t *));
|
||||
vdbe_t *__vdbe_create __P((DBSQL *));
|
||||
void __vdbe_trace __P((vdbe_t *, FILE *));
|
||||
int __vdbe_add_op __P((vdbe_t *, int, int, int));
|
||||
int __vdbe_make_label __P((vdbe_t *));
|
||||
void __vdbe_resolve_label __P((vdbe_t *, int));
|
||||
int __vdbe_current_addr __P((vdbe_t *));
|
||||
int __vdbe_add_op_list __P((vdbe_t *, int, const vdbe_op_t *));
|
||||
void __vdbe_change_p1 __P((vdbe_t *, int, int));
|
||||
void __vdbe_change_p2 __P((vdbe_t *, int, int));
|
||||
void __vdbe_change_p3 __P((vdbe_t *, int, const char *, int));
|
||||
void __vdbe_dequote_p3 __P((vdbe_t *, int));
|
||||
void __vdbe_compress_space __P((vdbe_t *, int));
|
||||
int __vdbe_find_op __P((vdbe_t *, int, int));
|
||||
vdbe_op_t *__vdbe_get_op __P((vdbe_t *, int));
|
||||
void __vdbe_print_op __P((FILE *, int, vdbe_op_t *));
|
||||
int __vdbe_list __P((vdbe_t *));
|
||||
void __vdbe_make_ready __P((vdbe_t *, int, dbsql_callback, void *, int));
|
||||
void __vdbe_sorter_reset __P((vdbe_t *));
|
||||
void __vdbe_agg_reset __P((agg_t *));
|
||||
void __vdbe_keylist_free __P((keylist_t *));
|
||||
void __vdbe_cleanup_cursor __P((cursor_t *));
|
||||
int __vdbe_reset __P((vdbe_t *, char **));
|
||||
int __vdbe_finalize __P((vdbe_t *, char **));
|
||||
int __api_bind __P((dbsql_stmt_t *, int, const char *, int, int));
|
||||
void __vdbe_delete __P((vdbe_t *));
|
||||
int __vdbe_byte_swap __P((int));
|
||||
int __vdbe_cursor_moveto __P((cursor_t *));
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* !_dbsql_ext_h_ */
|
1023
src/inc/dbsql_int.in
Normal file
1023
src/inc/dbsql_int.in
Normal file
File diff suppressed because it is too large
Load diff
130
src/inc/debug.h
Normal file
130
src/inc/debug.h
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1998-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DBSQL_DEBUG_H_
|
||||
#define _DBSQL_DEBUG_H_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Turn on additional error checking in gcc 3.X.
|
||||
*/
|
||||
#if !defined(__GNUC__) || __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
|
||||
#define __attribute__(s)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* When running with #DIAGNOSTIC defined, we smash memory and do memory
|
||||
* guarding with a special byte value.
|
||||
*/
|
||||
#define CLEAR_BYTE 0xdb
|
||||
#define GUARD_BYTE 0xdc
|
||||
|
||||
/*
|
||||
* DBSQL assertions.
|
||||
*
|
||||
* Use __STDC__ rather than STDC_HEADERS, the #e construct is ANSI C specific.
|
||||
*/
|
||||
#if defined(__STDC__) && defined(DIAGNOSTIC)
|
||||
#define DBSQL_ASSERT(e) ((e) ? (void)0 :__dbsql_assert(#e, __FILE__, __LINE__))
|
||||
#else
|
||||
#define DBSQL_ASSERT(e)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Purposly ignore return value.
|
||||
*/
|
||||
#define IGNORE_RESULT(x) \
|
||||
(void)!(x)
|
||||
|
||||
/*
|
||||
* "Shut that bloody compiler up!"
|
||||
*
|
||||
* Unused, or not-usedyet variable. We need to write and then read the
|
||||
* variable, some compilers are too bloody clever by half.
|
||||
*/
|
||||
#define COMPQUIET(n, v) \
|
||||
(n) = (v); \
|
||||
(n) = (n)
|
||||
|
||||
/*
|
||||
* Purify and other run-time tools complain about uninitialized reads/writes
|
||||
* of structure fields whose only purpose is padding, as well as when heap
|
||||
* memory that was never initialized is written to disk.
|
||||
*/
|
||||
#ifdef UMRW
|
||||
#define UMRW_SET(v) (v) = 0
|
||||
#else
|
||||
#define UMRW_SET(v)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Error message handling. Use a macro instead of a function because va_list
|
||||
* references to variadic arguments cannot be reset to the beginning of the
|
||||
* variadic argument list (and then rescanned), by functions other than the
|
||||
* original routine that took the variadic list of arguments.
|
||||
*/
|
||||
#if defined(STDC_HEADERS) || defined(__cplusplus)
|
||||
#define DBSQL_REAL_ERR(dbp, error, error_set, stderr_default, fmt) { \
|
||||
va_list ap; \
|
||||
\
|
||||
/* Call the user's callback function, if specified. */ \
|
||||
va_start(ap, fmt); \
|
||||
if ((dbp) != NULL && (dbp)->dbsql_errcall != NULL) \
|
||||
__dbsql_errcall(dbp, error, error_set, fmt, ap); \
|
||||
va_end(ap); \
|
||||
\
|
||||
/* Write to the user's file descriptor, if specified. */ \
|
||||
va_start(ap, fmt); \
|
||||
if ((dbp) != NULL && (dbp)->dbsql_errfile != NULL) \
|
||||
__dbsql_errfile(dbp, error, error_set, fmt, ap); \
|
||||
va_end(ap); \
|
||||
\
|
||||
/* \
|
||||
* If we have a default and we didn't do either of the above, \
|
||||
* write to the default. \
|
||||
*/ \
|
||||
va_start(ap, fmt); \
|
||||
if ((stderr_default) && ((dbp) == NULL || \
|
||||
((dbp)->dbsql_errcall == NULL && (dbp)->dbsql_errfile == NULL)))\
|
||||
__dbsql_errfile(dbp, error, error_set, fmt, ap); \
|
||||
va_end(ap); \
|
||||
}
|
||||
#else
|
||||
#define DBSQL_REAL_ERR(dbp, error, error_set, stderr_default, fmt) { \
|
||||
va_list ap; \
|
||||
\
|
||||
/* Call the user's callback function, if specified. */ \
|
||||
va_start(ap); \
|
||||
if ((dbp) != NULL && (dbp)->dbsql_errcall != NULL) \
|
||||
__dbsql_errcall(dbp, error, error_set, fmt, ap); \
|
||||
va_end(ap); \
|
||||
\
|
||||
/* Write to the user's file descriptor, if specified. */ \
|
||||
va_start(ap); \
|
||||
if ((dbp) != NULL && (dbp)->dbsql_errfile != NULL) \
|
||||
__dbsql_errfile(dbp, error, error_set, fmt, ap); \
|
||||
va_end(ap); \
|
||||
\
|
||||
/* \
|
||||
* If we have a default and we didn't do either of the above, \
|
||||
* write to the default. \
|
||||
*/ \
|
||||
va_start(ap); \
|
||||
if ((stderr_default) && ((dbp) == NULL || \
|
||||
((dbp)->dbsql_errcall == NULL && (dbp)->dbsql_errfile == NULL)))\
|
||||
__dbsql_errfile(dbp, error, error_set, fmt, ap); \
|
||||
va_end(ap); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* !_DBSQL_DEBUG_H_ */
|
25
src/inc/globals.h
Normal file
25
src/inc/globals.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
/*******************************************************
|
||||
* Global variables.
|
||||
*
|
||||
* Held in a single structure to minimize the name-space
|
||||
* pollution.
|
||||
*******************************************************/
|
||||
#ifdef HAVE_VXWORKS
|
||||
#include "semLib.h"
|
||||
#endif
|
||||
|
||||
typedef struct __dbsql_globals {
|
||||
const char *encoding;
|
||||
int dbseq_has_wrapped;
|
||||
} DBSQL_GLOBALS;
|
||||
|
||||
extern DBSQL_GLOBALS __dbsql_global_values;
|
||||
|
||||
#define DBSQL_GLOBAL(v) __dbsql_global_values.v
|
189
src/inc/hash.h
Normal file
189
src/inc/hash.h
Normal file
|
@ -0,0 +1,189 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Redistributions in any form must be accompanied by information on
|
||||
* how to obtain complete source code for the DB software and any
|
||||
* accompanying software that uses the DB software. The source code
|
||||
* must either be included in the distribution or be available for no
|
||||
* more than the cost of distribution plus a nominal fee, and must be
|
||||
* freely redistributable under reasonable conditions. For an
|
||||
* executable file, complete source code means the source code for all
|
||||
* modules it contains. It does not include source code for modules or
|
||||
* files that typically accompany the major components of the operating
|
||||
* system on which the executable file runs.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ORACLE CORPORATION ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
||||
* NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL ORACLE CORPORATION
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995
|
||||
*The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1995, 1996
|
||||
*The President and Fellows of Harvard University. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions
|
||||
*/
|
||||
|
||||
#ifndef _DBSQL_HASH_H_
|
||||
#define _DBSQL_HASH_H_
|
||||
|
||||
/*
|
||||
* This is the header file for the generic hash-table implemenation.
|
||||
*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations of structures. */
|
||||
typedef struct __hash hash_t;
|
||||
typedef struct __hash_ele hash_ele_t;
|
||||
|
||||
/*
|
||||
* A complete hash table is an instance of the following structure.
|
||||
* The internals of this structure are intended to be opaque -- client
|
||||
* code should not attempt to access or modify the fields of this structure
|
||||
* directly. Change this structure only by using the routines below.
|
||||
* However, many of the "procedures" and "functions" for modifying and
|
||||
* accessing this structure are really macros, so we can't really make
|
||||
* this structure opaque.
|
||||
*/
|
||||
struct __hash {
|
||||
char keyClass; /* DBSQL_HASH_INT, _POINTER, _STRING, _BINARY */
|
||||
char copyKey; /* True if copy of key made on insert */
|
||||
int count; /* Number of entries in this table */
|
||||
hash_ele_t *first;/* The first element of the array */
|
||||
int htsize; /* Number of buckets in the hash table */
|
||||
struct _ht { /* the hash table */
|
||||
int count; /* Number of entries with this hash */
|
||||
hash_ele_t *chain; /* Pointer to first entry with this hash */
|
||||
} *ht;
|
||||
};
|
||||
|
||||
/*
|
||||
* Each element in the hash table is an instance of the following
|
||||
* structure. All elements are stored on a single doubly-linked list.
|
||||
*
|
||||
* Again, this structure is intended to be opaque, but it can't really
|
||||
* be opaque because it is used by macros.
|
||||
*/
|
||||
struct __hash_ele {
|
||||
hash_ele_t *next, *prev; /* Next and previous elements in the table */
|
||||
void *data; /* Data associated with this element */
|
||||
void *pKey; int nKey; /* Key associated with this element */
|
||||
};
|
||||
|
||||
/*
|
||||
* There are 4 different modes of operation for a hash table:
|
||||
*
|
||||
* DBSQL_HASH_INT nKey is used as the key and pKey is ignored.
|
||||
*
|
||||
* DBSQL_HASH_STRING pKey points to a string that is nKey bytes long
|
||||
* (including the null-terminator, if any). Case
|
||||
* is ignored in comparisons.
|
||||
*
|
||||
* DBSQL_HASH_BINARY pKey points to binary data nKey bytes long.
|
||||
* __os_memcmp() is used to compare keys.
|
||||
*
|
||||
* A copy of the key is made for DBSQL_HASH_STRING and DBSQL_HASH_BINARY
|
||||
* if the copyKey parameter to HashInit is 1.
|
||||
*/
|
||||
#define DBSQL_HASH_INT 1
|
||||
#define DBSQL_HASH_STRING 3
|
||||
#define DBSQL_HASH_BINARY 4
|
||||
|
||||
/*
|
||||
* Macros for looping over all elements of a hash table. The idiom is
|
||||
* like this:
|
||||
*
|
||||
* hash_t h;
|
||||
* hash_ele_t *p;
|
||||
* ...
|
||||
* for(p=__hash_first(&h); p; p=__hash_next(p)){
|
||||
* SomeStructure *pData = __hash_data(p);
|
||||
* // do something with pData
|
||||
* }
|
||||
*/
|
||||
#define __hash_first(H) ((H)->first)
|
||||
#define __hash_next(E) ((E)->next)
|
||||
#define __hash_data(E) ((E)->data)
|
||||
#define __hash_key(E) ((E)->pKey)
|
||||
#define __hash_keysize(E) ((E)->nKey)
|
||||
|
||||
/*
|
||||
* Number of entries in a hash table
|
||||
*/
|
||||
#define __hash_count(H) ((H)->count)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* !_DBSQL_HASH_H_ */
|
15
src/inc/os_ext.h
Normal file
15
src/inc/os_ext.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* DO NOT EDIT: automatically built by dist/s_include. */
|
||||
#ifndef _os_ext_h_
|
||||
#define _os_ext_h_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int __os_jtime __P((double *));
|
||||
void __os_sleep __P((u_long secs, u_long usecs));
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* !_os_ext_h_ */
|
564
src/inc/queue.h
Normal file
564
src/inc/queue.h
Normal file
|
@ -0,0 +1,564 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
||||
* $FreeBSD: src/sys/sys/queue.h,v 1.54 2002/08/05 05:18:43 alfred Exp $
|
||||
*/
|
||||
|
||||
#ifndef _DB_QUEUE_H_
|
||||
#define _DB_QUEUE_H_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This file defines four types of data structures: singly-linked lists,
|
||||
* singly-linked tail queues, lists and tail queues.
|
||||
*
|
||||
* A singly-linked list is headed by a single forward pointer. The elements
|
||||
* are singly linked for minimum space and pointer manipulation overhead at
|
||||
* the expense of O(n) removal for arbitrary elements. New elements can be
|
||||
* added to the list after an existing element or at the head of the list.
|
||||
* Elements being removed from the head of the list should use the explicit
|
||||
* macro for this purpose for optimum efficiency. A singly-linked list may
|
||||
* only be traversed in the forward direction. Singly-linked lists are ideal
|
||||
* for applications with large datasets and few or no removals or for
|
||||
* implementing a LIFO queue.
|
||||
*
|
||||
* A singly-linked tail queue is headed by a pair of pointers, one to the
|
||||
* head of the list and the other to the tail of the list. The elements are
|
||||
* singly linked for minimum space and pointer manipulation overhead at the
|
||||
* expense of O(n) removal for arbitrary elements. New elements can be added
|
||||
* to the list after an existing element, at the head of the list, or at the
|
||||
* end of the list. Elements being removed from the head of the tail queue
|
||||
* should use the explicit macro for this purpose for optimum efficiency.
|
||||
* A singly-linked tail queue may only be traversed in the forward direction.
|
||||
* Singly-linked tail queues are ideal for applications with large datasets
|
||||
* and few or no removals or for implementing a FIFO queue.
|
||||
*
|
||||
* A list is headed by a single forward pointer (or an array of forward
|
||||
* pointers for a hash table header). The elements are doubly linked
|
||||
* so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before
|
||||
* or after an existing element or at the head of the list. A list
|
||||
* may only be traversed in the forward direction.
|
||||
*
|
||||
* A tail queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or
|
||||
* after an existing element, at the head of the list, or at the end of
|
||||
* the list. A tail queue may be traversed in either direction.
|
||||
*
|
||||
* For details on the use of these macros, see the queue(3) manual page.
|
||||
*
|
||||
*
|
||||
* SLIST LIST STAILQ TAILQ
|
||||
* _HEAD + + + +
|
||||
* _HEAD_INITIALIZER + + + +
|
||||
* _ENTRY + + + +
|
||||
* _INIT + + + +
|
||||
* _EMPTY + + + +
|
||||
* _FIRST + + + +
|
||||
* _NEXT + + + +
|
||||
* _PREV - - - +
|
||||
* _LAST - - + +
|
||||
* _FOREACH + + + +
|
||||
* _FOREACH_REVERSE - - - +
|
||||
* _INSERT_HEAD + + + +
|
||||
* _INSERT_BEFORE - + - +
|
||||
* _INSERT_AFTER + + + +
|
||||
* _INSERT_TAIL - - + +
|
||||
* _CONCAT - - + +
|
||||
* _REMOVE_HEAD + - + -
|
||||
* _REMOVE + + + +
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* We #undef all of the macros because there are incompatible versions of this
|
||||
* file and these macros on various systems. What makes the problem worse is
|
||||
* they are included and/or defined by system include files which we may have
|
||||
* already loaded into Berkeley DB before getting here. For example, FreeBSD's
|
||||
* <rpc/rpc.h> includes its system <sys/queue.h>, and VxWorks UnixLib.h defines
|
||||
* several of the LIST_XXX macros. Visual C.NET 7.0 also defines some of these
|
||||
* same macros in Vc7\PlatformSDK\Include\WinNT.h. Make sure we use ours.
|
||||
*/
|
||||
#undef LIST_EMPTY
|
||||
#undef LIST_ENTRY
|
||||
#undef LIST_FIRST
|
||||
#undef LIST_FOREACH
|
||||
#undef LIST_HEAD
|
||||
#undef LIST_HEAD_INITIALIZER
|
||||
#undef LIST_INIT
|
||||
#undef LIST_INSERT_AFTER
|
||||
#undef LIST_INSERT_BEFORE
|
||||
#undef LIST_INSERT_HEAD
|
||||
#undef LIST_NEXT
|
||||
#undef LIST_REMOVE
|
||||
#undef QMD_TRACE_ELEM
|
||||
#undef QMD_TRACE_HEAD
|
||||
#undef QUEUE_MACRO_DEBUG
|
||||
#undef SLIST_EMPTY
|
||||
#undef SLIST_ENTRY
|
||||
#undef SLIST_FIRST
|
||||
#undef SLIST_FOREACH
|
||||
#undef SLIST_FOREACH_PREVPTR
|
||||
#undef SLIST_HEAD
|
||||
#undef SLIST_HEAD_INITIALIZER
|
||||
#undef SLIST_INIT
|
||||
#undef SLIST_INSERT_AFTER
|
||||
#undef SLIST_INSERT_HEAD
|
||||
#undef SLIST_NEXT
|
||||
#undef SLIST_REMOVE
|
||||
#undef SLIST_REMOVE_HEAD
|
||||
#undef STAILQ_CONCAT
|
||||
#undef STAILQ_EMPTY
|
||||
#undef STAILQ_ENTRY
|
||||
#undef STAILQ_FIRST
|
||||
#undef STAILQ_FOREACH
|
||||
#undef STAILQ_HEAD
|
||||
#undef STAILQ_HEAD_INITIALIZER
|
||||
#undef STAILQ_INIT
|
||||
#undef STAILQ_INSERT_AFTER
|
||||
#undef STAILQ_INSERT_HEAD
|
||||
#undef STAILQ_INSERT_TAIL
|
||||
#undef STAILQ_LAST
|
||||
#undef STAILQ_NEXT
|
||||
#undef STAILQ_REMOVE
|
||||
#undef STAILQ_REMOVE_HEAD
|
||||
#undef STAILQ_REMOVE_HEAD_UNTIL
|
||||
#undef TAILQ_CONCAT
|
||||
#undef TAILQ_EMPTY
|
||||
#undef TAILQ_ENTRY
|
||||
#undef TAILQ_FIRST
|
||||
#undef TAILQ_FOREACH
|
||||
#undef TAILQ_FOREACH_REVERSE
|
||||
#undef TAILQ_HEAD
|
||||
#undef TAILQ_HEAD_INITIALIZER
|
||||
#undef TAILQ_INIT
|
||||
#undef TAILQ_INSERT_AFTER
|
||||
#undef TAILQ_INSERT_BEFORE
|
||||
#undef TAILQ_INSERT_HEAD
|
||||
#undef TAILQ_INSERT_TAIL
|
||||
#undef TAILQ_LAST
|
||||
#undef TAILQ_NEXT
|
||||
#undef TAILQ_PREV
|
||||
#undef TAILQ_REMOVE
|
||||
#undef TRACEBUF
|
||||
#undef TRASHIT
|
||||
|
||||
#define QUEUE_MACRO_DEBUG 0
|
||||
#if QUEUE_MACRO_DEBUG
|
||||
/* Store the last 2 places the queue element or head was altered */
|
||||
struct qm_trace {
|
||||
char * lastfile;
|
||||
int lastline;
|
||||
char * prevfile;
|
||||
int prevline;
|
||||
};
|
||||
|
||||
#define TRACEBUF struct qm_trace trace;
|
||||
#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
|
||||
|
||||
#define QMD_TRACE_HEAD(head) do { \
|
||||
(head)->trace.prevline = (head)->trace.lastline; \
|
||||
(head)->trace.prevfile = (head)->trace.lastfile; \
|
||||
(head)->trace.lastline = __LINE__; \
|
||||
(head)->trace.lastfile = __FILE__; \
|
||||
} while (0)
|
||||
|
||||
#define QMD_TRACE_ELEM(elem) do { \
|
||||
(elem)->trace.prevline = (elem)->trace.lastline; \
|
||||
(elem)->trace.prevfile = (elem)->trace.lastfile; \
|
||||
(elem)->trace.lastline = __LINE__; \
|
||||
(elem)->trace.lastfile = __FILE__; \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define QMD_TRACE_ELEM(elem)
|
||||
#define QMD_TRACE_HEAD(head)
|
||||
#define TRACEBUF
|
||||
#define TRASHIT(x)
|
||||
#endif /* QUEUE_MACRO_DEBUG */
|
||||
|
||||
/*
|
||||
* Singly-linked List declarations.
|
||||
*/
|
||||
#define SLIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *slh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define SLIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define SLIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sle_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked List functions.
|
||||
*/
|
||||
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
|
||||
|
||||
#define SLIST_FIRST(head) ((head)->slh_first)
|
||||
|
||||
#define SLIST_FOREACH(var, head, field) \
|
||||
for ((var) = SLIST_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = SLIST_NEXT((var), field))
|
||||
|
||||
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
|
||||
for ((varp) = &SLIST_FIRST((head)); \
|
||||
((var) = *(varp)) != NULL; \
|
||||
(varp) = &SLIST_NEXT((var), field))
|
||||
|
||||
#define SLIST_INIT(head) do { \
|
||||
SLIST_FIRST((head)) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
|
||||
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
|
||||
SLIST_NEXT((slistelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_INSERT_HEAD(head, elm, field) do { \
|
||||
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
|
||||
SLIST_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
||||
|
||||
#define SLIST_REMOVE(head, elm, type, field) do { \
|
||||
if (SLIST_FIRST((head)) == (elm)) { \
|
||||
SLIST_REMOVE_HEAD((head), field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = SLIST_FIRST((head)); \
|
||||
while (SLIST_NEXT(curelm, field) != (elm)) \
|
||||
curelm = SLIST_NEXT(curelm, field); \
|
||||
SLIST_NEXT(curelm, field) = \
|
||||
SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_REMOVE_HEAD(head, field) do { \
|
||||
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue declarations.
|
||||
*/
|
||||
#define STAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *stqh_first;/* first element */ \
|
||||
struct type **stqh_last;/* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define STAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).stqh_first }
|
||||
|
||||
#define STAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *stqe_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue functions.
|
||||
*/
|
||||
#define STAILQ_CONCAT(head1, head2) do { \
|
||||
if (!STAILQ_EMPTY((head2))) { \
|
||||
*(head1)->stqh_last = (head2)->stqh_first; \
|
||||
(head1)->stqh_last = (head2)->stqh_last; \
|
||||
STAILQ_INIT((head2)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
|
||||
|
||||
#define STAILQ_FIRST(head) ((head)->stqh_first)
|
||||
|
||||
#define STAILQ_FOREACH(var, head, field) \
|
||||
for ((var) = STAILQ_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = STAILQ_NEXT((var), field))
|
||||
|
||||
#define STAILQ_INIT(head) do { \
|
||||
STAILQ_FIRST((head)) = NULL; \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
|
||||
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
STAILQ_NEXT((tqelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
STAILQ_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
STAILQ_NEXT((elm), field) = NULL; \
|
||||
*(head)->stqh_last = (elm); \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_LAST(head, type, field) \
|
||||
(STAILQ_EMPTY((head)) ? \
|
||||
NULL : \
|
||||
((struct type *) \
|
||||
((char *)((head)->stqh_last) - __offsetof(struct type, field))))
|
||||
|
||||
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
|
||||
|
||||
#define STAILQ_REMOVE(head, elm, type, field) do { \
|
||||
if (STAILQ_FIRST((head)) == (elm)) { \
|
||||
STAILQ_REMOVE_HEAD((head), field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = STAILQ_FIRST((head)); \
|
||||
while (STAILQ_NEXT(curelm, field) != (elm)) \
|
||||
curelm = STAILQ_NEXT(curelm, field); \
|
||||
if ((STAILQ_NEXT(curelm, field) = \
|
||||
STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
|
||||
(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD(head, field) do { \
|
||||
if ((STAILQ_FIRST((head)) = \
|
||||
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
|
||||
if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* List declarations.
|
||||
*/
|
||||
#define LIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *lh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define LIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define LIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *le_next; /* next element */ \
|
||||
struct type **le_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* List functions.
|
||||
*/
|
||||
|
||||
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
|
||||
|
||||
#define LIST_FIRST(head) ((head)->lh_first)
|
||||
|
||||
#define LIST_FOREACH(var, head, field) \
|
||||
for ((var) = LIST_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = LIST_NEXT((var), field))
|
||||
|
||||
#define LIST_INIT(head) do { \
|
||||
LIST_FIRST((head)) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
|
||||
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
|
||||
LIST_NEXT((listelm), field)->field.le_prev = \
|
||||
&LIST_NEXT((elm), field); \
|
||||
LIST_NEXT((listelm), field) = (elm); \
|
||||
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.le_prev = (listelm)->field.le_prev; \
|
||||
LIST_NEXT((elm), field) = (listelm); \
|
||||
*(listelm)->field.le_prev = (elm); \
|
||||
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
|
||||
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
|
||||
LIST_FIRST((head)) = (elm); \
|
||||
(elm)->field.le_prev = &LIST_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
|
||||
|
||||
#define LIST_REMOVE(elm, field) do { \
|
||||
if (LIST_NEXT((elm), field) != NULL) \
|
||||
LIST_NEXT((elm), field)->field.le_prev = \
|
||||
(elm)->field.le_prev; \
|
||||
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Tail queue declarations.
|
||||
*/
|
||||
#define TAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *tqh_first; /* first element */ \
|
||||
struct type **tqh_last; /* addr of last next element */ \
|
||||
TRACEBUF \
|
||||
}
|
||||
|
||||
#define TAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).tqh_first }
|
||||
|
||||
#define TAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *tqe_next; /* next element */ \
|
||||
struct type **tqe_prev; /* address of previous next element */ \
|
||||
TRACEBUF \
|
||||
}
|
||||
|
||||
/*
|
||||
* Tail queue functions.
|
||||
*/
|
||||
#define TAILQ_CONCAT(head1, head2, field) do { \
|
||||
if (!TAILQ_EMPTY(head2)) { \
|
||||
*(head1)->tqh_last = (head2)->tqh_first; \
|
||||
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
|
||||
(head1)->tqh_last = (head2)->tqh_last; \
|
||||
TAILQ_INIT((head2)); \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
QMD_TRACE_HEAD(head2); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
|
||||
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
|
||||
#define TAILQ_FOREACH(var, head, field) \
|
||||
for ((var) = TAILQ_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = TAILQ_NEXT((var), field))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
|
||||
for ((var) = TAILQ_LAST((head), headname); \
|
||||
(var); \
|
||||
(var) = TAILQ_PREV((var), headname, field))
|
||||
|
||||
#define TAILQ_INIT(head) do { \
|
||||
TAILQ_FIRST((head)) = NULL; \
|
||||
(head)->tqh_last = &TAILQ_FIRST((head)); \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
|
||||
TAILQ_NEXT((elm), field)->field.tqe_prev = \
|
||||
&TAILQ_NEXT((elm), field); \
|
||||
else { \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
} \
|
||||
TAILQ_NEXT((listelm), field) = (elm); \
|
||||
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
QMD_TRACE_ELEM(&listelm->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
||||
TAILQ_NEXT((elm), field) = (listelm); \
|
||||
*(listelm)->field.tqe_prev = (elm); \
|
||||
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
QMD_TRACE_ELEM(&listelm->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
|
||||
TAILQ_FIRST((head))->field.tqe_prev = \
|
||||
&TAILQ_NEXT((elm), field); \
|
||||
else \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
TAILQ_FIRST((head)) = (elm); \
|
||||
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
TAILQ_NEXT((elm), field) = NULL; \
|
||||
(elm)->field.tqe_prev = (head)->tqh_last; \
|
||||
*(head)->tqh_last = (elm); \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_LAST(head, headname) \
|
||||
(*(((struct headname *)((head)->tqh_last))->tqh_last))
|
||||
|
||||
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
|
||||
#define TAILQ_PREV(elm, headname, field) \
|
||||
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
|
||||
|
||||
#define TAILQ_REMOVE(head, elm, field) do { \
|
||||
if ((TAILQ_NEXT((elm), field)) != NULL) \
|
||||
TAILQ_NEXT((elm), field)->field.tqe_prev = \
|
||||
(elm)->field.tqe_prev; \
|
||||
else { \
|
||||
(head)->tqh_last = (elm)->field.tqe_prev; \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
} \
|
||||
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
|
||||
TRASHIT((elm)->field.tqe_next); \
|
||||
TRASHIT((elm)->field.tqe_prev); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
} while (0)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* !_DB_QUEUE_H_ */
|
44
src/inc/random.h
Normal file
44
src/inc/random.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*-
|
||||
* DBSQL - A SQL database engine.
|
||||
*
|
||||
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as it
|
||||
* is applied to this software. View the full text of the exception in file
|
||||
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||
*
|
||||
* This library 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.
|
||||
*/
|
||||
|
||||
#ifndef _LRAND48_R_H_
|
||||
#define _LRAND48_R_H_
|
||||
|
||||
/*
|
||||
* A re-entrant version of a random number generator. This
|
||||
* random number generator is based on the RC4 algorithm.
|
||||
*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SRAND48_R
|
||||
struct drand48_data {
|
||||
int init_p; /* True if initialized */
|
||||
int i, j; /* State variables */
|
||||
int s[256]; /* State variables */
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* !_SRAND48_R_H_ */
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue