├── tests ├── test.mdb └── all.tcl ├── TODO ├── pkgIndex.tcl.in ├── README ├── license.terms ├── generic ├── odbcStubDefs.txt ├── odbcStubs.h ├── odbcStubInit.c └── fakesql.h ├── aclocal.m4 ├── doc └── tdbc_odbc.n ├── configure.in ├── library └── tdbcodbc.tcl ├── win ├── nmakehlp.c ├── rules.vc └── makefile.vc ├── Makefile.in └── ChangeLog /tests/test.mdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcltk/tdbcodbc/master/tests/test.mdb -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | db primarykeys? 2 | db indexes? 3 | 4 | Compound statements 5 | 6 | Restore 8.5 buildability. 7 | -------------------------------------------------------------------------------- /pkgIndex.tcl.in: -------------------------------------------------------------------------------- 1 | # Package index file for tdbc::odbc 2 | 3 | if {[catch {package require Tcl @TCL_VERSION_REQ@}]} { 4 | return 5 | } 6 | package ifneeded tdbc::odbc @PACKAGE_VERSION@ \ 7 | "[list source [file join $dir @PACKAGE_NAME@.tcl]]\;\ 8 | [list load [file join $dir @PKG_LIB_FILE@] @PACKAGE_NAME@]" 9 | -------------------------------------------------------------------------------- /tests/all.tcl: -------------------------------------------------------------------------------- 1 | # all.tcl -- 2 | # 3 | # This file contains a top-level script to run all of the Tcl 4 | # tests. Execute it by invoking "source all.test" when running tcltest 5 | # in this directory. 6 | # 7 | # Copyright (c) 1998-2000 by Scriptics Corporation. 8 | # All rights reserved. 9 | # 10 | # RCS: @(#) $Id: all.tcl,v 1.4 2004/07/04 22:04:20 patthoyts Exp $ 11 | 12 | package require Tcl 8.6 13 | package require tcltest 2.2 14 | ::tcltest::configure \ 15 | -testdir [file dirname [file normalize [info script]]] \ 16 | {*}$argv 17 | ::tcltest::runAllTests 18 | rename exit {} 19 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | README: tdbcodbc 2 | 3 | This is the 1.0.0 source distribution of the bridge between Tcl 4 | Database Connectivity (TDBC) and Open Database Connectivity 5 | (ODBC), a database-neutral API layer available on all Windows 6 | systems and many others.. TDBC and its drivers are available from 7 | a Fossil version control repository at http://tdbc.tcl.tk/ 8 | 9 | RCS: @(#) $Id: $ 10 | 11 | 1. Introduction 12 | 13 | This directory contains the source code, documentation, and test 14 | scripts for the ODBC driver for Tcl Database Connectivity. This 15 | module, plus TDBC itself, allow you to access ODBC databases using a 16 | standard application programming interface (API) from a Tcl script. 17 | This module is also available from http://tdbc.tcl.tk along with the 18 | source code of TDBC itself. A bug database and Wiki are available at 19 | the same location. 20 | 21 | Tdbc::odbc is a freely-available open source package. You can do 22 | virtually anything you like with it, such as modifying it, 23 | redistributing it, and selling it either in whole or in part. See the 24 | file "license.terms" for complete information. 25 | 26 | 2. Documentation 27 | 28 | The 'doc' subdirectory in this release contains a set of reference 29 | manual entries for tdbc::odbc. Files with an extension '.n' are for 30 | Tcl classes and commands; files with an extension '.3' are for C 31 | library functions. The file, 'doc/tdbcodbc.n' gives an overview, 32 | listing the classes and functions 33 | 34 | 3. See also 35 | 36 | More information about TDBC and its drivers are available in the 37 | README file for TDBC itself; refer to that file for compilation and 38 | installation instructions, and support information. 39 | -------------------------------------------------------------------------------- /license.terms: -------------------------------------------------------------------------------- 1 | This software is copyrighted by Kevin B. Kenny, and by other parties. 2 | The following terms apply to all files associated with the software 3 | unless explicitly disclaimed in individual files. 4 | 5 | The authors hereby grant permission to use, copy, modify, distribute, 6 | and license this software and its documentation for any purpose, provided 7 | that existing copyright notices are retained in all copies and that this 8 | notice is included verbatim in any distributions. No written agreement, 9 | license, or royalty fee is required for any of the authorized uses. 10 | Modifications to this software may be copyrighted by their authors 11 | and need not follow the licensing terms described here, provided that 12 | the new terms are clearly indicated on the first page of each file where 13 | they apply. 14 | 15 | IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY 16 | FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 17 | ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY 18 | DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE 19 | POSSIBILITY OF SUCH DAMAGE. 20 | 21 | THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, 22 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE 24 | IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE 25 | NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 26 | MODIFICATIONS. 27 | 28 | GOVERNMENT USE: If you are acquiring this software on behalf of the 29 | U.S. government, the Government shall have only "Restricted Rights" 30 | in the software and related documentation as defined in the Federal 31 | Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you 32 | are acquiring the software on behalf of the Department of Defense, the 33 | software shall be classified as "Commercial Computer Software" and the 34 | Government shall have only "Restricted Rights" as defined in Clause 35 | 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the 36 | authors grant the U.S. Government and others acting in its behalf 37 | permission to use and distribute the software in accordance with the 38 | terms specified in this license. 39 | -------------------------------------------------------------------------------- /generic/odbcStubDefs.txt: -------------------------------------------------------------------------------- 1 | # odbcStubDefs.txt -- 2 | # 3 | # Definitions of routines in the ODBC DLL that will be resolved 4 | # and imported at run time. 5 | # 6 | # This file contains only function declarations necessary to interoperability 7 | # with the SQL/CLI application programming interface. The programmers believe 8 | # that the material in this file is not subject to copyright, under the 9 | # doctrines of scenes a faire and of the merger of idea and expression. 10 | # Accordingly, this file is in the public domain. 11 | # 12 | #----------------------------------------------------------------------------- 13 | 14 | * STUBSTRUCT: odbcStubs 15 | * LIBRARY: odbc32 odbc libodbc32 libodbc 16 | * CONVENTION: SQL_API 17 | 18 | SQLRETURN SQLAllocHandle(SQLSMALLINT,SQLHANDLE,SQLHANDLE*); 19 | SQLRETURN SQLBindParameter(SQLHSTMT,SQLUSMALLINT,SQLSMALLINT,SQLSMALLINT,SQLSMALLINT,SQLULEN,SQLSMALLINT,SQLPOINTER,SQLLEN,SQLLEN*); 20 | SQLRETURN SQLCloseCursor(SQLHSTMT); 21 | SQLRETURN SQLColumnsW(SQLHSTMT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT ,SQLWCHAR*,SQLSMALLINT ); 22 | SQLRETURN SQLDataSourcesW(SQLHENV,SQLUSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*); 23 | SQLRETURN SQLDescribeColW(SQLHSTMT,SQLUSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*,SQLSMALLINT*,SQLULEN*,SQLSMALLINT*,SQLSMALLINT*); 24 | SQLRETURN SQLDescribeParam(SQLHSTMT,SQLUSMALLINT,SQLSMALLINT*,SQLULEN*,SQLSMALLINT*,SQLSMALLINT*); 25 | SQLRETURN SQLDisconnect(SQLHDBC); 26 | SQLRETURN SQLDriverConnectW(SQLHDBC,SQLHWND,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*,SQLUSMALLINT); 27 | SQLRETURN SQLDriversW(SQLHENV,SQLUSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*); 28 | SQLRETURN SQLEndTran(SQLSMALLINT,SQLHANDLE,SQLSMALLINT); 29 | SQLRETURN SQLExecute(SQLHSTMT); 30 | SQLRETURN SQLFetch(SQLHSTMT); 31 | SQLRETURN SQLForeignKeysW(SQLHSTMT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT); 32 | SQLRETURN SQLFreeHandle(SQLSMALLINT,SQLHANDLE); 33 | SQLRETURN SQLGetConnectAttr(SQLHDBC,SQLINTEGER,SQLPOINTER,SQLINTEGER,SQLINTEGER*); 34 | SQLRETURN SQLGetData(SQLHSTMT,SQLUSMALLINT,SQLSMALLINT,SQLPOINTER,SQLLEN,SQLLEN*); 35 | SQLRETURN SQLGetDiagFieldA(SQLSMALLINT,SQLHANDLE,SQLSMALLINT,SQLSMALLINT,SQLPOINTER,SQLSMALLINT,SQLSMALLINT*); 36 | SQLRETURN SQLGetDiagRecW(SQLSMALLINT,SQLHANDLE,SQLSMALLINT,SQLWCHAR*,SQLINTEGER*,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*); 37 | SQLRETURN SQLGetTypeInfo(SQLHSTMT,SQLSMALLINT); 38 | SQLRETURN SQLMoreResults(SQLHSTMT); 39 | SQLRETURN SQLNumParams(SQLHSTMT,SQLSMALLINT*); 40 | SQLRETURN SQLNumResultCols(SQLHSTMT,SQLSMALLINT*); 41 | SQLRETURN SQLPrepareW(SQLHSTMT,SQLWCHAR*,SQLINTEGER); 42 | SQLRETURN SQLPrimaryKeysW(SQLHSTMT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT); 43 | SQLRETURN SQLRowCount(SQLHSTMT,SQLLEN*); 44 | SQLRETURN SQLSetConnectAttr(SQLHDBC,SQLINTEGER,SQLPOINTER,SQLINTEGER); 45 | SQLRETURN SQLSetConnectOption(SQLHDBC,SQLUSMALLINT,SQLULEN); /* deprecated */ 46 | SQLRETURN SQLSetEnvAttr(SQLHENV,SQLINTEGER,SQLPOINTER,SQLINTEGER); 47 | SQLRETURN SQLTablesW(SQLHSTMT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT); 48 | -------------------------------------------------------------------------------- /aclocal.m4: -------------------------------------------------------------------------------- 1 | # 2 | # Include the TEA standard macro set 3 | # 4 | 5 | builtin(include,tclconfig/tcl.m4) 6 | 7 | # 8 | # Add here whatever m4 macros you want to define for your package 9 | # 10 | 11 | dnl Helper macros 12 | AC_DEFUN([TEAX_LAPPEND], [$1="[$]{$1} $2"]) 13 | AC_DEFUN([TEAX_FOREACH], [for $1 in $2; do $3; done]) 14 | AC_DEFUN([TEAX_IFEQ], [AS_IF([test "x$1" = "x$2"], [$3])]) 15 | AC_DEFUN([TEAX_IFNEQ], [AS_IF([test "x$1" != "x$2"], [$3])]) 16 | AC_DEFUN([TEAX_SWITCH], [case "$1" in TEAX_SWITCH_Cases(m4_shift($@)) esac]) 17 | AC_DEFUN([TEAX_SWITCH_Cases], [m4_if([$#],0,,[$#],1,,[TEAX_SWITCH_OneCase($1,$2)TEAX_SWITCH_Cases(m4_shift(m4_shift($@)))])]) 18 | AC_DEFUN([TEAX_SWITCH_OneCase],[ $1) $2;;]) 19 | AC_DEFUN([CygPath],[`${CYGPATH} $1`]) 20 | 21 | dnl Interesting macros 22 | AC_DEFUN([TEAX_SUBST_RESOURCE], [ 23 | AC_REQUIRE([TEA_CONFIG_CFLAGS])dnl 24 | TEAX_IFEQ($TEA_PLATFORM, windows, [ 25 | AC_CHECK_PROGS(RC_, 'windres -o' 'rc -nologo -fo', none) 26 | TEAX_SWITCH($RC_, 27 | windres*, [ 28 | rcdef_inc="--include " 29 | rcdef_start="--define " 30 | rcdef_q='\"' 31 | AC_SUBST(RES_SUFFIX, [res.o]) 32 | TEAX_LAPPEND(PKG_OBJECTS, ${PACKAGE_NAME}.res.o)], 33 | rc*, [ 34 | rcdef_inc="-i " 35 | rcdef_start="-d " 36 | rcdef_q='"' 37 | AC_SUBST(RES_SUFFIX, [res]) 38 | TEAX_LAPPEND(PKG_OBJECTS, ${PACKAGE_NAME}.res)], 39 | *, [ 40 | AC_MSG_WARN([could not find resource compiler]) 41 | RC_=: ])]) 42 | # This next line is because of the brokenness of TEA... 43 | AC_SUBST(RC, $RC_) 44 | TEAX_FOREACH(i, $1, [ 45 | TEAX_LAPPEND(RES_DEFS, ${rcdef_inc}\"CygPath($i)\")]) 46 | TEAX_FOREACH(i, $2, [ 47 | TEAX_LAPPEND(RES_DEFS, ${rcdef_start}$i='${rcdef_q}\$($i)${rcdef_q}')]) 48 | AC_SUBST(RES_DEFS)]) 49 | AC_DEFUN([TEAX_ADD_PRIVATE_HEADERS], [ 50 | TEAX_FOREACH(i, $@, [ 51 | # check for existence, be strict because it should be present! 52 | AS_IF([test ! -f "${srcdir}/$i"], [ 53 | AC_MSG_ERROR([could not find header file '${srcdir}/$i'])]) 54 | TEAX_LAPPEND(PKG_PRIVATE_HEADERS, $i)]) 55 | AC_SUBST(PKG_PRIVATE_HEADERS)]) 56 | 57 | dnl Extra magic to make things work with Vista and VC 58 | AC_DEFUN([TEAX_VC_MANIFEST], [ 59 | ADD_MANIFEST=":" 60 | AS_IF([test "$GCC" != yes \ 61 | -a ${TEA_PLATFORM} == "windows" \ 62 | -a "${SHARED_BUILD}" = "1"], [ 63 | # This refers to "Manifest Tool" not "Magnetic Tape utility" 64 | AC_CHECK_PROGS(MT, mt, none) 65 | AS_IF([test "$MT" != none], [ 66 | ADD_MANIFEST="${MT} -nologo -manifest [\$]@.manifest -outputresource:[\$]@\;2" 67 | CLEANFILES="$CLEANFILES ${PKG_LIB_FILE}.manifest"])]) 68 | AC_SUBST(ADD_MANIFEST)]) 69 | 70 | AC_DEFUN([TEAX_SDX], [ 71 | AC_PATH_PROG(SDX, sdx, none) 72 | TEAX_IFEQ($SDX, none, [ 73 | AC_PATH_PROG(SDX_KIT, sdx.kit, none) 74 | TEAX_IFNEQ($SDX_KIT, none, [ 75 | # We assume that sdx.kit is on the path, and that the default 76 | # tclsh is activetcl 77 | SDX="tclsh '${SDX_KIT}'"])]) 78 | TEAX_IFEQ($SDX, none, [ 79 | AC_MSG_WARN([cannot find sdx; building starkits will fail]) 80 | AC_MSG_NOTICE([building as a normal library still supported])])]) 81 | dnl TODO: Adapt this for OSX Frameworks... 82 | dnl This next bit is a bit ugly, but it makes things for tclooConfig.sh... 83 | AC_DEFUN([TEAX_PATH_LINE], [ 84 | eval "$1=\"[]CygPath($2)\"" 85 | AC_SUBST($1)]) 86 | AC_DEFUN([TEAX_INCLUDE_LINE], [ 87 | eval "$1=\"-I[]CygPath($2)\"" 88 | AC_SUBST($1)]) 89 | AC_DEFUN([TEAX_LINK_LINE], [ 90 | AS_IF([test ${TCL_LIB_VERSIONS_OK} = nodots], [ 91 | eval "$1=\"-L[]CygPath($2) -l$3${TCL_TRIM_DOTS}\"" 92 | ], [ 93 | eval "$1=\"-L[]CygPath($2) -l$3${PACKAGE_VERSION}\"" 94 | ]) 95 | AC_SUBST($1)]) 96 | 97 | dnl Local Variables: 98 | dnl mode: autoconf 99 | dnl End: 100 | -------------------------------------------------------------------------------- /generic/odbcStubs.h: -------------------------------------------------------------------------------- 1 | /* 2 | *----------------------------------------------------------------------------- 3 | * 4 | * ../generic/odbcStubs.h -- 5 | * 6 | * Stubs for procedures in odbcStubDefs.txt 7 | * 8 | * Generated by genExtStubs.tcl: DO NOT EDIT 9 | * 2011-01-22 20:11:52Z 10 | * 11 | *----------------------------------------------------------------------------- 12 | */ 13 | 14 | typedef struct odbcStubDefs { 15 | 16 | /* Functions from libraries: odbc32 odbc libodbc32 libodbc */ 17 | 18 | SQLRETURN (SQL_API*SQLAllocHandlePtr)(SQLSMALLINT,SQLHANDLE,SQLHANDLE*); 19 | SQLRETURN (SQL_API*SQLBindParameterPtr)(SQLHSTMT,SQLUSMALLINT,SQLSMALLINT,SQLSMALLINT,SQLSMALLINT,SQLULEN,SQLSMALLINT,SQLPOINTER,SQLLEN,SQLLEN*); 20 | SQLRETURN (SQL_API*SQLCloseCursorPtr)(SQLHSTMT); 21 | SQLRETURN (SQL_API*SQLColumnsWPtr)(SQLHSTMT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT ,SQLWCHAR*,SQLSMALLINT ); 22 | SQLRETURN (SQL_API*SQLDataSourcesWPtr)(SQLHENV,SQLUSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*); 23 | SQLRETURN (SQL_API*SQLDescribeColWPtr)(SQLHSTMT,SQLUSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*,SQLSMALLINT*,SQLULEN*,SQLSMALLINT*,SQLSMALLINT*); 24 | SQLRETURN (SQL_API*SQLDescribeParamPtr)(SQLHSTMT,SQLUSMALLINT,SQLSMALLINT*,SQLULEN*,SQLSMALLINT*,SQLSMALLINT*); 25 | SQLRETURN (SQL_API*SQLDisconnectPtr)(SQLHDBC); 26 | SQLRETURN (SQL_API*SQLDriverConnectWPtr)(SQLHDBC,SQLHWND,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*,SQLUSMALLINT); 27 | SQLRETURN (SQL_API*SQLDriversWPtr)(SQLHENV,SQLUSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*); 28 | SQLRETURN (SQL_API*SQLEndTranPtr)(SQLSMALLINT,SQLHANDLE,SQLSMALLINT); 29 | SQLRETURN (SQL_API*SQLExecutePtr)(SQLHSTMT); 30 | SQLRETURN (SQL_API*SQLFetchPtr)(SQLHSTMT); 31 | SQLRETURN (SQL_API*SQLForeignKeysWPtr)(SQLHSTMT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT); 32 | SQLRETURN (SQL_API*SQLFreeHandlePtr)(SQLSMALLINT,SQLHANDLE); 33 | SQLRETURN (SQL_API*SQLGetConnectAttrPtr)(SQLHDBC,SQLINTEGER,SQLPOINTER,SQLINTEGER,SQLINTEGER*); 34 | SQLRETURN (SQL_API*SQLGetDataPtr)(SQLHSTMT,SQLUSMALLINT,SQLSMALLINT,SQLPOINTER,SQLLEN,SQLLEN*); 35 | SQLRETURN (SQL_API*SQLGetDiagFieldAPtr)(SQLSMALLINT,SQLHANDLE,SQLSMALLINT,SQLSMALLINT,SQLPOINTER,SQLSMALLINT,SQLSMALLINT*); 36 | SQLRETURN (SQL_API*SQLGetDiagRecWPtr)(SQLSMALLINT,SQLHANDLE,SQLSMALLINT,SQLWCHAR*,SQLINTEGER*,SQLWCHAR*,SQLSMALLINT,SQLSMALLINT*); 37 | SQLRETURN (SQL_API*SQLGetTypeInfoPtr)(SQLHSTMT,SQLSMALLINT); 38 | SQLRETURN (SQL_API*SQLMoreResultsPtr)(SQLHSTMT); 39 | SQLRETURN (SQL_API*SQLNumParamsPtr)(SQLHSTMT,SQLSMALLINT*); 40 | SQLRETURN (SQL_API*SQLNumResultColsPtr)(SQLHSTMT,SQLSMALLINT*); 41 | SQLRETURN (SQL_API*SQLPrepareWPtr)(SQLHSTMT,SQLWCHAR*,SQLINTEGER); 42 | SQLRETURN (SQL_API*SQLPrimaryKeysWPtr)(SQLHSTMT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT); 43 | SQLRETURN (SQL_API*SQLRowCountPtr)(SQLHSTMT,SQLLEN*); 44 | SQLRETURN (SQL_API*SQLSetConnectAttrPtr)(SQLHDBC,SQLINTEGER,SQLPOINTER,SQLINTEGER); 45 | SQLRETURN (SQL_API*SQLSetConnectOptionPtr)(SQLHDBC,SQLUSMALLINT,SQLULEN); 46 | SQLRETURN (SQL_API*SQLSetEnvAttrPtr)(SQLHENV,SQLINTEGER,SQLPOINTER,SQLINTEGER); 47 | SQLRETURN (SQL_API*SQLTablesWPtr)(SQLHSTMT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT,SQLWCHAR*,SQLSMALLINT); 48 | } odbcStubDefs; 49 | #define SQLAllocHandle (odbcStubs->SQLAllocHandlePtr) 50 | #define SQLBindParameter (odbcStubs->SQLBindParameterPtr) 51 | #define SQLCloseCursor (odbcStubs->SQLCloseCursorPtr) 52 | #define SQLColumnsW (odbcStubs->SQLColumnsWPtr) 53 | #define SQLDataSourcesW (odbcStubs->SQLDataSourcesWPtr) 54 | #define SQLDescribeColW (odbcStubs->SQLDescribeColWPtr) 55 | #define SQLDescribeParam (odbcStubs->SQLDescribeParamPtr) 56 | #define SQLDisconnect (odbcStubs->SQLDisconnectPtr) 57 | #define SQLDriverConnectW (odbcStubs->SQLDriverConnectWPtr) 58 | #define SQLDriversW (odbcStubs->SQLDriversWPtr) 59 | #define SQLEndTran (odbcStubs->SQLEndTranPtr) 60 | #define SQLExecute (odbcStubs->SQLExecutePtr) 61 | #define SQLFetch (odbcStubs->SQLFetchPtr) 62 | #define SQLForeignKeysW (odbcStubs->SQLForeignKeysWPtr) 63 | #define SQLFreeHandle (odbcStubs->SQLFreeHandlePtr) 64 | #define SQLGetConnectAttr (odbcStubs->SQLGetConnectAttrPtr) 65 | #define SQLGetData (odbcStubs->SQLGetDataPtr) 66 | #define SQLGetDiagFieldA (odbcStubs->SQLGetDiagFieldAPtr) 67 | #define SQLGetDiagRecW (odbcStubs->SQLGetDiagRecWPtr) 68 | #define SQLGetTypeInfo (odbcStubs->SQLGetTypeInfoPtr) 69 | #define SQLMoreResults (odbcStubs->SQLMoreResultsPtr) 70 | #define SQLNumParams (odbcStubs->SQLNumParamsPtr) 71 | #define SQLNumResultCols (odbcStubs->SQLNumResultColsPtr) 72 | #define SQLPrepareW (odbcStubs->SQLPrepareWPtr) 73 | #define SQLPrimaryKeysW (odbcStubs->SQLPrimaryKeysWPtr) 74 | #define SQLRowCount (odbcStubs->SQLRowCountPtr) 75 | #define SQLSetConnectAttr (odbcStubs->SQLSetConnectAttrPtr) 76 | #define SQLSetConnectOption (odbcStubs->SQLSetConnectOptionPtr) 77 | #define SQLSetEnvAttr (odbcStubs->SQLSetEnvAttrPtr) 78 | #define SQLTablesW (odbcStubs->SQLTablesWPtr) 79 | MODULE_SCOPE odbcStubDefs *odbcStubs; 80 | -------------------------------------------------------------------------------- /generic/odbcStubInit.c: -------------------------------------------------------------------------------- 1 | /* 2 | * odbcStubInit.c -- 3 | * 4 | * Stubs tables for the foreign ODBC libraries so that 5 | * Tcl extensions can use them without the linker's knowing about them. 6 | * 7 | * @CREATED@ 2011-01-22 20:11:52Z by genExtStubs.tcl from ../generic/odbcStubDefs.txt 8 | * 9 | * Copyright (c) 2010 by Kevin B. Kenny. 10 | * 11 | * Please refer to the file, 'license.terms' for the conditions on 12 | * redistribution of this file and for a DISCLAIMER OF ALL WARRANTIES. 13 | * 14 | *----------------------------------------------------------------------------- 15 | */ 16 | 17 | #include 18 | #ifdef _WIN32 19 | #define WIN32_LEAN_AND_MEAN 20 | #include 21 | #endif 22 | #include "fakesql.h" 23 | 24 | /* 25 | * Static data used in this file 26 | */ 27 | 28 | /* 29 | * Names of the libraries that might contain the ODBC API 30 | */ 31 | 32 | static const char *const odbcStubLibNames[] = { 33 | /* @LIBNAMES@: DO NOT EDIT THESE NAMES */ 34 | "odbc32", "odbc", "libodbc32", "libodbc", NULL 35 | /* @END@ */ 36 | }; 37 | static const char *const odbcOptLibNames[] = { 38 | "odbccp", "odbccp32", "odbcinst", 39 | "libodbccp", "libodbccp32", "libodbcinst", NULL 40 | }; 41 | 42 | /* 43 | * Names of the functions that we need from ODBC 44 | */ 45 | 46 | static const char *const odbcSymbolNames[] = { 47 | /* @SYMNAMES@: DO NOT EDIT THESE NAMES */ 48 | "SQLAllocHandle", 49 | "SQLBindParameter", 50 | "SQLCloseCursor", 51 | "SQLColumnsW", 52 | "SQLDataSourcesW", 53 | "SQLDescribeColW", 54 | "SQLDescribeParam", 55 | "SQLDisconnect", 56 | "SQLDriverConnectW", 57 | "SQLDriversW", 58 | "SQLEndTran", 59 | "SQLExecute", 60 | "SQLFetch", 61 | "SQLForeignKeysW", 62 | "SQLFreeHandle", 63 | "SQLGetConnectAttr", 64 | "SQLGetData", 65 | "SQLGetDiagFieldA", 66 | "SQLGetDiagRecW", 67 | "SQLGetTypeInfo", 68 | "SQLMoreResults", 69 | "SQLNumParams", 70 | "SQLNumResultCols", 71 | "SQLPrepareW", 72 | "SQLPrimaryKeysW", 73 | "SQLRowCount", 74 | "SQLSetConnectAttr", 75 | "SQLSetConnectOption", 76 | "SQLSetEnvAttr", 77 | "SQLTablesW", 78 | NULL 79 | /* @END@ */ 80 | }; 81 | 82 | /* 83 | * Table containing pointers to the functions named above. 84 | */ 85 | 86 | static odbcStubDefs odbcStubsTable; 87 | odbcStubDefs* odbcStubs = &odbcStubsTable; 88 | 89 | /* 90 | * Pointers to optional functions in ODBCINST 91 | */ 92 | 93 | BOOL (INSTAPI* SQLConfigDataSourceW)(HWND, WORD, LPCWSTR, LPCWSTR) 94 | = NULL; 95 | BOOL (INSTAPI* SQLConfigDataSource)(HWND, WORD, LPCSTR, LPCSTR) 96 | = NULL; 97 | BOOL (INSTAPI* SQLInstallerError)(WORD, DWORD*, LPSTR, WORD, WORD*) 98 | = NULL; 99 | 100 | /* 101 | *----------------------------------------------------------------------------- 102 | * 103 | * OdbcInitStubs -- 104 | * 105 | * Initialize the Stubs table for the ODBC API 106 | * 107 | * Results: 108 | * Returns the handle to the loaded ODBC client library, or NULL 109 | * if the load is unsuccessful. Leaves an error message in the 110 | * interpreter. 111 | * 112 | *----------------------------------------------------------------------------- 113 | */ 114 | 115 | MODULE_SCOPE Tcl_LoadHandle 116 | OdbcInitStubs(Tcl_Interp* interp, 117 | /* Tcl interpreter */ 118 | Tcl_LoadHandle* handle2Ptr) 119 | /* Pointer to a second load handle 120 | * that represents the ODBCINST library */ 121 | { 122 | int i; 123 | int status; /* Status of Tcl library calls */ 124 | Tcl_Obj* path; /* Path name of a module to be loaded */ 125 | Tcl_Obj* shlibext; /* Extension to use for load modules */ 126 | Tcl_LoadHandle handle = NULL; 127 | /* Handle to a load module */ 128 | 129 | SQLConfigDataSourceW = NULL; 130 | SQLConfigDataSource = NULL; 131 | SQLInstallerError = NULL; 132 | 133 | /* 134 | * Determine the shared library extension 135 | */ 136 | status = Tcl_EvalEx(interp, "::info sharedlibextension", -1, 137 | TCL_EVAL_GLOBAL); 138 | if (status != TCL_OK) return NULL; 139 | shlibext = Tcl_GetObjResult(interp); 140 | Tcl_IncrRefCount(shlibext); 141 | 142 | /* 143 | * Walk the list of possible library names to find an ODBC client 144 | */ 145 | status = TCL_ERROR; 146 | for (i = 0; status == TCL_ERROR && odbcStubLibNames[i] != NULL; ++i) { 147 | path = Tcl_NewStringObj(odbcStubLibNames[i], -1); 148 | Tcl_AppendObjToObj(path, shlibext); 149 | Tcl_IncrRefCount(path); 150 | Tcl_ResetResult(interp); 151 | 152 | /* 153 | * Try to load a client library and resolve the ODBC API within it. 154 | */ 155 | status = Tcl_LoadFile(interp, path, odbcSymbolNames, 0, 156 | (void*)odbcStubs, &handle); 157 | Tcl_DecrRefCount(path); 158 | } 159 | 160 | /* 161 | * If a client library is found, then try to load ODBCINST as well. 162 | */ 163 | if (status == TCL_OK) { 164 | int status2 = TCL_ERROR; 165 | for (i = 0; status2 == TCL_ERROR && odbcOptLibNames[i] != NULL; ++i) { 166 | path = Tcl_NewStringObj(odbcOptLibNames[i], -1); 167 | Tcl_AppendObjToObj(path, shlibext); 168 | Tcl_IncrRefCount(path); 169 | status2 = Tcl_LoadFile(interp, path, NULL, 0, NULL, handle2Ptr); 170 | if (status2 == TCL_OK) { 171 | SQLConfigDataSourceW = 172 | (BOOL (INSTAPI*)(HWND, WORD, LPCWSTR, LPCWSTR)) 173 | Tcl_FindSymbol(NULL, *handle2Ptr, "SQLConfigDataSourceW"); 174 | if (SQLConfigDataSourceW == NULL) { 175 | SQLConfigDataSource = 176 | (BOOL (INSTAPI*)(HWND, WORD, LPCSTR, LPCSTR)) 177 | Tcl_FindSymbol(NULL, *handle2Ptr, 178 | "SQLConfigDataSource"); 179 | } 180 | SQLInstallerError = 181 | (BOOL (INSTAPI*)(WORD, DWORD*, LPSTR, WORD, WORD*)) 182 | Tcl_FindSymbol(NULL, *handle2Ptr, "SQLInstallerError"); 183 | } else { 184 | Tcl_ResetResult(interp); 185 | } 186 | Tcl_DecrRefCount(path); 187 | } 188 | } 189 | 190 | /* 191 | * Either we've successfully loaded a library (status == TCL_OK), 192 | * or we've run out of library names (in which case status==TCL_ERROR 193 | * and the error message reflects the last unsuccessful load attempt). 194 | */ 195 | Tcl_DecrRefCount(shlibext); 196 | if (status != TCL_OK) { 197 | return NULL; 198 | } 199 | return handle; 200 | } 201 | 202 | -------------------------------------------------------------------------------- /generic/fakesql.h: -------------------------------------------------------------------------------- 1 | /* 2 | * fakesql.h -- 3 | * 4 | * Include file that defines the subset of SQL/CLI that TDBC 5 | * uses, so that tdbc::odbc can build without an explicit ODBC 6 | * dependency. It comprises only data type, constant and 7 | * function declarations. 8 | * 9 | * The programmers of this file believe that it contains material not 10 | * subject to copyright under the doctrines of scenes a faire and 11 | * of merger of idea and expression. Accordingly, this file is in the 12 | * public domain. 13 | * 14 | *----------------------------------------------------------------------------- 15 | */ 16 | 17 | #ifndef FAKESQL_H_INCLUDED 18 | #define FAKESQL_H_INCLUDED 19 | 20 | #include 21 | 22 | #ifndef MODULE_SCOPE 23 | #define MODULE_SCOPE extern 24 | #endif 25 | 26 | /* Limits */ 27 | 28 | #define SQL_MAX_DSN_LENGTH 32 29 | #define SQL_MAX_MESSAGE_LENGTH 512 30 | 31 | /* Fundamental data types */ 32 | 33 | #ifndef _WIN32 34 | typedef int BOOL; 35 | typedef unsigned int DWORD; 36 | typedef void* HANDLE; 37 | typedef HANDLE HWND; 38 | typedef unsigned short WCHAR; 39 | typedef char* LPSTR; 40 | typedef WCHAR* LPWSTR; 41 | typedef const char* LPCSTR; 42 | typedef const WCHAR* LPCWSTR; 43 | typedef unsigned short WORD; 44 | #endif 45 | typedef void* PVOID; 46 | typedef short RETCODE; 47 | typedef long SDWORD; 48 | typedef short SWORD; 49 | typedef unsigned short USHORT; 50 | typedef USHORT UWORD; 51 | 52 | /* ODBC data types */ 53 | 54 | typedef Tcl_WideInt SQLBIGINT; 55 | typedef unsigned char SQLCHAR; 56 | typedef double SQLDOUBLE; 57 | typedef void* SQLHANDLE; 58 | typedef SDWORD SQLINTEGER; 59 | typedef PVOID SQLPOINTER; 60 | typedef SWORD SQLSMALLINT; 61 | typedef Tcl_WideUInt SQLUBIGINT; 62 | typedef unsigned char SQLUCHAR; 63 | typedef unsigned int SQLUINTEGER; 64 | typedef UWORD SQLUSMALLINT; 65 | typedef WCHAR SQLWCHAR; 66 | 67 | typedef SQLSMALLINT SQLRETURN; 68 | 69 | /* TODO - Check how the SQLLEN and SQLULEN types are handled on 70 | * 64-bit Unix. */ 71 | 72 | #if defined(__WIN64) 73 | typedef Tcl_WideInt SQLLEN; 74 | typedef Tcl_WideUInt SQLULEN; 75 | #else 76 | typedef SQLINTEGER SQLLEN; 77 | typedef SQLUINTEGER SQLULEN; 78 | #endif 79 | 80 | /* Handle types */ 81 | 82 | typedef SQLHANDLE SQLHENV; 83 | typedef SQLHANDLE SQLHDBC; 84 | typedef SQLHANDLE SQLHSTMT; 85 | typedef HWND SQLHWND; 86 | 87 | #define SQL_HANDLE_DBC 2 88 | #define SQL_HANDLE_ENV 1 89 | #define SQL_HANDLE_STMT 3 90 | 91 | /* Null handles */ 92 | 93 | #define SQL_NULL_HANDLE ((SQLHANDLE) 0) 94 | #define SQL_NULL_HENV ((SQLHENV) 0) 95 | #define SQL_NULL_HSTMT ((SQLHSTMT) 0) 96 | 97 | /* SQL data types */ 98 | 99 | enum _SQL_DATATYPE { 100 | SQL_BIGINT = -5, 101 | SQL_BINARY = -2, 102 | SQL_BIT = -7, 103 | SQL_CHAR = 1, 104 | SQL_DATE = 9, 105 | SQL_DECIMAL = 3, 106 | SQL_DOUBLE = 8, 107 | SQL_FLOAT = 6, 108 | SQL_INTEGER = 4, 109 | SQL_LONGVARBINARY = -4, 110 | SQL_LONGVARCHAR = -1, 111 | SQL_NUMERIC = 2, 112 | SQL_REAL = 7, 113 | SQL_SMALLINT = 5, 114 | SQL_TIME = 10, 115 | SQL_TIMESTAMP = 11, 116 | SQL_TINYINT = -6, 117 | SQL_VARBINARY = -3, 118 | SQL_VARCHAR = 12, 119 | SQL_WCHAR = -8, 120 | SQL_WVARCHAR = -9, 121 | SQL_WLONGVARCHAR = -10, 122 | }; 123 | 124 | /* C data types */ 125 | 126 | #define SQL_SIGNED_OFFSET (-20) 127 | 128 | #define SQL_C_BINARY SQL_BINARY 129 | #define SQL_C_CHAR SQL_CHAR 130 | #define SQL_C_DOUBLE SQL_DOUBLE 131 | #define SQL_C_LONG SQL_INTEGER 132 | #define SQL_C_SBIGINT SQL_BIGINT + SQL_SIGNED_OFFSET 133 | #define SQL_C_SLONG SQL_INTEGER + SQL_SIGNED_OFFSET 134 | #define SQL_C_WCHAR SQL_WCHAR 135 | 136 | /* Parameter transmission diretions */ 137 | 138 | #define SQL_PARAM_INPUT 1 139 | 140 | /* Status returns */ 141 | 142 | #define SQL_ERROR (-1) 143 | #define SQL_NO_DATA 100 144 | #define SQL_NO_TOTAL (-4) 145 | #define SQL_SUCCESS 0 146 | #define SQL_SUCCESS_WITH_INFO 1 147 | 148 | /* Diagnostic fields */ 149 | 150 | enum _SQL_DIAG { 151 | SQL_DIAG_SQLSTATE = 4, 152 | }; 153 | 154 | /* Transaction isolation levels */ 155 | 156 | #define SQL_TXN_READ_COMMITTED 2 157 | #define SQL_TXN_READ_UNCOMMITTED 1 158 | #define SQL_TXN_REPEATABLE_READ 4 159 | #define SQL_TXN_SERIALIZABLE 8 160 | 161 | /* Access modes */ 162 | 163 | #define SQL_MODE_READ_ONLY 1UL 164 | #define SQL_MODE_READ_WRITE 0UL 165 | 166 | /* ODBC properties */ 167 | 168 | #define SQL_ACCESS_MODE 101 169 | #define SQL_AUTOCOMMIT 102 170 | #define SQL_TXN_ISOLATION 108 171 | 172 | /* ODBC attributes */ 173 | 174 | #define SQL_ATTR_ACCESS_MODE SQL_ACCESS_MODE 175 | #define SQL_ATTR_CONNECTION_TIMEOUT 113 176 | #define SQL_ATTR_ODBC_VERSION 200 177 | #define SQL_ATTR_TXN_ISOLATION SQL_TXN_ISOLATION 178 | 179 | /* Nullable? */ 180 | 181 | #define SQL_NULLABLE_UNKNOWN 2 182 | 183 | /* Placeholder for length of missing data */ 184 | 185 | #define SQL_NULL_DATA (-1) 186 | 187 | /* ODBC versions */ 188 | 189 | #define SQL_OV_ODBC3 3UL 190 | 191 | /* SQLDriverConnect flags */ 192 | 193 | #define SQL_DRIVER_COMPLETE_REQUIRED 3 194 | #define SQL_DRIVER_NOPROMPT 0 195 | 196 | /* SQLGetTypeInfo flags */ 197 | 198 | #define SQL_ALL_TYPES 0 199 | 200 | /* Transaction actions */ 201 | 202 | #define SQL_COMMIT 0 203 | #define SQL_ROLLBACK 1 204 | 205 | /* Data source fetch flags */ 206 | 207 | #define SQL_FETCH_FIRST 2 208 | #define SQL_FETCH_FIRST_SYSTEM 32 209 | #define SQL_FETCH_FIRST_USER 31 210 | #define SQL_FETCH_NEXT 1 211 | 212 | /* ODBCINST actions */ 213 | 214 | #define ODBC_ADD_DSN 1 215 | #define ODBC_CONFIG_DSN 2 216 | #define ODBC_REMOVE_DSN 3 217 | #define ODBC_ADD_SYS_DSN 4 218 | #define ODBC_CONFIG_SYS_DSN 5 219 | #define ODBC_REMOVE_SYS_DSN 6 220 | 221 | /* ODBCINST errors */ 222 | 223 | #define ODBC_ERROR_GENERAL_ERR 1 224 | #define ODBC_ERROR_INVALID_BUFF_LEN 2 225 | #define ODBC_ERROR_INVALID_HWND 3 226 | #define ODBC_ERROR_INVALID_STR 4 227 | #define ODBC_ERROR_INVALID_REQUEST_TYPE 5 228 | #define ODBC_ERROR_COMPONENT_NOT_FOUND 6 229 | #define ODBC_ERROR_INVALID_NAME 7 230 | #define ODBC_ERROR_INVALID_KEYWORD_VALUE 8 231 | #define ODBC_ERROR_INVALID_DSN 9 232 | #define ODBC_ERROR_INVALID_INF 10 233 | #define ODBC_ERROR_REQUEST_FAILED 11 234 | #define ODBC_ERROR_INVALID_PATH 12 235 | #define ODBC_ERROR_LOAD_LIB_FAILED 13 236 | #define ODBC_ERROR_INVALID_PARAM_SEQUENCE 14 237 | #define ODBC_ERROR_INVALID_LOG_FILE 15 238 | #define ODBC_ERROR_USER_CANCELED 16 239 | #define ODBC_ERROR_USAGE_UPDATE_FAILED 17 240 | #define ODBC_ERROR_CREATE_DSN_FAILED 18 241 | #define ODBC_ERROR_WRITING_SYSINFO_FAILED 19 242 | #define ODBC_ERROR_REMOVE_DSN_FAILED 20 243 | #define ODBC_ERROR_OUT_OF_MEM 21 244 | #define ODBC_ERROR_OUTPUT_STRING_TRUNCATED 22 245 | 246 | /* ODBC client library entry points */ 247 | 248 | #ifdef _WIN32 249 | #define SQL_API __stdcall 250 | #define INSTAPI __stdcall 251 | #else 252 | #define SQL_API /* nothing */ 253 | #define INSTAPI /* nothing */ 254 | #endif 255 | 256 | #include "odbcStubs.h" 257 | MODULE_SCOPE odbcStubDefs* odbcStubs; 258 | 259 | /* 260 | * Additional entry points in ODBCINST - all of these are optional 261 | * and resolved with Tcl_FindSymbol, not directly in Tcl_LoadLibrary. 262 | */ 263 | 264 | MODULE_SCOPE BOOL (INSTAPI* SQLConfigDataSourceW)(HWND, WORD, LPCWSTR, 265 | LPCWSTR); 266 | MODULE_SCOPE BOOL (INSTAPI* SQLConfigDataSource)(HWND, WORD, LPCSTR, LPCSTR); 267 | MODULE_SCOPE BOOL (INSTAPI* SQLInstallerErrorW)(WORD, DWORD*, LPWSTR, WORD, 268 | WORD*); 269 | MODULE_SCOPE BOOL (INSTAPI* SQLInstallerError)(WORD, DWORD*, LPSTR, WORD, 270 | WORD*); 271 | 272 | /* 273 | * Function that initialises the stubs 274 | */ 275 | 276 | MODULE_SCOPE Tcl_LoadHandle OdbcInitStubs(Tcl_Interp*, Tcl_LoadHandle*); 277 | 278 | #endif 279 | -------------------------------------------------------------------------------- /doc/tdbc_odbc.n: -------------------------------------------------------------------------------- 1 | '\" 2 | .\" tdbc_odbc.n -- 3 | .\" 4 | .\" Copyright (c) 2008 by Kevin B. Kenny. 5 | .\" 6 | .\" See the file "license.terms" for information on usage and redistribution of 7 | .\" this file, and for a DISCLAIMER OF ALL WARRANTIES. 8 | .\" .so man.macros 9 | .if t .wh -1.3i ^B 10 | .nr ^l \n(.l 11 | .ad b 12 | .\" # BS - start boxed text 13 | .\" # ^y = starting y location 14 | .\" # ^b = 1 15 | .de BS 16 | .br 17 | .mk ^y 18 | .nr ^b 1u 19 | .if n .nf 20 | .if n .ti 0 21 | .if n \l'\\n(.lu\(ul' 22 | .if n .fi 23 | .. 24 | .\" # BE - end boxed text (draw box now) 25 | .de BE 26 | .nf 27 | .ti 0 28 | .mk ^t 29 | .ie n \l'\\n(^lu\(ul' 30 | .el \{\ 31 | .\" Draw four-sided box normally, but don't draw top of 32 | .\" box if the box started on an earlier page. 33 | .ie !\\n(^b-1 \{\ 34 | \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' 35 | .\} 36 | .el \}\ 37 | \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' 38 | .\} 39 | .\} 40 | .fi 41 | .br 42 | .nr ^b 0 43 | .. 44 | .\" # CS - begin code excerpt 45 | .de CS 46 | .RS 47 | .nf 48 | .ta .25i .5i .75i 1i 49 | .. 50 | .\" # CE - end code excerpt 51 | .de CE 52 | .fi 53 | .RE 54 | .. 55 | .TH "tdbc::odbc" n 8.6 Tcl "Tcl Database Connectivity" 56 | .BS 57 | .SH "NAME" 58 | tdbc::odbc \- TDBC-ODBC bridge 59 | .SH "SYNOPSIS" 60 | package require \fBtdbc::odbc 1.0\fR 61 | .sp 62 | \fBtdbc::odbc::connection create\fR \fIdb\fR \fIconnectionString\fR ?\fI-option value...\fR? 63 | .br 64 | \fBtdbc::odbc::connection new\fR \fIconnectionString\fR ?\fI-option value...\fR? 65 | .sp 66 | \fBtdbc::odbc::datasources\fR ?\fB-system\fR|\fB-user\fR? 67 | .sp 68 | \fBtdbc::odbc::drivers\fR 69 | .sp 70 | \fBtdbc::odbc::datasource\fR \fIcommand\fR \fIdriverName\fR ?\fIkeyword\fR-\fIvalue\fR?... 71 | .BE 72 | .SH "DESCRIPTION" 73 | .PP 74 | The \fBtdbc::odbc\fR driver provides a database interface that conforms 75 | to Tcl DataBase Connectivity (TDBC) and allows a Tcl script to connect 76 | to any SQL database presenting an ODBC interface. It is also provided 77 | as a worked example of how to write a database driver in C, so that 78 | driver authors have a starting point for further development. 79 | .PP 80 | Connection to an ODBC database is established by invoking 81 | \fBtdbc::odbc::connection create\fR, passing it the name to be used 82 | as a connection handle, followed by a standard ODBC 83 | connection string. As an alternative, \fBtdbc::odbc::connection new\fR 84 | may be used to create 85 | a database connection with an automatically assigned name. The return value 86 | from \fBtdbc::odbc::connection new\fR is the name that was chosen for the 87 | connection handle. 88 | .PP 89 | The connection string will include at least a 90 | \fBDRIVER\fR or \fBDSN\fR keyword, and may include others that are defined by a 91 | particular ODBC driver. (If the local ODBC system supports a graphical 92 | user interface, the \fB-parent\fR option (see below) may allow calling 93 | \fBtdbc::odbc::connection create\fR with an empty connection string.) 94 | .PP 95 | The side effect of \fBtdbc::odbc::connection create\fR is to create a 96 | new database connection.. See \fBtdbc::connection(n)\fR for the 97 | details of how to use the connection to manipulate a database. 98 | .PP 99 | In addition to a standard TDBC interface, \fBtdbc::odbc\fR supports 100 | three additional ccommands. The first of these, 101 | \fBtdbc::odbc::datasources\fR, which returns a Tcl 102 | list enumerating the named data sources available to the program (for 103 | connection with the \fBDSN\fR keyword in the connection string). 104 | The result of \fBtdbc::odbc::datasources\fR may be constrained to only 105 | system data sources or only user data sources by including the 106 | \fB-system\fR or \fB-user\fR options, respectively. 107 | .PP 108 | The \fBtdbc::odbc::drivers\fR command returns a dictionary whose keys 109 | are the names of drivers available for the \fBDRIVER\fR keyword in the 110 | connection string, and whose values are descriptions of the drivers. 111 | .PP 112 | The \fBtdbc::odbc::datasource\fR command allows configuration of named 113 | data sources on those systems that support the ODBC Installer 114 | application programming interface. It accepts a \fIcommand\fR, which 115 | specifies the operation to be performed, the name of a \fIdriver\fR 116 | for the database in question, and a set of keyword-value pairs that 117 | are interpreted by the given driver. The \fIcommand\fR must be one of 118 | the following: 119 | .IP \fBadd\fR 120 | Adds a user data source. The keyword-value pairs must include 121 | at least a \fBDSN\fR option naming the data source 122 | .IP \fBadd_system\fR 123 | Adds a system data source. The keyword-value pairs must include 124 | at least a \fBDSN\fR option naming the data source 125 | .IP \fBconfigure\fR 126 | Configures a user data source. The keyword-value pairs will usually 127 | include a \fBDSN\fR option naming the data source. Some drivers will 128 | support other options, such as the \fBCREATE_DB\fR option to the 129 | Microsoft Access driver on Windows. 130 | .IP \fBconfigure_system\fR 131 | Configures a system data source. 132 | .IP \fBremove\fR 133 | Removes a user data source. The keyword-value pairs must include a 134 | \fBDSN\fR option specifying the data source to remove. 135 | .IP \fBremove_system\fR 136 | Removes a system data source. The keyword-value pairs must include a 137 | \fBDSN\fR option specifying the data source to remove. 138 | .SH "CONNECTION OPTIONS" 139 | .PP 140 | The \fBtdbc::odbc::connection create\fR object command supports the 141 | \fB-encoding\fR, \fB-isolation\fR, \fB-readonly\fR and \fB-timeout\fR 142 | options common to all TDBC drivers. The \fB-encoding\fR option will 143 | succeed only if the requested encoding is the same as the system 144 | encoding; \fBtdbc::odbc\fR does not attempt to specify alternative 145 | encodings to an ODBC driver. (Some drivers accept encoding 146 | specifications in the connection string.) 147 | .PP 148 | In addition, if Tk is present in the requesting interpreter, 149 | and the local system's ODBC driver manager supports a graphical user 150 | interface, the \fBtdbc::odbc::connection create\fR object command 151 | supports a \fB-parent\fR option, whose value is the path name of 152 | a Tk window. If this option is specified, and a connection string does 153 | not specify all the information needed to connect to an interface, the 154 | ODBC driver manager will display a dialog box to request whatever 155 | additional information is required. The requesting interpreter will 156 | block until the user dismisses the dialog, at which point the 157 | connection is made. 158 | .SH EXAMPLES 159 | .PP 160 | Sincs ODBC connection strings are driver specific, it is often 161 | difficult to find the documentation needed to compose them. The 162 | following examples are known to work on most Windows systems and 163 | provide at least a few useful things that a program can do. 164 | .PP 165 | .CS 166 | tdbc::odbc::connection create db \\ 167 | "DSN={PAYROLL};UID={aladdin};PWD={Sesame}" 168 | .CE 169 | Connects to a named data source "PAYROLL", providing "aladdin" as a 170 | user name and "Sesame" as a password. Uses \fBdb\fR as the name of the 171 | connection. 172 | .PP 173 | .CS 174 | set connString {DRIVER={Microsoft Access Driver (*.mdb)};} 175 | append connString {FIL={MS Access}\\;} 176 | append connString {DBQ=} \\ 177 | [file nativename [file normalize $fileName]] 178 | tdbc::odbc::connection create db2 -readonly 1 $connString 179 | .CE 180 | Opens a connection to a Microsoft Access database file whose 181 | name is in \fI$fileName\fR. The database is opened in read-only 182 | mode. The resulting connection is called "db2". 183 | .PP 184 | .CS 185 | tdbc::odbc::connection create db3 \\ 186 | "DRIVER=SQLite3;DATABASE=$fileName" 187 | .CE 188 | Opens a connection to a SQLite3 database whose name is in "$fileName". 189 | .PP 190 | .CS 191 | tdbc::odbc::datasource add \\ 192 | {Microsoft Access Driver (*.mdb)} \\ 193 | DSN=MyTestDatabase \\ 194 | DBQ=[file native [file normalize $fileName]] 195 | .CE 196 | Creates a new user data source with the name, "MyTestDatabase" bound 197 | to a Microsoft Access file whose path name is in "$fileName". No 198 | connection is made to the data source until the program calls 199 | \fBtdbc::odbc::connection create\fR. 200 | .PP 201 | .CS 202 | tdbc::odbc::datasource configure \\ 203 | {Microsoft Access Driver (*.mdb)} \\ 204 | CREATE_DB=[file native [file normalize $fileName]] \\ 205 | General 206 | .CE 207 | Creates a new, empty Microsoft Access database in the file identified 208 | by "$fileName". No connection is made to the database until the 209 | program calls \fBtdbc::odbc::connection create\fR. 210 | .SH "SEE ALSO" 211 | tdbc(n), tdbc::connection(n), tdbc::resultset(n), tdbc::statement(n) 212 | .SH "KEYWORDS" 213 | TDBC, SQL, ODBC, database, connectivity, connection 214 | .SH "COPYRIGHT" 215 | Copyright (c) 2008 by Kevin B. Kenny. 216 | .\" Local Variables: 217 | .\" mode: nroff 218 | .\" End: 219 | .\" 220 | -------------------------------------------------------------------------------- /configure.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash -norc 2 | dnl This file is an input file used by the GNU "autoconf" program to 3 | dnl generate the file "configure", which is run during Tcl installation 4 | dnl to configure the system for the local environment. 5 | # 6 | # RCS: @(#) $Id: configure.in,v 1.47 2007/02/09 19:06:47 hobbs Exp $ 7 | 8 | #----------------------------------------------------------------------- 9 | # Sample configure.in for Tcl Extensions. The only places you should 10 | # need to modify this file are marked by the string __CHANGE__ 11 | #----------------------------------------------------------------------- 12 | 13 | #----------------------------------------------------------------------- 14 | # Set your package name and version numbers here. 15 | # 16 | # This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION 17 | # set as provided. These will also be added as -D defs in your Makefile 18 | # so you can encode the package version directly into the source files. 19 | #----------------------------------------------------------------------- 20 | 21 | AC_INIT([tdbcodbc], [1.0.0]) 22 | 23 | #-------------------------------------------------------------------- 24 | # Call TEA_INIT as the first TEA_ macro to set up initial vars. 25 | # This will define a ${TEA_PLATFORM} variable == "unix" or "windows" 26 | # as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. 27 | #-------------------------------------------------------------------- 28 | 29 | AC_CONFIG_AUX_DIR(tclconfig) 30 | TEA_INIT([3.9]) 31 | 32 | #-------------------------------------------------------------------- 33 | # Load the tclConfig.sh file 34 | #-------------------------------------------------------------------- 35 | 36 | TEA_PATH_TCLCONFIG 37 | TEA_LOAD_TCLCONFIG 38 | 39 | #-------------------------------------------------------------------- 40 | # Load the tclooConfig.sh file on Tcl versions where oo is an 41 | # extension. 42 | #-------------------------------------------------------------------- 43 | 44 | if test "${TCL_MAJOR_VERSION}" -lt 8 ; then 45 | AC_MSG_ERROR([${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 8.6 or newer. 46 | Found configuration for Tcl ${TCL_VERSION}.]) 47 | fi 48 | if test "${TCL_MAJOR_VERSION}" -eq 8 ; then 49 | if test "${TCL_MINOR_VERSION}" -lt 6 ; then 50 | AC_MSG_ERROR([${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 8.6 or newer. 51 | Found configuration for Tcl ${TCL_VERSION}.]) 52 | fi 53 | TCLOO_CFLAGS='' 54 | fi 55 | TCL_VERSION_REQ=8.6; AC_SUBST(TCL_VERSION_REQ) 56 | 57 | #-------------------------------------------------------------------- 58 | # Load the tdbcConfig.sh and prepare to put its paths in the Makefile 59 | #-------------------------------------------------------------------- 60 | 61 | TEA_PATH_CONFIG(tdbc) 62 | TEA_LOAD_CONFIG(tdbc) 63 | AC_SUBST(TDBC_VERSION) 64 | AC_SUBST(tdbc_BIN_DIR) 65 | AC_SUBST(TDBC_LIB_FILE) 66 | 67 | # The next bit probably ought to be in TEA_LOAD_CONFIG 68 | AC_MSG_WARN([Looking for "${tdbc_BIN_DIR}/Makefile"]) 69 | if test -f "${tdbc_BIN_DIR}/Makefile" ; then 70 | AC_MSG_WARN([Found Makefile - using build include spec and lib specs for tdbc]) 71 | tdbc_INCLUDE_SPEC=${tdbc_BUILD_INCLUDE_SPEC} 72 | tdbc_LIBRARY_PATH=${tdbc_BUILD_LIBRARY_PATH} 73 | fi 74 | AC_SUBST(tdbc_LIBRARY_PATH) 75 | 76 | #----------------------------------------------------------------------- 77 | # Handle the --prefix=... option by defaulting to what Tcl gave. 78 | # Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. 79 | #----------------------------------------------------------------------- 80 | 81 | TEA_PREFIX 82 | 83 | #----------------------------------------------------------------------- 84 | # Standard compiler checks. 85 | # This sets up CC by using the CC env var, or looks for gcc otherwise. 86 | # This also calls AC_PROG_CC and a few others to create the basic setup 87 | # necessary to compile executables. 88 | #----------------------------------------------------------------------- 89 | 90 | TEA_SETUP_COMPILER 91 | AC_C_INLINE 92 | AC_CHECK_TYPE([long long],[ 93 | AC_DEFINE([HAVE_LONG_LONG],[1]) 94 | AC_CHECK_SIZEOF([long long]) 95 | ],[],[]) 96 | AC_CHECK_SIZEOF([long]) 97 | AC_DEFINE([DONT_TD_VOID],[1]) 98 | 99 | #----------------------------------------------------------------------- 100 | # Specify the C source files to compile in TEA_ADD_SOURCES, 101 | # public headers that need to be installed in TEA_ADD_HEADERS, 102 | # stub library C source files to compile in TEA_ADD_STUB_SOURCES, 103 | # and runtime Tcl library files in TEA_ADD_TCL_SOURCES. 104 | # This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS 105 | # and PKG_TCL_SOURCES. 106 | #----------------------------------------------------------------------- 107 | 108 | TEA_ADD_SOURCES(generic/tdbcodbc.c generic/odbcStubInit.c) 109 | TEA_ADD_HEADERS(generic/fakesql.h generic/odbcStubs.h) 110 | if test "${TCL_MAJOR_VERSION}" -eq 8 ; then 111 | if test "${TCL_MINOR_VERSION}" -eq 5 ; then 112 | TEA_ADD_INCLUDES([${TCLOO_INCLUDE_SPEC}]) 113 | TEA_ADD_LIBS([${TCLOO_STUB_LIB_SPEC}]) 114 | fi 115 | fi 116 | TEA_ADD_CFLAGS([${TCLOO_CFLAGS}]) 117 | TEA_ADD_INCLUDES([${tdbc_INCLUDE_SPEC}]) 118 | if test "x${TEA_PLATFORM}" = "xwindows" -a "x${GCC}" != "xyes" ; then 119 | TEA_ADD_LIBS([\"`${CYGPATH} ${tdbc_STUB_LIB_PATH}`\"]) 120 | else 121 | TEA_ADD_LIBS([${tdbc_STUB_LIB_SPEC}]) 122 | fi 123 | TEA_ADD_CFLAGS([${tdbc_CFLAGS}]) 124 | TEA_ADD_STUB_SOURCES() 125 | TEA_ADD_TCL_SOURCES([library/tdbcodbc.tcl]) 126 | 127 | #-------------------------------------------------------------------- 128 | # A few miscellaneous platform-specific items: 129 | # 130 | # Define a special symbol for Windows (BUILD_sample in this case) so 131 | # that we create the export library with the dll. 132 | # 133 | # Windows creates a few extra files that need to be cleaned up. 134 | # You can add more files to clean if your extension creates any extra 135 | # files. 136 | # 137 | # TEA_ADD_* any platform specific compiler/build info here. 138 | #-------------------------------------------------------------------- 139 | 140 | # Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure 141 | # and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var. 142 | #CLEANFILES="$CLEANFILES pkgIndex.tcl" 143 | 144 | #-------------------------------------------------------------------- 145 | # Choose which headers you need. Extension authors should try very 146 | # hard to only rely on the Tcl public header files. Internal headers 147 | # contain private data structures and are subject to change without 148 | # notice. 149 | # This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG 150 | #-------------------------------------------------------------------- 151 | 152 | TEA_PUBLIC_TCL_HEADERS 153 | 154 | #-------------------------------------------------------------------- 155 | # Check whether --enable-threads or --disable-threads was given. 156 | # This auto-enables if Tcl was compiled threaded. 157 | #-------------------------------------------------------------------- 158 | 159 | TEA_ENABLE_THREADS 160 | 161 | #-------------------------------------------------------------------- 162 | # The statement below defines a collection of symbols related to 163 | # building as a shared library instead of a static library. 164 | #-------------------------------------------------------------------- 165 | 166 | TEA_ENABLE_SHARED 167 | 168 | #-------------------------------------------------------------------- 169 | # This macro figures out what flags to use with the compiler/linker 170 | # when building shared/static debug/optimized objects. This information 171 | # can be taken from the tclConfig.sh file, but this figures it all out. 172 | #-------------------------------------------------------------------- 173 | 174 | TEA_CONFIG_CFLAGS 175 | 176 | #-------------------------------------------------------------------- 177 | # Set the default compiler switches based on the --enable-symbols option. 178 | #-------------------------------------------------------------------- 179 | 180 | TEA_ENABLE_SYMBOLS 181 | 182 | #-------------------------------------------------------------------- 183 | # Everyone should be linking against the Tcl stub library. If you 184 | # can't for some reason, remove this definition. If you aren't using 185 | # stubs, you also need to modify the SHLIB_LD_LIBS setting below to 186 | # link against the non-stubbed Tcl library. Add Tk too if necessary. 187 | #-------------------------------------------------------------------- 188 | 189 | AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs]) 190 | #AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs]) 191 | 192 | #-------------------------------------------------------------------- 193 | # This macro generates a line to use when building a library. It 194 | # depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS, 195 | # and TEA_LOAD_TCLCONFIG macros above. 196 | #-------------------------------------------------------------------- 197 | 198 | TEA_MAKE_LIB 199 | TEAX_VC_MANIFEST 200 | 201 | #-------------------------------------------------------------------- 202 | # Determine the name of the tclsh and/or wish executables in the 203 | # Tcl and Tk build directories or the location they were installed 204 | # into. These paths are used to support running test cases only, 205 | # the Makefile should not be making use of these paths to generate 206 | # a pkgIndex.tcl file or anything else at extension build time. 207 | #-------------------------------------------------------------------- 208 | 209 | TEA_PROG_TCLSH 210 | 211 | #-------------------------------------------------------------------- 212 | # Finally, substitute all of the various values into the Makefile. 213 | # You may alternatively have a special pkgIndex.tcl.in or other files 214 | # which require substituting th AC variables in. Include these here. 215 | #-------------------------------------------------------------------- 216 | 217 | CONFIGURE_OUTPUTS="Makefile pkgIndex.tcl config.cache config.log config.status" 218 | AC_SUBST(CONFIGURE_OUTPUTS) 219 | 220 | AC_CONFIG_FILES([Makefile pkgIndex.tcl]) 221 | AC_OUTPUT 222 | 223 | # This is a comment added to force the 'execute' permission to update 224 | # in the Fossil repository. 225 | -------------------------------------------------------------------------------- /library/tdbcodbc.tcl: -------------------------------------------------------------------------------- 1 | # tdbcodbc.tcl -- 2 | # 3 | # Class definitions and Tcl-level methods for the tdbc::odbc bridge. 4 | # 5 | # Copyright (c) 2008 by Kevin B. Kenny 6 | # See the file "license.terms" for information on usage and redistribution 7 | # of this file, and for a DISCLAIMER OF ALL WARRANTIES. 8 | # 9 | # RCS: @(#) $Id: tdbcodbc.tcl,v 1.47 2008/02/27 02:08:27 kennykb Exp $ 10 | # 11 | #------------------------------------------------------------------------------ 12 | 13 | package require tdbc 14 | 15 | ::namespace eval ::tdbc::odbc { 16 | 17 | namespace export connection datasources drivers 18 | 19 | # Data types that are predefined in ODBC 20 | 21 | variable sqltypes [dict create \ 22 | 1 char \ 23 | 2 numeric \ 24 | 3 decimal \ 25 | 4 integer \ 26 | 5 smallint \ 27 | 6 float \ 28 | 7 real \ 29 | 8 double \ 30 | 9 datetime \ 31 | 12 varchar \ 32 | 91 date \ 33 | 92 time \ 34 | 93 timestamp \ 35 | -1 longvarchar \ 36 | -2 binary \ 37 | -3 varbinary \ 38 | -4 longvarbinary \ 39 | -5 bigint \ 40 | -6 tinyint \ 41 | -7 bit \ 42 | -8 wchar \ 43 | -9 wvarchar \ 44 | -10 wlongvarchar \ 45 | -11 guid] 46 | } 47 | 48 | #------------------------------------------------------------------------------ 49 | # 50 | # tdbc::odbc::connection -- 51 | # 52 | # Class representing a connection to a database through ODBC. 53 | # 54 | #------------------------------------------------------------------------------- 55 | 56 | ::oo::class create ::tdbc::odbc::connection { 57 | 58 | superclass ::tdbc::connection 59 | 60 | variable statementSeq typemap 61 | 62 | # The constructor is written in C. It takes the connection string 63 | # as its argument It sets up a namespace to hold the statements 64 | # associated with the connection, and then delegates to the 'init' 65 | # method (written in C) to do the actual work of attaching to the 66 | # database. When that comes back, it sets up a statement to query 67 | # the support types, makes a dictionary to enumerate them, and 68 | # calls back to set a flag if WVARCHAR is seen (If WVARCHAR is 69 | # seen, the database supports Unicode.) 70 | 71 | # The 'statementCreate' method forwards to the constructor of the 72 | # statement class 73 | 74 | forward statementCreate ::tdbc::odbc::statement create 75 | 76 | # The 'tables' method returns a dictionary describing the tables 77 | # in the database 78 | 79 | method tables {{pattern %}} { 80 | set stmt [::tdbc::odbc::tablesStatement create \ 81 | Stmt::[incr statementSeq] [self] $pattern] 82 | set status [catch { 83 | set retval {} 84 | $stmt foreach -as dicts row { 85 | if {[dict exists $row TABLE_NAME]} { 86 | dict set retval [dict get $row TABLE_NAME] $row 87 | } 88 | } 89 | set retval 90 | } result options] 91 | catch {rename $stmt {}} 92 | return -level 0 -options $options $result 93 | } 94 | 95 | # The 'columns' method returns a dictionary describing the tables 96 | # in the database 97 | 98 | method columns {table {pattern %}} { 99 | # Make sure that the type map is initialized 100 | my typemap 101 | 102 | # Query the columns from the database 103 | 104 | set stmt [::tdbc::odbc::columnsStatement create \ 105 | Stmt::[incr statementSeq] [self] $table $pattern] 106 | set status [catch { 107 | set retval {} 108 | $stmt foreach -as dicts origrow { 109 | 110 | # Map the type, precision, scale and nullable indicators 111 | # to tdbc's notation 112 | 113 | set row {} 114 | dict for {key value} $origrow { 115 | dict set row [string tolower $key] $value 116 | } 117 | if {[dict exists $row column_name]} { 118 | if {[dict exists $typemap \ 119 | [dict get $row data_type]]} { 120 | dict set row type \ 121 | [dict get $typemap \ 122 | [dict get $row data_type]] 123 | } else { 124 | dict set row type [dict get $row type_name] 125 | } 126 | if {[dict exists $row column_size]} { 127 | dict set row precision \ 128 | [dict get $row column_size] 129 | } 130 | if {[dict exists $row decimal_digits]} { 131 | dict set row scale \ 132 | [dict get $row decimal_digits] 133 | } 134 | if {![dict exists $row nullable]} { 135 | dict set row nullable \ 136 | [expr {!![string trim [dict get $row is_nullable]]}] 137 | } 138 | dict set retval [dict get $row column_name] $row 139 | } 140 | } 141 | set retval 142 | } result options] 143 | catch {rename $stmt {}} 144 | return -level 0 -options $options $result 145 | } 146 | 147 | # The 'primarykeys' method returns a dictionary describing the primary 148 | # keys of a table 149 | 150 | method primarykeys {tableName} { 151 | set stmt [::tdbc::odbc::primarykeysStatement create \ 152 | Stmt::[incr statementSeq] [self] $tableName] 153 | set status [catch { 154 | set retval {} 155 | $stmt foreach -as dicts row { 156 | foreach {odbcKey tdbcKey} { 157 | TABLE_CAT tableCatalog 158 | TABLE_SCHEM tableSchema 159 | TABLE_NAME tableName 160 | COLUMN_NAME columnName 161 | KEY_SEQ ordinalPosition 162 | PK_NAME constraintName 163 | } { 164 | if {[dict exists $row $odbcKey]} { 165 | dict set row $tdbcKey [dict get $row $odbcKey] 166 | dict unset row $odbcKey 167 | } 168 | } 169 | lappend retval $row 170 | } 171 | set retval 172 | } result options] 173 | catch {rename $stmt {}} 174 | return -level 0 -options $options $result 175 | } 176 | 177 | # The 'foreignkeys' method returns a dictionary describing the foreign 178 | # keys of a table 179 | 180 | method foreignkeys {args} { 181 | set stmt [::tdbc::odbc::foreignkeysStatement create \ 182 | Stmt::[incr statementSeq] [self] {*}$args] 183 | set status [catch { 184 | set fkseq 0 185 | set retval {} 186 | $stmt foreach -as dicts row { 187 | foreach {odbcKey tdbcKey} { 188 | PKTABLE_CAT primaryCatalog 189 | PKTABLE_SCHEM primarySchema 190 | PKTABLE_NAME primaryTable 191 | PKCOLUMN_NAME primaryColumn 192 | FKTABLE_CAT foreignCatalog 193 | FKTABLE_SCHEM foreignSchema 194 | FKTABLE_NAME foreignTable 195 | FKCOLUMN_NAME foreignColumn 196 | UPDATE_RULE updateRule 197 | DELETE_RULE deleteRule 198 | DEFERRABILITY deferrable 199 | KEY_SEQ ordinalPosition 200 | FK_NAME foreignConstraintName 201 | } { 202 | if {[dict exists $row $odbcKey]} { 203 | dict set row $tdbcKey [dict get $row $odbcKey] 204 | dict unset row $odbcKey 205 | } 206 | } 207 | # Horrible kludge: If the driver doesn't report FK_NAME, 208 | # make one up. 209 | if {![dict exists $row foreignConstraintName]} { 210 | if {![dict exists $row ordinalPosition] 211 | || [dict get $row ordinalPosition] == 1} { 212 | set fkname ?[dict get $row foreignTable]?[incr fkseq] 213 | } 214 | dict set row foreignConstraintName $fkname 215 | } 216 | lappend retval $row 217 | } 218 | set retval 219 | } result options] 220 | catch {rename $stmt {}} 221 | return -level 0 -options $options $result 222 | } 223 | 224 | # The 'prepareCall' method gives a portable interface to prepare 225 | # calls to stored procedures. It delegates to 'prepare' to do the 226 | # actual work. 227 | 228 | method preparecall {call} { 229 | 230 | regexp {^[[:space:]]*(?:([A-Za-z_][A-Za-z_0-9]*)[[:space:]]*=)?(.*)} \ 231 | $call -> varName rest 232 | if {$varName eq {}} { 233 | my prepare \\{CALL $rest\\} 234 | } else { 235 | my prepare \\{:$varName=CALL $rest\\} 236 | } 237 | 238 | if 0 { 239 | # Kevin thinks this is going to be 240 | 241 | if {![regexp -expanded { 242 | ^\s* # leading whitespace 243 | (?::([[:alpha:]_][[:alnum:]_]*)\s*=\s*) # possible variable name 244 | (?:(?:([[:alpha:]_][[:alnum:]_]*)\s*[.]\s*)? # catalog 245 | ([[:alpha:]_][[:alnum:]_]*)\s*[.]\s*)? # schema 246 | ([[:alpha:]_][[:alnum:]_]*)\s* # procedure 247 | (.*)$ # argument list 248 | } $call -> varName catalog schema procedure arglist]} { 249 | return -code error \ 250 | -errorCode [list TDBC \ 251 | SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION \ 252 | 42000 ODBC -1] \ 253 | "Syntax error in stored procedure call" 254 | } else { 255 | my PrepareCall $varName $catalog $schema $procedure $arglist 256 | } 257 | 258 | # at least if making all parameters 'inout' doesn't work. 259 | 260 | } 261 | 262 | } 263 | 264 | # The 'typemap' method returns the type map 265 | 266 | method typemap {} { 267 | if {![info exists typemap]} { 268 | set typemap $::tdbc::odbc::sqltypes 269 | set typesStmt [tdbc::odbc::typesStatement new [self]] 270 | $typesStmt foreach row { 271 | set typeNum [dict get $row DATA_TYPE] 272 | if {![dict exists $typemap $typeNum]} { 273 | dict set typemap $typeNum [string tolower \ 274 | [dict get $row TYPE_NAME]] 275 | } 276 | switch -exact -- $typeNum { 277 | -9 { 278 | [self] HasWvarchar 1 279 | } 280 | -5 { 281 | [self] HasBigint 1 282 | } 283 | } 284 | } 285 | rename $typesStmt {} 286 | } 287 | return $typemap 288 | } 289 | 290 | # The 'begintransaction', 'commit' and 'rollback' methods are 291 | # implemented in C. 292 | 293 | } 294 | 295 | #------------------------------------------------------------------------------- 296 | # 297 | # tdbc::odbc::statement -- 298 | # 299 | # The class 'tdbc::odbc::statement' models one statement against a 300 | # database accessed through an ODBC connection 301 | # 302 | #------------------------------------------------------------------------------- 303 | 304 | ::oo::class create ::tdbc::odbc::statement { 305 | 306 | superclass ::tdbc::statement 307 | 308 | # The constructor is implemented in C. It accepts the handle to 309 | # the connection and the SQL code for the statement to prepare. 310 | # It creates a subordinate namespace to hold the statement's 311 | # active result sets, and then delegates to the 'init' method, 312 | # written in C, to do the actual work of preparing the statement. 313 | 314 | # The 'resultSetCreate' method forwards to the result set constructor 315 | 316 | forward resultSetCreate ::tdbc::odbc::resultset create 317 | 318 | # The 'params' method describes the parameters to the statement 319 | 320 | method params {} { 321 | set typemap [[my connection] typemap] 322 | set result {} 323 | foreach {name flags typeNum precision scale nullable} [my ParamList] { 324 | set lst [dict create \ 325 | name $name \ 326 | direction [lindex {unknown in out inout} \ 327 | [expr {($flags & 0x06) >> 1}]] \ 328 | type [dict get $typemap $typeNum] \ 329 | precision $precision \ 330 | scale $scale] 331 | if {$nullable in {0 1}} { 332 | dict set list nullable $nullable 333 | } 334 | dict set result $name $lst 335 | } 336 | return $result 337 | } 338 | 339 | # Methods implemented in C: 340 | # init statement ?dictionary? 341 | # Does the heavy lifting for the constructor 342 | # connection 343 | # Returns the connection handle to which this statement belongs 344 | # paramtype paramname ?direction? type ?precision ?scale?? 345 | # Declares the type of a parameter in the statement 346 | 347 | } 348 | 349 | #------------------------------------------------------------------------------ 350 | # 351 | # tdbc::odbc::tablesStatement -- 352 | # 353 | # The class 'tdbc::odbc::tablesStatement' represents the special 354 | # statement that queries the tables in a database through an ODBC 355 | # connection. 356 | # 357 | #------------------------------------------------------------------------------ 358 | 359 | oo::class create ::tdbc::odbc::tablesStatement { 360 | 361 | superclass ::tdbc::statement 362 | 363 | # The constructor is written in C. It accepts the handle to the 364 | # connection and a pattern to match table names. It works in all 365 | # ways like the constructor of the 'statement' class except that 366 | # its 'init' method sets up to enumerate tables and not run a SQL 367 | # query. 368 | 369 | # The 'resultSetCreate' method forwards to the result set constructor 370 | 371 | forward resultSetCreate ::tdbc::odbc::resultset create 372 | 373 | } 374 | 375 | #------------------------------------------------------------------------------ 376 | # 377 | # tdbc::odbc::columnsStatement -- 378 | # 379 | # The class 'tdbc::odbc::tablesStatement' represents the special 380 | # statement that queries the columns of a table or view 381 | # in a database through an ODBC connection. 382 | # 383 | #------------------------------------------------------------------------------ 384 | 385 | oo::class create ::tdbc::odbc::columnsStatement { 386 | 387 | superclass ::tdbc::statement 388 | 389 | # The constructor is written in C. It accepts the handle to the 390 | # connection, a table name, and a pattern to match column 391 | # names. It works in all ways like the constructor of the 392 | # 'statement' class except that its 'init' method sets up to 393 | # enumerate tables and not run a SQL query. 394 | 395 | # The 'resultSetCreate' class forwards to the constructor of the 396 | # result set 397 | 398 | forward resultSetCreate ::tdbc::odbc::resultset create 399 | 400 | } 401 | 402 | #------------------------------------------------------------------------------ 403 | # 404 | # tdbc::odbc::primarykeysStatement -- 405 | # 406 | # The class 'tdbc::odbc::primarykeysStatement' represents the special 407 | # statement that queries the primary keys on a table through an ODBC 408 | # connection. 409 | # 410 | #------------------------------------------------------------------------------ 411 | 412 | oo::class create ::tdbc::odbc::primarykeysStatement { 413 | 414 | superclass ::tdbc::statement 415 | 416 | # The constructor is written in C. It accepts the handle to the 417 | # connection and a table name. It works in all 418 | # ways like the constructor of the 'statement' class except that 419 | # its 'init' method sets up to enumerate primary keys and not run a SQL 420 | # query. 421 | 422 | # The 'resultSetCreate' method forwards to the result set constructor 423 | 424 | forward resultSetCreate ::tdbc::odbc::resultset create 425 | 426 | } 427 | 428 | #------------------------------------------------------------------------------ 429 | # 430 | # tdbc::odbc::foreignkeysStatement -- 431 | # 432 | # The class 'tdbc::odbc::foreignkeysStatement' represents the special 433 | # statement that queries the foreign keys on a table through an ODBC 434 | # connection. 435 | # 436 | #------------------------------------------------------------------------------ 437 | 438 | oo::class create ::tdbc::odbc::foreignkeysStatement { 439 | 440 | superclass ::tdbc::statement 441 | 442 | # The constructor is written in C. It accepts the handle to the 443 | # connection and the -primary and -foreign options. It works in all 444 | # ways like the constructor of the 'statement' class except that 445 | # its 'init' method sets up to enumerate foreign keys and not run a SQL 446 | # query. 447 | 448 | # The 'resultSetCreate' method forwards to the result set constructor 449 | 450 | forward resultSetCreate ::tdbc::odbc::resultset create 451 | 452 | } 453 | 454 | #------------------------------------------------------------------------------ 455 | # 456 | # tdbc::odbc::typesStatement -- 457 | # 458 | # The class 'tdbc::odbc::typesStatement' represents the special 459 | # statement that queries the types available in a database through 460 | # an ODBC connection. 461 | # 462 | #------------------------------------------------------------------------------ 463 | 464 | 465 | oo::class create ::tdbc::odbc::typesStatement { 466 | 467 | superclass ::tdbc::statement 468 | 469 | # The constructor is written in C. It accepts the handle to the 470 | # connection, and (optionally) a data type number. It works in all 471 | # ways like the constructor of the 'statement' class except that 472 | # its 'init' method sets up to enumerate types and not run a SQL 473 | # query. 474 | 475 | # The 'resultSetCreate' method forwards to the constructor of result sets 476 | 477 | forward resultSetCreate ::tdbc::odbc::resultset create 478 | 479 | # The C code contains a variant implementation of the 'init' method. 480 | 481 | } 482 | 483 | #------------------------------------------------------------------------------ 484 | # 485 | # tdbc::odbc::resultset -- 486 | # 487 | # The class 'tdbc::odbc::resultset' models the result set that is 488 | # produced by executing a statement against an ODBC database. 489 | # 490 | #------------------------------------------------------------------------------ 491 | 492 | ::oo::class create ::tdbc::odbc::resultset { 493 | 494 | superclass ::tdbc::resultset 495 | 496 | # Methods implemented in C include: 497 | 498 | # constructor statement ?dictionary? 499 | # -- Executes the statement against the database, optionally providing 500 | # a dictionary of substituted parameters (default is to get params 501 | # from variables in the caller's scope). 502 | # columns 503 | # -- Returns a list of the names of the columns in the result. 504 | # nextdict 505 | # -- Stores the next row of the result set in the given variable in 506 | # the caller's scope as a dictionary whose keys are 507 | # column names and whose values are column values. 508 | # nextlist 509 | # -- Stores the next row of the result set in the given variable in 510 | # the caller's scope as a list of cells. 511 | # rowcount 512 | # -- Returns a count of rows affected by the statement, or -1 513 | # if the count of rows has not been determined. 514 | 515 | } 516 | -------------------------------------------------------------------------------- /win/nmakehlp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ---------------------------------------------------------------------------- 3 | * nmakehlp.c -- 4 | * 5 | * This is used to fix limitations within nmake and the environment. 6 | * 7 | * Copyright (c) 2002 by David Gravereaux. 8 | * Copyright (c) 2006 by Pat Thoyts 9 | * 10 | * See the file "license.terms" for information on usage and redistribution of 11 | * this file, and for a DISCLAIMER OF ALL WARRANTIES. 12 | * ---------------------------------------------------------------------------- 13 | */ 14 | 15 | #define _CRT_SECURE_NO_DEPRECATE 16 | #include 17 | #define NO_SHLWAPI_GDI 18 | #define NO_SHLWAPI_STREAM 19 | #define NO_SHLWAPI_REG 20 | #include 21 | #pragma comment (lib, "user32.lib") 22 | #pragma comment (lib, "kernel32.lib") 23 | #pragma comment (lib, "shlwapi.lib") 24 | #include 25 | #include 26 | 27 | /* 28 | * This library is required for x64 builds with _some_ versions of MSVC 29 | */ 30 | #if defined(_M_IA64) || defined(_M_AMD64) 31 | #if _MSC_VER >= 1400 && _MSC_VER < 1500 32 | #pragma comment(lib, "bufferoverflowU") 33 | #endif 34 | #endif 35 | 36 | /* ISO hack for dumb VC++ */ 37 | #ifdef _MSC_VER 38 | #define snprintf _snprintf 39 | #endif 40 | 41 | 42 | 43 | /* protos */ 44 | 45 | static int CheckForCompilerFeature(const char *option); 46 | static int CheckForLinkerFeature(const char *option); 47 | static int IsIn(const char *string, const char *substring); 48 | static int SubstituteFile(const char *substs, const char *filename); 49 | static int QualifyPath(const char *path); 50 | static const char *GetVersionFromFile(const char *filename, const char *match, int numdots); 51 | static DWORD WINAPI ReadFromPipe(LPVOID args); 52 | 53 | /* globals */ 54 | 55 | #define CHUNK 25 56 | #define STATICBUFFERSIZE 1000 57 | typedef struct { 58 | HANDLE pipe; 59 | char buffer[STATICBUFFERSIZE]; 60 | } pipeinfo; 61 | 62 | pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'}; 63 | pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'}; 64 | 65 | /* 66 | * exitcodes: 0 == no, 1 == yes, 2 == error 67 | */ 68 | 69 | int 70 | main( 71 | int argc, 72 | char *argv[]) 73 | { 74 | char msg[300]; 75 | DWORD dwWritten; 76 | int chars; 77 | 78 | /* 79 | * Make sure children (cl.exe and link.exe) are kept quiet. 80 | */ 81 | 82 | SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); 83 | 84 | /* 85 | * Make sure the compiler and linker aren't effected by the outside world. 86 | */ 87 | 88 | SetEnvironmentVariable("CL", ""); 89 | SetEnvironmentVariable("LINK", ""); 90 | 91 | if (argc > 1 && *argv[1] == '-') { 92 | switch (*(argv[1]+1)) { 93 | case 'c': 94 | if (argc != 3) { 95 | chars = snprintf(msg, sizeof(msg) - 1, 96 | "usage: %s -c \n" 97 | "Tests for whether cl.exe supports an option\n" 98 | "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); 99 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, 100 | &dwWritten, NULL); 101 | return 2; 102 | } 103 | return CheckForCompilerFeature(argv[2]); 104 | case 'l': 105 | if (argc != 3) { 106 | chars = snprintf(msg, sizeof(msg) - 1, 107 | "usage: %s -l \n" 108 | "Tests for whether link.exe supports an option\n" 109 | "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); 110 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, 111 | &dwWritten, NULL); 112 | return 2; 113 | } 114 | return CheckForLinkerFeature(argv[2]); 115 | case 'f': 116 | if (argc == 2) { 117 | chars = snprintf(msg, sizeof(msg) - 1, 118 | "usage: %s -f \n" 119 | "Find a substring within another\n" 120 | "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); 121 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, 122 | &dwWritten, NULL); 123 | return 2; 124 | } else if (argc == 3) { 125 | /* 126 | * If the string is blank, there is no match. 127 | */ 128 | 129 | return 0; 130 | } else { 131 | return IsIn(argv[2], argv[3]); 132 | } 133 | case 's': 134 | if (argc == 2) { 135 | chars = snprintf(msg, sizeof(msg) - 1, 136 | "usage: %s -s \n" 137 | "Perform a set of string map type substutitions on a file\n" 138 | "exitcodes: 0\n", 139 | argv[0]); 140 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, 141 | &dwWritten, NULL); 142 | return 2; 143 | } 144 | return SubstituteFile(argv[2], argv[3]); 145 | case 'V': 146 | if (argc != 4) { 147 | chars = snprintf(msg, sizeof(msg) - 1, 148 | "usage: %s -V filename matchstring\n" 149 | "Extract a version from a file:\n" 150 | "eg: pkgIndex.tcl \"package ifneeded http\"", 151 | argv[0]); 152 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, 153 | &dwWritten, NULL); 154 | return 0; 155 | } 156 | printf("%s\n", GetVersionFromFile(argv[2], argv[3], *(argv[1]+2) - '0')); 157 | return 0; 158 | case 'Q': 159 | if (argc != 3) { 160 | chars = snprintf(msg, sizeof(msg) - 1, 161 | "usage: %s -Q path\n" 162 | "Emit the fully qualified path\n" 163 | "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); 164 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, 165 | &dwWritten, NULL); 166 | return 2; 167 | } 168 | return QualifyPath(argv[2]); 169 | } 170 | } 171 | chars = snprintf(msg, sizeof(msg) - 1, 172 | "usage: %s -c|-f|-l|-Q|-s|-V ...\n" 173 | "This is a little helper app to equalize shell differences between WinNT and\n" 174 | "Win9x and get nmake.exe to accomplish its job.\n", 175 | argv[0]); 176 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); 177 | return 2; 178 | } 179 | 180 | static int 181 | CheckForCompilerFeature( 182 | const char *option) 183 | { 184 | STARTUPINFO si; 185 | PROCESS_INFORMATION pi; 186 | SECURITY_ATTRIBUTES sa; 187 | DWORD threadID; 188 | char msg[300]; 189 | BOOL ok; 190 | HANDLE hProcess, h, pipeThreads[2]; 191 | char cmdline[100]; 192 | 193 | hProcess = GetCurrentProcess(); 194 | 195 | ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); 196 | ZeroMemory(&si, sizeof(STARTUPINFO)); 197 | si.cb = sizeof(STARTUPINFO); 198 | si.dwFlags = STARTF_USESTDHANDLES; 199 | si.hStdInput = INVALID_HANDLE_VALUE; 200 | 201 | ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); 202 | sa.nLength = sizeof(SECURITY_ATTRIBUTES); 203 | sa.lpSecurityDescriptor = NULL; 204 | sa.bInheritHandle = FALSE; 205 | 206 | /* 207 | * Create a non-inheritible pipe. 208 | */ 209 | 210 | CreatePipe(&Out.pipe, &h, &sa, 0); 211 | 212 | /* 213 | * Dupe the write side, make it inheritible, and close the original. 214 | */ 215 | 216 | DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE, 217 | DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); 218 | 219 | /* 220 | * Same as above, but for the error side. 221 | */ 222 | 223 | CreatePipe(&Err.pipe, &h, &sa, 0); 224 | DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE, 225 | DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); 226 | 227 | /* 228 | * Base command line. 229 | */ 230 | 231 | lstrcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X -Fp.\\_junk.pch "); 232 | 233 | /* 234 | * Append our option for testing 235 | */ 236 | 237 | lstrcat(cmdline, option); 238 | 239 | /* 240 | * Filename to compile, which exists, but is nothing and empty. 241 | */ 242 | 243 | lstrcat(cmdline, " .\\nul"); 244 | 245 | ok = CreateProcess( 246 | NULL, /* Module name. */ 247 | cmdline, /* Command line. */ 248 | NULL, /* Process handle not inheritable. */ 249 | NULL, /* Thread handle not inheritable. */ 250 | TRUE, /* yes, inherit handles. */ 251 | DETACHED_PROCESS, /* No console for you. */ 252 | NULL, /* Use parent's environment block. */ 253 | NULL, /* Use parent's starting directory. */ 254 | &si, /* Pointer to STARTUPINFO structure. */ 255 | &pi); /* Pointer to PROCESS_INFORMATION structure. */ 256 | 257 | if (!ok) { 258 | DWORD err = GetLastError(); 259 | int chars = snprintf(msg, sizeof(msg) - 1, 260 | "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err); 261 | 262 | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS| 263 | FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars], 264 | (300-chars), 0); 265 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL); 266 | return 2; 267 | } 268 | 269 | /* 270 | * Close our references to the write handles that have now been inherited. 271 | */ 272 | 273 | CloseHandle(si.hStdOutput); 274 | CloseHandle(si.hStdError); 275 | 276 | WaitForInputIdle(pi.hProcess, 5000); 277 | CloseHandle(pi.hThread); 278 | 279 | /* 280 | * Start the pipe reader threads. 281 | */ 282 | 283 | pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID); 284 | pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID); 285 | 286 | /* 287 | * Block waiting for the process to end. 288 | */ 289 | 290 | WaitForSingleObject(pi.hProcess, INFINITE); 291 | CloseHandle(pi.hProcess); 292 | 293 | /* 294 | * Wait for our pipe to get done reading, should it be a little slow. 295 | */ 296 | 297 | WaitForMultipleObjects(2, pipeThreads, TRUE, 500); 298 | CloseHandle(pipeThreads[0]); 299 | CloseHandle(pipeThreads[1]); 300 | 301 | /* 302 | * Look for the commandline warning code in both streams. 303 | * - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002. 304 | */ 305 | 306 | return !(strstr(Out.buffer, "D4002") != NULL 307 | || strstr(Err.buffer, "D4002") != NULL 308 | || strstr(Out.buffer, "D9002") != NULL 309 | || strstr(Err.buffer, "D9002") != NULL 310 | || strstr(Out.buffer, "D2021") != NULL 311 | || strstr(Err.buffer, "D2021") != NULL); 312 | } 313 | 314 | static int 315 | CheckForLinkerFeature( 316 | const char *option) 317 | { 318 | STARTUPINFO si; 319 | PROCESS_INFORMATION pi; 320 | SECURITY_ATTRIBUTES sa; 321 | DWORD threadID; 322 | char msg[300]; 323 | BOOL ok; 324 | HANDLE hProcess, h, pipeThreads[2]; 325 | char cmdline[100]; 326 | 327 | hProcess = GetCurrentProcess(); 328 | 329 | ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); 330 | ZeroMemory(&si, sizeof(STARTUPINFO)); 331 | si.cb = sizeof(STARTUPINFO); 332 | si.dwFlags = STARTF_USESTDHANDLES; 333 | si.hStdInput = INVALID_HANDLE_VALUE; 334 | 335 | ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); 336 | sa.nLength = sizeof(SECURITY_ATTRIBUTES); 337 | sa.lpSecurityDescriptor = NULL; 338 | sa.bInheritHandle = TRUE; 339 | 340 | /* 341 | * Create a non-inheritible pipe. 342 | */ 343 | 344 | CreatePipe(&Out.pipe, &h, &sa, 0); 345 | 346 | /* 347 | * Dupe the write side, make it inheritible, and close the original. 348 | */ 349 | 350 | DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE, 351 | DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); 352 | 353 | /* 354 | * Same as above, but for the error side. 355 | */ 356 | 357 | CreatePipe(&Err.pipe, &h, &sa, 0); 358 | DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE, 359 | DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); 360 | 361 | /* 362 | * Base command line. 363 | */ 364 | 365 | lstrcpy(cmdline, "link.exe -nologo "); 366 | 367 | /* 368 | * Append our option for testing. 369 | */ 370 | 371 | lstrcat(cmdline, option); 372 | 373 | ok = CreateProcess( 374 | NULL, /* Module name. */ 375 | cmdline, /* Command line. */ 376 | NULL, /* Process handle not inheritable. */ 377 | NULL, /* Thread handle not inheritable. */ 378 | TRUE, /* yes, inherit handles. */ 379 | DETACHED_PROCESS, /* No console for you. */ 380 | NULL, /* Use parent's environment block. */ 381 | NULL, /* Use parent's starting directory. */ 382 | &si, /* Pointer to STARTUPINFO structure. */ 383 | &pi); /* Pointer to PROCESS_INFORMATION structure. */ 384 | 385 | if (!ok) { 386 | DWORD err = GetLastError(); 387 | int chars = snprintf(msg, sizeof(msg) - 1, 388 | "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err); 389 | 390 | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS| 391 | FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars], 392 | (300-chars), 0); 393 | WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL); 394 | return 2; 395 | } 396 | 397 | /* 398 | * Close our references to the write handles that have now been inherited. 399 | */ 400 | 401 | CloseHandle(si.hStdOutput); 402 | CloseHandle(si.hStdError); 403 | 404 | WaitForInputIdle(pi.hProcess, 5000); 405 | CloseHandle(pi.hThread); 406 | 407 | /* 408 | * Start the pipe reader threads. 409 | */ 410 | 411 | pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID); 412 | pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID); 413 | 414 | /* 415 | * Block waiting for the process to end. 416 | */ 417 | 418 | WaitForSingleObject(pi.hProcess, INFINITE); 419 | CloseHandle(pi.hProcess); 420 | 421 | /* 422 | * Wait for our pipe to get done reading, should it be a little slow. 423 | */ 424 | 425 | WaitForMultipleObjects(2, pipeThreads, TRUE, 500); 426 | CloseHandle(pipeThreads[0]); 427 | CloseHandle(pipeThreads[1]); 428 | 429 | /* 430 | * Look for the commandline warning code in the stderr stream. 431 | */ 432 | 433 | return !(strstr(Out.buffer, "LNK1117") != NULL || 434 | strstr(Err.buffer, "LNK1117") != NULL || 435 | strstr(Out.buffer, "LNK4044") != NULL || 436 | strstr(Err.buffer, "LNK4044") != NULL); 437 | } 438 | 439 | static DWORD WINAPI 440 | ReadFromPipe( 441 | LPVOID args) 442 | { 443 | pipeinfo *pi = (pipeinfo *) args; 444 | char *lastBuf = pi->buffer; 445 | DWORD dwRead; 446 | BOOL ok; 447 | 448 | again: 449 | if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) { 450 | CloseHandle(pi->pipe); 451 | return (DWORD)-1; 452 | } 453 | ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L); 454 | if (!ok || dwRead == 0) { 455 | CloseHandle(pi->pipe); 456 | return 0; 457 | } 458 | lastBuf += dwRead; 459 | goto again; 460 | 461 | return 0; /* makes the compiler happy */ 462 | } 463 | 464 | static int 465 | IsIn( 466 | const char *string, 467 | const char *substring) 468 | { 469 | return (strstr(string, substring) != NULL); 470 | } 471 | 472 | /* 473 | * GetVersionFromFile -- 474 | * Looks for a match string in a file and then returns the version 475 | * following the match where a version is anything acceptable to 476 | * package provide or package ifneeded. 477 | */ 478 | 479 | static const char * 480 | GetVersionFromFile( 481 | const char *filename, 482 | const char *match, 483 | int numdots) 484 | { 485 | size_t cbBuffer = 100; 486 | static char szBuffer[100]; 487 | char *szResult = NULL; 488 | FILE *fp = fopen(filename, "rt"); 489 | 490 | if (fp != NULL) { 491 | /* 492 | * Read data until we see our match string. 493 | */ 494 | 495 | while (fgets(szBuffer, cbBuffer, fp) != NULL) { 496 | LPSTR p, q; 497 | 498 | p = strstr(szBuffer, match); 499 | if (p != NULL) { 500 | /* 501 | * Skip to first digit after the match. 502 | */ 503 | 504 | p += strlen(match); 505 | while (*p && !isdigit(*p)) { 506 | ++p; 507 | } 508 | 509 | /* 510 | * Find ending whitespace. 511 | */ 512 | 513 | q = p; 514 | while (*q && (strchr("0123456789.ab", *q)) && ((!strchr(".ab", *q) 515 | && (!strchr("ab", q[-1])) || --numdots))) { 516 | ++q; 517 | } 518 | 519 | memcpy(szBuffer, p, q - p); 520 | szBuffer[q-p] = 0; 521 | szResult = szBuffer; 522 | break; 523 | } 524 | } 525 | fclose(fp); 526 | } 527 | return szResult; 528 | } 529 | 530 | /* 531 | * List helpers for the SubstituteFile function 532 | */ 533 | 534 | typedef struct list_item_t { 535 | struct list_item_t *nextPtr; 536 | char * key; 537 | char * value; 538 | } list_item_t; 539 | 540 | /* insert a list item into the list (list may be null) */ 541 | static list_item_t * 542 | list_insert(list_item_t **listPtrPtr, const char *key, const char *value) 543 | { 544 | list_item_t *itemPtr = malloc(sizeof(list_item_t)); 545 | if (itemPtr) { 546 | itemPtr->key = strdup(key); 547 | itemPtr->value = strdup(value); 548 | itemPtr->nextPtr = NULL; 549 | 550 | while(*listPtrPtr) { 551 | listPtrPtr = &(*listPtrPtr)->nextPtr; 552 | } 553 | *listPtrPtr = itemPtr; 554 | } 555 | return itemPtr; 556 | } 557 | 558 | static void 559 | list_free(list_item_t **listPtrPtr) 560 | { 561 | list_item_t *tmpPtr, *listPtr = *listPtrPtr; 562 | while (listPtr) { 563 | tmpPtr = listPtr; 564 | listPtr = listPtr->nextPtr; 565 | free(tmpPtr->key); 566 | free(tmpPtr->value); 567 | free(tmpPtr); 568 | } 569 | } 570 | 571 | /* 572 | * SubstituteFile -- 573 | * As windows doesn't provide anything useful like sed and it's unreliable 574 | * to use the tclsh you are building against (consider x-platform builds - 575 | * eg compiling AMD64 target from IX86) we provide a simple substitution 576 | * option here to handle autoconf style substitutions. 577 | * The substitution file is whitespace and line delimited. The file should 578 | * consist of lines matching the regular expression: 579 | * \s*\S+\s+\S*$ 580 | * 581 | * Usage is something like: 582 | * nmakehlp -S << $** > $@ 583 | * @PACKAGE_NAME@ $(PACKAGE_NAME) 584 | * @PACKAGE_VERSION@ $(PACKAGE_VERSION) 585 | * << 586 | */ 587 | 588 | static int 589 | SubstituteFile( 590 | const char *substitutions, 591 | const char *filename) 592 | { 593 | size_t cbBuffer = 1024; 594 | static char szBuffer[1024], szCopy[1024]; 595 | char *szResult = NULL; 596 | list_item_t *substPtr = NULL; 597 | FILE *fp, *sp; 598 | 599 | fp = fopen(filename, "rt"); 600 | if (fp != NULL) { 601 | 602 | /* 603 | * Build a list of substutitions from the first filename 604 | */ 605 | 606 | sp = fopen(substitutions, "rt"); 607 | if (sp != NULL) { 608 | while (fgets(szBuffer, cbBuffer, sp) != NULL) { 609 | char *ks, *ke, *vs, *ve; 610 | ks = szBuffer; 611 | while (ks && *ks && isspace(*ks)) ++ks; 612 | ke = ks; 613 | while (ke && *ke && !isspace(*ke)) ++ke; 614 | vs = ke; 615 | while (vs && *vs && isspace(*vs)) ++vs; 616 | ve = vs; 617 | while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve; 618 | *ke = 0, *ve = 0; 619 | list_insert(&substPtr, ks, vs); 620 | } 621 | fclose(sp); 622 | } 623 | 624 | /* debug: dump the list */ 625 | #ifdef _DEBUG 626 | { 627 | int n = 0; 628 | list_item_t *p = NULL; 629 | for (p = substPtr; p != NULL; p = p->nextPtr, ++n) { 630 | fprintf(stderr, "% 3d '%s' => '%s'\n", n, p->key, p->value); 631 | } 632 | } 633 | #endif 634 | 635 | /* 636 | * Run the substitutions over each line of the input 637 | */ 638 | 639 | while (fgets(szBuffer, cbBuffer, fp) != NULL) { 640 | list_item_t *p = NULL; 641 | for (p = substPtr; p != NULL; p = p->nextPtr) { 642 | char *m = strstr(szBuffer, p->key); 643 | if (m) { 644 | char *cp, *op, *sp; 645 | cp = szCopy; 646 | op = szBuffer; 647 | while (op != m) *cp++ = *op++; 648 | sp = p->value; 649 | while (sp && *sp) *cp++ = *sp++; 650 | op += strlen(p->key); 651 | while (*op) *cp++ = *op++; 652 | *cp = 0; 653 | memcpy(szBuffer, szCopy, sizeof(szCopy)); 654 | } 655 | } 656 | printf(szBuffer); 657 | } 658 | 659 | list_free(&substPtr); 660 | } 661 | fclose(fp); 662 | return 0; 663 | } 664 | 665 | /* 666 | * QualifyPath -- 667 | * 668 | * This composes the current working directory with a provided path 669 | * and returns the fully qualified and normalized path. 670 | * Mostly needed to setup paths for testing. 671 | */ 672 | 673 | static int 674 | QualifyPath( 675 | const char *szPath) 676 | { 677 | char szCwd[MAX_PATH + 1]; 678 | char szTmp[MAX_PATH + 1]; 679 | char *p; 680 | GetCurrentDirectory(MAX_PATH, szCwd); 681 | while ((p = strchr(szPath, '/')) && *p) 682 | *p = '\\'; 683 | PathCombine(szTmp, szCwd, szPath); 684 | PathCanonicalize(szCwd, szTmp); 685 | printf("%s\n", szCwd); 686 | return 0; 687 | } 688 | 689 | /* 690 | * Local variables: 691 | * mode: c 692 | * c-basic-offset: 4 693 | * fill-column: 78 694 | * indent-tabs-mode: t 695 | * tab-width: 8 696 | * End: 697 | */ 698 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile.in -- 2 | # 3 | # This file is a Makefile for Sample TEA Extension. If it has the name 4 | # "Makefile.in" then it is a template for a Makefile; to generate the 5 | # actual Makefile, run "./configure", which is a configuration script 6 | # generated by the "autoconf" program (constructs like "@foo@" will get 7 | # replaced in the actual Makefile. 8 | # 9 | # Copyright (c) 1999 Scriptics Corporation. 10 | # Copyright (c) 2002-2005 ActiveState Corporation. 11 | # 12 | # See the file "license.terms" for information on usage and redistribution 13 | # of this file, and for a DISCLAIMER OF ALL WARRANTIES. 14 | # 15 | # RCS: @(#) $Id: Makefile.in,v 1.64 2007/10/23 22:08:06 hobbs Exp $ 16 | 17 | #======================================================================== 18 | # Nothing of the variables below this line should need to be changed. 19 | # Please check the TARGETS section below to make sure the make targets 20 | # are correct. 21 | #======================================================================== 22 | 23 | #======================================================================== 24 | # The names of the source files is defined in the configure script. 25 | # The object files are used for linking into the final library. 26 | # This will be used when a dist target is added to the Makefile. 27 | # It is not important to specify the directory, as long as it is the 28 | # $(srcdir) or in the generic, win or unix subdirectory. 29 | #======================================================================== 30 | 31 | PKG_SOURCES = @PKG_SOURCES@ 32 | PKG_OBJECTS = @PKG_OBJECTS@ 33 | 34 | #======================================================================== 35 | # PKG_TCL_SOURCES identifies Tcl runtime files that are associated with 36 | # this package that need to be installed, if any. 37 | #======================================================================== 38 | 39 | PKG_TCL_SOURCES = @PKG_TCL_SOURCES@ 40 | 41 | #======================================================================== 42 | # This is a list of public header files to be installed, if any. 43 | #======================================================================== 44 | 45 | PKG_HEADERS = @PKG_HEADERS@ 46 | 47 | #======================================================================== 48 | # "PKG_LIB_FILE" refers to the library (dynamic or static as per 49 | # configuration options) composed of the named objects. 50 | #======================================================================== 51 | 52 | PKG_LIB_FILE = @PKG_LIB_FILE@ 53 | 54 | lib_BINARIES = $(PKG_LIB_FILE) 55 | BINARIES = $(lib_BINARIES) 56 | 57 | SHELL = @SHELL@ 58 | 59 | srcdir = @srcdir@ 60 | prefix = @prefix@ 61 | exec_prefix = @exec_prefix@ 62 | 63 | bindir = @bindir@ 64 | libdir = @libdir@ 65 | includedir = @includedir@ 66 | datarootdir = @datarootdir@ 67 | datadir = @datadir@ 68 | mandir = @mandir@ 69 | 70 | DESTDIR = 71 | 72 | PKG_DIR = $(PACKAGE_NAME)$(PACKAGE_VERSION) 73 | pkgdatadir = $(datadir)/$(PKG_DIR) 74 | pkglibdir = $(libdir)/$(PKG_DIR) 75 | pkgincludedir = $(includedir)/$(PKG_DIR) 76 | 77 | top_builddir = . 78 | 79 | INSTALL_OPTIONS = 80 | INSTALL = $(SHELL) $(srcdir)/tclconfig/install-sh -c ${INSTALL_OPTIONS} 81 | INSTALL_DATA_DIR = ${INSTALL} -d -m 755 82 | INSTALL_PROGRAM = ${INSTALL} -m 755 83 | INSTALL_DATA = ${INSTALL} -m 444 84 | INSTALL_SCRIPT = ${INSTALL_PROGRAM} 85 | INSTALL_LIBRARY = ${INSTALL_DATA} 86 | 87 | PACKAGE_NAME = @PACKAGE_NAME@ 88 | PACKAGE_VERSION = @PACKAGE_VERSION@ 89 | CC = @CC@ 90 | CFLAGS_DEFAULT = @CFLAGS_DEFAULT@ 91 | CFLAGS_WARNING = @CFLAGS_WARNING@ 92 | EXEEXT = @EXEEXT@ 93 | LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@ 94 | MAKE_LIB = @MAKE_LIB@ 95 | MAKE_SHARED_LIB = @MAKE_SHARED_LIB@ 96 | MAKE_STATIC_LIB = @MAKE_STATIC_LIB@ 97 | MAKE_STUB_LIB = @MAKE_STUB_LIB@ 98 | ADD_MANIFEST = @ADD_MANIFEST@ 99 | OBJEXT = @OBJEXT@ 100 | RANLIB = @RANLIB@ 101 | RANLIB_STUB = @RANLIB_STUB@ 102 | SHLIB_CFLAGS = @SHLIB_CFLAGS@ 103 | SHLIB_LD = @SHLIB_LD@ 104 | SHLIB_LD_LIBS = @SHLIB_LD_LIBS@ 105 | STLIB_LD = @STLIB_LD@ 106 | #TCL_DEFS = @TCL_DEFS@ 107 | TCL_BIN_DIR = @TCL_BIN_DIR@ 108 | TCL_SRC_DIR = @TCL_SRC_DIR@ 109 | #TK_BIN_DIR = @TK_BIN_DIR@ 110 | #TK_SRC_DIR = @TK_SRC_DIR@ 111 | 112 | TDBC_VERSION = @TDBC_VERSION@ 113 | TDBC_BIN_DIR = @tdbc_BIN_DIR@ 114 | TDBC_LIB_FILE = @TDBC_LIB_FILE@ 115 | 116 | # Not used, but retained for reference of what libs Tcl required 117 | #TCL_LIBS = @TCL_LIBS@ 118 | 119 | #======================================================================== 120 | # TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our 121 | # package without installing. The other environment variables allow us 122 | # to test against an uninstalled Tcl. Add special env vars that you 123 | # require for testing here (like TCLX_LIBRARY). 124 | #======================================================================== 125 | 126 | EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR) 127 | #EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR) 128 | TCLLIBPATH = $(top_builddir) 129 | TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` \ 130 | TDBC_LIBRARY=`@CYGPATH@ @tdbc_LIBRARY_PATH@` 131 | PKG_ENV = @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \ 132 | PATH="$(EXTRA_PATH):$(PATH)" \ 133 | TCLLIBPATH="$(TCLLIBPATH)" \ 134 | TDBCODBC_LIBRARY=`@CYGPATH@ $(srcdir)/library` 135 | 136 | TCLSH_PROG = @TCLSH_PROG@ 137 | TCLSH = $(PKG_ENV) $(TCLSH_ENV) $(TCLSH_PROG) 138 | 139 | #WISH_ENV = TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library` 140 | #WISH_PROG = @WISH_PROG@ 141 | #WISH = $(PKG_ENV) $(TCLSH_ENV) $(WISH_ENV) $(WISH_PROG) 142 | 143 | SHARED_BUILD = @SHARED_BUILD@ 144 | 145 | INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ 146 | # INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@ 147 | 148 | PKG_CFLAGS = @PKG_CFLAGS@ 149 | 150 | # TCL_DEFS is not strictly need here, but if you remove it, then you 151 | # must make sure that configure.in checks for the necessary components 152 | # that your library may use. TCL_DEFS can actually be a problem if 153 | # you do not compile with a similar machine setup as the Tcl core was 154 | # compiled with. 155 | #DEFS = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS) 156 | DEFS = @DEFS@ $(PKG_CFLAGS) 157 | 158 | # Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile 159 | CONFIGURE_OUTPUTS = @CONFIGURE_OUTPUTS@ 160 | CLEANFILES = @CLEANFILES@ 161 | 162 | CPPFLAGS = @CPPFLAGS@ 163 | LIBS = @PKG_LIBS@ @LIBS@ 164 | AR = @AR@ 165 | CFLAGS = @CFLAGS@ 166 | COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) 167 | 168 | VALGRIND = valgrind 169 | VALGRINDARGS = --tool=memcheck --num-callers=16 --leak-resolution=high --leak-check=yes --show-reachable=yes -v 170 | 171 | #======================================================================== 172 | # Start of user-definable TARGETS section 173 | #======================================================================== 174 | 175 | #======================================================================== 176 | # TEA TARGETS. Please note that the "libraries:" target refers to platform 177 | # independent files, and the "binaries:" target inclues executable programs and 178 | # platform-dependent libraries. Modify these targets so that they install 179 | # the various pieces of your package. The make and install rules 180 | # for the BINARIES that you specified above have already been done. 181 | #======================================================================== 182 | 183 | all: binaries libraries doc 184 | 185 | #======================================================================== 186 | # The binaries target builds executable programs, Windows .dll's, unix 187 | # shared/static libraries, and any other platform-dependent files. 188 | # The list of targets to build for "binaries:" is specified at the top 189 | # of the Makefile, in the "BINARIES" variable. 190 | #======================================================================== 191 | 192 | binaries: $(BINARIES) 193 | 194 | libraries: 195 | 196 | #======================================================================== 197 | # Your doc target should differentiate from doc builds (by the developer) 198 | # and doc installs (see install-doc), which just install the docs on the 199 | # end user machine when building from source. 200 | #======================================================================== 201 | 202 | doc: 203 | 204 | install: all install-binaries install-libraries install-doc 205 | 206 | install-binaries: binaries install-lib-binaries install-bin-binaries 207 | 208 | #======================================================================== 209 | # This rule installs platform-independent files, such as header files. 210 | # The list=...; for p in $$list handles the empty list case x-platform. 211 | #======================================================================== 212 | 213 | install-libraries: libraries 214 | @$(INSTALL_DATA_DIR) $(DESTDIR)$(includedir) 215 | @echo "Installing header files in $(DESTDIR)$(includedir)" 216 | @list='$(PKG_HEADERS)'; for i in $$list; do \ 217 | echo "Installing $(srcdir)/$$i" ; \ 218 | $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir) ; \ 219 | done; 220 | 221 | #======================================================================== 222 | # Install documentation. Unix manpages should go in the $(mandir) 223 | # directory. 224 | #======================================================================== 225 | 226 | install-doc: doc 227 | @$(INSTALL_DATA_DIR) $(DESTDIR)$(mandir)/mann 228 | @echo "Installing documentation in $(DESTDIR)$(mandir)" 229 | @list='$(srcdir)/doc/*.n'; for i in $$list; do \ 230 | echo "Installing $$i"; \ 231 | rm -f $(DESTDIR)$(mandir)/mann/`basename $$i`; \ 232 | $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \ 233 | done 234 | 235 | test: test-jet test-sqlserver test-sqlite 236 | 237 | test-jet: binaries libraries 238 | @echo testing tdbcodbc against Jet 239 | TDBCODBC_TYPE=jet \ 240 | $(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) \ 241 | -load "package ifneeded tdbc::odbc $(PACKAGE_VERSION) \ 242 | [list source `@CYGPATH@ $(srcdir)/library/tdbcodbc.tcl`]\;[list load `@CYGPATH@ $(PKG_LIB_FILE)` $(PACKAGE_NAME)];\ 243 | package ifneeded tdbc ${TDBC_VERSION} \ 244 | [list source `@CYGPATH@ $(TDBC_BIN_DIR)/tdbc.tcl`]\;[list load `@CYGPATH@ $(TDBC_BIN_DIR)/$(TDBC_LIB_FILE)` tdbc]" 245 | 246 | test-sqlserver: binaries libraries 247 | @echo testing tdbcodbc against SQL Server 248 | TDBCODBC_TYPE=sqlserver \ 249 | $(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) \ 250 | -load "package ifneeded tdbc::odbc ${PACKAGE_VERSION} \ 251 | [list source `@CYGPATH@ $(srcdir)/library/tdbcodbc.tcl`]\;[list load `@CYGPATH@ $(PKG_LIB_FILE)` $(PACKAGE_NAME)];\ 252 | package ifneeded tdbc ${TDBC_VERSION} \ 253 | [list source `@CYGPATH@ $(TDBC_BIN_DIR)/tdbc.tcl`]\;[list load `@CYGPATH@ $(TDBC_BIN_DIR)/$(TDBC_LIB_FILE)` tdbc]" 254 | 255 | test-sqlite: binaries libraries 256 | @echo testing tdbcodbc against SQLite 257 | TDBCODBC_TYPE=sqlite \ 258 | $(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) \ 259 | -load "package ifneeded tdbc::odbc ${PACKAGE_VERSION} \ 260 | [list source `@CYGPATH@ $(srcdir)/library/tdbcodbc.tcl`]\;[list load `@CYGPATH@ $(PKG_LIB_FILE)` $(PACKAGE_NAME)];\ 261 | package ifneeded tdbc ${TDBC_VERSION} \ 262 | [list source `@CYGPATH@ $(TDBC_BIN_DIR)/tdbc.tcl`]\;[list load `@CYGPATH@ $(TDBC_BIN_DIR)/$(TDBC_LIB_FILE)` tdbc]" 263 | 264 | valgrind-sqlite: binaries libraries 265 | TDBCODBC_TYPE=sqlite \ 266 | $(PKG_ENV) $(TCLSH_ENV) \ 267 | LD_PRELOAD=$(PKG_LIB_FILE) \ 268 | $(VALGRIND) $(VALGRINDARGS) \ 269 | $(TCLSH_PROG) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) \ 270 | -load "package ifneeded tdbc::odbc ${PACKAGE_VERSION} \ 271 | [list source `@CYGPATH@ $(srcdir)/library/tdbcodbc.tcl`]\;[list load `@CYGPATH@ $(PKG_LIB_FILE)` $(PACKAGE_NAME)];\ 272 | package ifneeded tdbc ${TDBC_VERSION} \ 273 | [list source `@CYGPATH@ $(TDBC_BIN_DIR)/tdbc.tcl`]\;[list load `@CYGPATH@ $(TDBC_BIN_DIR)/$(TDBC_LIB_FILE)` tdbc]" 274 | 275 | shell: binaries libraries 276 | @$(TCLSH) $(SCRIPT) 277 | 278 | gdb: 279 | $(TCLSH_ENV) $(PKG_ENV) gdb $(TCLSH_PROG) $(SCRIPT) 280 | 281 | depend: 282 | 283 | #======================================================================== 284 | # $(PKG_LIB_FILE) should be listed as part of the BINARIES variable 285 | # mentioned above. That will ensure that this target is built when you 286 | # run "make binaries". 287 | # 288 | # The $(PKG_OBJECTS) objects are created and linked into the final 289 | # library. In most cases these object files will correspond to the 290 | # source files above. 291 | #======================================================================== 292 | 293 | $(PKG_LIB_FILE): $(PKG_OBJECTS) 294 | -rm -f $(PKG_LIB_FILE) 295 | ${MAKE_LIB} 296 | $(ADD_MANIFEST) 297 | $(RANLIB) $(PKG_LIB_FILE) 298 | 299 | #======================================================================== 300 | # We need to enumerate the list of .c to .o lines here. 301 | # 302 | # In the following lines, $(srcdir) refers to the toplevel directory 303 | # containing your extension. If your sources are in a subdirectory, 304 | # you will have to modify the paths to reflect this: 305 | # 306 | # sample.$(OBJEXT): $(srcdir)/generic/sample.c 307 | # $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@ 308 | # 309 | # Setting the VPATH variable to a list of paths will cause the makefile 310 | # to look into these paths when resolving .c to .obj dependencies. 311 | # As necessary, add $(srcdir):$(srcdir)/compat:.... 312 | #======================================================================== 313 | 314 | VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win 315 | 316 | .c.@OBJEXT@: 317 | $(COMPILE) -c `@CYGPATH@ $<` -o $@ 318 | 319 | #======================================================================== 320 | # Distribution creation 321 | # You may need to tweak this target to make it work correctly. 322 | #======================================================================== 323 | 324 | #COMPRESS = tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar 325 | COMPRESS = tar zcvf $(PKG_DIR).tar.gz $(PKG_DIR) 326 | DIST_ROOT = /tmp/dist 327 | DIST_DIR = $(DIST_ROOT)/$(PKG_DIR) 328 | 329 | dist-clean: 330 | rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.* 331 | 332 | dist: dist-clean 333 | mkdir -p $(DIST_DIR) 334 | cp -p $(srcdir)/ChangeLog $(srcdir)/README* $(srcdir)/license* \ 335 | $(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/*.in \ 336 | $(DIST_DIR)/ 337 | chmod 664 $(DIST_DIR)/Makefile.in $(DIST_DIR)/aclocal.m4 338 | chmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.in 339 | 340 | for i in $(srcdir)/*.[ch]; do \ 341 | if [ -f $$i ]; then \ 342 | cp -p $$i $(DIST_DIR)/ ; \ 343 | fi; \ 344 | done; 345 | 346 | mkdir $(DIST_DIR)/tclconfig 347 | cp $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \ 348 | $(DIST_DIR)/tclconfig/ 349 | chmod 664 $(DIST_DIR)/tclconfig/tcl.m4 350 | chmod +x $(DIST_DIR)/tclconfig/install-sh 351 | 352 | mkdir $(DIST_DIR)/doc 353 | cp -p $(srcdir)/doc/tdbc_odbc.n $(DIST_DIR)/doc/ 354 | 355 | mkdir $(DIST_DIR)/generic 356 | cp -p $(srcdir)/generic/fakesql.h $(srcdir)/generic/odbcStubDefs.txt \ 357 | $(srcdir)/generic/odbcStubInit.c $(srcdir)/generic/odbcStubs.h \ 358 | $(srcdir)/generic/tdbcodbc.c \ 359 | $(DIST_DIR)/generic/ 360 | 361 | mkdir $(DIST_DIR)/library 362 | cp -p $(srcdir)/library/tdbcodbc.tcl $(DIST_DIR)/library/ 363 | 364 | mkdir $(DIST_DIR)/tests 365 | cp -p $(srcdir)/tests/all.tcl $(srcdir)/tests/tdbcodbc.test \ 366 | $(srcdir)/tests/test.mdb \ 367 | $(DIST_DIR)/tests/ 368 | 369 | mkdir $(DIST_DIR)/win 370 | cp -p $(srcdir)/win/makefile.vc $(srcdir)/win/nmakehlp.c \ 371 | $(srcdir)/win/rules.vc $(DIST_DIR)/win/ 372 | 373 | (cd $(DIST_ROOT); $(COMPRESS);) 374 | 375 | #======================================================================== 376 | # How to rebuild the package's stub table. 377 | #======================================================================== 378 | 379 | genstubs: $(srcdir)/../tdbc/tools/genExtStubs.tcl $(srcdir)/generic/odbcStubDefs.txt 380 | @echo $(TCLSH_PROGRAM) $(srcdir)/../tdbc/tools/genExtStubs.tcl \ 381 | $(srcdir)/generic/odbcStubDefs.txt \ 382 | $(srcdir)/generic/odbcStubs.h \ 383 | $(srcdir)/generic/odbcStubInit.c 384 | @$(TCLSH) $(srcdir)/../tdbc/tools/genExtStubs.tcl \ 385 | $(srcdir)/generic/odbcStubDefs.txt \ 386 | $(srcdir)/generic/odbcStubs.h \ 387 | $(srcdir)/generic/odbcStubInit.c 388 | 389 | #======================================================================== 390 | # End of user-definable section 391 | #======================================================================== 392 | 393 | #======================================================================== 394 | # Don't modify the file to clean here. Instead, set the "CLEANFILES" 395 | # variable in configure.in 396 | #======================================================================== 397 | 398 | clean: 399 | -test -z "$(BINARIES)" || rm -f $(BINARIES) 400 | -rm -f *.$(OBJEXT) core *.core 401 | -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 402 | 403 | distclean: clean 404 | -rm -f *.tab.c 405 | -rm -f $(CONFIGURE_OUTPUTS) 406 | -rm -f config.cache config.log config.status 407 | 408 | #======================================================================== 409 | # Install binary object libraries. On Windows this includes both .dll and 410 | # .lib files. Because the .lib files are not explicitly listed anywhere, 411 | # we need to deduce their existence from the .dll file of the same name. 412 | # Library files go into the lib directory. 413 | # In addition, this will generate the pkgIndex.tcl 414 | # file in the install location (assuming it can find a usable tclsh shell) 415 | # 416 | # You should not have to modify this target. 417 | #======================================================================== 418 | 419 | install-lib-binaries: binaries 420 | @$(INSTALL_DATA_DIR) $(DESTDIR)$(pkglibdir) 421 | @list='$(lib_BINARIES)'; for p in $$list; do \ 422 | if test -f $$p; then \ 423 | echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p"; \ 424 | $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p; \ 425 | stub=`echo $$p|sed -e "s/.*\(stub\).*/\1/"`; \ 426 | if test "x$$stub" = "xstub"; then \ 427 | echo " $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p"; \ 428 | $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \ 429 | else \ 430 | echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \ 431 | $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \ 432 | fi; \ 433 | ext=`echo $$p|sed -e "s/.*\.//"`; \ 434 | if test "x$$ext" = "xdll"; then \ 435 | lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \ 436 | if test -f $$lib; then \ 437 | echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \ 438 | $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \ 439 | fi; \ 440 | fi; \ 441 | fi; \ 442 | done 443 | @list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ 444 | if test -f $(srcdir)/$$p; then \ 445 | destp=`basename $$p`; \ 446 | echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \ 447 | $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \ 448 | fi; \ 449 | done 450 | @if test "x$(SHARED_BUILD)" = "x1"; then \ 451 | echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \ 452 | $(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir); \ 453 | fi 454 | 455 | #======================================================================== 456 | # Install binary executables (e.g. .exe files and dependent .dll files) 457 | # This is for files that must go in the bin directory (located next to 458 | # wish and tclsh), like dependent .dll files on Windows. 459 | # 460 | # You should not have to modify this target, except to define bin_BINARIES 461 | # above if necessary. 462 | #======================================================================== 463 | 464 | install-bin-binaries: binaries 465 | @$(INSTALL_DATA_DIR) $(DESTDIR)$(bindir) 466 | @list='$(bin_BINARIES)'; for p in $$list; do \ 467 | if test -f $$p; then \ 468 | echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \ 469 | $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \ 470 | fi; \ 471 | done 472 | 473 | .SUFFIXES: .c .$(OBJEXT) 474 | 475 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status 476 | cd $(top_builddir) \ 477 | && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status 478 | 479 | uninstall-binaries: 480 | list='$(lib_BINARIES)'; for p in $$list; do \ 481 | rm -f $(DESTDIR)$(pkglibdir)/$$p; \ 482 | done 483 | list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ 484 | p=`basename $$p`; \ 485 | rm -f $(DESTDIR)$(pkglibdir)/$$p; \ 486 | done 487 | list='$(bin_BINARIES)'; for p in $$list; do \ 488 | rm -f $(DESTDIR)$(bindir)/$$p; \ 489 | done 490 | 491 | .PHONY: all binaries clean depend distclean doc install libraries test 492 | 493 | # Tell versions [3.59,3.63) of GNU make to not export all variables. 494 | # Otherwise a system limit (for SysV at least) may be exceeded. 495 | .NOEXPORT: 496 | -------------------------------------------------------------------------------- /win/rules.vc: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # rules.vc -- 3 | # 4 | # Microsoft Visual C++ makefile include for decoding the commandline 5 | # macros. This file does not need editing to build Tcl. 6 | # 7 | # This version is modified from the Tcl source version to support 8 | # building extensions using nmake. 9 | # 10 | # See the file "license.terms" for information on usage and redistribution 11 | # of this file, and for a DISCLAIMER OF ALL WARRANTIES. 12 | # 13 | # Copyright (c) 2001-2003 David Gravereaux. 14 | # Copyright (c) 2003-2008 Patrick Thoyts 15 | #------------------------------------------------------------------------------ 16 | 17 | !ifndef _RULES_VC 18 | _RULES_VC = 1 19 | 20 | cc32 = $(CC) # built-in default. 21 | link32 = link 22 | lib32 = lib 23 | rc32 = $(RC) # built-in default. 24 | 25 | !ifndef INSTALLDIR 26 | ### Assume the normal default. 27 | _INSTALLDIR = C:\Program Files\Tcl 28 | !else 29 | ### Fix the path separators. 30 | _INSTALLDIR = $(INSTALLDIR:/=\) 31 | !endif 32 | 33 | #---------------------------------------------------------- 34 | # Set the proper copy method to avoid overwrite questions 35 | # to the user when copying files and selecting the right 36 | # "delete all" method. 37 | #---------------------------------------------------------- 38 | 39 | !if "$(OS)" == "Windows_NT" 40 | RMDIR = rmdir /S /Q 41 | ERRNULL = 2>NUL 42 | !if ![ver | find "4.0" > nul] 43 | CPY = echo y | xcopy /i >NUL 44 | COPY = copy >NUL 45 | !else 46 | CPY = xcopy /i /y >NUL 47 | COPY = copy /y >NUL 48 | !endif 49 | !else # "$(OS)" != "Windows_NT" 50 | CPY = xcopy /i >_JUNK.OUT # On Win98 NUL does not work here. 51 | COPY = copy >_JUNK.OUT # On Win98 NUL does not work here. 52 | RMDIR = deltree /Y 53 | NULL = \NUL # Used in testing directory existence 54 | ERRNULL = >NUL # Win9x shell cannot redirect stderr 55 | !endif 56 | MKDIR = mkdir 57 | 58 | #------------------------------------------------------------------------------ 59 | # Determine the host and target architectures and compiler version. 60 | #------------------------------------------------------------------------------ 61 | 62 | _HASH=^# 63 | _VC_MANIFEST_EMBED_EXE= 64 | _VC_MANIFEST_EMBED_DLL= 65 | VCVER=0 66 | !if ![echo VCVERSION=_MSC_VER > vercl.x] \ 67 | && ![echo $(_HASH)if defined(_M_IX86) >> vercl.x] \ 68 | && ![echo ARCH=IX86 >> vercl.x] \ 69 | && ![echo $(_HASH)elif defined(_M_AMD64) >> vercl.x] \ 70 | && ![echo ARCH=AMD64 >> vercl.x] \ 71 | && ![echo $(_HASH)endif >> vercl.x] \ 72 | && ![cl -nologo -TC -P vercl.x $(ERRNULL)] 73 | !include vercl.i 74 | !if ![echo VCVER= ^\> vercl.vc] \ 75 | && ![set /a $(VCVERSION) / 100 - 6 >> vercl.vc] 76 | !include vercl.vc 77 | !endif 78 | !endif 79 | !if ![del $(ERRNUL) /q/f vercl.x vercl.i vercl.vc] 80 | !endif 81 | 82 | !if ![reg query HKLM\Hardware\Description\System\CentralProcessor\0 /v Identifier | findstr /i x86] 83 | NATIVE_ARCH=IX86 84 | !else 85 | NATIVE_ARCH=AMD64 86 | !endif 87 | 88 | # Since MSVC8 we must deal with manifest resources. 89 | !if $(VCVERSION) >= 1400 90 | _VC_MANIFEST_EMBED_EXE=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1 91 | _VC_MANIFEST_EMBED_DLL=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2 92 | !endif 93 | 94 | !ifndef MACHINE 95 | MACHINE=$(ARCH) 96 | !endif 97 | 98 | !ifndef CFG_ENCODING 99 | CFG_ENCODING = \"cp1252\" 100 | !endif 101 | 102 | !message =============================================================================== 103 | 104 | #---------------------------------------------------------- 105 | # build the helper app we need to overcome nmake's limiting 106 | # environment. 107 | #---------------------------------------------------------- 108 | 109 | !if !exist(nmakehlp.exe) 110 | !if [$(cc32) -nologo nmakehlp.c -link -subsystem:console > nul] 111 | !endif 112 | !endif 113 | 114 | #---------------------------------------------------------- 115 | # Test for compiler features 116 | #---------------------------------------------------------- 117 | 118 | ### test for optimizations 119 | !if [nmakehlp -c -Ot] 120 | !message *** Compiler has 'Optimizations' 121 | OPTIMIZING = 1 122 | !else 123 | !message *** Compiler does not have 'Optimizations' 124 | OPTIMIZING = 0 125 | !endif 126 | 127 | OPTIMIZATIONS = 128 | 129 | !if [nmakehlp -c -Ot] 130 | OPTIMIZATIONS = $(OPTIMIZATIONS) -Ot 131 | !endif 132 | 133 | !if [nmakehlp -c -Oi] 134 | OPTIMIZATIONS = $(OPTIMIZATIONS) -Oi 135 | !endif 136 | 137 | !if [nmakehlp -c -Op] 138 | OPTIMIZATIONS = $(OPTIMIZATIONS) -Op 139 | !endif 140 | 141 | !if [nmakehlp -c -fp:strict] 142 | OPTIMIZATIONS = $(OPTIMIZATIONS) -fp:strict 143 | !endif 144 | 145 | !if [nmakehlp -c -Gs] 146 | OPTIMIZATIONS = $(OPTIMIZATIONS) -Gs 147 | !endif 148 | 149 | !if [nmakehlp -c -GS] 150 | OPTIMIZATIONS = $(OPTIMIZATIONS) -GS 151 | !endif 152 | 153 | !if [nmakehlp -c -GL] 154 | OPTIMIZATIONS = $(OPTIMIZATIONS) -GL 155 | !endif 156 | 157 | DEBUGFLAGS = 158 | 159 | !if [nmakehlp -c -RTC1] 160 | DEBUGFLAGS = $(DEBUGFLAGS) -RTC1 161 | !elseif [nmakehlp -c -GZ] 162 | DEBUGFLAGS = $(DEBUGFLAGS) -GZ 163 | !endif 164 | 165 | COMPILERFLAGS =-W3 166 | 167 | # In v13 -GL and -YX are incompatible. 168 | !if [nmakehlp -c -YX] 169 | !if ![nmakehlp -c -GL] 170 | OPTIMIZATIONS = $(OPTIMIZATIONS) -YX 171 | !endif 172 | !endif 173 | 174 | !if "$(MACHINE)" == "IX86" 175 | ### test for pentium errata 176 | !if [nmakehlp -c -QI0f] 177 | !message *** Compiler has 'Pentium 0x0f fix' 178 | COMPILERFLAGS = $(COMPILERFLAGS) -QI0f 179 | !else 180 | !message *** Compiler does not have 'Pentium 0x0f fix' 181 | !endif 182 | !endif 183 | 184 | !if "$(MACHINE)" == "IA64" 185 | ### test for Itanium errata 186 | !if [nmakehlp -c -QIA64_Bx] 187 | !message *** Compiler has 'B-stepping errata workarounds' 188 | COMPILERFLAGS = $(COMPILERFLAGS) -QIA64_Bx 189 | !else 190 | !message *** Compiler does not have 'B-stepping errata workarounds' 191 | !endif 192 | !endif 193 | 194 | !if "$(MACHINE)" == "IX86" 195 | ### test for -align:4096, when align:512 will do. 196 | !if [nmakehlp -l -opt:nowin98] 197 | !message *** Linker has 'Win98 alignment problem' 198 | ALIGN98_HACK = 1 199 | !else 200 | !message *** Linker does not have 'Win98 alignment problem' 201 | ALIGN98_HACK = 0 202 | !endif 203 | !else 204 | ALIGN98_HACK = 0 205 | !endif 206 | 207 | LINKERFLAGS = 208 | 209 | !if [nmakehlp -l -ltcg] 210 | LINKERFLAGS =-ltcg 211 | !endif 212 | 213 | #---------------------------------------------------------- 214 | # Decode the options requested. 215 | #---------------------------------------------------------- 216 | 217 | !if "$(OPTS)" == "" || [nmakehlp -f "$(OPTS)" "none"] 218 | STATIC_BUILD = 0 219 | TCL_THREADS = 1 220 | DEBUG = 0 221 | SYMBOLS = 0 222 | PROFILE = 0 223 | PGO = 0 224 | MSVCRT = 0 225 | LOIMPACT = 0 226 | UNCHECKED = 0 227 | !else 228 | !if [nmakehlp -f $(OPTS) "static"] 229 | !message *** Doing static 230 | STATIC_BUILD = 1 231 | !else 232 | STATIC_BUILD = 0 233 | !endif 234 | !if [nmakehlp -f $(OPTS) "msvcrt"] 235 | !message *** Doing msvcrt 236 | MSVCRT = 1 237 | !else 238 | MSVCRT = 0 239 | !endif 240 | !if [nmakehlp -f $(OPTS) "nothreads"] 241 | !message *** Compile explicitly for non-threaded tcl 242 | TCL_THREADS = 0 243 | !else 244 | TCL_THREADS = 1 245 | !endif 246 | !if [nmakehlp -f $(OPTS) "symbols"] 247 | !message *** Doing symbols 248 | DEBUG = 1 249 | !else 250 | DEBUG = 0 251 | !endif 252 | !if [nmakehlp -f $(OPTS) "pdbs"] 253 | !message *** Doing pdbs 254 | SYMBOLS = 1 255 | !else 256 | SYMBOLS = 0 257 | !endif 258 | !if [nmakehlp -f $(OPTS) "profile"] 259 | !message *** Doing profile 260 | PROFILE = 1 261 | !else 262 | PROFILE = 0 263 | !endif 264 | !if [nmakehlp -f $(OPTS) "pgi"] 265 | !message *** Doing profile guided optimization instrumentation 266 | PGO = 1 267 | !elseif [nmakehlp -f $(OPTS) "pgo"] 268 | !message *** Doing profile guided optimization 269 | PGO = 2 270 | !else 271 | PGO = 0 272 | !endif 273 | !if [nmakehlp -f $(OPTS) "loimpact"] 274 | !message *** Doing loimpact 275 | LOIMPACT = 1 276 | !else 277 | LOIMPACT = 0 278 | !endif 279 | !if [nmakehlp -f $(OPTS) "unchecked"] 280 | !message *** Doing unchecked 281 | UNCHECKED = 1 282 | !else 283 | UNCHECKED = 0 284 | !endif 285 | !endif 286 | 287 | 288 | !if !$(STATIC_BUILD) 289 | # Make sure we don't build overly fat DLLs. 290 | MSVCRT = 1 291 | # We shouldn't statically put the extensions inside the shell when dynamic. 292 | TCL_USE_STATIC_PACKAGES = 0 293 | !endif 294 | 295 | 296 | #---------------------------------------------------------- 297 | # Figure-out how to name our intermediate and output directories. 298 | # We wouldn't want different builds to use the same .obj files 299 | # by accident. 300 | #---------------------------------------------------------- 301 | 302 | #---------------------------------------- 303 | # Naming convention: 304 | # t = full thread support. 305 | # s = static library (as opposed to an 306 | # import library) 307 | # g = linked to the debug enabled C 308 | # run-time. 309 | # x = special static build when it 310 | # links to the dynamic C run-time. 311 | #---------------------------------------- 312 | SUFX = sgx 313 | 314 | !if $(DEBUG) 315 | BUILDDIRTOP = Debug 316 | !else 317 | BUILDDIRTOP = Release 318 | !endif 319 | 320 | !if "$(MACHINE)" != "IX86" 321 | BUILDDIRTOP =$(BUILDDIRTOP)_$(MACHINE) 322 | !endif 323 | !if $(VCVER) > 6 324 | BUILDDIRTOP =$(BUILDDIRTOP)_VC$(VCVER) 325 | !endif 326 | 327 | !if !$(DEBUG) || $(DEBUG) && $(UNCHECKED) 328 | SUFX = $(SUFX:g=) 329 | !endif 330 | 331 | TMP_DIRFULL = .\$(BUILDDIRTOP)\$(PROJECT)_ThreadedDynamicStaticX 332 | 333 | !if !$(STATIC_BUILD) 334 | TMP_DIRFULL = $(TMP_DIRFULL:Static=) 335 | SUFX = $(SUFX:s=) 336 | EXT = dll 337 | !if $(MSVCRT) 338 | TMP_DIRFULL = $(TMP_DIRFULL:X=) 339 | SUFX = $(SUFX:x=) 340 | !endif 341 | !else 342 | TMP_DIRFULL = $(TMP_DIRFULL:Dynamic=) 343 | EXT = lib 344 | !if !$(MSVCRT) 345 | TMP_DIRFULL = $(TMP_DIRFULL:X=) 346 | SUFX = $(SUFX:x=) 347 | !endif 348 | !endif 349 | 350 | !if !$(TCL_THREADS) 351 | TMP_DIRFULL = $(TMP_DIRFULL:Threaded=) 352 | SUFX = $(SUFX:t=) 353 | !endif 354 | 355 | !ifndef TMP_DIR 356 | TMP_DIR = $(TMP_DIRFULL) 357 | !ifndef OUT_DIR 358 | OUT_DIR = .\$(BUILDDIRTOP) 359 | !endif 360 | !else 361 | !ifndef OUT_DIR 362 | OUT_DIR = $(TMP_DIR) 363 | !endif 364 | !endif 365 | 366 | 367 | #---------------------------------------------------------- 368 | # Decode the statistics requested. 369 | #---------------------------------------------------------- 370 | 371 | !if "$(STATS)" == "" || [nmakehlp -f "$(STATS)" "none"] 372 | TCL_MEM_DEBUG = 0 373 | TCL_COMPILE_DEBUG = 0 374 | !else 375 | !if [nmakehlp -f $(STATS) "memdbg"] 376 | !message *** Doing memdbg 377 | TCL_MEM_DEBUG = 1 378 | !else 379 | TCL_MEM_DEBUG = 0 380 | !endif 381 | !if [nmakehlp -f $(STATS) "compdbg"] 382 | !message *** Doing compdbg 383 | TCL_COMPILE_DEBUG = 1 384 | !else 385 | TCL_COMPILE_DEBUG = 0 386 | !endif 387 | !endif 388 | 389 | 390 | #---------------------------------------------------------- 391 | # Decode the checks requested. 392 | #---------------------------------------------------------- 393 | 394 | !if "$(CHECKS)" == "" || [nmakehlp -f "$(CHECKS)" "none"] 395 | TCL_NO_DEPRECATED = 0 396 | WARNINGS = -W3 397 | !else 398 | !if [nmakehlp -f $(CHECKS) "nodep"] 399 | !message *** Doing nodep check 400 | TCL_NO_DEPRECATED = 1 401 | !else 402 | TCL_NO_DEPRECATED = 0 403 | !endif 404 | !if [nmakehlp -f $(CHECKS) "fullwarn"] 405 | !message *** Doing full warnings check 406 | WARNINGS = -W4 407 | !if [nmakehlp -l -warn:3] 408 | LINKERFLAGS = $(LINKERFLAGS) -warn:3 409 | !endif 410 | !else 411 | WARNINGS = -W3 412 | !endif 413 | !if [nmakehlp -f $(CHECKS) "64bit"] && [nmakehlp -c -Wp64] 414 | !message *** Doing 64bit portability warnings 415 | WARNINGS = $(WARNINGS) -Wp64 416 | !endif 417 | !endif 418 | 419 | !if $(PGO) > 1 420 | !if [nmakehlp -l -ltcg:pgoptimize] 421 | LINKERFLAGS = $(LINKERFLAGS:-ltcg=) -ltcg:pgoptimize 422 | !else 423 | MSG=^ 424 | This compiler does not support profile guided optimization. 425 | !error $(MSG) 426 | !endif 427 | !elseif $(PGO) > 0 428 | !if [nmakehlp -l -ltcg:pginstrument] 429 | LINKERFLAGS = $(LINKERFLAGS:-ltcg=) -ltcg:pginstrument 430 | !else 431 | MSG=^ 432 | This compiler does not support profile guided optimization. 433 | !error $(MSG) 434 | !endif 435 | !endif 436 | 437 | #---------------------------------------------------------- 438 | # Set our defines now armed with our options. 439 | #---------------------------------------------------------- 440 | 441 | OPTDEFINES = -DTCL_CFGVAL_ENCODING=$(CFG_ENCODING) -DSTDC_HEADERS 442 | 443 | !if $(TCL_MEM_DEBUG) 444 | OPTDEFINES = $(OPTDEFINES) -DTCL_MEM_DEBUG 445 | !endif 446 | !if $(TCL_COMPILE_DEBUG) 447 | OPTDEFINES = $(OPTDEFINES) -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS 448 | !endif 449 | !if $(TCL_THREADS) 450 | OPTDEFINES = $(OPTDEFINES) -DTCL_THREADS=1 451 | !endif 452 | !if $(STATIC_BUILD) 453 | OPTDEFINES = $(OPTDEFINES) -DSTATIC_BUILD 454 | !endif 455 | !if $(TCL_NO_DEPRECATED) 456 | OPTDEFINES = $(OPTDEFINES) -DTCL_NO_DEPRECATED 457 | !endif 458 | 459 | !if !$(DEBUG) 460 | OPTDEFINES = $(OPTDEFINES) -DNDEBUG 461 | !if $(OPTIMIZING) 462 | OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_OPTIMIZED 463 | !endif 464 | !endif 465 | !if $(PROFILE) 466 | OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_PROFILED 467 | !endif 468 | !if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64" 469 | OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_DO64BIT 470 | !endif 471 | 472 | 473 | #---------------------------------------------------------- 474 | # Get common info used when building extensions. 475 | #---------------------------------------------------------- 476 | 477 | !if "$(PROJECT)" != "tcl" 478 | 479 | # If INSTALLDIR set to tcl root dir then reset to the lib dir. 480 | !if exist("$(_INSTALLDIR)\include\tcl.h") 481 | _INSTALLDIR=$(_INSTALLDIR)\lib 482 | !endif 483 | 484 | !if !defined(TCLDIR) 485 | !if exist("$(_INSTALLDIR)\..\include\tcl.h") 486 | TCLINSTALL = 1 487 | _TCLDIR = $(_INSTALLDIR)\.. 488 | _TCL_H = $(_INSTALLDIR)\..\include\tcl.h 489 | TCLDIR = $(_INSTALLDIR)\.. 490 | !else 491 | MSG=^ 492 | Failed to find tcl.h. Set the TCLDIR macro. 493 | !error $(MSG) 494 | !endif 495 | !else 496 | _TCLDIR = $(TCLDIR:/=\) 497 | !if exist("$(_TCLDIR)\include\tcl.h") 498 | TCLINSTALL = 1 499 | _TCL_H = $(_TCLDIR)\include\tcl.h 500 | !elseif exist("$(_TCLDIR)\generic\tcl.h") 501 | TCLINSTALL = 0 502 | _TCL_H = $(_TCLDIR)\generic\tcl.h 503 | !else 504 | MSG =^ 505 | Failed to find tcl.h. The TCLDIR macro does not appear correct. 506 | !error $(MSG) 507 | !endif 508 | !endif 509 | !endif 510 | 511 | #-------------------------------------------------------------- 512 | # Extract various version numbers from tcl headers 513 | # The generated file is then included in the makefile. 514 | #-------------------------------------------------------------- 515 | 516 | !if [echo REM = This file is generated from rules.vc > versions.vc] 517 | !endif 518 | !if [echo TCL_MAJOR_VERSION = \>> versions.vc] \ 519 | && [nmakehlp -V "$(_TCL_H)" TCL_MAJOR_VERSION >> versions.vc] 520 | !endif 521 | !if [echo TCL_MINOR_VERSION = \>> versions.vc] \ 522 | && [nmakehlp -V "$(_TCL_H)" TCL_MINOR_VERSION >> versions.vc] 523 | !endif 524 | !if [echo TCL_PATCH_LEVEL = \>> versions.vc] \ 525 | && [nmakehlp -V "$(_TCL_H)" TCL_PATCH_LEVEL >> versions.vc] 526 | !endif 527 | 528 | # If building the tcl core then we need additional package versions 529 | !if "$(PROJECT)" == "tcl" 530 | !if [echo PKG_HTTP_VER = \>> versions.vc] \ 531 | && [nmakehlp -V ..\library\http\pkgIndex.tcl http >> versions.vc] 532 | !endif 533 | !if [echo PKG_TCLTEST_VER = \>> versions.vc] \ 534 | && [nmakehlp -V ..\library\tcltest\pkgIndex.tcl tcltest >> versions.vc] 535 | !endif 536 | !if [echo PKG_MSGCAT_VER = \>> versions.vc] \ 537 | && [nmakehlp -V ..\library\msgcat\pkgIndex.tcl msgcat >> versions.vc] 538 | !endif 539 | !if [echo PKG_PLATFORM_VER = \>> versions.vc] \ 540 | && [nmakehlp -V ..\library\platform\pkgIndex.tcl "platform " >> versions.vc] 541 | !endif 542 | !if [echo PKG_SHELL_VER = \>> versions.vc] \ 543 | && [nmakehlp -V ..\library\platform\pkgIndex.tcl "platform::shell" >> versions.vc] 544 | !endif 545 | !endif 546 | 547 | !include versions.vc 548 | 549 | #-------------------------------------------------------------- 550 | # Setup tcl version dependent stuff headers 551 | #-------------------------------------------------------------- 552 | 553 | !if "$(PROJECT)" != "tcl" 554 | 555 | TCL_VERSION = $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION) 556 | 557 | !if $(TCL_VERSION) < 81 558 | TCL_DOES_STUBS = 0 559 | !else 560 | TCL_DOES_STUBS = 1 561 | !endif 562 | 563 | !if $(TCLINSTALL) 564 | _TCLBINDIR = "$(_TCLDIR)\bin" 565 | TCLSH = "$(_TCLBINDIR)\tclsh$(TCL_VERSION)$(SUFX).exe" 566 | !if !exist($(TCLSH)) && $(TCL_THREADS) 567 | TCLSH = "$(_TCLBINDIR)\tclsh$(TCL_VERSION)t$(SUFX).exe" 568 | !endif 569 | TCLSTUBLIB = "$(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib" 570 | TCLIMPLIB = "$(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib" 571 | TCL_LIBRARY = $(_TCLDIR)\lib 572 | COFFBASE = \must\have\tcl\sources\to\build\this\target 573 | TCLTOOLSDIR = \must\have\tcl\sources\to\build\this\target 574 | TCL_INCLUDES = -I"$(_TCLDIR)\include" 575 | !else 576 | _TCLBINDIR = $(_TCLDIR)\win\$(BUILDDIRTOP) 577 | TCLSH = "$(_TCLBINDIR)\tclsh$(TCL_VERSION)$(SUFX).exe" 578 | !if !exist($(TCLSH)) && $(TCL_THREADS) 579 | TCLSH = "$(_TCLBINDIR)\tclsh$(TCL_VERSION)t$(SUFX).exe" 580 | !endif 581 | TCLSTUBLIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib" 582 | TCLIMPLIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX).lib" 583 | TCL_LIBRARY = $(_TCLDIR)\library 584 | COFFBASE = "$(_TCLDIR)\win\coffbase.txt" 585 | TCLTOOLSDIR = $(_TCLDIR)\tools 586 | TCL_INCLUDES = -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win" 587 | !endif 588 | 589 | !endif 590 | 591 | #---------------------------------------------------------- 592 | # Optionally check for Tk info for building extensions. 593 | #---------------------------------------------------------- 594 | 595 | !ifdef PROJECT_REQUIRES_TK 596 | !if !defined(TKDIR) 597 | !if exist("$(_INSTALLDIR)\..\include\tk.h") 598 | TKINSTALL = 1 599 | _TKDIR = $(_INSTALLDIR)\.. 600 | _TK_H = $(_TKDIR)\include\tk.h 601 | TKDIR = $(_TKDIR) 602 | !elseif exist("$(_TCLDIR)\include\tk.h") 603 | TKINSTALL = 1 604 | _TKDIR = $(_TCLDIR) 605 | _TK_H = $(_TKDIR)\include\tk.h 606 | TKDIR = $(_TKDIR) 607 | !endif 608 | !else 609 | _TKDIR = $(TKDIR:/=\) 610 | !if exist("$(_TKDIR)\include\tk.h") 611 | TKINSTALL = 1 612 | _TK_H = $(_TKDIR)\include\tk.h 613 | !elseif exist("$(_TKDIR)\generic\tk.h") 614 | TKINSTALL = 0 615 | _TK_H = $(_TKDIR)\generic\tk.h 616 | !else 617 | MSG =^ 618 | Failed to find tk.h. The TKDIR macro does not appear correct. 619 | !error $(MSG) 620 | !endif 621 | !endif 622 | !endif 623 | 624 | #------------------------------------------------------------------------- 625 | # Extract Tk version numbers 626 | #------------------------------------------------------------------------- 627 | 628 | !if defined(PROJECT_REQUIRES_TK) || "$(PROJECT)" == "tk" 629 | !if [echo TK_MAJOR_VERSION = \>> versions.vc] \ 630 | && [nmakehlp -V $(_TK_H) TK_MAJOR_VERSION >> versions.vc] 631 | !endif 632 | !if [echo TK_MINOR_VERSION = \>> versions.vc] \ 633 | && [nmakehlp -V $(_TK_H) TK_MINOR_VERSION >> versions.vc] 634 | !endif 635 | !if [echo TK_PATCH_LEVEL = \>> versions.vc] \ 636 | && [nmakehlp -V $(_TK_H) TK_PATCH_LEVEL >> versions.vc] 637 | !endif 638 | 639 | !include versions.vc 640 | 641 | TK_DOTVERSION = $(TK_MAJOR_VERSION).$(TK_MINOR_VERSION) 642 | TK_VERSION = $(TK_MAJOR_VERSION)$(TK_MINOR_VERSION) 643 | 644 | !if "$(PROJECT)" != "tk" 645 | !if $(TKINSTALL) 646 | _TKBINDIR = $(_TKDIR)\bin 647 | WISH = "$(_TKBINDIR)\wish$(TK_VERSION)$(SUFX).exe" 648 | !if !exist($(WISH)) && $(TCL_THREADS) 649 | WISH = "$(_TKBINDIR)\wish$(TK_VERSION)t$(SUFX).exe" 650 | !endif 651 | TKSTUBLIB = "$(_TKDIR)\lib\tkstub$(TK_VERSION).lib" 652 | TK_LIBRARY = $(_TKDIR)\lib 653 | TKIMPLIB = "$(_TKDIR)\lib\tk$(TK_VERSION)$(SUFX).lib" 654 | TK_INCLUDES = -I"$(_TKDIR)\include" 655 | !else 656 | _TKBINDIR = $(_TKDIR)\win\$(BUILDDIRTOP) 657 | WISH = "$(_TKBINDIR)\wish$(TCL_VERSION)$(SUFX).exe" 658 | !if !exist($(WISH)) && $(TCL_THREADS) 659 | WISH = "$(_TKBINDIR)\wish$(TCL_VERSION)t$(SUFX).exe" 660 | !endif 661 | TKSTUBLIB = "$(_TKDIR)\win\$(BUILDDIRTOP)\tkstub$(TCL_VERSION).lib" 662 | TKIMPLIB = "$(_TKDIR)\win\$(BUILDDIRTOP)\tk$(TCL_VERSION)$(SUFX).lib" 663 | TK_LIBRARY = $(_TKDIR)\library 664 | TK_INCLUDES = -I"$(_TKDIR)\generic" -I"$(_TKDIR)\win" -I"$(_TKDIR)\xlib" 665 | !endif 666 | !endif 667 | 668 | !endif 669 | 670 | #---------------------------------------------------------- 671 | # Setup the fully qualified OUT_DIR path as OUT_DIR_PATH 672 | #---------------------------------------------------------- 673 | !if [echo OUT_DIR_PATH = \>> versions.vc] \ 674 | && [nmakehlp -Q "$(OUT_DIR)" >> versions.vc] 675 | !endif 676 | !include versions.vc 677 | 678 | #---------------------------------------------------------- 679 | # Display stats being used. 680 | #---------------------------------------------------------- 681 | 682 | !message *** Intermediate directory will be '$(TMP_DIR)' 683 | !message *** Output directory will be '$(OUT_DIR)' 684 | !message *** Suffix for binaries will be '$(SUFX)' 685 | !message *** Optional defines are '$(OPTDEFINES)' 686 | !message *** Compiler version $(VCVER). Target machine is $(MACHINE) 687 | !message *** Host architecture is $(NATIVE_ARCH) 688 | !message *** Compiler options '$(COMPILERFLAGS) $(OPTIMIZATIONS) $(DEBUGFLAGS) $(WARNINGS)' 689 | !message *** Link options '$(LINKERFLAGS)' 690 | 691 | !endif 692 | -------------------------------------------------------------------------------- /win/makefile.vc: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------- -*- makefile -*- 2 | # makefile.vc -- 3 | # 4 | # Microsoft Visual C++ makefile for use with nmake.exe v1.62+ (VC++ 5.0+) 5 | # 6 | # This makefile is based upon the Tcl 8.6 Makefile.vc and modified to 7 | # make it suitable as a general package makefile. Look for the word EDIT 8 | # which marks sections that may need modification. As a minumum you will 9 | # need to change the PROJECT, DOTVERSION and DLLOBJS variables to values 10 | # relevant to your package. 11 | # 12 | # See the file "license.terms" for information on usage and redistribution 13 | # of this file, and for a DISCLAIMER OF ALL WARRANTIES. 14 | # 15 | # Copyright (c) 1995-1996 Sun Microsystems, Inc. 16 | # Copyright (c) 1998-2000 Ajuba Solutions. 17 | # Copyright (c) 2001-2005 ActiveState Corporation. 18 | # Copyright (c) 2001-2004 David Gravereaux. 19 | # Copyright (c) 2003-2008 Pat Thoyts. 20 | #------------------------------------------------------------------------------ 21 | 22 | # Check to see we are configured to build with MSVC (MSDEVDIR, MSVCDIR or 23 | # VCINSTALLDIR) or with the MS Platform SDK (MSSDK or WindowsSDKDir) 24 | !if !defined(MSDEVDIR) && !defined(MSVCDIR) && !defined(VCINSTALLDIR) && !defined(MSSDK) && !defined(WINDOWSSDKDIR) 25 | MSG = ^ 26 | You need to run vcvars32.bat from Developer Studio or setenv.bat from the^ 27 | Platform SDK first to setup the environment. Jump to this line to read^ 28 | the build instructions. 29 | !error $(MSG) 30 | !endif 31 | 32 | #------------------------------------------------------------------------------ 33 | # HOW TO USE this makefile: 34 | # 35 | # 1) It is now necessary to have MSVCDir, MSDevDir or MSSDK set in the 36 | # environment. This is used as a check to see if vcvars32.bat had been 37 | # run prior to running nmake or during the installation of Microsoft 38 | # Visual C++, MSVCDir had been set globally and the PATH adjusted. 39 | # Either way is valid. 40 | # 41 | # You'll need to run vcvars32.bat contained in the MsDev's vc(98)/bin 42 | # directory to setup the proper environment, if needed, for your 43 | # current setup. This is a needed bootstrap requirement and allows the 44 | # swapping of different environments to be easier. 45 | # 46 | # 2) To use the Platform SDK (not expressly needed), run setenv.bat after 47 | # vcvars32.bat according to the instructions for it. This can also 48 | # turn on the 64-bit compiler, if your SDK has it. 49 | # 50 | # 3) Targets are: 51 | # all -- Builds everything. 52 | # -- Builds the project (eg: nmake sample) 53 | # test -- Builds and runs the test suite. 54 | # install -- Installs the built binaries and libraries to $(INSTALLDIR) 55 | # in an appropriate subdirectory. 56 | # clean/realclean/distclean -- varying levels of cleaning. 57 | # 58 | # 4) Macros usable on the commandline: 59 | # INSTALLDIR= 60 | # Sets where to install Tcl from the built binaries. 61 | # C:\Progra~1\Tcl is assumed when not specified. 62 | # 63 | # OPTS=loimpact,msvcrt,nothreads,pdbs,profile,static,symbols,unchecked,none 64 | # Sets special options for the core. The default is for none. 65 | # Any combination of the above may be used (comma separated). 66 | # 'none' will over-ride everything to nothing. 67 | # 68 | # loimpact = Adds a flag for how NT treats the heap to keep memory 69 | # in use, low. This is said to impact alloc performance. 70 | # msvcrt = Affects the static option only to switch it from 71 | # using libcmt(d) as the C runtime [by default] to 72 | # msvcrt(d). This is useful for static embedding 73 | # support. 74 | # nothreads = Turns off multithreading support (not recommended) 75 | # static = Builds a static library of the core instead of a 76 | # dll. The shell will be static (and large), as well. 77 | # pdbs = Build detached symbols for release builds. 78 | # profile = Adds profiling hooks. Map file is assumed. 79 | # symbols = Debug build. Links to the debug C runtime, disables 80 | # optimizations and creates pdb symbols files. 81 | # unchecked = Allows a symbols build to not use the debug 82 | # enabled runtime (msvcrt.dll not msvcrtd.dll 83 | # or libcmt.lib not libcmtd.lib). 84 | # 85 | # STATS=memdbg,compdbg,none 86 | # Sets optional memory and bytecode compiler debugging code added 87 | # to the core. The default is for none. Any combination of the 88 | # above may be used (comma separated). 'none' will over-ride 89 | # everything to nothing. 90 | # 91 | # memdbg = Enables the debugging memory allocator. 92 | # compdbg = Enables byte compilation logging. 93 | # 94 | # CHECKS=64bit,fullwarn,nodep,none 95 | # Sets special macros for checking compatability. 96 | # 97 | # 64bit = Enable 64bit portability warnings (if available) 98 | # fullwarn = Builds with full compiler and link warnings enabled. 99 | # Very verbose. 100 | # nodep = Turns off compatability macros to ensure Tk isn't 101 | # being built with deprecated functions. 102 | # 103 | # MACHINE=(ALPHA|AMD64|IA64|IX86) 104 | # Set the machine type used for the compiler, linker, and 105 | # resource compiler. This hook is needed to tell the tools 106 | # when alternate platforms are requested. IX86 is the default 107 | # when not specified. If the CPU environment variable has been 108 | # set (ie: recent Platform SDK) then MACHINE is set from CPU. 109 | # 110 | # TMP_DIR= 111 | # OUT_DIR= 112 | # Hooks to allow the intermediate and output directories to be 113 | # changed. $(OUT_DIR) is assumed to be 114 | # $(BINROOT)\(Release|Debug) based on if symbols are requested. 115 | # $(TMP_DIR) will de $(OUT_DIR)\ by default. 116 | # 117 | # TESTPAT= 118 | # Reads the tests requested to be run from this file. 119 | # 120 | # 5) Examples: 121 | # 122 | # Basic syntax of calling nmake looks like this: 123 | # nmake [-nologo] -f makefile.vc [target|macrodef [target|macrodef] [...]] 124 | # 125 | # Standard (no frills) 126 | # c:\tcl_src\win\>c:\progra~1\micros~1\vc98\bin\vcvars32.bat 127 | # Setting environment for using Microsoft Visual C++ tools. 128 | # c:\tcl_src\win\>nmake -f makefile.vc all 129 | # c:\tcl_src\win\>nmake -f makefile.vc install INSTALLDIR=c:\progra~1\tcl 130 | # 131 | # Building for Win64 132 | # c:\tcl_src\win\>c:\progra~1\micros~1\vc98\bin\vcvars32.bat 133 | # Setting environment for using Microsoft Visual C++ tools. 134 | # c:\tcl_src\win\>c:\progra~1\platfo~1\setenv.bat /pre64 /RETAIL 135 | # Targeting Windows pre64 RETAIL 136 | # c:\tcl_src\win\>nmake -f makefile.vc MACHINE=IA64 137 | # 138 | #------------------------------------------------------------------------------ 139 | #============================================================================== 140 | #------------------------------------------------------------------------------ 141 | 142 | !if !exist("makefile.vc") 143 | MSG = ^ 144 | You must run this makefile only from the directory it is in.^ 145 | Please `cd` to its location first. 146 | !error $(MSG) 147 | !endif 148 | 149 | #------------------------------------------------------------------------- 150 | # Project specific information (EDIT) 151 | # 152 | # You should edit this with the name and version of your project. This 153 | # information is used to generate the name of the package library and 154 | # it's install location. 155 | # 156 | # For example, the sample extension is going to build sample05.dll and 157 | # would install it into $(INSTALLDIR)\lib\sample05 158 | # 159 | # You need to specify the object files that need to be linked into your 160 | # binary here. 161 | # 162 | #------------------------------------------------------------------------- 163 | 164 | PROJECT = tdbcodbc 165 | 166 | # Uncomment the following line if this is a Tk extension. 167 | #PROJECT_REQUIRES_TK=1 168 | !include "rules.vc" 169 | 170 | # nmakehelp -V will search the file for tag, skips until a 171 | # number and returns all character until a character not in [0-9.ab] 172 | # is read. 173 | 174 | !if [echo REM = This file is generated from Makefile.vc > versions.vc] 175 | !endif 176 | # get project version from row AC_INIT([tdbcodbc], [1.0b17]) 177 | !if [echo DOTVERSION = \>> versions.vc] \ 178 | && [nmakehlp -V ..\configure.in AC_INIT >> versions.vc] 179 | !endif 180 | !if [echo TCL_VERSION_REQ = \>> versions.vc] \ 181 | && [nmakehlp -V ..\configure.in TCL_VERSION_REQ >> versions.vc] 182 | !endif 183 | !include "versions.vc" 184 | 185 | VERSION = $(DOTVERSION:.=) 186 | STUBPREFIX = $(PROJECT)stub 187 | 188 | DLLOBJS = \ 189 | $(TMP_DIR)\tdbcodbc.obj \ 190 | $(TMP_DIR)\odbcStubInit.obj 191 | 192 | 193 | PRJSTUBOBJS = \ 194 | $(TMP_DIR)\odbcStubInit.obj 195 | 196 | PRJHEADERS = \ 197 | $(GENERICDIR)\fakesql.h \ 198 | $(GENERICDIR)\odbcStubs.h 199 | 200 | 201 | #------------------------------------------------------------------------- 202 | # Target names and paths ( shouldn't need changing ) 203 | #------------------------------------------------------------------------- 204 | 205 | BINROOT = $(MAKEDIR) 206 | ROOT = $(MAKEDIR)\.. 207 | 208 | PRJIMPLIB = $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib 209 | PRJLIBNAME = $(PROJECT)$(VERSION)$(SUFX).$(EXT) 210 | PRJLIB = $(OUT_DIR)\$(PRJLIBNAME) 211 | 212 | PRJSTUBLIBNAME = $(STUBPREFIX)$(VERSION).lib 213 | PRJSTUBLIB = $(OUT_DIR)\$(PRJSTUBLIBNAME) 214 | 215 | ### Make sure we use backslash only. 216 | PRJ_INSTALL_DIR = $(_INSTALLDIR)\$(PROJECT)$(DOTVERSION) 217 | LIB_INSTALL_DIR = $(PRJ_INSTALL_DIR) 218 | BIN_INSTALL_DIR = $(PRJ_INSTALL_DIR) 219 | DOC_INSTALL_DIR = $(PRJ_INSTALL_DIR) 220 | SCRIPT_INSTALL_DIR = $(PRJ_INSTALL_DIR) 221 | INCLUDE_INSTALL_DIR = $(_TCLDIR)\include 222 | 223 | ### The following paths CANNOT have spaces in them. 224 | GENERICDIR = $(ROOT)\generic 225 | WINDIR = $(ROOT)\win 226 | LIBDIR = $(ROOT)\library 227 | DOCDIR = $(ROOT)\doc 228 | TOOLSDIR = $(ROOT)\tools 229 | COMPATDIR = $(ROOT)\compat 230 | 231 | ### tdbc 232 | TDBC_DOTVERSION = $(DOTVERSION) 233 | TDBC_VERSION = $(TDBC_DOTVERSION:.=) 234 | # tdbc source folder is "../tdbc" in source distribution and 235 | # "../tdbc1.0.0" in tcl8.6.0 bundeled distribution 236 | TDBC_DIR = $(ROOT)\..\tdbc 237 | !if !exist($(TDBC_DIR)) 238 | TDBC_DIR = $(ROOT)\..\tdbc$(TDBC_DOTVERSION) 239 | !endif 240 | TDBC_GENERIC_DIR = $(TDBC_DIR)\generic 241 | ### tdbc stub lib 242 | TDBCSTUBLIBNAME = tdbcstub$(TDBC_VERSION).lib 243 | TDBCSTUBLIB = "$(_TCLDIR)\lib\$(TDBCSTUBLIBNAME)" 244 | !if !exist($(TDBCSTUBLIB)) 245 | TDBCSTUBLIB = $(TDBC_DIR)\win\$(BUILDDIRTOP)\$(TDBCSTUBLIBNAME) 246 | !endif 247 | TDBC_LIB_FILE = tdbc$(TDBC_VERSION).dll 248 | TDBC_BIN_DIR = $(TDBC_DIR)/win/$(BUILDDIRTOP) 249 | 250 | #--------------------------------------------------------------------- 251 | # Compile flags 252 | #--------------------------------------------------------------------- 253 | 254 | !if !$(DEBUG) 255 | !if $(OPTIMIZING) 256 | ### This cranks the optimization level to maximize speed 257 | cdebug = $(OPTIMIZATIONS) 258 | !else 259 | cdebug = 260 | !endif 261 | !else if "$(MACHINE)" == "IA64" 262 | ### Warnings are too many, can't support warnings into errors. 263 | cdebug = -Zi -Od $(DEBUGFLAGS) 264 | !else 265 | cdebug = -Zi -WX $(DEBUGFLAGS) 266 | !endif 267 | 268 | ### Declarations common to all compiler options 269 | cwarn = $(WARNINGS) -D _CRT_SECURE_NO_DEPRECATE -D _CRT_NONSTDC_NO_DEPRECATE 270 | cflags = -nologo -c $(COMPILERFLAGS) $(cwarn) -Fp$(TMP_DIR)^\ 271 | 272 | !if $(MSVCRT) 273 | !if $(DEBUG) && !$(UNCHECKED) 274 | crt = -MDd 275 | !else 276 | crt = -MD 277 | !endif 278 | !else 279 | !if $(DEBUG) && !$(UNCHECKED) 280 | crt = -MTd 281 | !else 282 | crt = -MT 283 | !endif 284 | !endif 285 | 286 | cflags = $(cflags) -DMODULE_SCOPE=extern 287 | 288 | !if !$(STATIC_BUILD) 289 | cflags = $(cflags) -DUSE_TCL_STUBS 290 | !if defined(TKSTUBLIB) 291 | cflags = $(cflags) -DUSE_TK_STUBS 292 | !endif 293 | !endif 294 | 295 | INCLUDES = $(TCL_INCLUDES) -I"$(WINDIR)" -I"$(GENERICDIR)" -I"$(TDBC_GENERIC_DIR)" 296 | BASE_CFLAGS = $(cflags) $(cdebug) $(crt) $(INCLUDES) 297 | CON_CFLAGS = $(cflags) $(cdebug) $(crt) -DCONSOLE 298 | TCL_CFLAGS = -DPACKAGE_NAME="\"$(PROJECT)\"" \ 299 | -DPACKAGE_VERSION="\"$(DOTVERSION)\"" \ 300 | -DBUILD_$(PROJECT) \ 301 | $(BASE_CFLAGS) $(OPTDEFINES) \ 302 | -Dinline=__inline 303 | 304 | ### Stubs files should not be compiled with -GL 305 | STUB_CFLAGS = $(cflags) $(cdebug:-GL=) #$(TK_DEFINES) 306 | 307 | #--------------------------------------------------------------------- 308 | # Link flags 309 | #--------------------------------------------------------------------- 310 | 311 | !if $(DEBUG) 312 | ldebug = -debug 313 | !if $(MSVCRT) 314 | ldebug = $(ldebug) -nodefaultlib:msvcrt 315 | !endif 316 | !else 317 | ldebug = -release -opt:ref -opt:icf,3 318 | !endif 319 | 320 | ### Declarations common to all linker options 321 | lflags = -nologo -machine:$(MACHINE) $(LINKERFLAGS) $(ldebug) 322 | 323 | !if $(PROFILE) 324 | lflags = $(lflags) -profile 325 | !endif 326 | 327 | !if $(ALIGN98_HACK) && !$(STATIC_BUILD) 328 | ### Align sections for PE size savings. 329 | lflags = $(lflags) -opt:nowin98 330 | !else if !$(ALIGN98_HACK) && $(STATIC_BUILD) 331 | ### Align sections for speed in loading by choosing the virtual page size. 332 | lflags = $(lflags) -align:4096 333 | !endif 334 | 335 | !if $(LOIMPACT) 336 | lflags = $(lflags) -ws:aggressive 337 | !endif 338 | 339 | dlllflags = $(lflags) -dll 340 | conlflags = $(lflags) -subsystem:console 341 | guilflags = $(lflags) -subsystem:windows 342 | !if !$(STATIC_BUILD) 343 | baselibs = $(TCLSTUBLIB) $(TDBCSTUBLIB) 344 | !if defined(TKSTUBLIB) 345 | baselibs = $(baselibs) $(TKSTUBLIB) 346 | !endif 347 | !endif 348 | 349 | # Avoid 'unresolved external symbol __security_cookie' errors. 350 | # c.f. http://support.microsoft.com/?id=894573 351 | !if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64" 352 | !if $(VCVERSION) > 1399 && $(VCVERSION) < 1500 353 | baselibs = $(baselibs) bufferoverflowU.lib 354 | !endif 355 | !endif 356 | 357 | #--------------------------------------------------------------------- 358 | # TclTest flags 359 | #--------------------------------------------------------------------- 360 | 361 | !if "$(TESTPAT)" != "" 362 | TESTFLAGS = $(TESTFLAGS) -file $(TESTPAT) 363 | !endif 364 | 365 | #--------------------------------------------------------------------- 366 | # Project specific targets (EDIT) 367 | #--------------------------------------------------------------------- 368 | 369 | all: setup $(PROJECT) 370 | $(PROJECT): setup pkgIndex $(PRJLIB) 371 | install: install-binaries install-libraries install-docs 372 | pkgIndex: setup $(OUT_DIR)\pkgIndex.tcl 373 | 374 | !if !$(STATIC_BUILD) 375 | $(PROJECT): $(PRJSTUBLIB) 376 | !endif 377 | 378 | test: test-jet test-sqlserver test-sqlite 379 | 380 | test: setup $(PROJECT) 381 | 382 | test-jet: setup $(PROJECT) 383 | @echo testing tdbcodbc against Jet 384 | @set TDBCODBC_TYPE=jet 385 | # the following is identical for all 3 tests 386 | @set TCL_LIBRARY=$(TCL_LIBRARY:\=/) 387 | @set TCLLIBPATH=$(OUT_DIR_PATH:\=/) 388 | @set TDBC_LIBRARY=$(LIBDIR:\=/) 389 | @$(CPY) $(LIBDIR)\*.tcl $(OUT_DIR) 390 | !if $(TCLINSTALL) 391 | @set PATH=$(_TCLDIR)\bin;$(PATH) 392 | $(DEBUGGER) $(TCLSH) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) 393 | !else 394 | @set PATH=$(_TCLDIR)\win\$(BUILDDIRTOP);$(PATH) 395 | $(DEBUGGER) $(TCLSH) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) \ 396 | -load "package ifneeded tdbc::odbc $(DOTVERSION) \ 397 | {source {$(LIBDIR:\=/)/tdbcodbc.tcl};load {$(PRJLIB:\=/)} $(PROJECT)};\ 398 | package ifneeded tdbc $(TDBC_DOTVERSION) \ 399 | {source {$(TDBC_BIN_DIR:\=/)/tdbc.tcl};load {$(TDBC_BIN_DIR:\=/)/$(TDBC_LIB_FILE)} tdbc}" 400 | !endif 401 | 402 | test-sqlserver: setup $(PROJECT) 403 | @echo testing tdbcodbc against SQL Server 404 | @set TDBCODBC_TYPE=sqlserver 405 | # the following is identical for all 3 tests 406 | @set TCL_LIBRARY=$(TCL_LIBRARY:\=/) 407 | @set TCLLIBPATH=$(OUT_DIR_PATH:\=/) 408 | @set TDBC_LIBRARY=$(LIBDIR:\=/) 409 | @$(CPY) $(LIBDIR)\*.tcl $(OUT_DIR) 410 | !if $(TCLINSTALL) 411 | @set PATH=$(_TCLDIR)\bin;$(PATH) 412 | $(DEBUGGER) $(TCLSH) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) 413 | !else 414 | @set PATH=$(_TCLDIR)\win\$(BUILDDIRTOP);$(PATH) 415 | $(DEBUGGER) $(TCLSH) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) \ 416 | -load "package ifneeded tdbc::odbc $(DOTVERSION) \ 417 | {source {$(LIBDIR:\=/)/tdbcodbc.tcl};load {$(PRJLIB:\=/)} $(PROJECT)};\ 418 | package ifneeded tdbc $(TDBC_DOTVERSION) \ 419 | {source {$(TDBC_BIN_DIR:\=/)/tdbc.tcl};load {$(TDBC_BIN_DIR:\=/)/$(TDBC_LIB_FILE)} tdbc}" 420 | !endif 421 | 422 | test-sqlite: setup $(PROJECT) 423 | @echo testing tdbcodbc against SQLite 424 | @set TDBCODBC_TYPE=sqlite 425 | # the following is identical for all 3 tests 426 | @set TCL_LIBRARY=$(TCL_LIBRARY:\=/) 427 | @set TCLLIBPATH=$(OUT_DIR_PATH:\=/) 428 | @set TDBC_LIBRARY=$(LIBDIR:\=/) 429 | @$(CPY) $(LIBDIR)\*.tcl $(OUT_DIR) 430 | !if $(TCLINSTALL) 431 | @set PATH=$(_TCLDIR)\bin;$(PATH) 432 | $(DEBUGGER) $(TCLSH) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) 433 | !else 434 | @set PATH=$(_TCLDIR)\win\$(BUILDDIRTOP);$(PATH) 435 | $(DEBUGGER) $(TCLSH) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) \ 436 | -load "package ifneeded tdbc::odbc $(DOTVERSION) \ 437 | {source {$(LIBDIR:\=/)/tdbcodbc.tcl};load {$(PRJLIB:\=/)} $(PROJECT)};\ 438 | package ifneeded tdbc $(TDBC_DOTVERSION) \ 439 | {source {$(TDBC_BIN_DIR:\=/)/tdbc.tcl};load {$(TDBC_BIN_DIR:\=/)/$(TDBC_LIB_FILE)} tdbc}" 440 | !endif 441 | 442 | shell: setup $(PROJECT) 443 | @set TCL_LIBRARY=$(TCL_LIBRARY:\=/) 444 | @set TDBC_LIBRARY=$(LIBDIR:\=/) 445 | !if $(TCLINSTALL) 446 | @set PATH=$(_TCLDIR)\bin;$(PATH) 447 | !else 448 | @set PATH=$(_TCLDIR)\win\$(BUILDDIRTOP);$(PATH) 449 | !endif 450 | $(DEBUGGER) $(TCLSH) $(SCRIPT) 451 | 452 | setup: 453 | @if not exist $(OUT_DIR)\nul mkdir $(OUT_DIR) 454 | @if not exist $(TMP_DIR)\nul mkdir $(TMP_DIR) 455 | 456 | # See /win/coffbase.txt for extension base addresses. 457 | $(PRJLIB): $(DLLOBJS) 458 | $(link32) $(dlllflags) -base:@$(COFFBASE),tdbc -out:$@ $(baselibs) @<< 459 | $** 460 | << 461 | $(_VC_MANIFEST_EMBED_DLL) 462 | -@del $*.exp 463 | 464 | $(PRJSTUBLIB): $(PRJSTUBOBJS) 465 | $(lib32) -nologo -out:$@ $(PRJSTUBOBJS) 466 | 467 | 468 | #--------------------------------------------------------------------- 469 | # Implicit rules 470 | #--------------------------------------------------------------------- 471 | 472 | {$(WINDIR)}.c{$(TMP_DIR)}.obj:: 473 | $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<< 474 | $< 475 | << 476 | 477 | {$(GENERICDIR)}.c{$(TMP_DIR)}.obj:: 478 | $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<< 479 | $< 480 | << 481 | 482 | {$(COMPATDIR)}.c{$(TMP_DIR)}.obj:: 483 | $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<< 484 | $< 485 | << 486 | 487 | {$(WINDIR)}.rc{$(TMP_DIR)}.res: 488 | $(rc32) -fo $@ -r -i "$(GENERICDIR)" -D__WIN32__ \ 489 | -DCOMMAVERSION=$(DOTVERSION:.=,),0 \ 490 | -DDOTVERSION=\"$(DOTVERSION)\" \ 491 | -DVERSION=\"$(VERSION)$(SUFX)\" \ 492 | !if $(DEBUG) 493 | -d DEBUG \ 494 | !endif 495 | !if $(TCL_THREADS) 496 | -d TCL_THREADS \ 497 | !endif 498 | !if $(STATIC_BUILD) 499 | -d STATIC_BUILD \ 500 | !endif 501 | $< 502 | 503 | .SUFFIXES: 504 | .SUFFIXES:.c .rc 505 | 506 | #------------------------------------------------------------------------- 507 | # Explicit dependency rules 508 | # 509 | #------------------------------------------------------------------------- 510 | .PHONY: $(OUT_DIR)\pkgIndex.tcl 511 | 512 | $(OUT_DIR)\pkgIndex.tcl: $(ROOT)\pkgIndex.tcl.in 513 | @nmakehlp -s << $** > $@ 514 | @PACKAGE_NAME@ $(PROJECT) 515 | @PACKAGE_VERSION@ $(DOTVERSION) 516 | @TCL_VERSION_REQ@ $(TCL_VERSION_REQ) 517 | @PKG_LIB_FILE@ $(PRJLIBNAME) 518 | << 519 | 520 | $(TMP_DIR)\odbcStubInit.obj : $(GENERICDIR)\odbcStubInit.c 521 | $(cc32) $(STUB_CFLAGS) $(TCL_INCLUDES) -Zl -DSTATIC_BUILD -Fo$@ $? 522 | 523 | #--------------------------------------------------------------------- 524 | # Installation. (EDIT) 525 | # 526 | # You may need to modify this section to reflect the final distribution 527 | # of your files and possibly to generate documentation. 528 | # 529 | #--------------------------------------------------------------------- 530 | 531 | install-binaries: 532 | @echo Installing binaries to '$(SCRIPT_INSTALL_DIR)' 533 | @if not exist "$(SCRIPT_INSTALL_DIR)" mkdir "$(SCRIPT_INSTALL_DIR)" 534 | @$(CPY) $(PRJLIB) "$(SCRIPT_INSTALL_DIR)" >NUL 535 | 536 | install-libraries: $(OUT_DIR)\pkgIndex.tcl 537 | @echo Installing libraries to '$(SCRIPT_INSTALL_DIR)' 538 | @if exist $(LIBDIR) $(CPY) $(LIBDIR)\*.tcl "$(SCRIPT_INSTALL_DIR)" 539 | @echo Installing package index in '$(SCRIPT_INSTALL_DIR)' 540 | @$(CPY) $(OUT_DIR)\pkgIndex.tcl "$(SCRIPT_INSTALL_DIR)" 541 | 542 | install-docs: 543 | @echo Installing documentation files to '$(DOC_INSTALL_DIR)' 544 | @if exist $(DOCDIR) $(CPY) $(DOCDIR)\*.n "$(DOC_INSTALL_DIR)" 545 | 546 | #--------------------------------------------------------------------- 547 | # Clean up 548 | #--------------------------------------------------------------------- 549 | 550 | clean: 551 | @if exist $(TMP_DIR)\nul $(RMDIR) $(TMP_DIR) 552 | @if exist $(WINDIR)\versions.vc del $(WINDIR)\versions.vc 553 | @if exist $(WINDIR)\vercl.i del $(WINDIR)\vercl.i 554 | @if exist $(WINDIR)\vercl.x del $(WINDIR)\vercl.x 555 | @if exist $(WINDIR)\_junk.pch del $(WINDIR)\_junk.pch 556 | 557 | realclean: clean 558 | @if exist $(OUT_DIR)\nul $(RMDIR) $(OUT_DIR) 559 | 560 | distclean: realclean 561 | @if exist $(WINDIR)\nmakehlp.exe del $(WINDIR)\nmakehlp.exe 562 | @if exist $(WINDIR)\nmakehlp.obj del $(WINDIR)\nmakehlp.obj 563 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2012-12-05 Harald Oehlmann 2 | 3 | * win/makefile.vc: Compiles when bundled and standalone, test fixed. 4 | 5 | 2012-11-14 Kevin B. Kenny 6 | 7 | * configure.in: Added code so that `make test` can find an 8 | * Makefile.in: uninstalled `tdbc` and load it from the build 9 | directory. 10 | * configure: autoconf-2.68 11 | *** ADVANCED THE AUTOCONF VERSION IN USE *** 12 | 13 | 2012-11-08 Don Porter 14 | 15 | * configure.in: 16 | * README: Advanced version number to 1.0.0. 17 | * configure: autoconf 2.59 18 | 19 | 2012-07-26 Jan Nijtmans 20 | 21 | * generic/odbcStubInit.s: Make some tables "const" 22 | * tclconfig/install-sh: Update to latest TEA 23 | * tclconfig/tcl.m4: 24 | * configure: autoconf-2.59 25 | 26 | 2012-07-13 Kevin B. Kenny 27 | 28 | * generic/tdbcodbc.c: A user asserts that certain 'output' parameters 29 | to SQLGetData must be initialized. While I have 30 | never seen the failure he reports, initializing 31 | them appears to be Mostly Harmless, so do so. 32 | (Bug [0dda7dbb73]). 33 | 34 | 2012-07-10 Kevin B. Kenny 35 | 36 | * generic/tdbcodbc.c: Fixed a non-static table argument to 37 | Tcl_GetIndexFromObjStruct. 38 | 39 | 2012-06-10 Jan Nijtmans 40 | 41 | * configure.in: make TDBC API functions MODULE_SCOPE 42 | * configure: autoconf-2.59 43 | 44 | 2012-06-08 Jan Nijtmans 45 | 46 | * tclconfig/ChangeLog: 47 | * tclconfig/tcl.m4: Update to latest TEA 48 | * configure: autoconf-2.59 49 | 50 | 2012-05-07 Kevin B. Kenny 51 | 52 | * generic/tdbcodbc.c: Fixed a crash when reporting SQLInstallError 53 | messages. pcbErrorMsg, documented to be 54 | an output parameter, needs to be preinitialized 55 | with the string length. 56 | 57 | 2011-08-30 Kevin B. Kenny 58 | 59 | * Makefile.in: Added a 'valgrind-sqlite' rule to allow for 60 | leak testing on Unix. 61 | * generic/odbcStubInit.c: 62 | * generic/tdbcodbc.c: A round of memory leak hunting. In the test 63 | suite, 6 'definitely lost' blocks remain, 64 | all of which at this point appear to be 65 | leaks in dependent libraries. Thanks to 66 | Giorgios Petasis for reporting the presence 67 | of the leaks and diagnosing two of them. 68 | * library/tdbcodbc.tcl: Corrected a typo in 'rename' statements that 69 | caused handles to leak (and potentially caused 70 | user commands to be deleted?) 71 | * tests/all.tcl: Added [rename exit {}] for leak checking. 72 | * tests/tdbcodbc.test: Removed a useless [catch] on a cleanup 73 | operation. 74 | 75 | 2011-07-19 Kevin B. Kenny 76 | 77 | * configure.in: 78 | * Makefile.in: 79 | * README: Advanced version number to 1.0b17. 80 | 81 | * configure: autoconf 2.59 82 | 83 | 2011-07-18 Don Porter 84 | 85 | * configure.in: Update to latest TEA 3.9 revisions. 86 | * Makefile.in: 87 | * tclconfig/*: 88 | 89 | * configure: autoconf-2.59 90 | 91 | 2011-02-21 Kevin B. Kenny 92 | 93 | * generic/tdbcodbc.c (GetCell, HasBigintMethod, ResultSetConstructor): 94 | Fix a crash where an error is returned from SQLGetData. 95 | Add a check for whether a connection supports 64-bit integers 96 | before trying to use them to replace NUMERIC or DECIMAL 97 | values. Add a method to determine 64-bit integer support. 98 | (Bug [8766b8dc40].) 99 | * library/tdbcodbc.tcl (tdbc::odbc::connection typemap): 100 | Add to initialization a check for 64-bit integer support 101 | so that the above change works. (Bug [8766b8dc40].) 102 | * tests/tdbcodbc.test: 103 | Code formatting changes to avoid long lines and spurious 104 | semicolons. 105 | 106 | 2011-02-20 Kevin B, Kenny 107 | 108 | * tests/tdbcodbc.test (tdbc::odbc-30.[45]): 109 | Added tests for [allrows] and [foreach] on multiple 110 | result sets. 111 | 112 | * generic/tdbcodbc.c (ResultSetNextresultsMethod): 113 | * tests/tdbcodbc.test (tdbc::odbc-{30.6,31.1}: 114 | Made 'rowcount' work for multiple result sets. Added a 115 | test for 'rowcount' in multiple result sets, and added 116 | a rudimentary test that stored procedures can be called. 117 | * library/tdbcodbc.tcl (tdbc::odbc::resultset preparecall) 118 | Added a non-executed sketch of how a preparse of 119 | a prepared statement call might go in order to allow 120 | the use of SQLProcedureColumns to determine parameter 121 | directions. (This code may or may not be used; a first 122 | experiment would simply be to make all SP parameters 123 | 'inout' and see if that works.) 124 | 125 | 2011-01-26 Kevin B. Kenny 126 | 127 | * doc/tdbc_odbc.n: 128 | Added empty comment at the start of each manpage because 'man' 129 | interprets comments there as directives. Thanks to Konstantin 130 | Kohmoutov for reporting and diagnosing this error. 131 | 132 | 2011-01-22 Kevin B. Kenny 133 | 134 | * odbcStubDefs.txt: Added SQLMoreResults, needed for multiple result 135 | sets. 136 | * odbcStubInit.c: 137 | * odbcStubs.h: make genstubs 138 | * tdbcodbc.c: Added a 'moreresults' method to the result set object 139 | to allow for SQL statements that return multiple result 140 | sets. 141 | Fixed a resource leak in the case where bad parameters 142 | are supplied to the 'foreignkeys' method. 143 | * tdbcodbc.test: Added tests that the 'moreresults' method works 144 | correctly in the event of 0, 1, and more than one 145 | result set. 146 | 147 | 2010-09-03 Kevin B. Kenny 148 | 149 | * tdbcodbc.test: Made tests more portable. 150 | 151 | * generic/odbcStubDefs.txt: 152 | * generic/tdbcodbc.c: 153 | * library/tdbcodbc.tcl: 154 | * tests/tdbcodbc.test: 155 | Added the 'primarykeys' and 'foreignkeys' methods, 156 | and the corresponding tests. 157 | * generic/odbcStubInit.c: 158 | * generic/odbcStubs.h: 159 | make genstubs 160 | 161 | * configure.in: 162 | * Makefile.in: 163 | * pkgIndex.tcl.in (new file): 164 | * README: 165 | * tclconfig/: Upgraded the build to use TEA 3.9. Changed the 166 | approach to pkgIndex.tcl generation. (It's now built 167 | at configure time, rather than from the Makefile.) 168 | Advanced version number to 1.0b16. 169 | 170 | * configure: autoconf 2.59 171 | 172 | 2010-06-19 Kevin B. Kenny 173 | 174 | * Makefile.in: Revised the code at the suggestion 175 | * generic/tdbcodbc.c: of Andreas Kupries to avoid using 176 | * tests/all.tcl: 'tcl_findLibrary' and instead execute 177 | * tests/tdbcodbc.test: both 'source' and 'load' commands from 178 | 'pkgIndex.tcl'. Revised the 'make test' 179 | rule, and the test scripts, to 180 | test successfully under the new regime. 181 | Thanks to Andreas for providing the 182 | original patch, and to Joe English 183 | for providing ideas for simplifying 184 | and repairing 'make test' under the 185 | new regime. 186 | 187 | 2010-05-12 Kevin B. Kenny 188 | 189 | * generic/fakesql.h: 190 | Eliminated uses of INT64 and UINT64 in 191 | favour of Tcl_WideInt and Tcl_WideUInt 192 | respectively. (Avoids a conflict with 193 | INT64 and UINT64 definitions in basetsd.h 194 | on Win64.) 195 | 196 | 2010-05-10 Kevin B. Kenny 197 | 198 | * aclocal.m4: Synchronized with the 'tdbc' package. 199 | * configure.in: Advanced release to 1.0b15 and TEA version to 3.7. 200 | Added code to detect VC++ and include the stub 201 | library by path rather than with -L and -l. 202 | * generic/fakesql.h: 203 | Corrected syntax of INSTAPI specifiers. 204 | * generic/odbcStubDefs.txt: 205 | Added a CONVENTION: SQL_API line so that 206 | genExtStubs.tcl can get the syntax right on the 207 | pointer-to-function declarations. 208 | * generic/odbcStubInit.txt: 209 | Corrected syntax of INSTAPI specifiers. Regenerated. 210 | * generic/odbcStubs.h: 211 | Regenerated. 212 | * generic/tdbcodbc.c: 213 | Silenced several VC++ warnings. 214 | * README: Advanced release to 1.0b15. 215 | * tclconfig/: Advanced to TEA 3.7 216 | * configure: autoconf-2.59 217 | 218 | 2010-05-10 Andreas Kupries 219 | 220 | * Makefile.in: Removed attempt to generate a stub library. Drivers 221 | do not export stub tables. 222 | 223 | 2010-04-30 Kevin B. Kenny 224 | 225 | * Makefile.in: Added missing files to 'make dist.' Added a 'genstubs' 226 | rule to automate building of the Stubs table from the 227 | ODBC library added at run time. 228 | * generic/fakesql.h: 229 | * generic/odbcStubDefs.txt: 230 | * generic/odbcStubInit.c: 231 | Fixed DOS line endings. 232 | 233 | 2010-04-25 Kevin B. Kenny 234 | 235 | * configure.in: 236 | * README: Advance version to 1.0b14 237 | * configure: autoconf 2-59 238 | 239 | 2010-04-10 Kevin B. Kenny 240 | 241 | * configure.in: 242 | * Makefile.in: Added code to specify to 'make test' and 'make shell' 243 | the value of TDBC_LIBRARY, needed for 244 | [package require tdbc] to work. This library is 245 | either the 'library' subdirectory of the TDBC source 246 | directory (when running from an un-installed TDBC) 247 | or else the TDBC library directory in the installed 248 | Tcl. 249 | * configure: autoconf 2.59 250 | 251 | 2010-04-08 Kevin B. Kenny 252 | 253 | * configure.in: Revised TDBC_ names to be tdbc_, because that's 254 | what TEA_LOAD_CONFIG does. Added a check to find 'tdbc.h' in the 255 | build directory if necessary. 256 | 257 | * configure: autoconf 2.59. 258 | 259 | 2010-03-17 Kevin B. Kenny 260 | 261 | * generic/odbcStubInit.c: Revised TIP 357 API yet again, adding a 262 | 'flags' parameter to Tcl_LoadFile. 263 | 264 | 2010-03-15 Kevin B. Kenny 265 | 266 | * generic/odbcStubInit.c: Adjusted to revised TIP 357 API. 267 | 268 | 2010-03-14 Kevin B. Kenny 269 | 270 | * configure.in: Removed all dependency on the native ODBC headers 271 | and import libraries. All ODBC references are now resolved at 272 | run time and contained in a 'fakesql.h' file. Removed references to 273 | Tk as well. 274 | * configure: autoconf-2.59 275 | * generic/fakesql.h (new file): Added file containing declarations 276 | of all ODBC API's used in this package, to avoid dependence on native 277 | headers. 278 | * generic/odbcStubsDefs.txt (new file): Declarations of functions 279 | imported from odbc32.dll using Tcl_LoadLibrary. 280 | * generic/odbcStubInit.c (new file): Code to load odbc32.dll and 281 | odbccp32.dll and initialize Stubs tables with the routines in them 282 | that are used in tdbc::odbc. 283 | * generic/odbcStubs.h (new file): Generated .h file with the Stubs 284 | structure defined in generic/odbcStubsDefs.txt. 285 | * tdbcodbc.c: Updated to use run-time-loaded ODBC libraries instead 286 | of associating to system headers at compile time and import libraries 287 | at link time. Revised handling of the '-parent' option so that the 288 | dependence on Tk is only at run time. 289 | 290 | 2009-09-29 Kevin B. Kenny 291 | 292 | * Makefile.in: Changed 'test' rule to test all available 293 | database types. 294 | * tests/tdbcodbc.test: Changed all TEST_* env vars to TDBCODBC_* 295 | for easier top-level scripting. Clarified 296 | and expanded database type selection. 297 | * generic/tdbcodbc.c: Replaced SQLSetConnectAttr with the obsolete 298 | SQLSetConnectOption, for better compatibility 299 | with older ODBC drivers. 300 | 301 | 2009-09-20 Kevin B. Kenny 302 | 303 | * README: 304 | * configure.in: Advance version number to 1.0b13 305 | * configure: autoconf-2.59 306 | 307 | 2009-07-02 Kevin B. Kenny 308 | 309 | * Makefile.in: Added testing on SQL Server Express so that 310 | * generic/tdbcodbc.c: more functionality and data types can be 311 | * tests/tdbcodbc.test: exposed. Added code to force column names 312 | in result sets to be unique. 313 | 314 | * library/tdbcodbc.tcl: Conditioned use of the IS_NULLABLE hack 315 | on the driver's not returning the NULLABLE 316 | flag in [$db columns]. This conditional 317 | fixes bug 3e523335bb, which fails when 318 | IS_NULLABLE is padded to a fixed length with 319 | spaces. 320 | * README: 321 | * configure.in: Advanced version to 1.0b12 322 | * configure: autoconf-2.59 323 | 324 | 2009-05-29 Kevin B. Kenny 325 | 326 | * README: 327 | * configure.in: Advanced version to 1.0b11 328 | * configure: autoconf-2.59 329 | 330 | * generic/tdbcodbc.c (GetCell): Corrected a problem where 331 | results longer than the preallocated buffer length had spurious 332 | NULL characters inserted. Corrected a subsequent problem where 333 | BLOBs had *missing* characters. (The ODBC documentation lies about 334 | terminating NULL bytes.) 335 | * tests/tdbcodbc.test (odbc-27.[12]): Corrected a problem where 336 | BLOB and MEMO tests didn't actually test anything. 337 | Thanks to Alan Grunwald for reporting these bugs 338 | 339 | 2009-04-19 Kevin B. Kenny 340 | 341 | * doc/tdbc_odbc.n: Added missing documentation for 'new' constructors. 342 | 343 | 2009-04-18 Kevin B. Kenny 344 | 345 | * doc/tdbc_odbc.n: Made changes so that NROFF formatting matches 346 | the Tcl standard. 347 | * generic/tdbcodbc.c: Changed so that all variable access failures 348 | are mapped to NULL rather than passing errors 349 | throught the interp. 350 | * tests/tdbcodbc.test: Adjusted test cases for inappropriate access 351 | to array variables. 352 | 353 | 2009-04-16 Kevin B. Kenny 354 | 355 | * README: 356 | * configure.in: Advanced version to 1.0b10 357 | * configure: autoconf-2.59 358 | 359 | 2009-03-03 Kevin B. Kenny 360 | 361 | * generic/tdbcodbc.c: 362 | * library/tdbcodbc.tcl: Replaced 'my variable' with variables at 363 | class level. Replaced 'init' methods with constructors implemented 364 | in C. Replaced 'statementClass' and 'resultSetClass' variables 365 | with forwarded 'statementCreate' and 'resultSetCreate' methods. 366 | 367 | 2009-02-16 Kevin B. Kenny 368 | 369 | * README: 370 | * configure.in: Advanced version to 1.0b9 371 | * configure: autoconf-2.59 372 | 373 | * Makefile.in: Removed useless TCL_VERSION_REQ test in the 374 | pkgIndex.tcl. 375 | * generic/tdbcodbc.c (GetCell): 376 | Fixed bad bug in retrieving LONGVARCHAR, LONGVARBINARY, 377 | CLOB, BLOB, etc. (The SQL_NO_TOTAL return was not being 378 | handled, resulting in infinite loops, memory corruption, 379 | or NULLS in place of the actual data.) 380 | * tests/tdbcodbc.test (tdbc::odbc-27.1): 381 | Added a test case for the above bug. 382 | Thanks to Patrick Dunnigan for the bug report. 383 | 384 | 2009-02-14 Kevin B. Kenny 385 | 386 | * configure.in: 387 | * README: Advance verwsion to 1.0b8 388 | * configure: autoconf-2.59 389 | 390 | * doc/tdbc_odbc.n: Formatting changes so that man2html works. 391 | 392 | * tests/tdbcodbc.test (tdbc::odbc-26.1): 393 | Removed superfluous difference between 394 | SQLite and non-SQLite tests - all now 395 | return the same SQLSTATE. 396 | 397 | 2009-02-01 Kevin B. Kenny 398 | 399 | * generic/tdbcodbc.c (StatementInitMethod): Corrected a bad check 400 | that caused SQLDescribeParam to be bypassed entirely. Corrected 401 | bad code that was exposed by this fix (SQLDescribeParam failure was 402 | handled incorrectly). Corrected the error code for variables in 403 | native SQL syntax. 404 | * tests/tdbcodbc.test: Corrected error codes for seven tests, to 405 | match the [try]-friendly error code syntax. 406 | 407 | 2009-01-31 Kevin B. Kenny 408 | 409 | * README: Advanced version to 1.0b7 410 | * configure.in: 411 | * configure: autoconf 2.59 412 | * generic/tdbcodbc.c: Revised error codes to be more [try]-friendly. 413 | * tests/tdbcodbc.test: Added test cases for revised error codes, 414 | and for an uncovered branch in ODBC statement error handling. 415 | 416 | 417 | 2009-01-05 Kevin B. Kenny 418 | 419 | * README: Advanced version to 1.0b6 420 | * configure.in: 421 | * configure: autoconf 2.59 422 | 423 | 2009-01-04 Kevin B. Kenny 424 | 425 | * README: Advanced version to 1.0b5 426 | * configure.in: 427 | * configure: autoconf 2.59 428 | 429 | 2008-12-30 Kevin B. Kenny 430 | 431 | * makefile.in: Changes to make 'make dist' work. 432 | * README: Advanced version to 1.0b4 433 | * configure.in: 434 | * configure: autoconf 2.59 435 | 436 | 2008-12-18 Kevin B. Kenny 437 | 438 | * configure: Autoconf 2.59, to conform with Tcl (mandir changes 439 | between 2.59 and 2.61). Signed manifest. 440 | 441 | 2008-12-08 Kevin B. Kenny 442 | 443 | * doc/tdbc_odbc.n: Added man page for the driver. 444 | 445 | 2008-12-07 Kevin B. Kenny 446 | 447 | * configure.in: 448 | * generic/tdbcodbc.c: 449 | * library/tdbcodbc.tcl: Advanced version to 1.0b1 in preparation for 450 | release, and cleaned up a little bit of dependency management. 451 | * configure: Autoconf 2.61 452 | 453 | 2008-12-06 Kevin B. Kenny 454 | 455 | * configure.in: 456 | * generic/tdbcodbc.c: Added the autoconf stuff to support finding 457 | the odbcinst libraries at configuration time. 458 | * configure: Autoconf 2.61 459 | 460 | 2008-12-05 Kevin B. Kenny 461 | 462 | * generic/tdbcodbc.c (DatasourceObjCmd): 463 | Added the tdbc::odbc::datasource command for adding, configuring 464 | and removing data sources. 465 | 466 | 2008-12-04 Kevin B. Kenny 467 | 468 | * generic/tdbcodc.c (ResultSetInitMethod, GetCell): 469 | * tests/tdbcodbc.test (tdbc::odbc-21.2): Added direct transfer of 470 | BINARY, VARBINARY, LONGVARBINARY parameters and results. 471 | 472 | 2008-12-03 Kevin B. Kenny 473 | 474 | * generic/tdbodbc.c: Added "tdbc::odbc::datasources" and 475 | * library/tdbcodbc.tcl: "tdbc::odbc::drivers" for inspection of 476 | * tests/tdbcodbc.test: available databases. 477 | 478 | 2008-12-01 Kevin B. Kenny 479 | 480 | * generic/tdbcodbc.c: Added '-encoding' and -timeout' options. 481 | Added direct transfer (rather than stringization) of parameters 482 | of integer and floating point types. 483 | * tests/tdbcodbc.test (tdbc::odbc-19.*): Added rudimentary 484 | configuration tests, and rudimentary tests of direct value 485 | transfers C <-> SQL. 486 | 487 | 2008-11-30 Kevin B. Kenny 488 | 489 | * configure.in: Changed PACKAGE_NAME to lowercase 'tdbcodbc' 490 | Changed PACKAGE_VERSION to 0.2a1 491 | * tclconfig/tcl.m4: 492 | Look in a few additional places for dependent packages. 493 | * library/tdbcodbc.tcl: Lowercased the 'tdbc' package and advanced the 494 | version number on which tdbcodbc depends. 495 | Added code to detect whether the connection 496 | supports Unicode. 497 | * generic/tdbcodbc.c: Added '-isolation' and '-readonly' configuration 498 | options. Added code to use Unicode if possible 499 | for columns of unknown type and wide-character 500 | columns. Changed the script-level package name 501 | to tdbc::odbc. 502 | * tests/tdbcodbc.test: Changed the script-level package name to 503 | tdbc::odbc. Renamed all tests accordingly. 504 | * Makefile.in: Changed the script-level package name to tdbc::odbc 505 | for building pkgIndex.tcl 506 | * test.mdb: Reverted a commit that corrupted this file. 507 | 508 | 2008-11-22 Kevin B. Kenny 509 | 510 | * configure.in: Changed configurator so that 8.6 no longer requires a 511 | dummy tclooConfig.h. 512 | * configure: Autoconf 2.61 513 | 514 | 2008-06-15 Kevin B. Kenny 515 | 516 | * generic/tdbcodbc.c: 517 | * tests/tdbcodbc.test: Removed the default check for Tk. Instead, 518 | added a '-parent window' option to the constructor of 519 | tdbc::odbc::connection that gives a parent window for the 520 | driver manager dialog. 521 | Added a 'configure' method to the connection object, and 522 | rudimentary tests. (No configuration options yet implemented) 523 | 524 | 2008-06-11 Kevin B. Kenny 525 | 526 | * generic/tdbcodbc.c: Split [$resultset nextrow] into two primitive 527 | methods: [$resultset nextlist] and [$resultset nextdict]. Refactored 528 | a little bit of the code that handles result sets. 529 | 530 | 2008-05-24 Kevin B Kenny 531 | 532 | * configure.in: Changed configuration to use TEA_PATH_CONFIG to 533 | * aclocal.m4: locate tcloo and tdbc. Removed the local code that 534 | did it from aclocal.m4. 535 | * configure: Autoconf 2.61 536 | 537 | 2008-05-13 Kevin B. Kenny 538 | 539 | * Makefile (deleted): Removed a superfluous file from an 540 | earlier stage of development. 541 | * generic/tdbcodbc.c (TablesStmtInitMethod,ResultSetNextrowMethod): 542 | Removed a cut-and-paste error in TablesStmtInitMethod that 543 | caused a pointer smash, and added a cast to silence a gcc 544 | warning. Changed the 'init2' method on the 'statement' 545 | class back to 'init' now that TclOO seems to be getting 546 | method resolution correct. 547 | * library/tdbcodbc.tcl (tdbc::sqlite::statement constructor): 548 | Changed the 'init2' method on 'statement' back to 549 | 'init' now that TclOO seems to be getting method resolution 550 | correct. 551 | * tests/tdbcodbc.test: Corrected misnumbering of tests, and added 552 | code to remove the test database on startup to avoid running 553 | with old data if a previous test run aborted. 554 | 555 | 2008-05-10 Kevin B. Kenny 556 | 557 | * tests/tdbcodbc.test (tdbcodbc-9.9): Corrected invalid test numbering. 558 | 559 | 2008-05-01 Kevin B. Kenny 560 | 561 | * tdbcodbc/Makefile.in: 562 | * tdbcodbc/TODO: 563 | * tdbcodbc/aclocal.m4: 564 | * tdbcodbc/configure: 565 | * tdbcodbc/configure.in: 566 | * tdbcodbc/generic/tdbcodbc.c: 567 | * tdbcodbc/library/tdbcodbc.tcl: 568 | * tdbcodbc/tclconfig/ChangeLog: 569 | * tdbcodbc/tclconfig/README.txt: 570 | * tdbcodbc/tclconfig/install-sh: 571 | * tdbcodbc/tclconfig/tcl.m4: 572 | * tdbcodbc/tests/all.tcl: 573 | * tdbcodbc/tests/tdbcodbc.test: 574 | * tdbcodbc/tests/test.mdb: 575 | Initial commit of a 'tdbcodbc' package that provides a reference 576 | implementation of a TDBC driver layered atop ODBC. 577 | --------------------------------------------------------------------------------