Import Tcl 8.6.11

This commit is contained in:
Steve Dower
2021-03-30 00:51:39 +01:00
parent 3bb8e3e086
commit 1aadb2455c
923 changed files with 79104 additions and 62616 deletions

View File

@@ -0,0 +1,600 @@
2015-01-23 Don Porter <dgp@users.sourceforge.net>
* configure.in:
* README: Advanced version number to 1.0.3.
* configure: TEA update; autoconf-2.69.
2014-10-27 Don Porter <dgp@users.sourceforge.net>
* generic/tdbcodbc.c: Used && instead of &.
2014-10-23 Don Porter <dgp@users.sourceforge.net>
* configure.in:
* README: Advanced version number to 1.0.2.
* configure: TEA update; autoconf-2.68.
* doc/*.[3n]: [Bug 00b792] OpenBSD friendly docs.
2014-08-14 Don Porter <dgp@users.sourceforge.net>
* configure.in:
* README: Advanced version number to 1.0.1.
* configure: autoconf-2.68.
2012-12-05 Harald Oehlmann <oehhar@users.sf.net>
* win/makefile.vc: Compiles when bundled and standalone, test fixed.
2012-11-14 Kevin B. Kenny <kennykb@acm.org>
* configure.in: Added code so that `make test` can find an
* Makefile.in: uninstalled `tdbc` and load it from the build
directory.
* configure: autoconf-2.68
*** ADVANCED THE AUTOCONF VERSION IN USE ***
2012-11-08 Don Porter <dgp@users.sourceforge.net>
* configure.in:
* README: Advanced version number to 1.0.0.
* configure: autoconf 2.59
2012-07-26 Jan Nijtmans <jan.nijtmans@gmail.com>
* generic/odbcStubInit.s: Make some tables "const"
* tclconfig/install-sh: Update to latest TEA
* tclconfig/tcl.m4:
* configure: autoconf-2.59
2012-07-13 Kevin B. Kenny <kennykb@acm.org>
* generic/tdbcodbc.c: A user asserts that certain 'output' parameters
to SQLGetData must be initialized. While I have
never seen the failure he reports, initializing
them appears to be Mostly Harmless, so do so.
(Bug [0dda7dbb73]).
2012-07-10 Kevin B. Kenny <kennykb@acm.org>
* generic/tdbcodbc.c: Fixed a non-static table argument to
Tcl_GetIndexFromObjStruct.
2012-06-10 Jan Nijtmans <jan.nijtmans@gmail.com>
* configure.in: make TDBC API functions MODULE_SCOPE
* configure: autoconf-2.59
2012-06-08 Jan Nijtmans <jan.nijtmans@gmail.com>
* tclconfig/ChangeLog:
* tclconfig/tcl.m4: Update to latest TEA
* configure: autoconf-2.59
2012-05-07 Kevin B. Kenny <kennykb@acm.org>
* generic/tdbcodbc.c: Fixed a crash when reporting SQLInstallError
messages. pcbErrorMsg, documented to be
an output parameter, needs to be preinitialized
with the string length.
2011-08-30 Kevin B. Kenny <kennykb@acm.org>
* Makefile.in: Added a 'valgrind-sqlite' rule to allow for
leak testing on Unix.
* generic/odbcStubInit.c:
* generic/tdbcodbc.c: A round of memory leak hunting. In the test
suite, 6 'definitely lost' blocks remain,
all of which at this point appear to be
leaks in dependent libraries. Thanks to
Giorgios Petasis for reporting the presence
of the leaks and diagnosing two of them.
* library/tdbcodbc.tcl: Corrected a typo in 'rename' statements that
caused handles to leak (and potentially caused
user commands to be deleted?)
* tests/all.tcl: Added [rename exit {}] for leak checking.
* tests/tdbcodbc.test: Removed a useless [catch] on a cleanup
operation.
2011-07-19 Kevin B. Kenny <kennykb@acm.org>
* configure.in:
* Makefile.in:
* README: Advanced version number to 1.0b17.
* configure: autoconf 2.59
2011-07-18 Don Porter <dgp@users.sourceforge.net>
* configure.in: Update to latest TEA 3.9 revisions.
* Makefile.in:
* tclconfig/*:
* configure: autoconf-2.59
2011-02-21 Kevin B. Kenny <kennykb@acm.org>
* generic/tdbcodbc.c (GetCell, HasBigintMethod, ResultSetConstructor):
Fix a crash where an error is returned from SQLGetData.
Add a check for whether a connection supports 64-bit integers
before trying to use them to replace NUMERIC or DECIMAL
values. Add a method to determine 64-bit integer support.
(Bug [8766b8dc40].)
* library/tdbcodbc.tcl (tdbc::odbc::connection typemap):
Add to initialization a check for 64-bit integer support
so that the above change works. (Bug [8766b8dc40].)
* tests/tdbcodbc.test:
Code formatting changes to avoid long lines and spurious
semicolons.
2011-02-20 Kevin B, Kenny <kennykb@acm.org>
* tests/tdbcodbc.test (tdbc::odbc-30.[45]):
Added tests for [allrows] and [foreach] on multiple
result sets.
* generic/tdbcodbc.c (ResultSetNextresultsMethod):
* tests/tdbcodbc.test (tdbc::odbc-{30.6,31.1}:
Made 'rowcount' work for multiple result sets. Added a
test for 'rowcount' in multiple result sets, and added
a rudimentary test that stored procedures can be called.
* library/tdbcodbc.tcl (tdbc::odbc::resultset preparecall)
Added a non-executed sketch of how a preparse of
a prepared statement call might go in order to allow
the use of SQLProcedureColumns to determine parameter
directions. (This code may or may not be used; a first
experiment would simply be to make all SP parameters
'inout' and see if that works.)
2011-01-26 Kevin B. Kenny <kennykb@acm.org>
* doc/tdbc_odbc.n:
Added empty comment at the start of each manpage because 'man'
interprets comments there as directives. Thanks to Konstantin
Kohmoutov for reporting and diagnosing this error.
2011-01-22 Kevin B. Kenny <kennykb@acm.org>
* odbcStubDefs.txt: Added SQLMoreResults, needed for multiple result
sets.
* odbcStubInit.c:
* odbcStubs.h: make genstubs
* tdbcodbc.c: Added a 'moreresults' method to the result set object
to allow for SQL statements that return multiple result
sets.
Fixed a resource leak in the case where bad parameters
are supplied to the 'foreignkeys' method.
* tdbcodbc.test: Added tests that the 'moreresults' method works
correctly in the event of 0, 1, and more than one
result set.
2010-09-03 Kevin B. Kenny <kennykb@acm.org>
* tdbcodbc.test: Made tests more portable.
* generic/odbcStubDefs.txt:
* generic/tdbcodbc.c:
* library/tdbcodbc.tcl:
* tests/tdbcodbc.test:
Added the 'primarykeys' and 'foreignkeys' methods,
and the corresponding tests.
* generic/odbcStubInit.c:
* generic/odbcStubs.h:
make genstubs
* configure.in:
* Makefile.in:
* pkgIndex.tcl.in (new file):
* README:
* tclconfig/: Upgraded the build to use TEA 3.9. Changed the
approach to pkgIndex.tcl generation. (It's now built
at configure time, rather than from the Makefile.)
Advanced version number to 1.0b16.
* configure: autoconf 2.59
2010-06-19 Kevin B. Kenny <kennykb@acm.org>
* Makefile.in: Revised the code at the suggestion
* generic/tdbcodbc.c: of Andreas Kupries to avoid using
* tests/all.tcl: 'tcl_findLibrary' and instead execute
* tests/tdbcodbc.test: both 'source' and 'load' commands from
'pkgIndex.tcl'. Revised the 'make test'
rule, and the test scripts, to
test successfully under the new regime.
Thanks to Andreas for providing the
original patch, and to Joe English
for providing ideas for simplifying
and repairing 'make test' under the
new regime.
2010-05-12 Kevin B. Kenny <kennykb@acm.org>
* generic/fakesql.h:
Eliminated uses of INT64 and UINT64 in
favour of Tcl_WideInt and Tcl_WideUInt
respectively. (Avoids a conflict with
INT64 and UINT64 definitions in basetsd.h
on Win64.)
2010-05-10 Kevin B. Kenny <kennykb@acm.org>
* aclocal.m4: Synchronized with the 'tdbc' package.
* configure.in: Advanced release to 1.0b15 and TEA version to 3.7.
Added code to detect VC++ and include the stub
library by path rather than with -L and -l.
* generic/fakesql.h:
Corrected syntax of INSTAPI specifiers.
* generic/odbcStubDefs.txt:
Added a CONVENTION: SQL_API line so that
genExtStubs.tcl can get the syntax right on the
pointer-to-function declarations.
* generic/odbcStubInit.txt:
Corrected syntax of INSTAPI specifiers. Regenerated.
* generic/odbcStubs.h:
Regenerated.
* generic/tdbcodbc.c:
Silenced several VC++ warnings.
* README: Advanced release to 1.0b15.
* tclconfig/: Advanced to TEA 3.7
* configure: autoconf-2.59
2010-05-10 Andreas Kupries <andreask@activestate.com>
* Makefile.in: Removed attempt to generate a stub library. Drivers
do not export stub tables.
2010-04-30 Kevin B. Kenny <kennykb@acm.org>
* Makefile.in: Added missing files to 'make dist.' Added a 'genstubs'
rule to automate building of the Stubs table from the
ODBC library added at run time.
* generic/fakesql.h:
* generic/odbcStubDefs.txt:
* generic/odbcStubInit.c:
Fixed DOS line endings.
2010-04-25 Kevin B. Kenny <kennykb@acm.org>
* configure.in:
* README: Advance version to 1.0b14
* configure: autoconf 2-59
2010-04-10 Kevin B. Kenny <kennykb@acm.org>
* configure.in:
* Makefile.in: Added code to specify to 'make test' and 'make shell'
the value of TDBC_LIBRARY, needed for
[package require tdbc] to work. This library is
either the 'library' subdirectory of the TDBC source
directory (when running from an un-installed TDBC)
or else the TDBC library directory in the installed
Tcl.
* configure: autoconf 2.59
2010-04-08 Kevin B. Kenny <kennykb@acm.org>
* configure.in: Revised TDBC_ names to be tdbc_, because that's
what TEA_LOAD_CONFIG does. Added a check to find 'tdbc.h' in the
build directory if necessary.
* configure: autoconf 2.59.
2010-03-17 Kevin B. Kenny <kennykb@acm.org>
* generic/odbcStubInit.c: Revised TIP 357 API yet again, adding a
'flags' parameter to Tcl_LoadFile.
2010-03-15 Kevin B. Kenny <kennykb@acm.org>
* generic/odbcStubInit.c: Adjusted to revised TIP 357 API.
2010-03-14 Kevin B. Kenny <kennykb@acm.org>
* configure.in: Removed all dependency on the native ODBC headers
and import libraries. All ODBC references are now resolved at
run time and contained in a 'fakesql.h' file. Removed references to
Tk as well.
* configure: autoconf-2.59
* generic/fakesql.h (new file): Added file containing declarations
of all ODBC API's used in this package, to avoid dependence on native
headers.
* generic/odbcStubsDefs.txt (new file): Declarations of functions
imported from odbc32.dll using Tcl_LoadLibrary.
* generic/odbcStubInit.c (new file): Code to load odbc32.dll and
odbccp32.dll and initialize Stubs tables with the routines in them
that are used in tdbc::odbc.
* generic/odbcStubs.h (new file): Generated .h file with the Stubs
structure defined in generic/odbcStubsDefs.txt.
* tdbcodbc.c: Updated to use run-time-loaded ODBC libraries instead
of associating to system headers at compile time and import libraries
at link time. Revised handling of the '-parent' option so that the
dependence on Tk is only at run time.
2009-09-29 Kevin B. Kenny <kennykb@acm.org>
* Makefile.in: Changed 'test' rule to test all available
database types.
* tests/tdbcodbc.test: Changed all TEST_* env vars to TDBCODBC_*
for easier top-level scripting. Clarified
and expanded database type selection.
* generic/tdbcodbc.c: Replaced SQLSetConnectAttr with the obsolete
SQLSetConnectOption, for better compatibility
with older ODBC drivers.
2009-09-20 Kevin B. Kenny <kennykb@acm.org>
* README:
* configure.in: Advance version number to 1.0b13
* configure: autoconf-2.59
2009-07-02 Kevin B. Kenny <kennykb@acm.org>
* Makefile.in: Added testing on SQL Server Express so that
* generic/tdbcodbc.c: more functionality and data types can be
* tests/tdbcodbc.test: exposed. Added code to force column names
in result sets to be unique.
* library/tdbcodbc.tcl: Conditioned use of the IS_NULLABLE hack
on the driver's not returning the NULLABLE
flag in [$db columns]. This conditional
fixes bug 3e523335bb, which fails when
IS_NULLABLE is padded to a fixed length with
spaces.
* README:
* configure.in: Advanced version to 1.0b12
* configure: autoconf-2.59
2009-05-29 Kevin B. Kenny <kennykb@acm.org>
* README:
* configure.in: Advanced version to 1.0b11
* configure: autoconf-2.59
* generic/tdbcodbc.c (GetCell): Corrected a problem where
results longer than the preallocated buffer length had spurious
NULL characters inserted. Corrected a subsequent problem where
BLOBs had *missing* characters. (The ODBC documentation lies about
terminating NULL bytes.)
* tests/tdbcodbc.test (odbc-27.[12]): Corrected a problem where
BLOB and MEMO tests didn't actually test anything.
Thanks to Alan Grunwald for reporting these bugs
2009-04-19 Kevin B. Kenny <kennykb@acm.org>
* doc/tdbc_odbc.n: Added missing documentation for 'new' constructors.
2009-04-18 Kevin B. Kenny <kennykb@acm.org>
* doc/tdbc_odbc.n: Made changes so that NROFF formatting matches
the Tcl standard.
* generic/tdbcodbc.c: Changed so that all variable access failures
are mapped to NULL rather than passing errors
throught the interp.
* tests/tdbcodbc.test: Adjusted test cases for inappropriate access
to array variables.
2009-04-16 Kevin B. Kenny <kennykb@acm.org>
* README:
* configure.in: Advanced version to 1.0b10
* configure: autoconf-2.59
2009-03-03 Kevin B. Kenny <kennykb@acm.org>
* generic/tdbcodbc.c:
* library/tdbcodbc.tcl: Replaced 'my variable' with variables at
class level. Replaced 'init' methods with constructors implemented
in C. Replaced 'statementClass' and 'resultSetClass' variables
with forwarded 'statementCreate' and 'resultSetCreate' methods.
2009-02-16 Kevin B. Kenny <kennykb@acm.org>
* README:
* configure.in: Advanced version to 1.0b9
* configure: autoconf-2.59
* Makefile.in: Removed useless TCL_VERSION_REQ test in the
pkgIndex.tcl.
* generic/tdbcodbc.c (GetCell):
Fixed bad bug in retrieving LONGVARCHAR, LONGVARBINARY,
CLOB, BLOB, etc. (The SQL_NO_TOTAL return was not being
handled, resulting in infinite loops, memory corruption,
or NULLS in place of the actual data.)
* tests/tdbcodbc.test (tdbc::odbc-27.1):
Added a test case for the above bug.
Thanks to Patrick Dunnigan for the bug report.
2009-02-14 Kevin B. Kenny <kennykb@acm.org>
* configure.in:
* README: Advance verwsion to 1.0b8
* configure: autoconf-2.59
* doc/tdbc_odbc.n: Formatting changes so that man2html works.
* tests/tdbcodbc.test (tdbc::odbc-26.1):
Removed superfluous difference between
SQLite and non-SQLite tests - all now
return the same SQLSTATE.
2009-02-01 Kevin B. Kenny <kennykb@acm.org>
* generic/tdbcodbc.c (StatementInitMethod): Corrected a bad check
that caused SQLDescribeParam to be bypassed entirely. Corrected
bad code that was exposed by this fix (SQLDescribeParam failure was
handled incorrectly). Corrected the error code for variables in
native SQL syntax.
* tests/tdbcodbc.test: Corrected error codes for seven tests, to
match the [try]-friendly error code syntax.
2009-01-31 Kevin B. Kenny <kennykb@acm.org>
* README: Advanced version to 1.0b7
* configure.in:
* configure: autoconf 2.59
* generic/tdbcodbc.c: Revised error codes to be more [try]-friendly.
* tests/tdbcodbc.test: Added test cases for revised error codes,
and for an uncovered branch in ODBC statement error handling.
2009-01-05 Kevin B. Kenny <kennykb@acm.org>
* README: Advanced version to 1.0b6
* configure.in:
* configure: autoconf 2.59
2009-01-04 Kevin B. Kenny <kennykb@acm.org>
* README: Advanced version to 1.0b5
* configure.in:
* configure: autoconf 2.59
2008-12-30 Kevin B. Kenny <kennykb@acm.org>
* makefile.in: Changes to make 'make dist' work.
* README: Advanced version to 1.0b4
* configure.in:
* configure: autoconf 2.59
2008-12-18 Kevin B. Kenny <kennykb@acm.org>
* configure: Autoconf 2.59, to conform with Tcl (mandir changes
between 2.59 and 2.61). Signed manifest.
2008-12-08 Kevin B. Kenny <kennykb@acm.org>
* doc/tdbc_odbc.n: Added man page for the driver.
2008-12-07 Kevin B. Kenny <kennykb@acm.org>
* configure.in:
* generic/tdbcodbc.c:
* library/tdbcodbc.tcl: Advanced version to 1.0b1 in preparation for
release, and cleaned up a little bit of dependency management.
* configure: Autoconf 2.61
2008-12-06 Kevin B. Kenny <kennykb@acm.org>
* configure.in:
* generic/tdbcodbc.c: Added the autoconf stuff to support finding
the odbcinst libraries at configuration time.
* configure: Autoconf 2.61
2008-12-05 Kevin B. Kenny <kennykb@acm.org>
* generic/tdbcodbc.c (DatasourceObjCmd):
Added the tdbc::odbc::datasource command for adding, configuring
and removing data sources.
2008-12-04 Kevin B. Kenny <kennykb@acm.org>
* generic/tdbcodc.c (ResultSetInitMethod, GetCell):
* tests/tdbcodbc.test (tdbc::odbc-21.2): Added direct transfer of
BINARY, VARBINARY, LONGVARBINARY parameters and results.
2008-12-03 Kevin B. Kenny <kennykb@acm.org>
* generic/tdbodbc.c: Added "tdbc::odbc::datasources" and
* library/tdbcodbc.tcl: "tdbc::odbc::drivers" for inspection of
* tests/tdbcodbc.test: available databases.
2008-12-01 Kevin B. Kenny <kennykb@acm.org>
* generic/tdbcodbc.c: Added '-encoding' and -timeout' options.
Added direct transfer (rather than stringization) of parameters
of integer and floating point types.
* tests/tdbcodbc.test (tdbc::odbc-19.*): Added rudimentary
configuration tests, and rudimentary tests of direct value
transfers C <-> SQL.
2008-11-30 Kevin B. Kenny <kennykb@acm.org>
* configure.in: Changed PACKAGE_NAME to lowercase 'tdbcodbc'
Changed PACKAGE_VERSION to 0.2a1
* tclconfig/tcl.m4:
Look in a few additional places for dependent packages.
* library/tdbcodbc.tcl: Lowercased the 'tdbc' package and advanced the
version number on which tdbcodbc depends.
Added code to detect whether the connection
supports Unicode.
* generic/tdbcodbc.c: Added '-isolation' and '-readonly' configuration
options. Added code to use Unicode if possible
for columns of unknown type and wide-character
columns. Changed the script-level package name
to tdbc::odbc.
* tests/tdbcodbc.test: Changed the script-level package name to
tdbc::odbc. Renamed all tests accordingly.
* Makefile.in: Changed the script-level package name to tdbc::odbc
for building pkgIndex.tcl
* test.mdb: Reverted a commit that corrupted this file.
2008-11-22 Kevin B. Kenny <kennykb@acm.org>
* configure.in: Changed configurator so that 8.6 no longer requires a
dummy tclooConfig.h.
* configure: Autoconf 2.61
2008-06-15 Kevin B. Kenny <kennykb@acm.org>
* generic/tdbcodbc.c:
* tests/tdbcodbc.test: Removed the default check for Tk. Instead,
added a '-parent window' option to the constructor of
tdbc::odbc::connection that gives a parent window for the
driver manager dialog.
Added a 'configure' method to the connection object, and
rudimentary tests. (No configuration options yet implemented)
2008-06-11 Kevin B. Kenny <kennykb@acm.org>
* generic/tdbcodbc.c: Split [$resultset nextrow] into two primitive
methods: [$resultset nextlist] and [$resultset nextdict]. Refactored
a little bit of the code that handles result sets.
2008-05-24 Kevin B Kenny <kennykb@acm.org>
* configure.in: Changed configuration to use TEA_PATH_CONFIG to
* aclocal.m4: locate tcloo and tdbc. Removed the local code that
did it from aclocal.m4.
* configure: Autoconf 2.61
2008-05-13 Kevin B. Kenny <kennykb@acm.org>
* Makefile (deleted): Removed a superfluous file from an
earlier stage of development.
* generic/tdbcodbc.c (TablesStmtInitMethod,ResultSetNextrowMethod):
Removed a cut-and-paste error in TablesStmtInitMethod that
caused a pointer smash, and added a cast to silence a gcc
warning. Changed the 'init2' method on the 'statement'
class back to 'init' now that TclOO seems to be getting
method resolution correct.
* library/tdbcodbc.tcl (tdbc::sqlite::statement constructor):
Changed the 'init2' method on 'statement' back to
'init' now that TclOO seems to be getting method resolution
correct.
* tests/tdbcodbc.test: Corrected misnumbering of tests, and added
code to remove the test database on startup to avoid running
with old data if a previous test run aborted.
2008-05-10 Kevin B. Kenny <kennykb@acm.org>
* tests/tdbcodbc.test (tdbcodbc-9.9): Corrected invalid test numbering.
2008-05-01 Kevin B. Kenny <kennykb@acm.org>
* tdbcodbc/Makefile.in:
* tdbcodbc/TODO:
* tdbcodbc/aclocal.m4:
* tdbcodbc/configure:
* tdbcodbc/configure.in:
* tdbcodbc/generic/tdbcodbc.c:
* tdbcodbc/library/tdbcodbc.tcl:
* tdbcodbc/tclconfig/ChangeLog:
* tdbcodbc/tclconfig/README.txt:
* tdbcodbc/tclconfig/install-sh:
* tdbcodbc/tclconfig/tcl.m4:
* tdbcodbc/tests/all.tcl:
* tdbcodbc/tests/tdbcodbc.test:
* tdbcodbc/tests/test.mdb:
Initial commit of a 'tdbcodbc' package that provides a reference
implementation of a TDBC driver layered atop ODBC.

View File

@@ -0,0 +1,502 @@
# Makefile.in --
#
# This file is a Makefile for Sample TEA Extension. If it has the name
# "Makefile.in" then it is a template for a Makefile; to generate the
# actual Makefile, run "./configure", which is a configuration script
# generated by the "autoconf" program (constructs like "@foo@" will get
# replaced in the actual Makefile.
#
# Copyright (c) 1999 Scriptics Corporation.
# Copyright (c) 2002-2005 ActiveState Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#========================================================================
# Add additional lines to handle any additional AC_SUBST cases that
# have been added in a customized configure script.
#========================================================================
#SAMPLE_NEW_VAR = @SAMPLE_NEW_VAR@
#========================================================================
# Nothing of the variables below this line should need to be changed.
# Please check the TARGETS section below to make sure the make targets
# are correct.
#========================================================================
#========================================================================
# The names of the source files is defined in the configure script.
# The object files are used for linking into the final library.
# This will be used when a dist target is added to the Makefile.
# It is not important to specify the directory, as long as it is the
# $(srcdir) or in the generic, win or unix subdirectory.
#========================================================================
PKG_SOURCES = @PKG_SOURCES@
PKG_OBJECTS = @PKG_OBJECTS@
PKG_STUB_SOURCES = @PKG_STUB_SOURCES@
PKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@
#========================================================================
# PKG_TCL_SOURCES identifies Tcl runtime files that are associated with
# this package that need to be installed, if any.
#========================================================================
PKG_TCL_SOURCES = @PKG_TCL_SOURCES@
#========================================================================
# This is a list of public header files to be installed, if any.
#========================================================================
PKG_HEADERS = @PKG_HEADERS@
#========================================================================
# "PKG_LIB_FILE" refers to the library (dynamic or static as per
# configuration options) composed of the named objects.
#========================================================================
PKG_LIB_FILE = @PKG_LIB_FILE@
PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@
lib_BINARIES = $(PKG_LIB_FILE)
BINARIES = $(lib_BINARIES)
SHELL = @SHELL@
srcdir = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
libdir = @libdir@
includedir = @includedir@
datarootdir = @datarootdir@
datadir = @datadir@
mandir = @mandir@
DESTDIR =
PKG_DIR = $(PACKAGE_NAME)$(PACKAGE_VERSION)
pkgdatadir = $(datadir)/$(PKG_DIR)
pkglibdir = $(libdir)/$(PKG_DIR)
pkgincludedir = $(includedir)/$(PKG_DIR)
top_builddir = @abs_top_builddir@
INSTALL_OPTIONS =
INSTALL = @INSTALL@ $(INSTALL_OPTIONS)
INSTALL_DATA_DIR = @INSTALL_DATA_DIR@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_LIBRARY = @INSTALL_LIBRARY@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
CC = @CC@
CFLAGS_DEFAULT = @CFLAGS_DEFAULT@
CFLAGS_WARNING = @CFLAGS_WARNING@
EXEEXT = @EXEEXT@
LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@
MAKE_LIB = @MAKE_LIB@
MAKE_SHARED_LIB = @MAKE_SHARED_LIB@
MAKE_STATIC_LIB = @MAKE_STATIC_LIB@
MAKE_STUB_LIB = @MAKE_STUB_LIB@
OBJEXT = @OBJEXT@
RANLIB = @RANLIB@
RANLIB_STUB = @RANLIB_STUB@
SHLIB_CFLAGS = @SHLIB_CFLAGS@
SHLIB_LD = @SHLIB_LD@
SHLIB_LD_LIBS = @SHLIB_LD_LIBS@
STLIB_LD = @STLIB_LD@
#TCL_DEFS = @TCL_DEFS@
TCL_BIN_DIR = @TCL_BIN_DIR@
TCL_SRC_DIR = @TCL_SRC_DIR@
#TK_BIN_DIR = @TK_BIN_DIR@
#TK_SRC_DIR = @TK_SRC_DIR@
TDBC_VERSION = @TDBC_VERSION@
TDBC_SRC_DIR = @tdbc_SRC_DIR@
TDBC_BIN_DIR = @tdbc_BIN_DIR@
TDBC_LIB_FILE = @TDBC_LIB_FILE@
# Not used, but retained for reference of what libs Tcl required
#TCL_LIBS = @TCL_LIBS@
#========================================================================
# TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our
# package without installing. The other environment variables allow us
# to test against an uninstalled Tcl. Add special env vars that you
# require for testing here (like TCLX_LIBRARY).
#========================================================================
EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR)
#EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR)
TCLLIBPATH = $(top_builddir) $(TDBC_BIN_DIR)
TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library`
PKG_ENV = @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \
PATH="$(EXTRA_PATH):$(PATH)" \
TDBCODBC_LIBRARY=`@CYGPATH@ $(srcdir)/library` \
TDBC_LIBRARY=`@CYGPATH@ @tdbc_LIBRARY_PATH@` \
TCLLIBPATH="$(TCLLIBPATH)"
TCLSH_PROG = @TCLSH_PROG@
TCLSH = $(TCLSH_ENV) $(PKG_ENV) $(TCLSH_PROG)
#WISH_ENV = TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library`
#WISH_PROG = @WISH_PROG@
#WISH = $(TCLSH_ENV) $(WISH_ENV) $(PKG_ENV) $(WISH_PROG)
SHARED_BUILD = @SHARED_BUILD@
INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@
#INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@
PKG_CFLAGS = @PKG_CFLAGS@
# TCL_DEFS is not strictly need here, but if you remove it, then you
# must make sure that configure.ac checks for the necessary components
# that your library may use. TCL_DEFS can actually be a problem if
# you do not compile with a similar machine setup as the Tcl core was
# compiled with.
#DEFS = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS)
DEFS = @DEFS@ $(PKG_CFLAGS)
# Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile
CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl tdbcConfig.sh
CLEANFILES = @CLEANFILES@
CPPFLAGS = @CPPFLAGS@
LIBS = @PKG_LIBS@ @LIBS@
AR = @AR@
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
GDB = gdb
VALGRIND = valgrind
VALGRINDARGS = --tool=memcheck --num-callers=16 --leak-resolution=high \
--leak-check=yes --show-reachable=yes -v
.SUFFIXES: .c .$(OBJEXT)
#========================================================================
# Start of user-definable TARGETS section
#========================================================================
#========================================================================
# TEA TARGETS. Please note that the "libraries:" target refers to platform
# independent files, and the "binaries:" target includes executable programs and
# platform-dependent libraries. Modify these targets so that they install
# the various pieces of your package. The make and install rules
# for the BINARIES that you specified above have already been done.
#========================================================================
all: binaries libraries doc
#========================================================================
# The binaries target builds executable programs, Windows .dll's, unix
# shared/static libraries, and any other platform-dependent files.
# The list of targets to build for "binaries:" is specified at the top
# of the Makefile, in the "BINARIES" variable.
#========================================================================
binaries: $(BINARIES)
libraries:
#========================================================================
# Your doc target should differentiate from doc builds (by the developer)
# and doc installs (see install-doc), which just install the docs on the
# end user machine when building from source.
#========================================================================
doc:
install: all install-binaries install-libraries install-doc
install-binaries: binaries install-lib-binaries install-bin-binaries
#========================================================================
# This rule installs platform-independent files, such as header files.
# The list=...; for p in $$list handles the empty list case x-platform.
#========================================================================
install-libraries: libraries
@$(INSTALL_DATA_DIR) $(DESTDIR)$(includedir)
@echo "Installing header files in $(DESTDIR)$(includedir)"
@list='$(PKG_HEADERS)'; for i in $$list; do \
echo "Installing $(srcdir)/$$i" ; \
$(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir) ; \
done;
#========================================================================
# Install documentation. Unix manpages should go in the $(mandir)
# directory.
#========================================================================
install-doc: doc
@$(INSTALL_DATA_DIR) $(DESTDIR)$(mandir)/mann
@echo "Installing documentation in $(DESTDIR)$(mandir)"
@list='$(srcdir)/doc/*.n'; for i in $$list; do \
echo "Installing $$i"; \
$(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \
done
test: test-jet test-sqlserver test-sqlite
test-jet: binaries libraries
@echo testing tdbcodbc against Jet
TDBCODBC_TEST_TYPE=jet \
$(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) \
-load "package ifneeded tdbc::odbc $(PACKAGE_VERSION) \
[list source `@CYGPATH@ $(srcdir)/library/tdbcodbc.tcl`]\;[list load `@CYGPATH@ $(PKG_LIB_FILE)` $(PACKAGE_NAME)]"
test-sqlserver: binaries libraries
@echo testing tdbcodbc against SQL Server
TDBCODBC_TEST_TYPE=sqlserver \
$(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) \
-load "package ifneeded tdbc::odbc ${PACKAGE_VERSION} \
[list source `@CYGPATH@ $(srcdir)/library/tdbcodbc.tcl`]\;[list load `@CYGPATH@ $(PKG_LIB_FILE)` $(PACKAGE_NAME)]"
test-sqlite: binaries libraries
@echo testing tdbcodbc against SQLite
TDBCODBC_TEST_TYPE=sqlite \
$(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) \
-load "package ifneeded tdbc::odbc ${PACKAGE_VERSION} \
[list source `@CYGPATH@ $(srcdir)/library/tdbcodbc.tcl`]\;[list load `@CYGPATH@ $(PKG_LIB_FILE)` $(PACKAGE_NAME)]"
valgrind-sqlite: binaries libraries
TDBCODBC_TEST_TYPE=sqlite \
$(PKG_ENV) $(TCLSH_ENV) \
LD_PRELOAD=$(PKG_LIB_FILE) \
$(VALGRIND) $(VALGRINDARGS) \
$(TCLSH_PROG) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) \
-load "package ifneeded tdbc::odbc ${PACKAGE_VERSION} \
[list source `@CYGPATH@ $(srcdir)/library/tdbcodbc.tcl`]\;[list load `@CYGPATH@ $(PKG_LIB_FILE)` $(PACKAGE_NAME)]"
shell: binaries libraries
@$(TCLSH) $(SCRIPT)
gdb:
$(TCLSH_ENV) $(PKG_ENV) $(GDB) $(TCLSH_PROG) $(SCRIPT)
depend:
#========================================================================
# $(PKG_LIB_FILE) should be listed as part of the BINARIES variable
# mentioned above. That will ensure that this target is built when you
# run "make binaries".
#
# The $(PKG_OBJECTS) objects are created and linked into the final
# library. In most cases these object files will correspond to the
# source files above.
#========================================================================
$(PKG_LIB_FILE): $(PKG_OBJECTS)
-rm -f $(PKG_LIB_FILE)
${MAKE_LIB}
$(RANLIB) $(PKG_LIB_FILE)
$(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS)
-rm -f $(PKG_STUB_LIB_FILE)
${MAKE_STUB_LIB}
$(RANLIB_STUB) $(PKG_STUB_LIB_FILE)
#========================================================================
# We need to enumerate the list of .c to .o lines here.
#
# In the following lines, $(srcdir) refers to the toplevel directory
# containing your extension. If your sources are in a subdirectory,
# you will have to modify the paths to reflect this:
#
# sample.$(OBJEXT): $(srcdir)/generic/sample.c
# $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@
#
# Setting the VPATH variable to a list of paths will cause the makefile
# to look into these paths when resolving .c to .obj dependencies.
# As necessary, add $(srcdir):$(srcdir)/compat:....
#========================================================================
VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win
.c.@OBJEXT@:
$(COMPILE) -c `@CYGPATH@ $<` -o $@
#========================================================================
# Distribution creation
# You may need to tweak this target to make it work correctly.
#========================================================================
#COMPRESS = tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar
COMPRESS = tar zcvf $(PKG_DIR).tar.gz $(PKG_DIR)
DIST_ROOT = /tmp/dist
DIST_DIR = $(DIST_ROOT)/$(PKG_DIR)
DIST_INSTALL_DATA = CPPROG='cp -p' $(INSTALL) -m 644
DIST_INSTALL_SCRIPT = CPPROG='cp -p' $(INSTALL) -m 755
dist-clean:
rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.*
dist: dist-clean
$(INSTALL_DATA_DIR) $(DIST_DIR)
# TEA files
$(DIST_INSTALL_DATA) $(srcdir)/Makefile.in \
$(srcdir)/aclocal.m4 $(srcdir)/configure.ac \
$(DIST_DIR)/
$(DIST_INSTALL_SCRIPT) $(srcdir)/configure $(DIST_DIR)/
$(INSTALL_DATA_DIR) $(DIST_DIR)/tclconfig
$(DIST_INSTALL_DATA) $(srcdir)/tclconfig/README.txt \
$(srcdir)/tclconfig/tcl.m4 $(srcdir)/tclconfig/install-sh \
$(DIST_DIR)/tclconfig/
# Extension files
$(DIST_INSTALL_DATA) \
$(srcdir)/ChangeLog \
$(srcdir)/license.terms \
$(srcdir)/README \
$(srcdir)/pkgIndex.tcl.in \
$(DIST_DIR)/
$(INSTALL_DATA_DIR) $(DIST_DIR)/doc
$(DIST_INSTALL_DATA) $(srcdir)/doc/tdbc_odbc.n $(DIST_DIR)/doc/
$(INSTALL_DATA_DIR) $(DIST_DIR)/generic
$(DIST_INSTALL_DATA) \
$(srcdir)/generic/fakesql.h $(srcdir)/generic/odbcStubDefs.txt \
$(srcdir)/generic/odbcStubInit.c $(srcdir)/generic/odbcStubs.h \
$(srcdir)/generic/tdbcodbc.c \
$(srcdir)/generic/int2ptr_ptr2int.h \
$(DIST_DIR)/generic/
$(INSTALL_DATA_DIR) $(DIST_DIR)/library
$(DIST_INSTALL_DATA) $(srcdir)/library/tdbcodbc.tcl $(DIST_DIR)/library/
$(INSTALL_DATA_DIR) $(DIST_DIR)/tests
$(DIST_INSTALL_DATA) $(srcdir)/tests/all.tcl $(srcdir)/tests/tdbcodbc.test \
$(srcdir)/tests/test.mdb \
$(DIST_DIR)/tests/
$(INSTALL_DATA_DIR) $(DIST_DIR)/win
$(DIST_INSTALL_DATA) $(srcdir)/win/makefile.vc $(srcdir)/win/nmakehlp.c \
$(srcdir)/win/targets.vc $(srcdir)/win/rules-ext.vc \
$(srcdir)/win/rules.vc $(DIST_DIR)/win/
(cd $(DIST_ROOT); $(COMPRESS);)
#========================================================================
# How to rebuild the package's stub table.
#========================================================================
genstubs: $(TDBC_SRC_DIR)/tools/genExtStubs.tcl $(srcdir)/generic/odbcStubDefs.txt
@echo $(TCLSH_PROGRAM) $(TDBC_SRC_DIR)/tools/genExtStubs.tcl \
$(srcdir)/generic/odbcStubDefs.txt \
$(srcdir)/generic/odbcStubs.h \
$(srcdir)/generic/odbcStubInit.c
@$(TCLSH) $(TDBC_SRC_DIR)/tools/genExtStubs.tcl \
$(srcdir)/generic/odbcStubDefs.txt \
$(srcdir)/generic/odbcStubs.h \
$(srcdir)/generic/odbcStubInit.c
#========================================================================
# End of user-definable section
#========================================================================
#========================================================================
# Don't modify the file to clean here. Instead, set the "CLEANFILES"
# variable in configure.ac
#========================================================================
clean:
-test -z "$(BINARIES)" || rm -f $(BINARIES)
-rm -f *.$(OBJEXT) core *.core
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean: clean
-rm -f *.tab.c
-rm -f $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log config.status
#========================================================================
# Install binary object libraries. On Windows this includes both .dll and
# .lib files. Because the .lib files are not explicitly listed anywhere,
# we need to deduce their existence from the .dll file of the same name.
# Library files go into the lib directory.
# In addition, this will generate the pkgIndex.tcl
# file in the install location (assuming it can find a usable tclsh shell)
#
# You should not have to modify this target.
#========================================================================
install-lib-binaries: binaries
@$(INSTALL_DATA_DIR) $(DESTDIR)$(pkglibdir)
@list='$(lib_BINARIES)'; for p in $$list; do \
if test -f $$p; then \
echo " $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p"; \
$(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p; \
ext=`echo $$p|sed -e "s/.*\.//"`; \
if test "x$$ext" = "xdll"; then \
lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \
if test -f $$lib; then \
echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \
$(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \
fi; \
fi; \
fi; \
done
@list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
if test -f $(srcdir)/$$p; then \
destp=`basename $$p`; \
echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \
$(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \
fi; \
done
@if test "x$(SHARED_BUILD)" = "x1"; then \
echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \
$(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir); \
fi
#========================================================================
# Install binary executables (e.g. .exe files and dependent .dll files)
# This is for files that must go in the bin directory (located next to
# wish and tclsh), like dependent .dll files on Windows.
#
# You should not have to modify this target, except to define bin_BINARIES
# above if necessary.
#========================================================================
install-bin-binaries: binaries
@$(INSTALL_DATA_DIR) $(DESTDIR)$(bindir)
@list='$(bin_BINARIES)'; for p in $$list; do \
if test -f $$p; then \
echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \
fi; \
done
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
uninstall-binaries:
list='$(lib_BINARIES)'; for p in $$list; do \
rm -f $(DESTDIR)$(pkglibdir)/$$p; \
done
list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
p=`basename $$p`; \
rm -f $(DESTDIR)$(pkglibdir)/$$p; \
done
list='$(bin_BINARIES)'; for p in $$list; do \
rm -f $(DESTDIR)$(bindir)/$$p; \
done
.PHONY: all binaries clean depend distclean doc install libraries test
.PHONY: gdb
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

38
pkgs/tdbcodbc1.1.2/README Normal file
View File

@@ -0,0 +1,38 @@
README: tdbcodbc
This is the 1.1.2 source distribution of the bridge between Tcl
Database Connectivity (TDBC) and Open Database Connectivity
(ODBC), a database-neutral API layer available on all Windows
systems and many others.. TDBC and its drivers are available from
a Fossil version control repository at http://tdbc.tcl.tk/
RCS: @(#) $Id: $
1. Introduction
This directory contains the source code, documentation, and test
scripts for the ODBC driver for Tcl Database Connectivity. This
module, plus TDBC itself, allow you to access ODBC databases using a
standard application programming interface (API) from a Tcl script.
This module is also available from http://tdbc.tcl.tk along with the
source code of TDBC itself. A bug database and Wiki are available at
the same location.
Tdbc::odbc is a freely-available open source package. You can do
virtually anything you like with it, such as modifying it,
redistributing it, and selling it either in whole or in part. See the
file "license.terms" for complete information.
2. Documentation
The 'doc' subdirectory in this release contains a set of reference
manual entries for tdbc::odbc. Files with an extension '.n' are for
Tcl classes and commands; files with an extension '.3' are for C
library functions. The file, 'doc/tdbcodbc.n' gives an overview,
listing the classes and functions
3. See also
More information about TDBC and its drivers are available in the
README file for TDBC itself; refer to that file for compilation and
installation instructions, and support information.

86
pkgs/tdbcodbc1.1.2/aclocal.m4 vendored Normal file
View File

@@ -0,0 +1,86 @@
#
# Include the TEA standard macro set
#
builtin(include,tclconfig/tcl.m4)
#
# Add here whatever m4 macros you want to define for your package
#
dnl Helper macros
AC_DEFUN([TEAX_LAPPEND], [$1="[$]{$1} $2"])
AC_DEFUN([TEAX_FOREACH], [for $1 in $2; do $3; done])
AC_DEFUN([TEAX_IFEQ], [AS_IF([test "x$1" = "x$2"], [$3])])
AC_DEFUN([TEAX_IFNEQ], [AS_IF([test "x$1" != "x$2"], [$3])])
AC_DEFUN([TEAX_SWITCH], [case "$1" in TEAX_SWITCH_Cases(m4_shift($@)) esac])
AC_DEFUN([TEAX_SWITCH_Cases], [m4_if([$#],0,,[$#],1,,[TEAX_SWITCH_OneCase($1,$2)TEAX_SWITCH_Cases(m4_shift(m4_shift($@)))])])
AC_DEFUN([TEAX_SWITCH_OneCase],[ $1) $2;;])
AC_DEFUN([CygPath],[`${CYGPATH} $1`])
dnl Interesting macros
AC_DEFUN([TEAX_SUBST_RESOURCE], [
AC_REQUIRE([TEA_CONFIG_CFLAGS])dnl
TEAX_IFEQ($TEA_PLATFORM, windows, [
AC_CHECK_PROGS(RC_, 'windres -o' 'rc -nologo -fo', none)
TEAX_SWITCH($RC_,
windres*, [
rcdef_inc="--include "
rcdef_start="--define "
rcdef_q='\"'
AC_SUBST(RES_SUFFIX, [res.o])
TEAX_LAPPEND(PKG_OBJECTS, ${PACKAGE_NAME}.res.o)],
rc*, [
rcdef_inc="-i "
rcdef_start="-d "
rcdef_q='"'
AC_SUBST(RES_SUFFIX, [res])
TEAX_LAPPEND(PKG_OBJECTS, ${PACKAGE_NAME}.res)],
*, [
AC_MSG_WARN([could not find resource compiler])
RC_=: ])])
# This next line is because of the brokenness of TEA...
AC_SUBST(RC, $RC_)
TEAX_FOREACH(i, $1, [
TEAX_LAPPEND(RES_DEFS, ${rcdef_inc}\"CygPath($i)\")])
TEAX_FOREACH(i, $2, [
TEAX_LAPPEND(RES_DEFS, ${rcdef_start}$i='${rcdef_q}\$($i)${rcdef_q}')])
AC_SUBST(RES_DEFS)])
AC_DEFUN([TEAX_ADD_PRIVATE_HEADERS], [
TEAX_FOREACH(i, $@, [
# check for existence, be strict because it should be present!
AS_IF([test ! -f "${srcdir}/$i"], [
AC_MSG_ERROR([could not find header file '${srcdir}/$i'])])
TEAX_LAPPEND(PKG_PRIVATE_HEADERS, $i)])
AC_SUBST(PKG_PRIVATE_HEADERS)])
AC_DEFUN([TEAX_SDX], [
AC_PATH_PROG(SDX, sdx, none)
TEAX_IFEQ($SDX, none, [
AC_PATH_PROG(SDX_KIT, sdx.kit, none)
TEAX_IFNEQ($SDX_KIT, none, [
# We assume that sdx.kit is on the path, and that the default
# tclsh is activetcl
SDX="tclsh '${SDX_KIT}'"])])
TEAX_IFEQ($SDX, none, [
AC_MSG_WARN([cannot find sdx; building starkits will fail])
AC_MSG_NOTICE([building as a normal library still supported])])])
dnl TODO: Adapt this for OSX Frameworks...
dnl This next bit is a bit ugly, but it makes things for tclooConfig.sh...
AC_DEFUN([TEAX_PATH_LINE], [
eval "$1=\"[]CygPath($2)\""
AC_SUBST($1)])
AC_DEFUN([TEAX_INCLUDE_LINE], [
eval "$1=\"-I[]CygPath($2)\""
AC_SUBST($1)])
AC_DEFUN([TEAX_LINK_LINE], [
AS_IF([test ${TCL_LIB_VERSIONS_OK} = nodots], [
eval "$1=\"-L[]CygPath($2) -l$3${TCL_TRIM_DOTS}\""
], [
eval "$1=\"-L[]CygPath($2) -l$3${PACKAGE_VERSION}\""
])
AC_SUBST($1)])
dnl Local Variables:
dnl mode: autoconf
dnl End:

10126
pkgs/tdbcodbc1.1.2/configure vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,246 @@
#!/bin/bash -norc
dnl This file is an input file used by the GNU "autoconf" program to
dnl generate the file "configure", which is run during Tcl installation
dnl to configure the system for the local environment.
#-----------------------------------------------------------------------
# Sample configure.ac for Tcl Extensions. The only places you should
# need to modify this file are marked by the string __CHANGE__
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
# __CHANGE__
# Set your package name and version numbers here.
#
# This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION
# set as provided. These will also be added as -D defs in your Makefile
# so you can encode the package version directly into the source files.
# This will also define a special symbol for Windows (BUILD_<PACKAGE_NAME>
# so that we create the export library with the dll.
#-----------------------------------------------------------------------
AC_INIT([tdbcodbc], [1.1.2])
#--------------------------------------------------------------------
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
# This will define a ${TEA_PLATFORM} variable == "unix" or "windows"
# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE.
#--------------------------------------------------------------------
TEA_INIT()
AC_CONFIG_AUX_DIR(tclconfig)
#--------------------------------------------------------------------
# Load the tclConfig.sh file
#--------------------------------------------------------------------
TEA_PATH_TCLCONFIG
TEA_LOAD_TCLCONFIG
#--------------------------------------------------------------------
# Load the tkConfig.sh file if necessary (Tk extension)
#--------------------------------------------------------------------
#TEA_PATH_TKCONFIG
#TEA_LOAD_TKCONFIG
#--------------------------------------------------------------------
# Load the tclooConfig.sh file on Tcl versions where oo is an
# extension.
#--------------------------------------------------------------------
if test "${TCL_MAJOR_VERSION}" -lt 8 ; then
AC_MSG_ERROR([${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 8.6 or newer.
Found configuration for Tcl ${TCL_VERSION}.])
fi
if test "${TCL_MAJOR_VERSION}" -eq 8 ; then
if test "${TCL_MINOR_VERSION}" -lt 6 ; then
AC_MSG_ERROR([${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 8.6 or newer.
Found configuration for Tcl ${TCL_VERSION}.])
fi
TCLOO_CFLAGS=''
fi
TCL_VERSION_REQ=8.6; AC_SUBST(TCL_VERSION_REQ)
TEA_PATH_CONFIG(tdbc)
TEA_LOAD_CONFIG(tdbc)
# The next bit probably ought to be in TEA_LOAD_CONFIG
AC_MSG_WARN([Looking for "${tdbc_BIN_DIR}/Makefile"])
if test -f "${tdbc_BIN_DIR}/Makefile" ; then
AC_MSG_WARN([Found Makefile - using build include spec and lib specs for tdbc])
tdbc_INCLUDE_SPEC=${tdbc_BUILD_INCLUDE_SPEC}
tdbc_LIBRARY_PATH=${tdbc_BUILD_LIBRARY_PATH}
fi
AC_SUBST(tdbc_LIBRARY_PATH)
AC_SUBST(TDBC_VERSION)
AC_SUBST(tdbc_SRC_DIR)
AC_SUBST(tdbc_BIN_DIR)
AC_SUBST(TDBC_LIB_FILE)
#-----------------------------------------------------------------------
# Handle the --prefix=... option by defaulting to what Tcl gave.
# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER.
#-----------------------------------------------------------------------
TEA_PREFIX
#-----------------------------------------------------------------------
# Standard compiler checks.
# This sets up CC by using the CC env var, or looks for gcc otherwise.
# This also calls AC_PROG_CC and a few others to create the basic setup
# necessary to compile executables.
#-----------------------------------------------------------------------
TEA_SETUP_COMPILER
#-----------------------------------------------------------------------
# Setup inlining if available. Check sizeof long long.
#-----------------------------------------------------------------------
AC_C_INLINE
AC_CHECK_TYPE([long long],[
AC_DEFINE([HAVE_LONG_LONG],[1])
AC_CHECK_SIZEOF([long long])
],[],[])
AC_CHECK_SIZEOF([long])
#-----------------------------------------------------------------------
# __CHANGE__
# Specify the C source files to compile in TEA_ADD_SOURCES,
# public headers that need to be installed in TEA_ADD_HEADERS,
# stub library C source files to compile in TEA_ADD_STUB_SOURCES,
# and runtime Tcl library files in TEA_ADD_TCL_SOURCES.
# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS
# and PKG_TCL_SOURCES.
#-----------------------------------------------------------------------
TEA_ADD_SOURCES(generic/tdbcodbc.c generic/odbcStubInit.c)
TEA_ADD_HEADERS(generic/fakesql.h generic/odbcStubs.h)
if test "${TCL_MAJOR_VERSION}" -eq 8 ; then
if test "${TCL_MINOR_VERSION}" -eq 5 ; then
TEA_ADD_INCLUDES([${TCLOO_INCLUDE_SPEC}])
TEA_ADD_LIBS([${TCLOO_STUB_LIB_SPEC}])
fi
fi
TEA_ADD_CFLAGS([${TCLOO_CFLAGS}])
TEA_ADD_INCLUDES([${tdbc_INCLUDE_SPEC}])
if test "x${TEA_PLATFORM}" = "xwindows" -a "x${GCC}" != "xyes" ; then
TEA_ADD_LIBS([\"`${CYGPATH} ${tdbc_STUB_LIB_PATH}`\"])
else
TEA_ADD_LIBS([${tdbc_STUB_LIB_SPEC}])
fi
TEA_ADD_CFLAGS([${tdbc_CFLAGS}])
TEA_ADD_STUB_SOURCES()
TEA_ADD_TCL_SOURCES([library/tdbcodbc.tcl])
#--------------------------------------------------------------------
# __CHANGE__
#
# You can add more files to clean if your extension creates any extra
# files by extending CLEANFILES.
# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure
# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var.
#
# A few miscellaneous platform-specific items:
# TEA_ADD_* any platform specific compiler/build info here.
#--------------------------------------------------------------------
#CLEANFILES="$CLEANFILES pkgIndex.tcl"
if test "${TEA_PLATFORM}" = "windows" ; then
# Ensure no empty if clauses
:
#TEA_ADD_SOURCES([win/winFile.c])
#TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"])
else
# Ensure no empty else clauses
:
#TEA_ADD_SOURCES([unix/unixFile.c])
#TEA_ADD_LIBS([-lsuperfly])
fi
#--------------------------------------------------------------------
# __CHANGE__
# Choose which headers you need. Extension authors should try very
# hard to only rely on the Tcl public header files. Internal headers
# contain private data structures and are subject to change without
# notice.
# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG
#--------------------------------------------------------------------
TEA_PUBLIC_TCL_HEADERS
#TEA_PRIVATE_TCL_HEADERS
#TEA_PUBLIC_TK_HEADERS
#TEA_PRIVATE_TK_HEADERS
#TEA_PATH_X
#--------------------------------------------------------------------
# Check whether --enable-threads or --disable-threads was given.
# This auto-enables if Tcl was compiled threaded.
#--------------------------------------------------------------------
TEA_ENABLE_THREADS
#--------------------------------------------------------------------
# The statement below defines a collection of symbols related to
# building as a shared library instead of a static library.
#--------------------------------------------------------------------
TEA_ENABLE_SHARED
#--------------------------------------------------------------------
# This macro figures out what flags to use with the compiler/linker
# when building shared/static debug/optimized objects. This information
# can be taken from the tclConfig.sh file, but this figures it all out.
#--------------------------------------------------------------------
TEA_CONFIG_CFLAGS
#--------------------------------------------------------------------
# Set the default compiler switches based on the --enable-symbols option.
#--------------------------------------------------------------------
TEA_ENABLE_SYMBOLS
#--------------------------------------------------------------------
# Integer pointer types used by the (U)INT2PTR / PTR2(U)INT macros.
#--------------------------------------------------------------------
AC_TYPE_INTPTR_T
AC_TYPE_UINTPTR_T
#--------------------------------------------------------------------
# Locate the ws2_32 library; we need it for ntohs and friends
#--------------------------------------------------------------------
AC_CHECK_LIB(ws2_32,main,TEA_ADD_LIBS([-lws2_32]),[
AC_CHECK_LIB(winsock,main,TEA_ADD_LIBS([-lwinsock]))
])
#--------------------------------------------------------------------
# This macro generates a line to use when building a library. It
# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS,
# and TEA_LOAD_TCLCONFIG macros above.
#--------------------------------------------------------------------
TEA_MAKE_LIB
#--------------------------------------------------------------------
# Determine the name of the tclsh and/or wish executables in the
# Tcl and Tk build directories or the location they were installed
# into. These paths are used to support running test cases only,
# the Makefile should not be making use of these paths to generate
# a pkgIndex.tcl file or anything else at extension build time.
#--------------------------------------------------------------------
TEA_PROG_TCLSH
#TEA_PROG_WISH
#--------------------------------------------------------------------
# Finally, substitute all of the various values into the Makefile.
# You may alternatively have a special pkgIndex.tcl.in or other files
# which require substituting the AC variables in. Include these here.
#--------------------------------------------------------------------
AC_OUTPUT([Makefile pkgIndex.tcl])

View File

@@ -0,0 +1,219 @@
'\"
.\" tdbc_odbc.n --
.\"
.\" Copyright (c) 2008 by Kevin B. Kenny.
.\"
.\" See the file "license.terms" for information on usage and redistribution of
.\" this file, and for a DISCLAIMER OF ALL WARRANTIES.
.TH "tdbc::odbc" n 8.6 Tcl "Tcl Database Connectivity"
.\" .so man.macros
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
.\" # BS - start boxed text
.\" # ^y = starting y location
.\" # ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
.\" # BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\" Draw four-sided box normally, but don't draw top of
.\" box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\" # CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\" # CE - end code excerpt
.de CE
.fi
.RE
..
.BS
.SH "NAME"
tdbc::odbc \- TDBC-ODBC bridge
.SH "SYNOPSIS"
package require \fBtdbc::odbc 1.0\fR
.sp
\fBtdbc::odbc::connection create\fR \fIdb\fR \fIconnectionString\fR ?\fI-option value...\fR?
.br
\fBtdbc::odbc::connection new\fR \fIconnectionString\fR ?\fI-option value...\fR?
.sp
\fBtdbc::odbc::datasources\fR ?\fB-system\fR|\fB-user\fR?
.sp
\fBtdbc::odbc::drivers\fR
.sp
\fBtdbc::odbc::datasource\fR \fIcommand\fR \fIdriverName\fR ?\fIkeyword\fR-\fIvalue\fR?...
.BE
.SH "DESCRIPTION"
.PP
The \fBtdbc::odbc\fR driver provides a database interface that conforms
to Tcl DataBase Connectivity (TDBC) and allows a Tcl script to connect
to any SQL database presenting an ODBC interface. It is also provided
as a worked example of how to write a database driver in C, so that
driver authors have a starting point for further development.
.PP
Connection to an ODBC database is established by invoking
\fBtdbc::odbc::connection create\fR, passing it the name to be used
as a connection handle, followed by a standard ODBC
connection string. As an alternative, \fBtdbc::odbc::connection new\fR
may be used to create
a database connection with an automatically assigned name. The return value
from \fBtdbc::odbc::connection new\fR is the name that was chosen for the
connection handle.
.PP
The connection string will include at least a
\fBDRIVER\fR or \fBDSN\fR keyword, and may include others that are defined by a
particular ODBC driver. (If the local ODBC system supports a graphical
user interface, the \fB-parent\fR option (see below) may allow calling
\fBtdbc::odbc::connection create\fR with an empty connection string.)
.PP
The side effect of \fBtdbc::odbc::connection create\fR is to create a
new database connection.. See \fBtdbc::connection(n)\fR for the
details of how to use the connection to manipulate a database.
.PP
In addition to a standard TDBC interface, \fBtdbc::odbc\fR supports
three additional ccommands. The first of these,
\fBtdbc::odbc::datasources\fR, which returns a Tcl
list enumerating the named data sources available to the program (for
connection with the \fBDSN\fR keyword in the connection string).
The result of \fBtdbc::odbc::datasources\fR may be constrained to only
system data sources or only user data sources by including the
\fB-system\fR or \fB-user\fR options, respectively.
.PP
The \fBtdbc::odbc::drivers\fR command returns a dictionary whose keys
are the names of drivers available for the \fBDRIVER\fR keyword in the
connection string, and whose values are descriptions of the drivers.
.PP
The \fBtdbc::odbc::datasource\fR command allows configuration of named
data sources on those systems that support the ODBC Installer
application programming interface. It accepts a \fIcommand\fR, which
specifies the operation to be performed, the name of a \fIdriver\fR
for the database in question, and a set of keyword-value pairs that
are interpreted by the given driver. The \fIcommand\fR must be one of
the following:
.IP \fBadd\fR
Adds a user data source. The keyword-value pairs must include
at least a \fBDSN\fR option naming the data source
.IP \fBadd_system\fR
Adds a system data source. The keyword-value pairs must include
at least a \fBDSN\fR option naming the data source
.IP \fBconfigure\fR
Configures a user data source. The keyword-value pairs will usually
include a \fBDSN\fR option naming the data source. Some drivers will
support other options, such as the \fBCREATE_DB\fR option to the
Microsoft Access driver on Windows.
.IP \fBconfigure_system\fR
Configures a system data source.
.IP \fBremove\fR
Removes a user data source. The keyword-value pairs must include a
\fBDSN\fR option specifying the data source to remove.
.IP \fBremove_system\fR
Removes a system data source. The keyword-value pairs must include a
\fBDSN\fR option specifying the data source to remove.
.SH "CONNECTION OPTIONS"
.PP
The \fBtdbc::odbc::connection create\fR object command supports the
\fB-encoding\fR, \fB-isolation\fR, \fB-readonly\fR and \fB-timeout\fR
options common to all TDBC drivers. The \fB-encoding\fR option will
succeed only if the requested encoding is the same as the system
encoding; \fBtdbc::odbc\fR does not attempt to specify alternative
encodings to an ODBC driver. (Some drivers accept encoding
specifications in the connection string.)
.PP
In addition, if Tk is present in the requesting interpreter,
and the local system's ODBC driver manager supports a graphical user
interface, the \fBtdbc::odbc::connection create\fR object command
supports a \fB-parent\fR option, whose value is the path name of
a Tk window. If this option is specified, and a connection string does
not specify all the information needed to connect to an interface, the
ODBC driver manager will display a dialog box to request whatever
additional information is required. The requesting interpreter will
block until the user dismisses the dialog, at which point the
connection is made.
.SH EXAMPLES
.PP
Sincs ODBC connection strings are driver specific, it is often
difficult to find the documentation needed to compose them. The
following examples are known to work on most Windows systems and
provide at least a few useful things that a program can do.
.PP
.CS
tdbc::odbc::connection create db \\
"DSN={PAYROLL};UID={aladdin};PWD={Sesame}"
.CE
Connects to a named data source "PAYROLL", providing "aladdin" as a
user name and "Sesame" as a password. Uses \fBdb\fR as the name of the
connection.
.PP
.CS
set connString {DRIVER={Microsoft Access Driver (*.mdb)};}
append connString {FIL={MS Access}\\;}
append connString {DBQ=} \\
[file nativename [file normalize $fileName]]
tdbc::odbc::connection create db2 -readonly 1 $connString
.CE
Opens a connection to a Microsoft Access database file whose
name is in \fI$fileName\fR. The database is opened in read-only
mode. The resulting connection is called "db2".
.PP
.CS
tdbc::odbc::connection create db3 \\
"DRIVER=SQLite3;DATABASE=$fileName"
.CE
Opens a connection to a SQLite3 database whose name is in "$fileName".
.PP
.CS
tdbc::odbc::datasource add \\
{Microsoft Access Driver (*.mdb)} \\
DSN=MyTestDatabase \\
DBQ=[file native [file normalize $fileName]]
.CE
Creates a new user data source with the name, "MyTestDatabase" bound
to a Microsoft Access file whose path name is in "$fileName". No
connection is made to the data source until the program calls
\fBtdbc::odbc::connection create\fR.
.PP
.CS
tdbc::odbc::datasource configure \\
{Microsoft Access Driver (*.mdb)} \\
CREATE_DB=[file native [file normalize $fileName]] \\
General
.CE
Creates a new, empty Microsoft Access database in the file identified
by "$fileName". No connection is made to the database until the
program calls \fBtdbc::odbc::connection create\fR.
.SH "SEE ALSO"
tdbc(n), tdbc::connection(n), tdbc::resultset(n), tdbc::statement(n)
.SH "KEYWORDS"
TDBC, SQL, ODBC, database, connectivity, connection
.SH "COPYRIGHT"
Copyright (c) 2008 by Kevin B. Kenny.
.\" Local Variables:
.\" mode: nroff
.\" End:
.\"

View File

@@ -0,0 +1,282 @@
/*
* fakesql.h --
*
* Include file that defines the subset of SQL/CLI that TDBC
* uses, so that tdbc::odbc can build without an explicit ODBC
* dependency. It comprises only data type, constant and
* function declarations.
*
* The programmers of this file believe that it contains material not
* subject to copyright under the doctrines of scenes a faire and
* of merger of idea and expression. Accordingly, this file is in the
* public domain.
*
*-----------------------------------------------------------------------------
*/
#ifndef FAKESQL_H_INCLUDED
#define FAKESQL_H_INCLUDED
#include <stddef.h>
#ifndef MODULE_SCOPE
#define MODULE_SCOPE extern
#endif
/* Limits */
#define SQL_MAX_DSN_LENGTH 32
#define SQL_MAX_MESSAGE_LENGTH 512
/* Fundamental data types */
#ifndef _WIN32
typedef int BOOL;
typedef unsigned int DWORD;
typedef void* HANDLE;
typedef HANDLE HWND;
typedef unsigned short WCHAR;
typedef char* LPSTR;
typedef WCHAR* LPWSTR;
typedef const char* LPCSTR;
typedef const WCHAR* LPCWSTR;
typedef unsigned short WORD;
#endif
typedef void* PVOID;
typedef short RETCODE;
typedef long SDWORD;
typedef short SWORD;
typedef unsigned short USHORT;
typedef USHORT UWORD;
/* ODBC data types */
typedef Tcl_WideInt SQLBIGINT;
typedef unsigned char SQLCHAR;
typedef double SQLDOUBLE;
typedef void* SQLHANDLE;
typedef SDWORD SQLINTEGER;
typedef PVOID SQLPOINTER;
typedef SWORD SQLSMALLINT;
typedef Tcl_WideUInt SQLUBIGINT;
typedef unsigned char SQLUCHAR;
typedef unsigned int SQLUINTEGER;
typedef UWORD SQLUSMALLINT;
typedef WCHAR SQLWCHAR;
typedef SQLSMALLINT SQLRETURN;
/* TODO - Check how the SQLLEN and SQLULEN types are handled on
* 64-bit Unix. */
#if defined(_WIN64)
typedef Tcl_WideInt SQLLEN;
typedef Tcl_WideUInt SQLULEN;
#else
typedef SQLINTEGER SQLLEN;
typedef SQLUINTEGER SQLULEN;
#endif
/* Handle types */
typedef SQLHANDLE SQLHENV;
typedef SQLHANDLE SQLHDBC;
typedef SQLHANDLE SQLHSTMT;
typedef HWND SQLHWND;
#define SQL_HANDLE_DBC 2
#define SQL_HANDLE_ENV 1
#define SQL_HANDLE_STMT 3
/* Null handles */
#define SQL_NULL_HANDLE ((SQLHANDLE) 0)
#define SQL_NULL_HENV ((SQLHENV) 0)
#define SQL_NULL_HDBC ((SQLHDBC) 0)
#define SQL_NULL_HSTMT ((SQLHSTMT) 0)
/* SQL data types */
enum _SQL_DATATYPE {
SQL_BIGINT = -5,
SQL_BINARY = -2,
SQL_BIT = -7,
SQL_CHAR = 1,
SQL_DATE = 9,
SQL_DECIMAL = 3,
SQL_DOUBLE = 8,
SQL_FLOAT = 6,
SQL_INTEGER = 4,
SQL_LONGVARBINARY = -4,
SQL_LONGVARCHAR = -1,
SQL_NUMERIC = 2,
SQL_REAL = 7,
SQL_SMALLINT = 5,
SQL_TIME = 10,
SQL_TIMESTAMP = 11,
SQL_TINYINT = -6,
SQL_VARBINARY = -3,
SQL_VARCHAR = 12,
SQL_WCHAR = -8,
SQL_WVARCHAR = -9,
SQL_WLONGVARCHAR = -10,
};
/* C data types */
#define SQL_SIGNED_OFFSET (-20)
#define SQL_C_BINARY SQL_BINARY
#define SQL_C_CHAR SQL_CHAR
#define SQL_C_DOUBLE SQL_DOUBLE
#define SQL_C_LONG SQL_INTEGER
#define SQL_C_SBIGINT SQL_BIGINT + SQL_SIGNED_OFFSET
#define SQL_C_SLONG SQL_INTEGER + SQL_SIGNED_OFFSET
#define SQL_C_WCHAR SQL_WCHAR
/* Parameter transmission diretions */
#define SQL_PARAM_INPUT 1
/* Status returns */
#define SQL_ERROR (-1)
#define SQL_NO_DATA 100
#define SQL_NO_TOTAL (-4)
#define SQL_SUCCESS 0
#define SQL_SUCCESS_WITH_INFO 1
#define SQL_SUCCEEDED(rc) (((rc)&(~1))==0)
/* Diagnostic fields */
enum _SQL_DIAG {
SQL_DIAG_SQLSTATE = 4,
};
/* Transaction isolation levels */
#define SQL_TXN_READ_COMMITTED 2
#define SQL_TXN_READ_UNCOMMITTED 1
#define SQL_TXN_REPEATABLE_READ 4
#define SQL_TXN_SERIALIZABLE 8
/* Access modes */
#define SQL_MODE_READ_ONLY 1UL
#define SQL_MODE_READ_WRITE 0UL
/* ODBC properties */
#define SQL_ACCESS_MODE 101
#define SQL_AUTOCOMMIT 102
#define SQL_TXN_ISOLATION 108
/* ODBC attributes */
#define SQL_ATTR_ACCESS_MODE SQL_ACCESS_MODE
#define SQL_ATTR_CONNECTION_TIMEOUT 113
#define SQL_ATTR_ODBC_VERSION 200
#define SQL_ATTR_TXN_ISOLATION SQL_TXN_ISOLATION
#define SQL_ATTR_AUTOCOMMIT SQL_AUTOCOMMIT
/* Nullable? */
#define SQL_NULLABLE_UNKNOWN 2
/* Placeholder for length of missing data */
#define SQL_NULL_DATA (-1)
/* ODBC versions */
#define SQL_OV_ODBC3 3UL
#define SQL_ODBC_VER 10
/* SQLDriverConnect flags */
#define SQL_DRIVER_COMPLETE_REQUIRED 3
#define SQL_DRIVER_NOPROMPT 0
/* SQLGetTypeInfo flags */
#define SQL_ALL_TYPES 0
/* Transaction actions */
#define SQL_COMMIT 0
#define SQL_ROLLBACK 1
/* Data source fetch flags */
#define SQL_FETCH_FIRST 2
#define SQL_FETCH_FIRST_SYSTEM 32
#define SQL_FETCH_FIRST_USER 31
#define SQL_FETCH_NEXT 1
/* ODBCINST actions */
#define ODBC_ADD_DSN 1
#define ODBC_CONFIG_DSN 2
#define ODBC_REMOVE_DSN 3
#define ODBC_ADD_SYS_DSN 4
#define ODBC_CONFIG_SYS_DSN 5
#define ODBC_REMOVE_SYS_DSN 6
/* ODBCINST errors */
#define ODBC_ERROR_GENERAL_ERR 1
#define ODBC_ERROR_INVALID_BUFF_LEN 2
#define ODBC_ERROR_INVALID_HWND 3
#define ODBC_ERROR_INVALID_STR 4
#define ODBC_ERROR_INVALID_REQUEST_TYPE 5
#define ODBC_ERROR_COMPONENT_NOT_FOUND 6
#define ODBC_ERROR_INVALID_NAME 7
#define ODBC_ERROR_INVALID_KEYWORD_VALUE 8
#define ODBC_ERROR_INVALID_DSN 9
#define ODBC_ERROR_INVALID_INF 10
#define ODBC_ERROR_REQUEST_FAILED 11
#define ODBC_ERROR_INVALID_PATH 12
#define ODBC_ERROR_LOAD_LIB_FAILED 13
#define ODBC_ERROR_INVALID_PARAM_SEQUENCE 14
#define ODBC_ERROR_INVALID_LOG_FILE 15
#define ODBC_ERROR_USER_CANCELED 16
#define ODBC_ERROR_USAGE_UPDATE_FAILED 17
#define ODBC_ERROR_CREATE_DSN_FAILED 18
#define ODBC_ERROR_WRITING_SYSINFO_FAILED 19
#define ODBC_ERROR_REMOVE_DSN_FAILED 20
#define ODBC_ERROR_OUT_OF_MEM 21
#define ODBC_ERROR_OUTPUT_STRING_TRUNCATED 22
/* ODBC client library entry points */
#ifdef _WIN32
#define SQL_API __stdcall
#define INSTAPI __stdcall
#else
#define SQL_API /* nothing */
#define INSTAPI /* nothing */
#endif
#include "odbcStubs.h"
MODULE_SCOPE const odbcStubDefs* odbcStubs;
/*
* Additional entry points in ODBCINST - all of these are optional
* and resolved with Tcl_FindSymbol, not directly in Tcl_LoadLibrary.
*/
MODULE_SCOPE BOOL (INSTAPI* SQLConfigDataSourceW)(HWND, WORD, LPCWSTR,
LPCWSTR);
MODULE_SCOPE BOOL (INSTAPI* SQLConfigDataSource)(HWND, WORD, LPCSTR, LPCSTR);
MODULE_SCOPE BOOL (INSTAPI* SQLInstallerErrorW)(WORD, DWORD*, LPWSTR, WORD,
WORD*);
MODULE_SCOPE BOOL (INSTAPI* SQLInstallerError)(WORD, DWORD*, LPSTR, WORD,
WORD*);
/*
* Function that initialises the stubs
*/
MODULE_SCOPE Tcl_LoadHandle OdbcInitStubs(Tcl_Interp*, Tcl_LoadHandle*);
#endif

View File

@@ -0,0 +1,24 @@
/*
* Macros used to cast between pointers and integers (e.g. when storing an int
* in ClientData), on 64-bit architectures they avoid gcc warning about "cast
* to/from pointer from/to integer of different size".
*/
#if !defined(INT2PTR) && !defined(PTR2INT)
# if defined(HAVE_INTPTR_T) || defined(intptr_t)
# define INT2PTR(p) ((void *)(intptr_t)(p))
# define PTR2INT(p) ((int)(intptr_t)(p))
# else
# define INT2PTR(p) ((void *)(p))
# define PTR2INT(p) ((int)(p))
# endif
#endif
#if !defined(UINT2PTR) && !defined(PTR2UINT)
# if defined(HAVE_UINTPTR_T) || defined(uintptr_t)
# define UINT2PTR(p) ((void *)(uintptr_t)(p))
# define PTR2UINT(p) ((unsigned int)(uintptr_t)(p))
# else
# define UINT2PTR(p) ((void *)(p))
# define PTR2UINT(p) ((unsigned int)(p))
# endif
#endif

View File

@@ -0,0 +1,47 @@
# odbcStubDefs.txt --
#
# Definitions of routines in the ODBC DLL that will be resolved
# and imported at run time.
#
# This file contains only function declarations necessary to interoperability
# with the SQL/CLI application programming interface. The programmers believe
# that the material in this file is not subject to copyright, under the
# doctrines of scenes a faire and of the merger of idea and expression.
# Accordingly, this file is in the public domain.
#
#-----------------------------------------------------------------------------
* STUBSTRUCT: odbcStubs
* CONVENTION: SQL_API
SQLRETURN SQLAllocHandle(SQLSMALLINT,SQLHANDLE,SQLHANDLE*);
SQLRETURN SQLBindParameter(SQLHSTMT,SQLUSMALLINT,SQLSMALLINT,SQLSMALLINT,SQLSMALLINT,SQLULEN,SQLSMALLINT,SQLPOINTER,SQLLEN,SQLLEN*);
SQLRETURN SQLCloseCursor(SQLHSTMT);
SQLRETURN SQLColumnsW(SQLHSTMT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT ,SQLWCHAR*,SQLSMALLINT );
SQLRETURN SQLDataSourcesW(SQLHENV,SQLUSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*);
SQLRETURN SQLDescribeColW(SQLHSTMT,SQLUSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*,SQLSMALLINT*,SQLULEN*,SQLSMALLINT*,SQLSMALLINT*);
SQLRETURN SQLDescribeParam(SQLHSTMT,SQLUSMALLINT,SQLSMALLINT*,SQLULEN*,SQLSMALLINT*,SQLSMALLINT*);
SQLRETURN SQLDisconnect(SQLHDBC);
SQLRETURN SQLDriverConnectW(SQLHDBC,SQLHWND,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*,SQLUSMALLINT);
SQLRETURN SQLDriversW(SQLHENV,SQLUSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*);
SQLRETURN SQLEndTran(SQLSMALLINT,SQLHANDLE,SQLSMALLINT);
SQLRETURN SQLExecute(SQLHSTMT);
SQLRETURN SQLFetch(SQLHSTMT);
SQLRETURN SQLForeignKeysW(SQLHSTMT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT);
SQLRETURN SQLFreeHandle(SQLSMALLINT,SQLHANDLE);
SQLRETURN SQLGetConnectAttr(SQLHDBC,SQLINTEGER,SQLPOINTER,SQLINTEGER,SQLINTEGER*);
SQLRETURN SQLGetData(SQLHSTMT,SQLUSMALLINT,SQLSMALLINT,SQLPOINTER,SQLLEN,SQLLEN*);
SQLRETURN SQLGetDiagFieldA(SQLSMALLINT,SQLHANDLE,SQLSMALLINT,SQLSMALLINT,SQLPOINTER,SQLSMALLINT,SQLSMALLINT*);
SQLRETURN SQLGetDiagRecW(SQLSMALLINT,SQLHANDLE,SQLSMALLINT,SQLWCHAR*,SQLINTEGER*,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*);
SQLRETURN SQLGetInfoW(SQLHANDLE,SQLUSMALLINT,SQLPOINTER,SQLSMALLINT,SQLSMALLINT*);
SQLRETURN SQLGetTypeInfo(SQLHSTMT,SQLSMALLINT);
SQLRETURN SQLMoreResults(SQLHSTMT);
SQLRETURN SQLNumParams(SQLHSTMT,SQLSMALLINT*);
SQLRETURN SQLNumResultCols(SQLHSTMT,SQLSMALLINT*);
SQLRETURN SQLPrepareW(SQLHSTMT,SQLWCHAR*,SQLINTEGER);
SQLRETURN SQLPrimaryKeysW(SQLHSTMT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT);
SQLRETURN SQLRowCount(SQLHSTMT,SQLLEN*);
SQLRETURN SQLSetConnectAttr(SQLHDBC,SQLINTEGER,SQLPOINTER,SQLINTEGER);
SQLRETURN SQLSetConnectOption(SQLHDBC,SQLUSMALLINT,SQLULEN); /* deprecated */
SQLRETURN SQLSetEnvAttr(SQLHENV,SQLINTEGER,SQLPOINTER,SQLINTEGER);
SQLRETURN SQLTablesW(SQLHSTMT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT);

View File

@@ -0,0 +1,214 @@
/*
* odbcStubInit.c --
*
* Stubs tables for the foreign ODBC libraries so that
* Tcl extensions can use them without the linker's knowing about them.
*
* @CREATED@ 2018-05-12 16:18:48Z by genExtStubs.tcl from odbcStubDefs.txt
*
* Copyright (c) 2010 by Kevin B. Kenny.
*
* Please refer to the file, 'license.terms' for the conditions on
* redistribution of this file and for a DISCLAIMER OF ALL WARRANTIES.
*
*-----------------------------------------------------------------------------
*/
#include <tcl.h>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include "fakesql.h"
/*
* Static data used in this file
*/
/*
* Names of the libraries that might contain the ODBC API
*/
static const char *const odbcStubLibNames[] = {
#if defined(__APPLE__)
"libiodbc.2",
#elif defined(__OpenBSD__)
"libiodbc",
#else
"odbc32", "odbc", "libodbc32", "libodbc", "libiodbc",
#endif
NULL
/* @END@ */
};
static const char *const odbcOptLibNames[] = {
#if defined(__APPLE__)
"libiodbcinst.2",
#elif defined(__OpenBSD__)
"libiodbcinst",
#else
"odbccp", "odbccp32", "odbcinst",
"libodbccp", "libodbccp32", "libodbcinst", "libiodbcinst",
#endif
NULL
};
/*
* Names of the functions that we need from ODBC
*/
static const char *const odbcSymbolNames[] = {
/* @SYMNAMES@: DO NOT EDIT THESE NAMES */
"SQLAllocHandle",
"SQLBindParameter",
"SQLCloseCursor",
"SQLColumnsW",
"SQLDataSourcesW",
"SQLDescribeColW",
"SQLDescribeParam",
"SQLDisconnect",
"SQLDriverConnectW",
"SQLDriversW",
"SQLEndTran",
"SQLExecute",
"SQLFetch",
"SQLForeignKeysW",
"SQLFreeHandle",
"SQLGetConnectAttr",
"SQLGetData",
"SQLGetDiagFieldA",
"SQLGetDiagRecW",
"SQLGetInfoW",
"SQLGetTypeInfo",
"SQLMoreResults",
"SQLNumParams",
"SQLNumResultCols",
"SQLPrepareW",
"SQLPrimaryKeysW",
"SQLRowCount",
"SQLSetConnectAttr",
"SQLSetConnectOption",
"SQLSetEnvAttr",
"SQLTablesW",
NULL
/* @END@ */
};
/*
* Table containing pointers to the functions named above.
*/
static odbcStubDefs odbcStubsTable;
const odbcStubDefs* odbcStubs = &odbcStubsTable;
/*
* Pointers to optional functions in ODBCINST
*/
BOOL (INSTAPI* SQLConfigDataSourceW)(HWND, WORD, LPCWSTR, LPCWSTR)
= NULL;
BOOL (INSTAPI* SQLConfigDataSource)(HWND, WORD, LPCSTR, LPCSTR)
= NULL;
BOOL (INSTAPI* SQLInstallerError)(WORD, DWORD*, LPSTR, WORD, WORD*)
= NULL;
/*
*-----------------------------------------------------------------------------
*
* OdbcInitStubs --
*
* Initialize the Stubs table for the ODBC API
*
* Results:
* Returns the handle to the loaded ODBC client library, or NULL
* if the load is unsuccessful. Leaves an error message in the
* interpreter.
*
*-----------------------------------------------------------------------------
*/
MODULE_SCOPE Tcl_LoadHandle
OdbcInitStubs(Tcl_Interp* interp,
/* Tcl interpreter */
Tcl_LoadHandle* handle2Ptr)
/* Pointer to a second load handle
* that represents the ODBCINST library */
{
int i;
int status; /* Status of Tcl library calls */
Tcl_Obj* path; /* Path name of a module to be loaded */
Tcl_Obj* shlibext; /* Extension to use for load modules */
Tcl_LoadHandle handle = NULL;
/* Handle to a load module */
SQLConfigDataSourceW = NULL;
SQLConfigDataSource = NULL;
SQLInstallerError = NULL;
/*
* Determine the shared library extension
*/
status = Tcl_EvalEx(interp, "::info sharedlibextension", -1,
TCL_EVAL_GLOBAL);
if (status != TCL_OK) return NULL;
shlibext = Tcl_GetObjResult(interp);
Tcl_IncrRefCount(shlibext);
/*
* Walk the list of possible library names to find an ODBC client
*/
status = TCL_ERROR;
for (i = 0; status == TCL_ERROR && odbcStubLibNames[i] != NULL; ++i) {
path = Tcl_NewStringObj(odbcStubLibNames[i], -1);
Tcl_AppendObjToObj(path, shlibext);
Tcl_IncrRefCount(path);
Tcl_ResetResult(interp);
/*
* Try to load a client library and resolve the ODBC API within it.
*/
status = Tcl_LoadFile(interp, path, odbcSymbolNames, 0,
(void*)odbcStubs, &handle);
Tcl_DecrRefCount(path);
}
/*
* If a client library is found, then try to load ODBCINST as well.
*/
if (status == TCL_OK) {
int status2 = TCL_ERROR;
for (i = 0; status2 == TCL_ERROR && odbcOptLibNames[i] != NULL; ++i) {
path = Tcl_NewStringObj(odbcOptLibNames[i], -1);
Tcl_AppendObjToObj(path, shlibext);
Tcl_IncrRefCount(path);
status2 = Tcl_LoadFile(interp, path, NULL, 0, NULL, handle2Ptr);
if (status2 == TCL_OK) {
SQLConfigDataSourceW =
(BOOL (INSTAPI*)(HWND, WORD, LPCWSTR, LPCWSTR))
Tcl_FindSymbol(NULL, *handle2Ptr, "SQLConfigDataSourceW");
if (SQLConfigDataSourceW == NULL) {
SQLConfigDataSource =
(BOOL (INSTAPI*)(HWND, WORD, LPCSTR, LPCSTR))
Tcl_FindSymbol(NULL, *handle2Ptr,
"SQLConfigDataSource");
}
SQLInstallerError =
(BOOL (INSTAPI*)(WORD, DWORD*, LPSTR, WORD, WORD*))
Tcl_FindSymbol(NULL, *handle2Ptr, "SQLInstallerError");
} else {
Tcl_ResetResult(interp);
}
Tcl_DecrRefCount(path);
}
}
/*
* Either we've successfully loaded a library (status == TCL_OK),
* or we've run out of library names (in which case status==TCL_ERROR
* and the error message reflects the last unsuccessful load attempt).
*/
Tcl_DecrRefCount(shlibext);
if (status != TCL_OK) {
return NULL;
}
return handle;
}

View File

@@ -0,0 +1,78 @@
/*
*-----------------------------------------------------------------------------
*
* odbcStubs.h --
*
* Stubs for procedures in odbcStubDefs.txt
*
* Generated by genExtStubs.tcl: DO NOT EDIT
* 2018-05-12 16:18:48Z
*
*-----------------------------------------------------------------------------
*/
typedef struct odbcStubDefs {
SQLRETURN (SQL_API*SQLAllocHandlePtr)(SQLSMALLINT,SQLHANDLE,SQLHANDLE*);
SQLRETURN (SQL_API*SQLBindParameterPtr)(SQLHSTMT,SQLUSMALLINT,SQLSMALLINT,SQLSMALLINT,SQLSMALLINT,SQLULEN,SQLSMALLINT,SQLPOINTER,SQLLEN,SQLLEN*);
SQLRETURN (SQL_API*SQLCloseCursorPtr)(SQLHSTMT);
SQLRETURN (SQL_API*SQLColumnsWPtr)(SQLHSTMT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT ,SQLWCHAR*,SQLSMALLINT );
SQLRETURN (SQL_API*SQLDataSourcesWPtr)(SQLHENV,SQLUSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*);
SQLRETURN (SQL_API*SQLDescribeColWPtr)(SQLHSTMT,SQLUSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*,SQLSMALLINT*,SQLULEN*,SQLSMALLINT*,SQLSMALLINT*);
SQLRETURN (SQL_API*SQLDescribeParamPtr)(SQLHSTMT,SQLUSMALLINT,SQLSMALLINT*,SQLULEN*,SQLSMALLINT*,SQLSMALLINT*);
SQLRETURN (SQL_API*SQLDisconnectPtr)(SQLHDBC);
SQLRETURN (SQL_API*SQLDriverConnectWPtr)(SQLHDBC,SQLHWND,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*,SQLUSMALLINT);
SQLRETURN (SQL_API*SQLDriversWPtr)(SQLHENV,SQLUSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*);
SQLRETURN (SQL_API*SQLEndTranPtr)(SQLSMALLINT,SQLHANDLE,SQLSMALLINT);
SQLRETURN (SQL_API*SQLExecutePtr)(SQLHSTMT);
SQLRETURN (SQL_API*SQLFetchPtr)(SQLHSTMT);
SQLRETURN (SQL_API*SQLForeignKeysWPtr)(SQLHSTMT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT);
SQLRETURN (SQL_API*SQLFreeHandlePtr)(SQLSMALLINT,SQLHANDLE);
SQLRETURN (SQL_API*SQLGetConnectAttrPtr)(SQLHDBC,SQLINTEGER,SQLPOINTER,SQLINTEGER,SQLINTEGER*);
SQLRETURN (SQL_API*SQLGetDataPtr)(SQLHSTMT,SQLUSMALLINT,SQLSMALLINT,SQLPOINTER,SQLLEN,SQLLEN*);
SQLRETURN (SQL_API*SQLGetDiagFieldAPtr)(SQLSMALLINT,SQLHANDLE,SQLSMALLINT,SQLSMALLINT,SQLPOINTER,SQLSMALLINT,SQLSMALLINT*);
SQLRETURN (SQL_API*SQLGetDiagRecWPtr)(SQLSMALLINT,SQLHANDLE,SQLSMALLINT,SQLWCHAR*,SQLINTEGER*,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*);
SQLRETURN (SQL_API*SQLGetInfoWPtr)(SQLHANDLE,SQLUSMALLINT,SQLPOINTER,SQLSMALLINT,SQLSMALLINT*);
SQLRETURN (SQL_API*SQLGetTypeInfoPtr)(SQLHSTMT,SQLSMALLINT);
SQLRETURN (SQL_API*SQLMoreResultsPtr)(SQLHSTMT);
SQLRETURN (SQL_API*SQLNumParamsPtr)(SQLHSTMT,SQLSMALLINT*);
SQLRETURN (SQL_API*SQLNumResultColsPtr)(SQLHSTMT,SQLSMALLINT*);
SQLRETURN (SQL_API*SQLPrepareWPtr)(SQLHSTMT,SQLWCHAR*,SQLINTEGER);
SQLRETURN (SQL_API*SQLPrimaryKeysWPtr)(SQLHSTMT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT);
SQLRETURN (SQL_API*SQLRowCountPtr)(SQLHSTMT,SQLLEN*);
SQLRETURN (SQL_API*SQLSetConnectAttrPtr)(SQLHDBC,SQLINTEGER,SQLPOINTER,SQLINTEGER);
SQLRETURN (SQL_API*SQLSetConnectOptionPtr)(SQLHDBC,SQLUSMALLINT,SQLULEN);
SQLRETURN (SQL_API*SQLSetEnvAttrPtr)(SQLHENV,SQLINTEGER,SQLPOINTER,SQLINTEGER);
SQLRETURN (SQL_API*SQLTablesWPtr)(SQLHSTMT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT);
} odbcStubDefs;
#define SQLAllocHandle (odbcStubs->SQLAllocHandlePtr)
#define SQLBindParameter (odbcStubs->SQLBindParameterPtr)
#define SQLCloseCursor (odbcStubs->SQLCloseCursorPtr)
#define SQLColumnsW (odbcStubs->SQLColumnsWPtr)
#define SQLDataSourcesW (odbcStubs->SQLDataSourcesWPtr)
#define SQLDescribeColW (odbcStubs->SQLDescribeColWPtr)
#define SQLDescribeParam (odbcStubs->SQLDescribeParamPtr)
#define SQLDisconnect (odbcStubs->SQLDisconnectPtr)
#define SQLDriverConnectW (odbcStubs->SQLDriverConnectWPtr)
#define SQLDriversW (odbcStubs->SQLDriversWPtr)
#define SQLEndTran (odbcStubs->SQLEndTranPtr)
#define SQLExecute (odbcStubs->SQLExecutePtr)
#define SQLFetch (odbcStubs->SQLFetchPtr)
#define SQLForeignKeysW (odbcStubs->SQLForeignKeysWPtr)
#define SQLFreeHandle (odbcStubs->SQLFreeHandlePtr)
#define SQLGetConnectAttr (odbcStubs->SQLGetConnectAttrPtr)
#define SQLGetData (odbcStubs->SQLGetDataPtr)
#define SQLGetDiagFieldA (odbcStubs->SQLGetDiagFieldAPtr)
#define SQLGetDiagRecW (odbcStubs->SQLGetDiagRecWPtr)
#define SQLGetInfoW (odbcStubs->SQLGetInfoWPtr)
#define SQLGetTypeInfo (odbcStubs->SQLGetTypeInfoPtr)
#define SQLMoreResults (odbcStubs->SQLMoreResultsPtr)
#define SQLNumParams (odbcStubs->SQLNumParamsPtr)
#define SQLNumResultCols (odbcStubs->SQLNumResultColsPtr)
#define SQLPrepareW (odbcStubs->SQLPrepareWPtr)
#define SQLPrimaryKeysW (odbcStubs->SQLPrimaryKeysWPtr)
#define SQLRowCount (odbcStubs->SQLRowCountPtr)
#define SQLSetConnectAttr (odbcStubs->SQLSetConnectAttrPtr)
#define SQLSetConnectOption (odbcStubs->SQLSetConnectOptionPtr)
#define SQLSetEnvAttr (odbcStubs->SQLSetEnvAttrPtr)
#define SQLTablesW (odbcStubs->SQLTablesWPtr)
MODULE_SCOPE const odbcStubDefs *odbcStubs;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,515 @@
# tdbcodbc.tcl --
#
# Class definitions and Tcl-level methods for the tdbc::odbc bridge.
#
# Copyright (c) 2008 by Kevin B. Kenny
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: tdbcodbc.tcl,v 1.47 2008/02/27 02:08:27 kennykb Exp $
#
#------------------------------------------------------------------------------
package require tdbc
::namespace eval ::tdbc::odbc {
namespace export connection datasources drivers
# Data types that are predefined in ODBC
variable sqltypes [dict create \
1 char \
2 numeric \
3 decimal \
4 integer \
5 smallint \
6 float \
7 real \
8 double \
9 datetime \
12 varchar \
91 date \
92 time \
93 timestamp \
-1 longvarchar \
-2 binary \
-3 varbinary \
-4 longvarbinary \
-5 bigint \
-6 tinyint \
-7 bit \
-8 wchar \
-9 wvarchar \
-10 wlongvarchar \
-11 guid]
}
#------------------------------------------------------------------------------
#
# tdbc::odbc::connection --
#
# Class representing a connection to a database through ODBC.
#
#-------------------------------------------------------------------------------
::oo::class create ::tdbc::odbc::connection {
superclass ::tdbc::connection
variable statementSeq typemap
# The constructor is written in C. It takes the connection string
# as its argument It sets up a namespace to hold the statements
# associated with the connection, and then delegates to the 'init'
# method (written in C) to do the actual work of attaching to the
# database. When that comes back, it sets up a statement to query
# the support types, makes a dictionary to enumerate them, and
# calls back to set a flag if WVARCHAR is seen (If WVARCHAR is
# seen, the database supports Unicode.)
# The 'statementCreate' method forwards to the constructor of the
# statement class
forward statementCreate ::tdbc::odbc::statement create
# The 'tables' method returns a dictionary describing the tables
# in the database
method tables {{pattern %}} {
set stmt [::tdbc::odbc::tablesStatement create \
Stmt::[incr statementSeq] [self] $pattern]
set status [catch {
set retval {}
$stmt foreach -as dicts row {
if {[dict exists $row TABLE_NAME]} {
dict set retval [dict get $row TABLE_NAME] $row
}
}
set retval
} result options]
catch {rename $stmt {}}
return -level 0 -options $options $result
}
# The 'columns' method returns a dictionary describing the tables
# in the database
method columns {table {pattern %}} {
# Make sure that the type map is initialized
my typemap
# Query the columns from the database
set stmt [::tdbc::odbc::columnsStatement create \
Stmt::[incr statementSeq] [self] $table $pattern]
set status [catch {
set retval {}
$stmt foreach -as dicts origrow {
# Map the type, precision, scale and nullable indicators
# to tdbc's notation
set row {}
dict for {key value} $origrow {
dict set row [string tolower $key] $value
}
if {[dict exists $row column_name]} {
if {[dict exists $typemap \
[dict get $row data_type]]} {
dict set row type \
[dict get $typemap \
[dict get $row data_type]]
} else {
dict set row type [dict get $row type_name]
}
if {[dict exists $row column_size]} {
dict set row precision \
[dict get $row column_size]
}
if {[dict exists $row decimal_digits]} {
dict set row scale \
[dict get $row decimal_digits]
}
if {![dict exists $row nullable]} {
dict set row nullable \
[expr {!![string trim [dict get $row is_nullable]]}]
}
dict set retval [dict get $row column_name] $row
}
}
set retval
} result options]
catch {rename $stmt {}}
return -level 0 -options $options $result
}
# The 'primarykeys' method returns a dictionary describing the primary
# keys of a table
method primarykeys {tableName} {
set stmt [::tdbc::odbc::primarykeysStatement create \
Stmt::[incr statementSeq] [self] $tableName]
set status [catch {
set retval {}
$stmt foreach -as dicts row {
foreach {odbcKey tdbcKey} {
TABLE_CAT tableCatalog
TABLE_SCHEM tableSchema
TABLE_NAME tableName
COLUMN_NAME columnName
KEY_SEQ ordinalPosition
PK_NAME constraintName
} {
if {[dict exists $row $odbcKey]} {
dict set row $tdbcKey [dict get $row $odbcKey]
dict unset row $odbcKey
}
}
lappend retval $row
}
set retval
} result options]
catch {rename $stmt {}}
return -level 0 -options $options $result
}
# The 'foreignkeys' method returns a dictionary describing the foreign
# keys of a table
method foreignkeys {args} {
set stmt [::tdbc::odbc::foreignkeysStatement create \
Stmt::[incr statementSeq] [self] {*}$args]
set status [catch {
set fkseq 0
set retval {}
$stmt foreach -as dicts row {
foreach {odbcKey tdbcKey} {
PKTABLE_CAT primaryCatalog
PKTABLE_SCHEM primarySchema
PKTABLE_NAME primaryTable
PKCOLUMN_NAME primaryColumn
FKTABLE_CAT foreignCatalog
FKTABLE_SCHEM foreignSchema
FKTABLE_NAME foreignTable
FKCOLUMN_NAME foreignColumn
UPDATE_RULE updateRule
DELETE_RULE deleteRule
DEFERRABILITY deferrable
KEY_SEQ ordinalPosition
FK_NAME foreignConstraintName
} {
if {[dict exists $row $odbcKey]} {
dict set row $tdbcKey [dict get $row $odbcKey]
dict unset row $odbcKey
}
}
# Horrible kludge: If the driver doesn't report FK_NAME,
# make one up.
if {![dict exists $row foreignConstraintName]} {
if {![dict exists $row ordinalPosition]
|| [dict get $row ordinalPosition] == 1} {
set fkname ?[dict get $row foreignTable]?[incr fkseq]
}
dict set row foreignConstraintName $fkname
}
lappend retval $row
}
set retval
} result options]
catch {rename $stmt {}}
return -level 0 -options $options $result
}
# The 'prepareCall' method gives a portable interface to prepare
# calls to stored procedures. It delegates to 'prepare' to do the
# actual work.
method preparecall {call} {
regexp {^[[:space:]]*(?:([A-Za-z_][A-Za-z_0-9]*)[[:space:]]*=)?(.*)} \
$call -> varName rest
if {$varName eq {}} {
my prepare \\{CALL $rest\\}
} else {
my prepare \\{:$varName=CALL $rest\\}
}
if 0 {
# Kevin thinks this is going to be
if {![regexp -expanded {
^\s* # leading whitespace
(?::([[:alpha:]_][[:alnum:]_]*)\s*=\s*) # possible variable name
(?:(?:([[:alpha:]_][[:alnum:]_]*)\s*[.]\s*)? # catalog
([[:alpha:]_][[:alnum:]_]*)\s*[.]\s*)? # schema
([[:alpha:]_][[:alnum:]_]*)\s* # procedure
(.*)$ # argument list
} $call -> varName catalog schema procedure arglist]} {
return -code error \
-errorCode [list TDBC \
SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION \
42000 ODBC -1] \
"Syntax error in stored procedure call"
} else {
my PrepareCall $varName $catalog $schema $procedure $arglist
}
# at least if making all parameters 'inout' doesn't work.
}
}
# The 'typemap' method returns the type map
method typemap {} {
if {![info exists typemap]} {
set typemap $::tdbc::odbc::sqltypes
set typesStmt [tdbc::odbc::typesStatement new [self]]
$typesStmt foreach row {
set typeNum [dict get $row DATA_TYPE]
if {![dict exists $typemap $typeNum]} {
dict set typemap $typeNum [string tolower \
[dict get $row TYPE_NAME]]
}
switch -exact -- $typeNum {
-9 {
[self] HasWvarchar 1
}
-5 {
[self] HasBigint 1
}
}
}
rename $typesStmt {}
}
return $typemap
}
# The 'begintransaction', 'commit' and 'rollback' methods are
# implemented in C.
}
#-------------------------------------------------------------------------------
#
# tdbc::odbc::statement --
#
# The class 'tdbc::odbc::statement' models one statement against a
# database accessed through an ODBC connection
#
#-------------------------------------------------------------------------------
::oo::class create ::tdbc::odbc::statement {
superclass ::tdbc::statement
# The constructor is implemented in C. It accepts the handle to
# the connection and the SQL code for the statement to prepare.
# It creates a subordinate namespace to hold the statement's
# active result sets, and then delegates to the 'init' method,
# written in C, to do the actual work of preparing the statement.
# The 'resultSetCreate' method forwards to the result set constructor
forward resultSetCreate ::tdbc::odbc::resultset create
# The 'params' method describes the parameters to the statement
method params {} {
set typemap [[my connection] typemap]
set result {}
foreach {name flags typeNum precision scale nullable} [my ParamList] {
set lst [dict create \
name $name \
direction [lindex {unknown in out inout} \
[expr {($flags & 0x06) >> 1}]] \
type [dict get $typemap $typeNum] \
precision $precision \
scale $scale]
if {$nullable in {0 1}} {
dict set list nullable $nullable
}
dict set result $name $lst
}
return $result
}
# Methods implemented in C:
# init statement ?dictionary?
# Does the heavy lifting for the constructor
# connection
# Returns the connection handle to which this statement belongs
# paramtype paramname ?direction? type ?precision ?scale??
# Declares the type of a parameter in the statement
}
#------------------------------------------------------------------------------
#
# tdbc::odbc::tablesStatement --
#
# The class 'tdbc::odbc::tablesStatement' represents the special
# statement that queries the tables in a database through an ODBC
# connection.
#
#------------------------------------------------------------------------------
oo::class create ::tdbc::odbc::tablesStatement {
superclass ::tdbc::statement
# The constructor is written in C. It accepts the handle to the
# connection and a pattern to match table names. It works in all
# ways like the constructor of the 'statement' class except that
# its 'init' method sets up to enumerate tables and not run a SQL
# query.
# The 'resultSetCreate' method forwards to the result set constructor
forward resultSetCreate ::tdbc::odbc::resultset create
}
#------------------------------------------------------------------------------
#
# tdbc::odbc::columnsStatement --
#
# The class 'tdbc::odbc::tablesStatement' represents the special
# statement that queries the columns of a table or view
# in a database through an ODBC connection.
#
#------------------------------------------------------------------------------
oo::class create ::tdbc::odbc::columnsStatement {
superclass ::tdbc::statement
# The constructor is written in C. It accepts the handle to the
# connection, a table name, and a pattern to match column
# names. It works in all ways like the constructor of the
# 'statement' class except that its 'init' method sets up to
# enumerate tables and not run a SQL query.
# The 'resultSetCreate' class forwards to the constructor of the
# result set
forward resultSetCreate ::tdbc::odbc::resultset create
}
#------------------------------------------------------------------------------
#
# tdbc::odbc::primarykeysStatement --
#
# The class 'tdbc::odbc::primarykeysStatement' represents the special
# statement that queries the primary keys on a table through an ODBC
# connection.
#
#------------------------------------------------------------------------------
oo::class create ::tdbc::odbc::primarykeysStatement {
superclass ::tdbc::statement
# The constructor is written in C. It accepts the handle to the
# connection and a table name. It works in all
# ways like the constructor of the 'statement' class except that
# its 'init' method sets up to enumerate primary keys and not run a SQL
# query.
# The 'resultSetCreate' method forwards to the result set constructor
forward resultSetCreate ::tdbc::odbc::resultset create
}
#------------------------------------------------------------------------------
#
# tdbc::odbc::foreignkeysStatement --
#
# The class 'tdbc::odbc::foreignkeysStatement' represents the special
# statement that queries the foreign keys on a table through an ODBC
# connection.
#
#------------------------------------------------------------------------------
oo::class create ::tdbc::odbc::foreignkeysStatement {
superclass ::tdbc::statement
# The constructor is written in C. It accepts the handle to the
# connection and the -primary and -foreign options. It works in all
# ways like the constructor of the 'statement' class except that
# its 'init' method sets up to enumerate foreign keys and not run a SQL
# query.
# The 'resultSetCreate' method forwards to the result set constructor
forward resultSetCreate ::tdbc::odbc::resultset create
}
#------------------------------------------------------------------------------
#
# tdbc::odbc::typesStatement --
#
# The class 'tdbc::odbc::typesStatement' represents the special
# statement that queries the types available in a database through
# an ODBC connection.
#
#------------------------------------------------------------------------------
oo::class create ::tdbc::odbc::typesStatement {
superclass ::tdbc::statement
# The constructor is written in C. It accepts the handle to the
# connection, and (optionally) a data type number. It works in all
# ways like the constructor of the 'statement' class except that
# its 'init' method sets up to enumerate types and not run a SQL
# query.
# The 'resultSetCreate' method forwards to the constructor of result sets
forward resultSetCreate ::tdbc::odbc::resultset create
# The C code contains a variant implementation of the 'init' method.
}
#------------------------------------------------------------------------------
#
# tdbc::odbc::resultset --
#
# The class 'tdbc::odbc::resultset' models the result set that is
# produced by executing a statement against an ODBC database.
#
#------------------------------------------------------------------------------
::oo::class create ::tdbc::odbc::resultset {
superclass ::tdbc::resultset
# Methods implemented in C include:
# constructor statement ?dictionary?
# -- Executes the statement against the database, optionally providing
# a dictionary of substituted parameters (default is to get params
# from variables in the caller's scope).
# columns
# -- Returns a list of the names of the columns in the result.
# nextdict
# -- Stores the next row of the result set in the given variable in
# the caller's scope as a dictionary whose keys are
# column names and whose values are column values.
# nextlist
# -- Stores the next row of the result set in the given variable in
# the caller's scope as a list of cells.
# rowcount
# -- Returns a count of rows affected by the statement, or -1
# if the count of rows has not been determined.
}

View File

@@ -0,0 +1,38 @@
This software is copyrighted by Kevin B. Kenny, and by 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.

View File

@@ -0,0 +1,8 @@
# Index file to load the TDBC ODBC package.
if {[catch {package require Tcl @TCL_VERSION_REQ@}]} {
return
}
package ifneeded tdbc::odbc @PACKAGE_VERSION@ \
"[list source [file join $dir @PACKAGE_NAME@.tcl]]\;\
[list load [file join $dir @PKG_LIB_FILE@] @PACKAGE_NAME@]"

View File

@@ -0,0 +1,26 @@
These files comprise the basic building blocks for a Tcl Extension
Architecture (TEA) extension. For more information on TEA see:
http://www.tcl.tk/doc/tea/
This package is part of the Tcl project at SourceForge, but sources
and bug/patch database are hosted on fossil here:
https://core.tcl-lang.org/tclconfig
This package is a freely available open source package. You can do
virtually anything you like with it, such as modifying it, redistributing
it, and selling it either in whole or in part.
CONTENTS
========
The following is a short description of the files you will find in
the sample extension.
README.txt This file
install-sh Program used for copying binaries and script files
to their install locations.
tcl.m4 Collection of Tcl autoconf macros. Included by a package's
aclocal.m4 to define TEA_* macros.

View File

@@ -0,0 +1,518 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2020-07-26.22; # 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
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 the last 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.
-s $stripprog installed files.
-S OPTION $stripprog installed files using OPTION.
-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
"
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;;
-s) stripcmd=$stripprog;;
-S) stripcmd="$stripprog $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=$?
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
# 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 -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$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:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
# all.tcl --
#
# This file contains a top-level script to run all of the Tcl
# tests. Execute it by invoking "source all.test" when running tcltest
# in this directory.
#
# Copyright (c) 1998-2000 by Scriptics Corporation.
# All rights reserved.
#
# RCS: @(#) $Id: all.tcl,v 1.4 2004/07/04 22:04:20 patthoyts Exp $
package require Tcl 8.6
package require tcltest 2.2
::tcltest::configure \
-testdir [file dirname [file normalize [info script]]] \
{*}$argv
::tcltest::runAllTests
rename exit {}

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,159 @@
#------------------------------------------------------------- -*- makefile -*-
#
# Makefile for TBDC ODBC interface
#
# Basic build, test and install
# nmake /s /nologo /f makefile.vc INSTALLDIR=c:\path\to\installdir
# nmake /s /nologo /f makefile.vc INSTALLDIR=c:\path\to\installdir install
# nmake /s /nologo /f makefile.vc INSTALLDIR=c:\path\to\installdir test
#
# For other build options (debug, static etc.)
# See TIP 477 (https://core.tcl-lang.org/tips/doc/trunk/tip/477.md) for
# detailed documentation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
#------------------------------------------------------------------------------
PROJECT = tdbcodbc
# Tcl 8.6 etc. compile with /DUNICODE. TDBC pre-nmake reform compiled
# without -DUNICODE. Keep that behaviour for now.
USE_WIDECHAR_API = 0
!include "rules-ext.vc"
# nmakehelp -V <file> <tag> will search the file for tag, skips until a
# number and returns all character until a character not in [0-9.ab]
# is read.
!if [echo REM = This file is generated from Makefile.vc > versions.vc]
!endif
!if [echo TCL_VERSION_REQ = \>> versions.vc] \
&& [nmakehlp -V ..\configure.ac TCL_VERSION_REQ >> versions.vc]
!endif
!include "versions.vc"
PRJ_OBJS = \
$(TMP_DIR)\tdbcodbc.obj \
$(TMP_DIR)\odbcStubInit.obj
# Uncomment the following line if you want to build and install stubs
# PRJ_STUBOBJS = $(TMP_DIR)\odbcStubInit.obj
PRJ_HEADERS = \
$(GENERICDIR)\fakesql.h \
$(GENERICDIR)\odbcStubs.h
# Locate TDBC headers and libraries.
# In principle, we don't need the TDBC source directory, and an installed
# TDBC should suffice. But that needs additional machinery not implemented
# yet.
!if [echo TDBC_DIR = \> nmakehlp.out] \
|| [nmakehlp -L generic\tdbcInt.h >> nmakehlp.out]
!error Could not locate TDBC source directory.
!endif
!include nmakehlp.out
# Get the TDBC version from its configure.ac
!if [echo TDBC_DOTVERSION = \> versions.vc] \
&& [nmakehlp -V "$(TDBC_DIR)\configure.ac" tdbc >> versions.vc]
!error Could not retrieve TDBC version.
!endif
!include versions.vc
TDBC_VERSION = $(TDBC_DOTVERSION:.=)
TDBC_GENERIC_DIR = $(TDBC_DIR)\generic
TDBCSTUBLIBNAME = tdbcstub$(TDBC_VERSION).lib
TDBCSTUBLIB = $(TDBC_DIR)\win\$(BUILDDIRTOP)\$(TDBCSTUBLIBNAME)
TDBC_LIB_FILE = tdbc$(TDBC_VERSION).dll
TDBC_BIN_DIR = $(TDBC_DIR)/win/$(BUILDDIRTOP)
PRJ_INCLUDES = -I"$(TDBC_GENERIC_DIR)"
PRJ_DEFINES = -Dinline=__inline
!if !$(STATIC_BUILD)
PRJ_LIBS = $(TDBCSTUBLIB)
!endif
# Disable standard tes target because we have a custom one.
DISABLE_TARGET_test = 1
!include "$(_RULESDIR)\targets.vc"
# Install needs some extra default actions.
install: default-install-docs-n
# The TIP 477 generation of pkgIndex.tcl from pkgIndex.tcl.in does not include
# all replacements below so define our own it.
pkgindex: $(OUT_DIR)\pkgIndex.tcl
$(OUT_DIR)\pkgIndex.tcl: $(ROOT)\pkgIndex.tcl.in
@nmakehlp -s << $** > $@
@PACKAGE_NAME@ $(PROJECT)
@PACKAGE_VERSION@ $(DOTVERSION)
@TCL_VERSION_REQ@ $(TCL_VERSION_REQ)
@PKG_LIB_FILE@ $(PRJLIBNAME)
<<
test: test-jet test-sqlserver test-sqlite
test: setup $(PROJECT)
test-jet: setup $(PROJECT)
@echo testing tdbcodbc against Jet
@set TDBCODBC_TYPE=jet
# the following is identical for all 3 tests
@set TCL_LIBRARY=$(TCL_LIBRARY:\=/)
@set TCLLIBPATH=$(OUT_DIR_PATH:\=/)
@set TDBC_LIBRARY=$(LIBDIR:\=/)
@$(CPY) $(LIBDIR)\*.tcl $(OUT_DIR)
!if $(TCLINSTALL)
@set PATH=$(_TCLDIR)\bin;$(PATH)
$(DEBUGGER) $(TCLSH) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS)
!else
@set PATH=$(_TCLDIR)\win\$(BUILDDIRTOP);$(PATH)
$(DEBUGGER) $(TCLSH) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) \
-load "package ifneeded tdbc::odbc $(DOTVERSION) \
{source {$(LIBDIR:\=/)/tdbcodbc.tcl};load {$(PRJLIB:\=/)} $(PROJECT)};\
package ifneeded tdbc $(TDBC_DOTVERSION) \
{source {$(TDBC_BIN_DIR:\=/)/tdbc.tcl};load {$(TDBC_BIN_DIR:\=/)/$(TDBC_LIB_FILE)} tdbc}"
!endif
test-sqlserver: setup $(PROJECT)
@echo testing tdbcodbc against SQL Server
@set TDBCODBC_TYPE=sqlserver
# the following is identical for all 3 tests
@set TCL_LIBRARY=$(TCL_LIBRARY:\=/)
@set TCLLIBPATH=$(OUT_DIR_PATH:\=/)
@set TDBC_LIBRARY=$(LIBDIR:\=/)
@$(CPY) $(LIBDIR)\*.tcl $(OUT_DIR)
!if $(TCLINSTALL)
@set PATH=$(_TCLDIR)\bin;$(PATH)
$(DEBUGGER) $(TCLSH) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS)
!else
@set PATH=$(_TCLDIR)\win\$(BUILDDIRTOP);$(PATH)
$(DEBUGGER) $(TCLSH) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) \
-load "package ifneeded tdbc::odbc $(DOTVERSION) \
{source {$(LIBDIR:\=/)/tdbcodbc.tcl};load {$(PRJLIB:\=/)} $(PROJECT)};\
package ifneeded tdbc $(TDBC_DOTVERSION) \
{source {$(TDBC_BIN_DIR:\=/)/tdbc.tcl};load {$(TDBC_BIN_DIR:\=/)/$(TDBC_LIB_FILE)} tdbc}"
!endif
test-sqlite: setup $(PROJECT)
@echo testing tdbcodbc against SQLite
@set TDBCODBC_TYPE=sqlite
# the following is identical for all 3 tests
@set TCL_LIBRARY=$(TCL_LIBRARY:\=/)
@set TCLLIBPATH=$(OUT_DIR_PATH:\=/)
@set TDBC_LIBRARY=$(LIBDIR:\=/)
@$(CPY) $(LIBDIR)\*.tcl $(OUT_DIR)
!if $(TCLINSTALL)
@set PATH=$(_TCLDIR)\bin;$(PATH)
$(DEBUGGER) $(TCLSH) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS)
!else
@set PATH=$(_TCLDIR)\win\$(BUILDDIRTOP);$(PATH)
$(DEBUGGER) $(TCLSH) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) \
-load "package ifneeded tdbc::odbc $(DOTVERSION) \
{source {$(LIBDIR:\=/)/tdbcodbc.tcl};load {$(PRJLIB:\=/)} $(PROJECT)};\
package ifneeded tdbc $(TDBC_DOTVERSION) \
{source {$(TDBC_BIN_DIR:\=/)/tdbc.tcl};load {$(TDBC_BIN_DIR:\=/)/$(TDBC_LIB_FILE)} tdbc}"
!endif

View File

@@ -0,0 +1,815 @@
/*
* ----------------------------------------------------------------------------
* nmakehlp.c --
*
* This is used to fix limitations within nmake and the environment.
*
* Copyright (c) 2002 by David Gravereaux.
* Copyright (c) 2006 by Pat Thoyts
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
* ----------------------------------------------------------------------------
*/
#define _CRT_SECURE_NO_DEPRECATE
#include <windows.h>
#pragma comment (lib, "user32.lib")
#pragma comment (lib, "kernel32.lib")
#include <stdio.h>
#include <math.h>
/*
* This library is required for x64 builds with _some_ versions of MSVC
*/
#if defined(_M_IA64) || defined(_M_AMD64)
#if _MSC_VER >= 1400 && _MSC_VER < 1500
#pragma comment(lib, "bufferoverflowU")
#endif
#endif
/* ISO hack for dumb VC++ */
#ifdef _MSC_VER
#define snprintf _snprintf
#endif
/* protos */
static int CheckForCompilerFeature(const char *option);
static int CheckForLinkerFeature(const char **options, int count);
static int IsIn(const char *string, const char *substring);
static int SubstituteFile(const char *substs, const char *filename);
static int QualifyPath(const char *path);
static int LocateDependency(const char *keyfile);
static const char *GetVersionFromFile(const char *filename, const char *match, int numdots);
static DWORD WINAPI ReadFromPipe(LPVOID args);
/* globals */
#define CHUNK 25
#define STATICBUFFERSIZE 1000
typedef struct {
HANDLE pipe;
char buffer[STATICBUFFERSIZE];
} pipeinfo;
pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'};
pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'};
/*
* exitcodes: 0 == no, 1 == yes, 2 == error
*/
int
main(
int argc,
char *argv[])
{
char msg[300];
DWORD dwWritten;
int chars;
const char *s;
/*
* Make sure children (cl.exe and link.exe) are kept quiet.
*/
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
/*
* Make sure the compiler and linker aren't effected by the outside world.
*/
SetEnvironmentVariable("CL", "");
SetEnvironmentVariable("LINK", "");
if (argc > 1 && *argv[1] == '-') {
switch (*(argv[1]+1)) {
case 'c':
if (argc != 3) {
chars = snprintf(msg, sizeof(msg) - 1,
"usage: %s -c <compiler option>\n"
"Tests for whether cl.exe supports an option\n"
"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
&dwWritten, NULL);
return 2;
}
return CheckForCompilerFeature(argv[2]);
case 'l':
if (argc < 3) {
chars = snprintf(msg, sizeof(msg) - 1,
"usage: %s -l <linker option> ?<mandatory option> ...?\n"
"Tests for whether link.exe supports an option\n"
"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
&dwWritten, NULL);
return 2;
}
return CheckForLinkerFeature(&argv[2], argc-2);
case 'f':
if (argc == 2) {
chars = snprintf(msg, sizeof(msg) - 1,
"usage: %s -f <string> <substring>\n"
"Find a substring within another\n"
"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
&dwWritten, NULL);
return 2;
} else if (argc == 3) {
/*
* If the string is blank, there is no match.
*/
return 0;
} else {
return IsIn(argv[2], argv[3]);
}
case 's':
if (argc == 2) {
chars = snprintf(msg, sizeof(msg) - 1,
"usage: %s -s <substitutions file> <file>\n"
"Perform a set of string map type substutitions on a file\n"
"exitcodes: 0\n",
argv[0]);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
&dwWritten, NULL);
return 2;
}
return SubstituteFile(argv[2], argv[3]);
case 'V':
if (argc != 4) {
chars = snprintf(msg, sizeof(msg) - 1,
"usage: %s -V filename matchstring\n"
"Extract a version from a file:\n"
"eg: pkgIndex.tcl \"package ifneeded http\"",
argv[0]);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
&dwWritten, NULL);
return 0;
}
s = GetVersionFromFile(argv[2], argv[3], *(argv[1]+2) - '0');
if (s && *s) {
printf("%s\n", s);
return 0;
} else
return 1; /* Version not found. Return non-0 exit code */
case 'Q':
if (argc != 3) {
chars = snprintf(msg, sizeof(msg) - 1,
"usage: %s -Q path\n"
"Emit the fully qualified path\n"
"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
&dwWritten, NULL);
return 2;
}
return QualifyPath(argv[2]);
case 'L':
if (argc != 3) {
chars = snprintf(msg, sizeof(msg) - 1,
"usage: %s -L keypath\n"
"Emit the fully qualified path of directory containing keypath\n"
"exitcodes: 0 == success, 1 == not found, 2 == error\n", argv[0]);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
&dwWritten, NULL);
return 2;
}
return LocateDependency(argv[2]);
}
}
chars = snprintf(msg, sizeof(msg) - 1,
"usage: %s -c|-f|-l|-Q|-s|-V ...\n"
"This is a little helper app to equalize shell differences between WinNT and\n"
"Win9x and get nmake.exe to accomplish its job.\n",
argv[0]);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
return 2;
}
static int
CheckForCompilerFeature(
const char *option)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
SECURITY_ATTRIBUTES sa;
DWORD threadID;
char msg[300];
BOOL ok;
HANDLE hProcess, h, pipeThreads[2];
char cmdline[100];
hProcess = GetCurrentProcess();
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = INVALID_HANDLE_VALUE;
ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = FALSE;
/*
* Create a non-inheritible pipe.
*/
CreatePipe(&Out.pipe, &h, &sa, 0);
/*
* Dupe the write side, make it inheritible, and close the original.
*/
DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
/*
* Same as above, but for the error side.
*/
CreatePipe(&Err.pipe, &h, &sa, 0);
DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
/*
* Base command line.
*/
lstrcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X -Fp.\\_junk.pch ");
/*
* Append our option for testing
*/
lstrcat(cmdline, option);
/*
* Filename to compile, which exists, but is nothing and empty.
*/
lstrcat(cmdline, " .\\nul");
ok = CreateProcess(
NULL, /* Module name. */
cmdline, /* Command line. */
NULL, /* Process handle not inheritable. */
NULL, /* Thread handle not inheritable. */
TRUE, /* yes, inherit handles. */
DETACHED_PROCESS, /* No console for you. */
NULL, /* Use parent's environment block. */
NULL, /* Use parent's starting directory. */
&si, /* Pointer to STARTUPINFO structure. */
&pi); /* Pointer to PROCESS_INFORMATION structure. */
if (!ok) {
DWORD err = GetLastError();
int chars = snprintf(msg, sizeof(msg) - 1,
"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
(300-chars), 0);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
return 2;
}
/*
* Close our references to the write handles that have now been inherited.
*/
CloseHandle(si.hStdOutput);
CloseHandle(si.hStdError);
WaitForInputIdle(pi.hProcess, 5000);
CloseHandle(pi.hThread);
/*
* Start the pipe reader threads.
*/
pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
/*
* Block waiting for the process to end.
*/
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
/*
* Wait for our pipe to get done reading, should it be a little slow.
*/
WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
CloseHandle(pipeThreads[0]);
CloseHandle(pipeThreads[1]);
/*
* Look for the commandline warning code in both streams.
* - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002.
*/
return !(strstr(Out.buffer, "D4002") != NULL
|| strstr(Err.buffer, "D4002") != NULL
|| strstr(Out.buffer, "D9002") != NULL
|| strstr(Err.buffer, "D9002") != NULL
|| strstr(Out.buffer, "D2021") != NULL
|| strstr(Err.buffer, "D2021") != NULL);
}
static int
CheckForLinkerFeature(
const char **options,
int count)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
SECURITY_ATTRIBUTES sa;
DWORD threadID;
char msg[300];
BOOL ok;
HANDLE hProcess, h, pipeThreads[2];
int i;
char cmdline[255];
hProcess = GetCurrentProcess();
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = INVALID_HANDLE_VALUE;
ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
/*
* Create a non-inheritible pipe.
*/
CreatePipe(&Out.pipe, &h, &sa, 0);
/*
* Dupe the write side, make it inheritible, and close the original.
*/
DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
/*
* Same as above, but for the error side.
*/
CreatePipe(&Err.pipe, &h, &sa, 0);
DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
/*
* Base command line.
*/
lstrcpy(cmdline, "link.exe -nologo ");
/*
* Append our option for testing.
*/
for (i = 0; i < count; i++) {
lstrcat(cmdline, " \"");
lstrcat(cmdline, options[i]);
lstrcat(cmdline, "\"");
}
ok = CreateProcess(
NULL, /* Module name. */
cmdline, /* Command line. */
NULL, /* Process handle not inheritable. */
NULL, /* Thread handle not inheritable. */
TRUE, /* yes, inherit handles. */
DETACHED_PROCESS, /* No console for you. */
NULL, /* Use parent's environment block. */
NULL, /* Use parent's starting directory. */
&si, /* Pointer to STARTUPINFO structure. */
&pi); /* Pointer to PROCESS_INFORMATION structure. */
if (!ok) {
DWORD err = GetLastError();
int chars = snprintf(msg, sizeof(msg) - 1,
"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
(300-chars), 0);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
return 2;
}
/*
* Close our references to the write handles that have now been inherited.
*/
CloseHandle(si.hStdOutput);
CloseHandle(si.hStdError);
WaitForInputIdle(pi.hProcess, 5000);
CloseHandle(pi.hThread);
/*
* Start the pipe reader threads.
*/
pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
/*
* Block waiting for the process to end.
*/
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
/*
* Wait for our pipe to get done reading, should it be a little slow.
*/
WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
CloseHandle(pipeThreads[0]);
CloseHandle(pipeThreads[1]);
/*
* Look for the commandline warning code in the stderr stream.
*/
return !(strstr(Out.buffer, "LNK1117") != NULL ||
strstr(Err.buffer, "LNK1117") != NULL ||
strstr(Out.buffer, "LNK4044") != NULL ||
strstr(Err.buffer, "LNK4044") != NULL ||
strstr(Out.buffer, "LNK4224") != NULL ||
strstr(Err.buffer, "LNK4224") != NULL);
}
static DWORD WINAPI
ReadFromPipe(
LPVOID args)
{
pipeinfo *pi = (pipeinfo *) args;
char *lastBuf = pi->buffer;
DWORD dwRead;
BOOL ok;
again:
if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) {
CloseHandle(pi->pipe);
return (DWORD)-1;
}
ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L);
if (!ok || dwRead == 0) {
CloseHandle(pi->pipe);
return 0;
}
lastBuf += dwRead;
goto again;
return 0; /* makes the compiler happy */
}
static int
IsIn(
const char *string,
const char *substring)
{
return (strstr(string, substring) != NULL);
}
/*
* GetVersionFromFile --
* Looks for a match string in a file and then returns the version
* following the match where a version is anything acceptable to
* package provide or package ifneeded.
*/
static const char *
GetVersionFromFile(
const char *filename,
const char *match,
int numdots)
{
size_t cbBuffer = 100;
static char szBuffer[100];
char *szResult = NULL;
FILE *fp = fopen(filename, "rt");
if (fp != NULL) {
/*
* Read data until we see our match string.
*/
while (fgets(szBuffer, cbBuffer, fp) != NULL) {
LPSTR p, q;
p = strstr(szBuffer, match);
if (p != NULL) {
/*
* Skip to first digit after the match.
*/
p += strlen(match);
while (*p && !isdigit(*p)) {
++p;
}
/*
* Find ending whitespace.
*/
q = p;
while (*q && (strchr("0123456789.ab", *q)) && ((!strchr(".ab", *q)
&& (!strchr("ab", q[-1])) || --numdots))) {
++q;
}
memcpy(szBuffer, p, q - p);
szBuffer[q-p] = 0;
szResult = szBuffer;
break;
}
}
fclose(fp);
}
return szResult;
}
/*
* List helpers for the SubstituteFile function
*/
typedef struct list_item_t {
struct list_item_t *nextPtr;
char * key;
char * value;
} list_item_t;
/* insert a list item into the list (list may be null) */
static list_item_t *
list_insert(list_item_t **listPtrPtr, const char *key, const char *value)
{
list_item_t *itemPtr = malloc(sizeof(list_item_t));
if (itemPtr) {
itemPtr->key = strdup(key);
itemPtr->value = strdup(value);
itemPtr->nextPtr = NULL;
while(*listPtrPtr) {
listPtrPtr = &(*listPtrPtr)->nextPtr;
}
*listPtrPtr = itemPtr;
}
return itemPtr;
}
static void
list_free(list_item_t **listPtrPtr)
{
list_item_t *tmpPtr, *listPtr = *listPtrPtr;
while (listPtr) {
tmpPtr = listPtr;
listPtr = listPtr->nextPtr;
free(tmpPtr->key);
free(tmpPtr->value);
free(tmpPtr);
}
}
/*
* SubstituteFile --
* As windows doesn't provide anything useful like sed and it's unreliable
* to use the tclsh you are building against (consider x-platform builds -
* eg compiling AMD64 target from IX86) we provide a simple substitution
* option here to handle autoconf style substitutions.
* The substitution file is whitespace and line delimited. The file should
* consist of lines matching the regular expression:
* \s*\S+\s+\S*$
*
* Usage is something like:
* nmakehlp -S << $** > $@
* @PACKAGE_NAME@ $(PACKAGE_NAME)
* @PACKAGE_VERSION@ $(PACKAGE_VERSION)
* <<
*/
static int
SubstituteFile(
const char *substitutions,
const char *filename)
{
size_t cbBuffer = 1024;
static char szBuffer[1024], szCopy[1024];
char *szResult = NULL;
list_item_t *substPtr = NULL;
FILE *fp, *sp;
fp = fopen(filename, "rt");
if (fp != NULL) {
/*
* Build a list of substutitions from the first filename
*/
sp = fopen(substitutions, "rt");
if (sp != NULL) {
while (fgets(szBuffer, cbBuffer, sp) != NULL) {
unsigned char *ks, *ke, *vs, *ve;
ks = (unsigned char*)szBuffer;
while (ks && *ks && isspace(*ks)) ++ks;
ke = ks;
while (ke && *ke && !isspace(*ke)) ++ke;
vs = ke;
while (vs && *vs && isspace(*vs)) ++vs;
ve = vs;
while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve;
*ke = 0, *ve = 0;
list_insert(&substPtr, (char*)ks, (char*)vs);
}
fclose(sp);
}
/* debug: dump the list */
#ifndef NDEBUG
{
int n = 0;
list_item_t *p = NULL;
for (p = substPtr; p != NULL; p = p->nextPtr, ++n) {
fprintf(stderr, "% 3d '%s' => '%s'\n", n, p->key, p->value);
}
}
#endif
/*
* Run the substitutions over each line of the input
*/
while (fgets(szBuffer, cbBuffer, fp) != NULL) {
list_item_t *p = NULL;
for (p = substPtr; p != NULL; p = p->nextPtr) {
char *m = strstr(szBuffer, p->key);
if (m) {
char *cp, *op, *sp;
cp = szCopy;
op = szBuffer;
while (op != m) *cp++ = *op++;
sp = p->value;
while (sp && *sp) *cp++ = *sp++;
op += strlen(p->key);
while (*op) *cp++ = *op++;
*cp = 0;
memcpy(szBuffer, szCopy, sizeof(szCopy));
}
}
printf(szBuffer);
}
list_free(&substPtr);
}
fclose(fp);
return 0;
}
BOOL FileExists(LPCTSTR szPath)
{
#ifndef INVALID_FILE_ATTRIBUTES
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
#endif
DWORD pathAttr = GetFileAttributes(szPath);
return (pathAttr != INVALID_FILE_ATTRIBUTES &&
!(pathAttr & FILE_ATTRIBUTE_DIRECTORY));
}
/*
* QualifyPath --
*
* This composes the current working directory with a provided path
* and returns the fully qualified and normalized path.
* Mostly needed to setup paths for testing.
*/
static int
QualifyPath(
const char *szPath)
{
char szCwd[MAX_PATH + 1];
GetFullPathName(szPath, sizeof(szCwd)-1, szCwd, NULL);
printf("%s\n", szCwd);
return 0;
}
/*
* Implements LocateDependency for a single directory. See that command
* for an explanation.
* Returns 0 if found after printing the directory.
* Returns 1 if not found but no errors.
* Returns 2 on any kind of error
* Basically, these are used as exit codes for the process.
*/
static int LocateDependencyHelper(const char *dir, const char *keypath)
{
HANDLE hSearch;
char path[MAX_PATH+1];
int dirlen, keylen, ret;
WIN32_FIND_DATA finfo;
if (dir == NULL || keypath == NULL)
return 2; /* Have no real error reporting mechanism into nmake */
dirlen = strlen(dir);
if ((dirlen + 3) > sizeof(path))
return 2;
strncpy(path, dir, dirlen);
strncpy(path+dirlen, "\\*", 3); /* Including terminating \0 */
keylen = strlen(keypath);
#if 0 /* This function is not available in Visual C++ 6 */
/*
* Use numerics 0 -> FindExInfoStandard,
* 1 -> FindExSearchLimitToDirectories,
* as these are not defined in Visual C++ 6
*/
hSearch = FindFirstFileEx(path, 0, &finfo, 1, NULL, 0);
#else
hSearch = FindFirstFile(path, &finfo);
#endif
if (hSearch == INVALID_HANDLE_VALUE)
return 1; /* Not found */
/* Loop through all subdirs checking if the keypath is under there */
ret = 1; /* Assume not found */
do {
int sublen;
/*
* We need to check it is a directory despite the
* FindExSearchLimitToDirectories in the above call. See SDK docs
*/
if ((finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
continue;
sublen = strlen(finfo.cFileName);
if ((dirlen+1+sublen+1+keylen+1) > sizeof(path))
continue; /* Path does not fit, assume not matched */
strncpy(path+dirlen+1, finfo.cFileName, sublen);
path[dirlen+1+sublen] = '\\';
strncpy(path+dirlen+1+sublen+1, keypath, keylen+1);
if (FileExists(path)) {
/* Found a match, print to stdout */
path[dirlen+1+sublen] = '\0';
QualifyPath(path);
ret = 0;
break;
}
} while (FindNextFile(hSearch, &finfo));
FindClose(hSearch);
return ret;
}
/*
* LocateDependency --
*
* Locates a dependency for a package.
* keypath - a relative path within the package directory
* that is used to confirm it is the correct directory.
* The search path for the package directory is currently only
* the parent and grandparent of the current working directory.
* If found, the command prints
* name_DIRPATH=<full path of located directory>
* and returns 0. If not found, does not print anything and returns 1.
*/
static int LocateDependency(const char *keypath)
{
int i, ret;
static const char *paths[] = {"..", "..\\..", "..\\..\\.."};
for (i = 0; i < (sizeof(paths)/sizeof(paths[0])); ++i) {
ret = LocateDependencyHelper(paths[i], keypath);
if (ret == 0)
return ret;
}
return ret;
}
/*
* Local variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* indent-tabs-mode: t
* tab-width: 8
* End:
*/

View File

@@ -0,0 +1,118 @@
# This file should only be included in makefiles for Tcl extensions,
# NOT in the makefile for Tcl itself.
!ifndef _RULES_EXT_VC
# We need to run from the directory the parent makefile is located in.
# nmake does not tell us what makefile was used to invoke it so parent
# makefile has to set the MAKEFILEVC macro or we just make a guess and
# warn if we think that is not the case.
!if "$(MAKEFILEVC)" == ""
!if exist("$(PROJECT).vc")
MAKEFILEVC = $(PROJECT).vc
!elseif exist("makefile.vc")
MAKEFILEVC = makefile.vc
!endif
!endif # "$(MAKEFILEVC)" == ""
!if !exist("$(MAKEFILEVC)")
MSG = ^
You must run nmake from the directory containing the project makefile.^
If you are doing that and getting this message, set the MAKEFILEVC^
macro to the name of the project makefile.
!message WARNING: $(MSG)
!endif
!if "$(PROJECT)" == "tcl"
!error The rules-ext.vc file is not intended for Tcl itself.
!endif
# We extract version numbers using the nmakehlp program. For now use
# the local copy of nmakehlp. Once we locate Tcl, we will use that
# one if it is newer.
!if [$(CC) -nologo -DNDEBUG "nmakehlp.c" -link -subsystem:console > nul]
!endif
# First locate the Tcl directory that we are working with.
!if "$(TCLDIR)" != ""
_RULESDIR = $(TCLDIR:/=\)
!else
# If an installation path is specified, that is also the Tcl directory.
# Also Tk never builds against an installed Tcl, it needs Tcl sources
!if defined(INSTALLDIR) && "$(PROJECT)" != "tk"
_RULESDIR=$(INSTALLDIR:/=\)
!else
# Locate Tcl sources
!if [echo _RULESDIR = \> nmakehlp.out] \
|| [nmakehlp -L generic\tcl.h >> nmakehlp.out]
_RULESDIR = ..\..\tcl
!else
!include nmakehlp.out
!endif
!endif # defined(INSTALLDIR)....
!endif # ifndef TCLDIR
# Now look for the targets.vc file under the Tcl root. Note we check this
# file and not rules.vc because the latter also exists on older systems.
!if exist("$(_RULESDIR)\lib\nmake\targets.vc") # Building against installed Tcl
_RULESDIR = $(_RULESDIR)\lib\nmake
!elseif exist("$(_RULESDIR)\win\targets.vc") # Building against Tcl sources
_RULESDIR = $(_RULESDIR)\win
!else
# If we have not located Tcl's targets file, most likely we are compiling
# against an older version of Tcl and so must use our own support files.
_RULESDIR = .
!endif
!if "$(_RULESDIR)" != "."
# Potentially using Tcl's support files. If this extension has its own
# nmake support files, need to compare the versions and pick newer.
!if exist("rules.vc") # The extension has its own copy
!if [echo TCL_RULES_MAJOR = \> versions.vc] \
&& [nmakehlp -V "$(_RULESDIR)\rules.vc" RULES_VERSION_MAJOR >> versions.vc]
!endif
!if [echo TCL_RULES_MINOR = \>> versions.vc] \
&& [nmakehlp -V "$(_RULESDIR)\rules.vc" RULES_VERSION_MINOR >> versions.vc]
!endif
!if [echo OUR_RULES_MAJOR = \>> versions.vc] \
&& [nmakehlp -V "rules.vc" RULES_VERSION_MAJOR >> versions.vc]
!endif
!if [echo OUR_RULES_MINOR = \>> versions.vc] \
&& [nmakehlp -V "rules.vc" RULES_VERSION_MINOR >> versions.vc]
!endif
!include versions.vc
# We have a newer version of the support files, use them
!if ($(TCL_RULES_MAJOR) != $(OUR_RULES_MAJOR)) || ($(TCL_RULES_MINOR) < $(OUR_RULES_MINOR))
_RULESDIR = .
!endif
!endif # if exist("rules.vc")
!endif # if $(_RULESDIR) != "."
# Let rules.vc know what copy of nmakehlp.c to use.
NMAKEHLPC = $(_RULESDIR)\nmakehlp.c
# Get rid of our internal defines before calling rules.vc
!undef TCL_RULES_MAJOR
!undef TCL_RULES_MINOR
!undef OUR_RULES_MAJOR
!undef OUR_RULES_MINOR
!if exist("$(_RULESDIR)\rules.vc")
!message *** Using $(_RULESDIR)\rules.vc
!include "$(_RULESDIR)\rules.vc"
!else
!error *** Could not locate rules.vc in $(_RULESDIR)
!endif
!endif # _RULES_EXT_VC

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,98 @@
#------------------------------------------------------------- -*- makefile -*-
# targets.vc --
#
# Part of the nmake based build system for Tcl and its extensions.
# This file defines some standard targets for the convenience of extensions
# and can be optionally included by the extension makefile.
# See TIP 477 (https://core.tcl-lang.org/tips/doc/main/tip/477.md) for docs.
$(PROJECT): setup pkgindex $(PRJLIB)
!ifdef PRJ_STUBOBJS
$(PROJECT): $(PRJSTUBLIB)
$(PRJSTUBLIB): $(PRJ_STUBOBJS)
$(LIBCMD) $**
$(PRJ_STUBOBJS):
$(CCSTUBSCMD) %s
!endif # PRJ_STUBOBJS
!ifdef PRJ_MANIFEST
$(PROJECT): $(PRJLIB).manifest
$(PRJLIB).manifest: $(PRJ_MANIFEST)
@nmakehlp -s << $** >$@
@MACHINE@ $(MACHINE:IX86=X86)
<<
!endif
!if "$(PROJECT)" != "tcl" && "$(PROJECT)" != "tk"
$(PRJLIB): $(PRJ_OBJS) $(RESFILE)
!if $(STATIC_BUILD)
$(LIBCMD) $**
!else
$(DLLCMD) $**
$(_VC_MANIFEST_EMBED_DLL)
!endif
-@del $*.exp
!endif
!if "$(PRJ_HEADERS)" != "" && "$(PRJ_OBJS)" != ""
$(PRJ_OBJS): $(PRJ_HEADERS)
!endif
# If parent makefile has defined stub objects, add their installation
# to the default install
!if "$(PRJ_STUBOBJS)" != ""
default-install: default-install-stubs
!endif
# Unlike the other default targets, these cannot be in rules.vc because
# the executed command depends on existence of macro PRJ_HEADERS_PUBLIC
# that the parent makefile will not define until after including rules-ext.vc
!if "$(PRJ_HEADERS_PUBLIC)" != ""
default-install: default-install-headers
default-install-headers:
@echo Installing headers to '$(INCLUDE_INSTALL_DIR)'
@for %f in ($(PRJ_HEADERS_PUBLIC)) do @$(COPY) %f "$(INCLUDE_INSTALL_DIR)"
!endif
!if "$(DISABLE_STANDARD_TARGETS)" == ""
DISABLE_STANDARD_TARGETS = 0
!endif
!if "$(DISABLE_TARGET_setup)" == ""
DISABLE_TARGET_setup = 0
!endif
!if "$(DISABLE_TARGET_install)" == ""
DISABLE_TARGET_install = 0
!endif
!if "$(DISABLE_TARGET_clean)" == ""
DISABLE_TARGET_clean = 0
!endif
!if "$(DISABLE_TARGET_test)" == ""
DISABLE_TARGET_test = 0
!endif
!if "$(DISABLE_TARGET_shell)" == ""
DISABLE_TARGET_shell = 0
!endif
!if !$(DISABLE_STANDARD_TARGETS)
!if !$(DISABLE_TARGET_setup)
setup: default-setup
!endif
!if !$(DISABLE_TARGET_install)
install: default-install
!endif
!if !$(DISABLE_TARGET_clean)
clean: default-clean
realclean: hose
hose: default-hose
distclean: realclean default-distclean
!endif
!if !$(DISABLE_TARGET_test)
test: default-test
!endif
!if !$(DISABLE_TARGET_shell)
shell: default-shell
!endif
!endif # DISABLE_STANDARD_TARGETS