Remove all of the libpgtcl and pgtclsh files, including all references to

them within the various makefiles

with_tcl is still required for the src/pl/tcl language
This commit is contained in:
PostgreSQL Daemon 2004-04-20 00:33:53 +00:00
parent d1b3915ce1
commit 41fa9e9bae
22 changed files with 8 additions and 4186 deletions

View File

@ -1,7 +1,7 @@
#
# PostgreSQL top level makefile
#
# $PostgreSQL: pgsql/GNUmakefile.in,v 1.37 2004/01/19 21:20:04 tgl Exp $
# $PostgreSQL: pgsql/GNUmakefile.in,v 1.38 2004/04/20 00:33:44 pgsql Exp $
#
subdir =
@ -71,8 +71,6 @@ $(distdir).tar: distdir
opt_files := \
src/tools src/corba src/tutorial \
src/bin/pgtclsh \
$(addprefix src/interfaces/, libpgtcl) \
$(addprefix src/pl/, plperl plpython tcl)
docs_files := doc/postgres.tar.gz doc/src doc/TODO.detail

121
configure vendored
View File

@ -859,9 +859,7 @@ Optional Packages:
--with-libs=DIRS alternative spelling of --with-libraries
--with-pgport=PORTNUM change default port number 5432
--with-tcl build Tcl and Tk interfaces
--without-tk do not build Tk interfaces if Tcl is enabled
--with-tclconfig=DIR tclConfig.sh and tkConfig.sh are in DIR
--with-tkconfig=DIR tkConfig.sh is in DIR
--with-tclconfig=DIR tclConfig.sh is in DIR
--with-perl build Perl modules (PL/Perl)
--with-python build Python modules (PL/Python)
--with-krb4 build with Kerberos 4 support
@ -2999,44 +2997,6 @@ echo "$as_me:$LINENO: result: $with_tcl" >&5
echo "${ECHO_T}$with_tcl" >&6
# If Tcl is enabled (above) then Tk is also, unless the user disables it using --without-tk
echo "$as_me:$LINENO: checking whether to build with Tk" >&5
echo $ECHO_N "checking whether to build with Tk... $ECHO_C" >&6
if test "$with_tcl" = yes; then
# Check whether --with-tk or --without-tk was given.
if test "${with_tk+set}" = set; then
withval="$with_tk"
case $withval in
yes)
:
;;
no)
:
;;
*)
{ { echo "$as_me:$LINENO: error: no argument expected for --with-tk option" >&5
echo "$as_me: error: no argument expected for --with-tk option" >&2;}
{ (exit 1); exit 1; }; }
;;
esac
else
with_tk=yes
fi;
else
with_tk=no
fi
echo "$as_me:$LINENO: result: $with_tk" >&5
echo "${ECHO_T}$with_tk" >&6
# We see if the path to the Tcl/Tk configuration scripts is specified.
# This will override the use of tclsh to find the paths to search.
@ -3066,35 +3026,6 @@ echo "$as_me: error: argument required for --with-tclconfig option" >&2;}
fi;
# We see if the path to the Tk configuration scripts is specified.
# This will override the use of tclsh to find the paths to search.
# Check whether --with-tkconfig or --without-tkconfig was given.
if test "${with_tkconfig+set}" = set; then
withval="$with_tkconfig"
case $withval in
yes)
{ { echo "$as_me:$LINENO: error: argument required for --with-tkconfig option" >&5
echo "$as_me: error: argument required for --with-tkconfig option" >&2;}
{ (exit 1); exit 1; }; }
;;
no)
{ { echo "$as_me:$LINENO: error: argument required for --with-tkconfig option" >&5
echo "$as_me: error: argument required for --with-tkconfig option" >&2;}
{ (exit 1); exit 1; }; }
;;
*)
;;
esac
fi;
#
# Optionally build Perl modules (PL/Perl)
#
@ -17233,51 +17164,6 @@ eval TCL_SHARED_BUILD=\"$TCL_SHARED_BUILD\"
fi
# Check for Tk configuration script tkConfig.sh
if test "$with_tk" = yes; then
echo "$as_me:$LINENO: checking for tkConfig.sh" >&5
echo $ECHO_N "checking for tkConfig.sh... $ECHO_C" >&6
# Let user override test
if test -z "$TK_CONFIG_SH"; then
pgac_test_dirs="$with_tkconfig $with_tclconfig"
set X $pgac_test_dirs; shift
if test $# -eq 0; then
test -z "$TCLSH" && { { echo "$as_me:$LINENO: error: unable to locate tkConfig.sh because no Tcl shell was found" >&5
echo "$as_me: error: unable to locate tkConfig.sh because no Tcl shell was found" >&2;}
{ (exit 1); exit 1; }; }
set X `echo 'puts $auto_path' | $TCLSH`; shift
fi
for pgac_dir do
if test -r "$pgac_dir/tkConfig.sh"; then
TK_CONFIG_SH=$pgac_dir/tkConfig.sh
break
fi
done
fi
if test -z "$TK_CONFIG_SH"; then
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
{ { echo "$as_me:$LINENO: error: file 'tkConfig.sh' is required for Tk" >&5
echo "$as_me: error: file 'tkConfig.sh' is required for Tk" >&2;}
{ (exit 1); exit 1; }; }
else
echo "$as_me:$LINENO: result: $TK_CONFIG_SH" >&5
echo "${ECHO_T}$TK_CONFIG_SH" >&6
fi
. "$TK_CONFIG_SH"
eval TK_LIBS=\"$TK_LIBS\"
eval TK_LIB_SPEC=\"$TK_LIB_SPEC\"
eval TK_XINCLUDES=\"$TK_XINCLUDES\"
fi
#
# Check for DocBook and tools
#
@ -18197,7 +18083,6 @@ s,@autodepend@,$autodepend,;t t
s,@INCLUDES@,$INCLUDES,;t t
s,@enable_thread_safety@,$enable_thread_safety,;t t
s,@with_tcl@,$with_tcl,;t t
s,@with_tk@,$with_tk,;t t
s,@with_perl@,$with_perl,;t t
s,@with_python@,$with_python,;t t
s,@with_krb4@,$with_krb4,;t t
@ -18253,10 +18138,6 @@ s,@TCL_LIBS@,$TCL_LIBS,;t t
s,@TCL_LIB_SPEC@,$TCL_LIB_SPEC,;t t
s,@TCL_SHARED_BUILD@,$TCL_SHARED_BUILD,;t t
s,@TCL_SHLIB_LD_LIBS@,$TCL_SHLIB_LD_LIBS,;t t
s,@TK_CONFIG_SH@,$TK_CONFIG_SH,;t t
s,@TK_LIBS@,$TK_LIBS,;t t
s,@TK_LIB_SPEC@,$TK_LIB_SPEC,;t t
s,@TK_XINCLUDES@,$TK_XINCLUDES,;t t
s,@NSGMLS@,$NSGMLS,;t t
s,@JADE@,$JADE,;t t
s,@have_docbook@,$have_docbook,;t t

View File

@ -1,5 +1,5 @@
dnl Process this file with autoconf to produce a configure script.
dnl $PostgreSQL: pgsql/configure.in,v 1.322 2004/03/24 03:54:16 momjian Exp $
dnl $PostgreSQL: pgsql/configure.in,v 1.323 2004/04/20 00:33:45 pgsql Exp $
dnl
dnl Developers, please strive to achieve this order:
dnl
@ -372,26 +372,10 @@ PGAC_ARG_BOOL(with, tcl, no, [ --with-tcl build Tcl and Tk interfa
AC_MSG_RESULT([$with_tcl])
AC_SUBST([with_tcl])
# If Tcl is enabled (above) then Tk is also, unless the user disables it using --without-tk
AC_MSG_CHECKING([whether to build with Tk])
if test "$with_tcl" = yes; then
PGAC_ARG_BOOL(with, tk, yes, [ --without-tk do not build Tk interfaces if Tcl is enabled])
else
with_tk=no
fi
AC_MSG_RESULT([$with_tk])
AC_SUBST([with_tk])
# We see if the path to the Tcl/Tk configuration scripts is specified.
# This will override the use of tclsh to find the paths to search.
PGAC_ARG_REQ(with, tclconfig, [ --with-tclconfig=DIR tclConfig.sh and tkConfig.sh are in DIR])
# We see if the path to the Tk configuration scripts is specified.
# This will override the use of tclsh to find the paths to search.
PGAC_ARG_REQ(with, tkconfig, [ --with-tkconfig=DIR tkConfig.sh is in DIR])
PGAC_ARG_REQ(with, tclconfig, [ --with-tclconfig=DIR tclConfig.sh is in DIR])
#
# Optionally build Perl modules (PL/Perl)
@ -1189,13 +1173,6 @@ if test "$with_tcl" = yes; then
AC_SUBST(TCL_SHLIB_LD_LIBS)dnl don't want to double-evaluate that one
fi
# Check for Tk configuration script tkConfig.sh
if test "$with_tk" = yes; then
PGAC_PATH_TKCONFIGSH([$with_tkconfig $with_tclconfig])
PGAC_EVAL_TCLCONFIGSH([$TK_CONFIG_SH], [TK_LIBS,TK_LIB_SPEC,TK_XINCLUDES])
fi
#
# Check for DocBook and tools
#

View File

@ -1,5 +1,5 @@
# -*-makefile-*-
# $PostgreSQL: pgsql/src/Makefile.global.in,v 1.176 2004/03/10 21:12:46 momjian Exp $
# $PostgreSQL: pgsql/src/Makefile.global.in,v 1.177 2004/04/20 00:33:46 pgsql Exp $
#------------------------------------------------------------------------------
# All PostgreSQL makefiles include this file and use the variables it sets,
@ -123,7 +123,6 @@ localedir := @localedir@
with_perl = @with_perl@
with_python = @with_python@
with_tcl = @with_tcl@
with_tk = @with_tk@
enable_shared = @enable_shared@
enable_rpath = @enable_rpath@
enable_nls = @enable_nls@

View File

@ -5,7 +5,7 @@
# Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California
#
# $PostgreSQL: pgsql/src/bin/Makefile,v 1.41 2003/12/17 18:44:08 petere Exp $
# $PostgreSQL: pgsql/src/bin/Makefile,v 1.42 2004/04/20 00:33:47 pgsql Exp $
#
#-------------------------------------------------------------------------
@ -17,10 +17,6 @@ DIRS := initdb initlocation ipcclean pg_ctl pg_dump \
psql scripts pg_config pg_controldata pg_resetxlog \
pg_encoding
ifeq ($(with_tcl), yes)
DIRS += pgtclsh
endif
all install installdirs uninstall depend distprep:
@for dir in $(DIRS); do $(MAKE) -C $$dir $@ || exit; done

View File

@ -1,58 +0,0 @@
#-------------------------------------------------------------------------
#
# Makefile for src/bin/pgtclsh
# (a tclsh workalike with pgtcl commands installed)
#
# Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California
#
# $PostgreSQL: pgsql/src/bin/pgtclsh/Makefile,v 1.43 2003/12/19 11:54:25 petere Exp $
#
#-------------------------------------------------------------------------
subdir = src/bin/pgtclsh
top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
libpgtcl_srcdir = $(top_srcdir)/src/interfaces/libpgtcl
libpgtcl_builddir = $(top_builddir)/src/interfaces/libpgtcl
libpgtcl = -L$(libpgtcl_builddir) -lpgtcl
override CPPFLAGS := -I$(libpgtcl_srcdir) $(TK_XINCLUDES) $(TCL_INCLUDE_SPEC) $(CPPFLAGS)
# If we are here then Tcl is available
PROGRAMS = pgtclsh
# Add Tk targets if Tk is available
ifeq ($(with_tk), yes)
PROGRAMS += pgtksh
endif
all: submake $(PROGRAMS)
pgtclsh: pgtclAppInit.o
$(CC) $(CFLAGS) $^ $(libpgtcl) $(libpq) $(TCL_LIB_SPEC) $(TCL_LIBS) $(LDFLAGS) $(LIBS) -o $@
pgtksh: pgtkAppInit.o
$(CC) $(CFLAGS) $^ $(libpgtcl) $(libpq) $(TK_LIB_SPEC) $(TK_LIBS) $(TCL_LIB_SPEC) $(LDFLAGS) $(LIBS) -o $@
.PHONY: submake
submake:
$(MAKE) -C $(libpgtcl_builddir) all
install: all installdirs
$(INSTALL_PROGRAM) pgtclsh$(X) $(DESTDIR)$(bindir)/pgtclsh$(X)
ifeq ($(with_tk), yes)
$(INSTALL_PROGRAM) pgtksh$(X) $(DESTDIR)$(bindir)/pgtksh$(X)
endif
installdirs:
$(mkinstalldirs) $(DESTDIR)$(bindir)
uninstall:
rm -f $(DESTDIR)$(bindir)/pgtclsh$(X) $(DESTDIR)$(bindir)/pgtksh$(X)
clean distclean maintainer-clean:
rm -f pgtclAppInit.o pgtkAppInit.o pgtclsh pgtksh

View File

@ -1,10 +0,0 @@
pgtclsh is an example of a tclsh extended with the new Tcl
commands provided by the libpgtcl library. By using pgtclsh, one can
write front-end applications to PostgreSQL in Tcl without having to
deal with any libpq programming at all.
The pgtclsh is an enhanced version of tclsh. Similarly, pgtksh is a
wish replacement with PostgreSQL bindings.
For details of the libpgtcl interface, please see the Programmer's
Guide.

View File

@ -1,112 +0,0 @@
/*
* pgtclAppInit.c
* a skeletal Tcl_AppInit that provides pgtcl initialization
* to create a tclsh that can talk to pglite backends
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1993 The Regents of the University of California.
* Copyright (c) 1994 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <tcl.h>
#include "libpgtcl.h"
/*
* The following variable is a special hack that is needed in order for
* Sun shared libraries to be used for Tcl.
*/
#ifdef NEED_MATHERR
extern int matherr();
int *tclDummyMathPtr = (int *) matherr;
#endif
/*
*----------------------------------------------------------------------
*
* main
*
* This is the main program for the application.
*
* Results:
* None: Tcl_Main never returns here, so this procedure never
* returns either.
*
* Side effects:
* Whatever the application does.
*
*----------------------------------------------------------------------
*/
int
main(int argc, char **argv)
{
Tcl_Main(argc, argv, Tcl_AppInit);
return 0; /* Needed only to prevent compiler
* warning. */
}
/*
*----------------------------------------------------------------------
*
* Tcl_AppInit
*
* This procedure performs application-specific initialization.
* Most applications, especially those that incorporate additional
* packages, will have their own version of this procedure.
*
* Results:
* Returns a standard Tcl completion code, and leaves an error
* message in interp->result if an error occurs.
*
* Side effects:
* Depends on the startup script.
*
*----------------------------------------------------------------------
*/
int
Tcl_AppInit(Tcl_Interp *interp)
{
if (Tcl_Init(interp) == TCL_ERROR)
return TCL_ERROR;
/*
* Call the init procedures for included packages. Each call should
* look like this:
*
* if (Mod_Init(interp) == TCL_ERROR) { return TCL_ERROR; }
*
* where "Mod" is the name of the module.
*/
if (Pgtcl_Init(interp) == TCL_ERROR)
return TCL_ERROR;
/*
* Call Tcl_CreateCommand for application-specific commands, if they
* weren't already created by the init procedures called above.
*/
/*
* Specify a user-specific startup file to invoke if the application
* is run interactively. Typically the startup file is "~/.apprc"
* where "app" is the name of the application. If this line is
* deleted then no user-specific startup file will be run under any
* conditions.
*/
#if (TCL_MAJOR_VERSION <= 7) && (TCL_MINOR_VERSION < 5)
tcl_RcFileName = "~/.tclshrc";
#else
Tcl_SetVar(interp, "tcl_rcFileName", "~/.tclshrc", TCL_GLOBAL_ONLY);
#endif
return TCL_OK;
}

View File

@ -1,17 +0,0 @@
# getDBs :
# get the names of all the databases at a given host and port number
# with the defaults being the localhost and port 5432
# return them in alphabetical order
proc getDBs { {host "localhost"} {port "5432"} } {
# datnames is the list to be result
set conn [pg_connect template1 -host $host -port $port]
set res [pg_exec $conn "SELECT datname FROM pg_database ORDER BY datname"]
set ntups [pg_result $res -numTuples]
for {set i 0} {$i < $ntups} {incr i} {
lappend datnames [pg_result $res -getTuple $i]
}
pg_result $res -clear
pg_disconnect $conn
return $datnames
}

View File

@ -1,114 +0,0 @@
/*
* pgtkAppInit.c
*
* a skeletal Tcl_AppInit that provides pgtcl initialization
* to create a tclsh that can talk to pglite backends
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1993 The Regents of the University of California.
* Copyright (c) 1994 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <tk.h>
#include "libpgtcl.h"
/*
* The following variable is a special hack that is needed in order for
* Sun shared libraries to be used for Tcl.
*/
#ifdef NEED_MATHERR
extern int matherr();
int *tclDummyMathPtr = (int *) matherr;
#endif
/*
*----------------------------------------------------------------------
*
* main
*
* This is the main program for the application.
*
* Results:
* None: Tk_Main never returns here, so this procedure never
* returns either.
*
* Side effects:
* Whatever the application does.
*
*----------------------------------------------------------------------
*/
int
main(int argc, char **argv)
{
Tk_Main(argc, argv, Tcl_AppInit);
return 0; /* Needed only to prevent compiler
* warning. */
}
/*
*----------------------------------------------------------------------
*
* Tcl_AppInit
*
* This procedure performs application-specific initialization.
* Most applications, especially those that incorporate additional
* packages, will have their own version of this procedure.
*
* Results:
* Returns a standard Tcl completion code, and leaves an error
* message in interp->result if an error occurs.
*
* Side effects:
* Depends on the startup script.
*
*----------------------------------------------------------------------
*/
int
Tcl_AppInit(Tcl_Interp *interp)
{
if (Tcl_Init(interp) == TCL_ERROR)
return TCL_ERROR;
if (Tk_Init(interp) == TCL_ERROR)
return TCL_ERROR;
/*
* Call the init procedures for included packages. Each call should
* look like this:
*
* if (Mod_Init(interp) == TCL_ERROR) { return TCL_ERROR; }
*
* where "Mod" is the name of the module.
*/
if (Pgtcl_Init(interp) == TCL_ERROR)
return TCL_ERROR;
/*
* Call Tcl_CreateCommand for application-specific commands, if they
* weren't already created by the init procedures called above.
*/
/*
* Specify a user-specific startup file to invoke if the application
* is run interactively. Typically the startup file is "~/.apprc"
* where "app" is the name of the application. If this line is
* deleted then no user-specific startup file will be run under any
* conditions.
*/
#if (TCL_MAJOR_VERSION <= 7) && (TCL_MINOR_VERSION < 5)
tcl_RcFileName = "~/.wishrc";
#else
Tcl_SetVar(interp, "tcl_rcFileName", "~/.wishrc", TCL_GLOBAL_ONLY);
#endif
return TCL_OK;
}

View File

@ -1,71 +0,0 @@
#
# updateStats
# updates the statistic of number of distinct attribute values
# (this should really be done by the vacuum command)
# this is kind of brute force and slow, but it works
# since we use SELECT DISTINCT to calculate the number of distinct values
# and that does a sort, you need to have plenty of disk space for the
# intermediate sort files.
#
# - jolly 6/8/95
#
# update_attnvals
# takes in a table and updates the attnvals columns for the attributes
# of that table
#
# conn is the database connection
# rel is the table name
proc update_attnvals {conn rel} {
# first, get the oid of the rel
set res [pg_exec $conn "SELECT oid FROM pg_class where relname = '$rel'"]
if { [pg_result $res -numTuples] == "0"} {
puts stderr "update_attnvals: Relation named $rel was not found"
return
}
set oid [pg_result $res -getTuple 0]
pg_result $res -clear
# use this query to find the names of the attributes
set res [pg_exec $conn "SELECT * FROM $rel WHERE 'f'::bool"]
set attrNames [pg_result $res -attributes]
puts "attrNames = $attrNames"
foreach att $attrNames {
# find how many distinct values there are for this attribute
# this may fail if the user-defined type doesn't have
# comparison operators defined
set res2 [pg_exec $conn "SELECT DISTINCT $att FROM $rel"]
set NVALS($att) [pg_result $res2 -numTuples]
puts "NVALS($att) is $NVALS($att)"
pg_result $res2 -clear
}
pg_result $res -clear
# now, update the pg_attribute table
foreach att $attrNames {
# first find the oid of the row to change
set res [pg_exec $conn "SELECT oid FROM pg_attribute a WHERE a.attname = '$att' and a.attrelid = '$oid'"]
set attoid [pg_result $res -getTuple 0]
set res2 [pg_exec $conn "UPDATE pg_attribute SET attnvals = $NVALS($att) where pg_attribute.oid = '$attoid'::oid"]
}
}
# updateStats
# takes in a database name
# and updates the attnval stat for all the user-defined tables
# in the database
proc updateStats { dbName } {
# datnames is the list to be result
set conn [pg_connect $dbName]
set res [pg_exec $conn "SELECT relname FROM pg_class WHERE relkind = 'r' and relname !~ '^pg_'"]
set ntups [pg_result $res -numTuples]
for {set i 0} {$i < $ntups} {incr i} {
set rel [pg_result $res -getTuple $i]
puts "updating attnvals stats on table $rel"
update_attnvals $conn $rel
}
pg_disconnect $conn
}

View File

@ -4,7 +4,7 @@
#
# Copyright (c) 1994, Regents of the University of California
#
# $PostgreSQL: pgsql/src/interfaces/Makefile,v 1.52 2004/01/19 21:20:06 tgl Exp $
# $PostgreSQL: pgsql/src/interfaces/Makefile,v 1.53 2004/04/20 00:33:51 pgsql Exp $
#
#-------------------------------------------------------------------------
@ -14,12 +14,7 @@ include $(top_builddir)/src/Makefile.global
DIRS := libpq ecpg
ALLDIRS := $(DIRS) libpgtcl
ifeq ($(with_tcl), yes)
DIRS += libpgtcl
endif
ALLDIRS := $(DIRS)
all install installdirs uninstall dep depend distprep:
@for dir in $(DIRS); do $(MAKE) -C $$dir $@ || exit; done

View File

@ -1,51 +0,0 @@
#-------------------------------------------------------------------------
#
# Makefile for libpgtcl library
#
# Copyright (c) 1994, Regents of the University of California
#
# $PostgreSQL: pgsql/src/interfaces/libpgtcl/Makefile,v 1.36 2004/02/10 07:26:25 tgl Exp $
#
#-------------------------------------------------------------------------
subdir = src/interfaces/libpgtcl
top_builddir = ../../..
include ../../Makefile.global
NAME= pgtcl
SO_MAJOR_VERSION= 2
SO_MINOR_VERSION= 5
override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) $(TCL_INCLUDE_SPEC)
OBJS= pgtcl.o pgtclCmds.o pgtclId.o
SHLIB_LINK = $(libpq) $(TCL_LIB_SPEC) $(TCL_LIBS) \
$(filter -lintl -lssl -lcrypto -lkrb5 -lcrypt, $(LIBS)) $(THREAD_LIBS)
all: submake-libpq all-lib
# Shared library stuff
include $(top_srcdir)/src/Makefile.shlib
install: all installdirs install-headers install-lib
.PHONY: install-headers
install-headers: libpgtcl.h
$(INSTALL_DATA) $< $(DESTDIR)$(includedir)/libpgtcl.h
installdirs:
$(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir)
uninstall: uninstall-lib
rm -f $(DESTDIR)$(includedir)/libpgtcl.h
clean distclean maintainer-clean: clean-lib
rm -f $(OBJS)
depend dep:
$(CC) -MM $(CFLAGS) *.c >depend
ifeq (depend,$(wildcard depend))
include depend
endif

View File

@ -1,38 +0,0 @@
libpgtcl is a library that implements Tcl commands for front-end
clients to interact with the Postgresql 6.3 (and perhaps later)
backends. See libpgtcl.doc for details.
For an example of how to build a new tclsh to use libpgtcl, see the
directory ../bin/pgtclsh
Note this version is modified by NeoSoft to have the following additional
features:
1. Postgres connections are a valid Tcl channel, and can therefore
be manipulated by the interp command (ie. shared or transfered).
A connection handle's results are transfered/shared with it.
(Result handles are NOT channels, though it was tempting). Note
that a "close $connection" is now functionally identical to a
"pg_disconnect $connection", although pg_connect must be used
to create a connection.
2. Result handles are changed in format: ${connection}.<result#>.
This just means for a connection 'pgtcl0', they look like pgtcl0.0,
pgtcl0.1, etc. Enforcing this syntax makes it easy to look up
the real pointer by indexing into an array associated with the
connection.
3. I/O routines are now defined for the connection handle. I/O to/from
the connection is only valid under certain circumstances: following
the execution of the queries "copy <table> from stdin" or
"copy <table> to stdout". In these cases, the result handle obtains
an intermediate status of "PGRES_COPY_IN" or "PGRES_COPY_OUT". The
programmer is then expected to use Tcl gets or read commands on the
database connection (not the result handle) to extract the copy data.
For copy outs, read until the standard EOF indication is encountered.
For copy ins, puts a single terminator (\.). The statement for this
would be
puts $conn "\\." or puts $conn {\.}
In either case (upon detecting the EOF or putting the `\.', the status
of the result handle will change to "PGRES_COMMAND_OK", and any further
I/O attempts will cause a Tcl error.

View File

@ -1,8 +0,0 @@
;libpgtcl.def
; The LIBRARY entry must be same as the name of your DLL, the name of
; our DLL is libpgtcl.dll
LIBRARY libpgtcl
EXPORTS
Pgtcl_Init
Pgtcl_SafeInit

View File

@ -1,24 +0,0 @@
/*-------------------------------------------------------------------------
*
* libpgtcl.h
*
* libpgtcl is a tcl package for front-ends to interface with PostgreSQL.
* It's a Tcl wrapper for libpq.
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/interfaces/libpgtcl/libpgtcl.h,v 1.17 2003/11/29 22:41:25 pgsql Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef LIBPGTCL_H
#define LIBPGTCL_H
#include <tcl.h>
extern int Pgtcl_Init(Tcl_Interp *interp);
extern int Pgtcl_SafeInit(Tcl_Interp *interp);
#endif /* LIBPGTCL_H */

View File

@ -1,170 +0,0 @@
/*-------------------------------------------------------------------------
*
* pgtcl.c
*
* libpgtcl is a tcl package for front-ends to interface with PostgreSQL.
* It's a Tcl wrapper for libpq.
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/interfaces/libpgtcl/pgtcl.c,v 1.31 2004/02/02 00:35:08 neilc Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres_fe.h"
#include "libpgtcl.h"
#include "pgtclCmds.h"
#include "pgtclId.h"
/*
* Pgtcl_Init
* initialization package for the PGTCL Tcl package
*
*/
int
Pgtcl_Init(Tcl_Interp *interp)
{
double tclversion;
/*
* finish off the ChannelType struct. Much easier to do it here then
* to guess where it might be by position in the struct. This is
* needed for Tcl7.6 *only*, which has the getfileproc.
*/
#if HAVE_TCL_GETFILEPROC
Pg_ConnType.getFileProc = PgGetFileProc;
#endif
/*
* Tcl versions >= 8.1 use UTF-8 for their internal string
* representation. Therefore PGCLIENTENCODING must be set to UNICODE
* for these versions.
*/
Tcl_GetDouble(interp, Tcl_GetVar(interp, "tcl_version", TCL_GLOBAL_ONLY), &tclversion);
if (tclversion >= 8.1)
Tcl_PutEnv("PGCLIENTENCODING=UNICODE");
/* register all pgtcl commands */
Tcl_CreateCommand(interp,
"pg_conndefaults",
Pg_conndefaults,
NULL, NULL);
Tcl_CreateCommand(interp,
"pg_connect",
Pg_connect,
NULL, NULL);
Tcl_CreateCommand(interp,
"pg_disconnect",
Pg_disconnect,
NULL, NULL);
Tcl_CreateCommand(interp,
"pg_exec",
Pg_exec,
NULL, NULL);
Tcl_CreateCommand(interp,
"pg_select",
Pg_select,
NULL, NULL);
Tcl_CreateCommand(interp,
"pg_result",
Pg_result,
NULL, NULL);
Tcl_CreateCommand(interp,
"pg_execute",
Pg_execute,
NULL, NULL);
Tcl_CreateCommand(interp,
"pg_lo_open",
Pg_lo_open,
NULL, NULL);
Tcl_CreateCommand(interp,
"pg_lo_close",
Pg_lo_close,
NULL, NULL);
#ifdef PGTCL_USE_TCLOBJ
Tcl_CreateObjCommand(interp,
"pg_lo_read",
Pg_lo_read,
NULL, NULL);
Tcl_CreateObjCommand(interp,
"pg_lo_write",
Pg_lo_write,
NULL, NULL);
#else
Tcl_CreateCommand(interp,
"pg_lo_read",
Pg_lo_read,
NULL, NULL);
Tcl_CreateCommand(interp,
"pg_lo_write",
Pg_lo_write,
NULL, NULL);
#endif
Tcl_CreateCommand(interp,
"pg_lo_lseek",
Pg_lo_lseek,
NULL, NULL);
Tcl_CreateCommand(interp,
"pg_lo_creat",
Pg_lo_creat,
NULL, NULL);
Tcl_CreateCommand(interp,
"pg_lo_tell",
Pg_lo_tell,
NULL, NULL);
Tcl_CreateCommand(interp,
"pg_lo_unlink",
Pg_lo_unlink,
NULL, NULL);
Tcl_CreateCommand(interp,
"pg_lo_import",
Pg_lo_import,
NULL, NULL);
Tcl_CreateCommand(interp,
"pg_lo_export",
Pg_lo_export,
NULL, NULL);
Tcl_CreateCommand(interp,
"pg_listen",
Pg_listen,
NULL, NULL);
Tcl_CreateCommand(interp,
"pg_on_connection_loss",
Pg_on_connection_loss,
NULL, NULL);
Tcl_PkgProvide(interp, "Pgtcl", "1.4");
return TCL_OK;
}
int
Pgtcl_SafeInit(Tcl_Interp *interp)
{
return Pgtcl_Init(interp);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,143 +0,0 @@
/*-------------------------------------------------------------------------
*
* pgtclCmds.h
* declarations for the C functions which implement pg_* tcl commands
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/interfaces/libpgtcl/pgtclCmds.h,v 1.32 2003/11/29 22:41:25 pgsql Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PGTCLCMDS_H
#define PGTCLCMDS_H
#include <tcl.h>
#include "libpq-fe.h"
/* Hack to deal with Tcl 8.4 const-ification without losing compatibility */
#ifndef CONST84
#define CONST84
#endif
#define RES_HARD_MAX 128
#define RES_START 16
/*
* From Tcl version 8.0 on we can make large object access binary.
*/
#ifdef TCL_MAJOR_VERSION
#if (TCL_MAJOR_VERSION >= 8)
#define PGTCL_USE_TCLOBJ
#endif
#endif
/*
* Each Pg_ConnectionId has a list of Pg_TclNotifies structs, one for each
* Tcl interpreter that has executed any pg_listens on the connection.
* We need this arrangement to be able to clean up if an interpreter is
* deleted while the connection remains open. A free side benefit is that
* multiple interpreters can be registered to listen for the same notify
* name. (All their callbacks will be called, but in an unspecified order.)
*
* We use the same approach for pg_on_connection_loss callbacks, but they
* are not kept in a hashtable since there's no name associated.
*/
typedef struct Pg_TclNotifies_s
{
struct Pg_TclNotifies_s *next; /* list link */
Tcl_Interp *interp; /* This Tcl interpreter */
/*
* NB: if interp == NULL, the interpreter is gone but we haven't yet
* got round to deleting the Pg_TclNotifies structure.
*/
Tcl_HashTable notify_hash; /* Active pg_listen requests */
char *conn_loss_cmd; /* pg_on_connection_loss cmd, or NULL */
} Pg_TclNotifies;
typedef struct Pg_ConnectionId_s
{
char id[32];
PGconn *conn;
int res_max; /* Max number of results allocated */
int res_hardmax; /* Absolute max to allow */
int res_count; /* Current count of active results */
int res_last; /* Optimize where to start looking */
int res_copy; /* Query result with active copy */
int res_copyStatus; /* Copying status */
PGresult **results; /* The results */
Pg_TclNotifies *notify_list; /* head of list of notify info */
int notifier_running; /* notify event source is live */
#if TCL_MAJOR_VERSION >= 8
Tcl_Channel notifier_channel; /* Tcl_Channel on which notifier
* is listening */
#else
int notifier_socket; /* PQsocket on which notifier is listening */
#endif
} Pg_ConnectionId;
/* Values of res_copyStatus */
#define RES_COPY_NONE 0
#define RES_COPY_INPROGRESS 1
#define RES_COPY_FIN 2
/* **************************/
/* registered Tcl functions */
/* **************************/
extern int Pg_conndefaults(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
extern int Pg_connect(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
extern int Pg_disconnect(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
extern int Pg_exec(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
extern int Pg_execute(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
extern int Pg_select(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
extern int Pg_result(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
extern int Pg_lo_open(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
extern int Pg_lo_close(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
#ifdef PGTCL_USE_TCLOBJ
extern int Pg_lo_read(ClientData cData, Tcl_Interp *interp, int objc,
Tcl_Obj *CONST objv[]);
extern int Pg_lo_write(ClientData cData, Tcl_Interp *interp, int objc,
Tcl_Obj *CONST objv[]);
#else
extern int Pg_lo_read(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
extern int Pg_lo_write(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
#endif
extern int Pg_lo_lseek(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
extern int Pg_lo_creat(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
extern int Pg_lo_tell(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
extern int Pg_lo_unlink(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
extern int Pg_lo_import(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
extern int Pg_lo_export(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
extern int Pg_listen(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
extern int Pg_on_connection_loss(ClientData cData, Tcl_Interp *interp,
int argc, CONST84 char *argv[]);
#endif /* PGTCLCMDS_H */

View File

@ -1,862 +0,0 @@
/*-------------------------------------------------------------------------
*
* pgtclId.c
*
* Contains Tcl "channel" interface routines, plus useful routines
* to convert between strings and pointers. These are needed because
* everything in Tcl is a string, but in C, pointers to data structures
* are needed.
*
* ASSUMPTION: sizeof(long) >= sizeof(void*)
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/interfaces/libpgtcl/pgtclId.c,v 1.45 2004/01/07 18:56:29 neilc Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres_fe.h"
#include <errno.h>
#include "pgtclCmds.h"
#include "pgtclId.h"
static int
PgEndCopy(Pg_ConnectionId * connid, int *errorCodePtr)
{
connid->res_copyStatus = RES_COPY_NONE;
if (PQendcopy(connid->conn))
{
PQclear(connid->results[connid->res_copy]);
connid->results[connid->res_copy] =
PQmakeEmptyPGresult(connid->conn, PGRES_BAD_RESPONSE);
connid->res_copy = -1;
*errorCodePtr = EIO;
return -1;
}
else
{
PQclear(connid->results[connid->res_copy]);
connid->results[connid->res_copy] =
PQmakeEmptyPGresult(connid->conn, PGRES_COMMAND_OK);
connid->res_copy = -1;
return 0;
}
}
/*
* Called when reading data (via gets) for a copy <rel> to stdout.
*/
int
PgInputProc(DRIVER_INPUT_PROTO)
{
Pg_ConnectionId *connid;
PGconn *conn;
int avail;
connid = (Pg_ConnectionId *) cData;
conn = connid->conn;
if (connid->res_copy < 0 ||
PQresultStatus(connid->results[connid->res_copy]) != PGRES_COPY_OUT)
{
*errorCodePtr = EBUSY;
return -1;
}
/*
* Read any newly arrived data into libpq's buffer, thereby clearing
* the socket's read-ready condition.
*/
if (!PQconsumeInput(conn))
{
*errorCodePtr = EIO;
return -1;
}
/* Move data from libpq's buffer to Tcl's. */
avail = PQgetlineAsync(conn, buf, bufSize);
if (avail < 0)
{
/* Endmarker detected, change state and return 0 */
return PgEndCopy(connid, errorCodePtr);
}
return avail;
}
/*
* Called when writing data (via puts) for a copy <rel> from stdin
*/
int
PgOutputProc(DRIVER_OUTPUT_PROTO)
{
Pg_ConnectionId *connid;
PGconn *conn;
connid = (Pg_ConnectionId *) cData;
conn = connid->conn;
if (connid->res_copy < 0 ||
PQresultStatus(connid->results[connid->res_copy]) != PGRES_COPY_IN)
{
*errorCodePtr = EBUSY;
return -1;
}
if (PQputnbytes(conn, buf, bufSize))
{
*errorCodePtr = EIO;
return -1;
}
/*
* This assumes Tcl script will write the terminator line in a single
* operation; maybe not such a good assumption?
*/
if (bufSize >= 3 && strncmp(&buf[bufSize - 3], "\\.\n", 3) == 0)
{
if (PgEndCopy(connid, errorCodePtr) == -1)
return -1;
}
return bufSize;
}
#if HAVE_TCL_GETFILEPROC
Tcl_File
PgGetFileProc(ClientData cData, int direction)
{
return NULL;
}
#endif
/*
* The WatchProc and GetHandleProc are no-ops but must be present.
*/
static void
PgWatchProc(ClientData instanceData, int mask)
{
}
static int
PgGetHandleProc(ClientData instanceData, int direction,
ClientData *handlePtr)
{
return TCL_ERROR;
}
Tcl_ChannelType Pg_ConnType = {
"pgsql", /* channel type */
NULL, /* blockmodeproc */
PgDelConnectionId, /* closeproc */
PgInputProc, /* inputproc */
PgOutputProc, /* outputproc */
NULL, /* SeekProc, Not used */
NULL, /* SetOptionProc, Not used */
NULL, /* GetOptionProc, Not used */
PgWatchProc, /* WatchProc, must be defined */
PgGetHandleProc, /* GetHandleProc, must be defined */
NULL /* Close2Proc, Not used */
};
/*
* Create and register a new channel for the connection
*/
void
PgSetConnectionId(Tcl_Interp *interp, PGconn *conn)
{
Tcl_Channel conn_chan;
Pg_ConnectionId *connid;
int i;
connid = (Pg_ConnectionId *) ckalloc(sizeof(Pg_ConnectionId));
connid->conn = conn;
connid->res_count = 0;
connid->res_last = -1;
connid->res_max = RES_START;
connid->res_hardmax = RES_HARD_MAX;
connid->res_copy = -1;
connid->res_copyStatus = RES_COPY_NONE;
connid->results = (PGresult **) ckalloc(sizeof(PGresult *) * RES_START);
for (i = 0; i < RES_START; i++)
connid->results[i] = NULL;
connid->notify_list = NULL;
connid->notifier_running = 0;
sprintf(connid->id, "pgsql%d", PQsocket(conn));
#if TCL_MAJOR_VERSION >= 8
connid->notifier_channel = Tcl_MakeTcpClientChannel((ClientData) PQsocket(conn));
Tcl_RegisterChannel(NULL, connid->notifier_channel);
#else
connid->notifier_socket = -1;
#endif
#if TCL_MAJOR_VERSION == 7 && TCL_MINOR_VERSION == 5
/* Original signature (only seen in Tcl 7.5) */
conn_chan = Tcl_CreateChannel(&Pg_ConnType, connid->id, NULL, NULL, (ClientData) connid);
#else
/* Tcl 7.6 and later use this */
conn_chan = Tcl_CreateChannel(&Pg_ConnType, connid->id, (ClientData) connid,
TCL_READABLE | TCL_WRITABLE);
#endif
Tcl_SetChannelOption(interp, conn_chan, "-buffering", "line");
Tcl_SetResult(interp, connid->id, TCL_VOLATILE);
Tcl_RegisterChannel(interp, conn_chan);
}
/*
* Get back the connection from the Id
*/
PGconn *
PgGetConnectionId(Tcl_Interp *interp, CONST84 char *id,
Pg_ConnectionId ** connid_p)
{
Tcl_Channel conn_chan;
Pg_ConnectionId *connid;
conn_chan = Tcl_GetChannel(interp, id, 0);
if (conn_chan == NULL || Tcl_GetChannelType(conn_chan) != &Pg_ConnType)
{
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, id, " is not a valid postgresql connection", 0);
if (connid_p)
*connid_p = NULL;
return NULL;
}
connid = (Pg_ConnectionId *) Tcl_GetChannelInstanceData(conn_chan);
if (connid_p)
*connid_p = connid;
return connid->conn;
}
/*
* Remove a connection Id from the hash table and
* close all portals the user forgot.
*/
int
PgDelConnectionId(DRIVER_DEL_PROTO)
{
Tcl_HashEntry *entry;
Tcl_HashSearch hsearch;
Pg_ConnectionId *connid;
Pg_TclNotifies *notifies;
int i;
connid = (Pg_ConnectionId *) cData;
for (i = 0; i < connid->res_max; i++)
{
if (connid->results[i])
PQclear(connid->results[i]);
}
ckfree((void *) connid->results);
/* Release associated notify info */
while ((notifies = connid->notify_list) != NULL)
{
connid->notify_list = notifies->next;
for (entry = Tcl_FirstHashEntry(&notifies->notify_hash, &hsearch);
entry != NULL;
entry = Tcl_NextHashEntry(&hsearch))
ckfree((char *) Tcl_GetHashValue(entry));
Tcl_DeleteHashTable(&notifies->notify_hash);
if (notifies->conn_loss_cmd)
ckfree((void *) notifies->conn_loss_cmd);
if (notifies->interp)
Tcl_DontCallWhenDeleted(notifies->interp, PgNotifyInterpDelete,
(ClientData) notifies);
ckfree((void *) notifies);
}
/*
* Turn off the Tcl event source for this connection, and delete any
* pending notify and connection-loss events.
*/
PgStopNotifyEventSource(connid, true);
/* Close the libpq connection too */
PQfinish(connid->conn);
connid->conn = NULL;
/*
* Kill the notifier channel, too. We must not do this until after
* we've closed the libpq connection, because Tcl will try to close
* the socket itself!
*
* XXX Unfortunately, while this works fine if we are closing due to
* explicit pg_disconnect, all Tcl versions through 8.4.1 dump core if
* we try to do it during interpreter shutdown. Not clear why. For
* now, we kill the channel during pg_disconnect, but during interp
* shutdown we just accept leakage of the (fairly small) amount of
* memory taken for the channel state representation. (Note we are not
* leaking a socket, since libpq closed that already.) We tell the
* difference between pg_disconnect and interpreter shutdown by
* testing for interp != NULL, which is an undocumented but apparently
* safe way to tell.
*/
#if TCL_MAJOR_VERSION >= 8
if (connid->notifier_channel != NULL && interp != NULL)
Tcl_UnregisterChannel(NULL, connid->notifier_channel);
#endif
/*
* We must use Tcl_EventuallyFree because we don't want the connid
* struct to vanish instantly if Pg_Notify_EventProc is active for it.
* (Otherwise, closing the connection from inside a pg_listen callback
* could lead to coredump.) Pg_Notify_EventProc can detect that the
* connection has been deleted from under it by checking connid->conn.
*/
Tcl_EventuallyFree((ClientData) connid, TCL_DYNAMIC);
return 0;
}
/*
* Find a slot for a new result id. If the table is full, expand it by
* a factor of 2. However, do not expand past the hard max, as the client
* is probably just not clearing result handles like they should.
*/
int
PgSetResultId(Tcl_Interp *interp, CONST84 char *connid_c, PGresult *res)
{
Tcl_Channel conn_chan;
Pg_ConnectionId *connid;
int resid,
i;
char buf[32];
conn_chan = Tcl_GetChannel(interp, connid_c, 0);
if (conn_chan == NULL)
return TCL_ERROR;
connid = (Pg_ConnectionId *) Tcl_GetChannelInstanceData(conn_chan);
/* search, starting at slot after the last one used */
resid = connid->res_last;
for (;;)
{
/* advance, with wraparound */
if (++resid >= connid->res_max)
resid = 0;
/* this slot empty? */
if (!connid->results[resid])
{
connid->res_last = resid;
break; /* success exit */
}
/* checked all slots? */
if (resid == connid->res_last)
break; /* failure exit */
}
if (connid->results[resid])
{
/* no free slot found, so try to enlarge array */
if (connid->res_max >= connid->res_hardmax)
{
Tcl_SetResult(interp, "hard limit on result handles reached",
TCL_STATIC);
return TCL_ERROR;
}
connid->res_last = resid = connid->res_max;
connid->res_max *= 2;
if (connid->res_max > connid->res_hardmax)
connid->res_max = connid->res_hardmax;
connid->results = (PGresult **) ckrealloc((void *) connid->results,
sizeof(PGresult *) * connid->res_max);
for (i = connid->res_last; i < connid->res_max; i++)
connid->results[i] = NULL;
}
connid->results[resid] = res;
sprintf(buf, "%s.%d", connid_c, resid);
Tcl_SetResult(interp, buf, TCL_VOLATILE);
return resid;
}
static int
getresid(Tcl_Interp *interp, CONST84 char *id, Pg_ConnectionId ** connid_p)
{
Tcl_Channel conn_chan;
char *mark;
int resid;
Pg_ConnectionId *connid;
if (!(mark = strchr(id, '.')))
return -1;
*mark = '\0';
conn_chan = Tcl_GetChannel(interp, id, 0);
*mark = '.';
if (conn_chan == NULL || Tcl_GetChannelType(conn_chan) != &Pg_ConnType)
{
Tcl_SetResult(interp, "Invalid connection handle", TCL_STATIC);
return -1;
}
if (Tcl_GetInt(interp, mark + 1, &resid) == TCL_ERROR)
{
Tcl_SetResult(interp, "Poorly formated result handle", TCL_STATIC);
return -1;
}
connid = (Pg_ConnectionId *) Tcl_GetChannelInstanceData(conn_chan);
if (resid < 0 || resid >= connid->res_max || connid->results[resid] == NULL)
{
Tcl_SetResult(interp, "Invalid result handle", TCL_STATIC);
return -1;
}
*connid_p = connid;
return resid;
}
/*
* Get back the result pointer from the Id
*/
PGresult *
PgGetResultId(Tcl_Interp *interp, CONST84 char *id)
{
Pg_ConnectionId *connid;
int resid;
if (!id)
return NULL;
resid = getresid(interp, id, &connid);
if (resid == -1)
return NULL;
return connid->results[resid];
}
/*
* Remove a result Id from the hash tables
*/
void
PgDelResultId(Tcl_Interp *interp, CONST84 char *id)
{
Pg_ConnectionId *connid;
int resid;
resid = getresid(interp, id, &connid);
if (resid == -1)
return;
connid->results[resid] = 0;
}
/*
* Get the connection Id from the result Id
*/
int
PgGetConnByResultId(Tcl_Interp *interp, CONST84 char *resid_c)
{
char *mark;
Tcl_Channel conn_chan;
if (!(mark = strchr(resid_c, '.')))
goto error_out;
*mark = '\0';
conn_chan = Tcl_GetChannel(interp, resid_c, 0);
*mark = '.';
if (conn_chan && Tcl_GetChannelType(conn_chan) == &Pg_ConnType)
{
Tcl_SetResult(interp, (char *) Tcl_GetChannelName(conn_chan),
TCL_VOLATILE);
return TCL_OK;
}
error_out:
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, resid_c, " is not a valid connection\n", 0);
return TCL_ERROR;
}
/*-------------------------------------------
Notify event source
These functions allow asynchronous notify messages arriving from
the SQL server to be dispatched as Tcl events. See the Tcl
Notifier(3) man page for more info.
The main trick in this code is that we have to cope with status changes
between the queueing and the execution of a Tcl event. For example,
if the user changes or cancels the pg_listen callback command, we should
use the new setting; we do that by not resolving the notify relation
name until the last possible moment.
We also have to handle closure of the channel or deletion of the interpreter
to be used for the callback (note that with multiple interpreters,
the channel can outlive the interpreter it was created by!)
Upon closure of the channel, we immediately delete the file event handler
for it, which has the effect of disabling any file-ready events that might
be hanging about in the Tcl event queue. But for interpreter deletion,
we just set any matching interp pointers in the Pg_TclNotifies list to NULL.
The list item stays around until the connection is deleted. (This avoids
trouble with walking through a list whose members may get deleted under us.)
Another headache is that Ousterhout keeps changing the Tcl I/O interfaces.
libpgtcl currently claims to work with Tcl 7.5, 7.6, and 8.0, and each of
'em is different. Worse, the Tcl_File type went away in 8.0, which means
there is no longer any platform-independent way of waiting for file ready.
So we now have to use a Unix-specific interface. Grumble.
In the current design, Pg_Notify_FileHandler is a file handler that
we establish by calling Tcl_CreateFileHandler(). It gets invoked from
the Tcl event loop whenever the underlying PGconn's socket is read-ready.
We suck up any available data (to clear the OS-level read-ready condition)
and then transfer any available PGnotify events into the Tcl event queue.
Eventually these events will be dispatched to Pg_Notify_EventProc. When
we do an ordinary PQexec, we must also transfer PGnotify events into Tcl's
event queue, since libpq might have read them when we weren't looking.
------------------------------------------*/
typedef struct
{
Tcl_Event header; /* Standard Tcl event info */
PGnotify *notify; /* Notify event from libpq, or NULL */
/* We use a NULL notify pointer to denote a connection-loss event */
Pg_ConnectionId *connid; /* Connection for server */
} NotifyEvent;
/* Dispatch a NotifyEvent that has reached the front of the event queue */
static int
Pg_Notify_EventProc(Tcl_Event *evPtr, int flags)
{
NotifyEvent *event = (NotifyEvent *) evPtr;
Pg_TclNotifies *notifies;
char *callback;
char *svcallback;
/* We classify SQL notifies as Tcl file events. */
if (!(flags & TCL_FILE_EVENTS))
return 0;
/* If connection's been closed, just forget the whole thing. */
if (event->connid == NULL)
{
if (event->notify)
PQfreemem(event->notify);
return 1;
}
/*
* Preserve/Release to ensure the connection struct doesn't disappear
* underneath us.
*/
Tcl_Preserve((ClientData) event->connid);
/*
* Loop for each interpreter that has ever registered on the
* connection. Each one can get a callback.
*/
for (notifies = event->connid->notify_list;
notifies != NULL;
notifies = notifies->next)
{
Tcl_Interp *interp = notifies->interp;
if (interp == NULL)
continue; /* ignore deleted interpreter */
/*
* Find the callback to be executed for this interpreter, if any.
*/
if (event->notify)
{
/* Ordinary NOTIFY event */
Tcl_HashEntry *entry;
entry = Tcl_FindHashEntry(&notifies->notify_hash,
event->notify->relname);
if (entry == NULL)
continue; /* no pg_listen in this interpreter */
callback = (char *) Tcl_GetHashValue(entry);
}
else
{
/* Connection-loss event */
callback = notifies->conn_loss_cmd;
}
if (callback == NULL)
continue; /* nothing to do for this interpreter */
/*
* We have to copy the callback string in case the user executes a
* new pg_listen or pg_on_connection_loss during the callback.
*/
svcallback = (char *) ckalloc((unsigned) (strlen(callback) + 1));
strcpy(svcallback, callback);
/*
* Execute the callback.
*/
Tcl_Preserve((ClientData) interp);
if (Tcl_GlobalEval(interp, svcallback) != TCL_OK)
{
if (event->notify)
Tcl_AddErrorInfo(interp, "\n (\"pg_listen\" script)");
else
Tcl_AddErrorInfo(interp, "\n (\"pg_on_connection_loss\" script)");
Tcl_BackgroundError(interp);
}
Tcl_Release((ClientData) interp);
ckfree(svcallback);
/*
* Check for the possibility that the callback closed the
* connection.
*/
if (event->connid->conn == NULL)
break;
}
Tcl_Release((ClientData) event->connid);
if (event->notify)
PQfreemem(event->notify);
return 1;
}
/*
* Transfer any notify events available from libpq into the Tcl event queue.
* Note that this must be called after each PQexec (to capture notifies
* that arrive during command execution) as well as in Pg_Notify_FileHandler
* (to capture notifies that arrive when we're idle).
*/
void
PgNotifyTransferEvents(Pg_ConnectionId * connid)
{
PGnotify *notify;
while ((notify = PQnotifies(connid->conn)) != NULL)
{
NotifyEvent *event = (NotifyEvent *) ckalloc(sizeof(NotifyEvent));
event->header.proc = Pg_Notify_EventProc;
event->notify = notify;
event->connid = connid;
Tcl_QueueEvent((Tcl_Event *) event, TCL_QUEUE_TAIL);
}
/*
* This is also a good place to check for unexpected closure of the
* connection (ie, backend crash), in which case we must shut down the
* notify event source to keep Tcl from trying to select() on the now-
* closed socket descriptor. But don't kill on-connection-loss
* events; in fact, register one.
*/
if (PQsocket(connid->conn) < 0)
PgConnLossTransferEvents(connid);
}
/*
* Handle a connection-loss event
*/
void
PgConnLossTransferEvents(Pg_ConnectionId * connid)
{
if (connid->notifier_running)
{
/* Put the on-connection-loss event in the Tcl queue */
NotifyEvent *event = (NotifyEvent *) ckalloc(sizeof(NotifyEvent));
event->header.proc = Pg_Notify_EventProc;
event->notify = NULL;
event->connid = connid;
Tcl_QueueEvent((Tcl_Event *) event, TCL_QUEUE_TAIL);
}
/*
* Shut down the notify event source to keep Tcl from trying to
* select() on the now-closed socket descriptor. And zap any
* unprocessed notify events ... but not, of course, the
* connection-loss event.
*/
PgStopNotifyEventSource(connid, false);
}
/*
* Cleanup code for coping when an interpreter or a channel is deleted.
*
* PgNotifyInterpDelete is registered as an interpreter deletion callback
* for each extant Pg_TclNotifies structure.
* NotifyEventDeleteProc is used by PgStopNotifyEventSource to cancel
* pending Tcl NotifyEvents that reference a dying connection.
*/
void
PgNotifyInterpDelete(ClientData clientData, Tcl_Interp *interp)
{
/* Mark the interpreter dead, but don't do anything else yet */
Pg_TclNotifies *notifies = (Pg_TclNotifies *) clientData;
notifies->interp = NULL;
}
/*
* Comparison routines for detecting events to be removed by Tcl_DeleteEvents.
* NB: In (at least) Tcl versions 7.6 through 8.0.3, there is a serious
* bug in Tcl_DeleteEvents: if there are multiple events on the queue and
* you tell it to delete the last one, the event list pointers get corrupted,
* with the result that events queued immediately thereafter get lost.
* Therefore we daren't tell Tcl_DeleteEvents to actually delete anything!
* We simply use it as a way of scanning the event queue. Events matching
* the about-to-be-deleted connid are marked dead by setting their connid
* fields to NULL. Then Pg_Notify_EventProc will do nothing when those
* events are executed.
*/
static int
NotifyEventDeleteProc(Tcl_Event *evPtr, ClientData clientData)
{
Pg_ConnectionId *connid = (Pg_ConnectionId *) clientData;
if (evPtr->proc == Pg_Notify_EventProc)
{
NotifyEvent *event = (NotifyEvent *) evPtr;
if (event->connid == connid && event->notify != NULL)
event->connid = NULL;
}
return 0;
}
/* This version deletes on-connection-loss events too */
static int
AllNotifyEventDeleteProc(Tcl_Event *evPtr, ClientData clientData)
{
Pg_ConnectionId *connid = (Pg_ConnectionId *) clientData;
if (evPtr->proc == Pg_Notify_EventProc)
{
NotifyEvent *event = (NotifyEvent *) evPtr;
if (event->connid == connid)
event->connid = NULL;
}
return 0;
}
/*
* File handler callback: called when Tcl has detected read-ready on socket.
* The clientData is a pointer to the associated connection.
* We can ignore the condition mask since we only ever ask about read-ready.
*/
static void
Pg_Notify_FileHandler(ClientData clientData, int mask)
{
Pg_ConnectionId *connid = (Pg_ConnectionId *) clientData;
/*
* Consume any data available from the SQL server (this just buffers
* it internally to libpq; but it will clear the read-ready
* condition).
*/
if (PQconsumeInput(connid->conn))
{
/* Transfer notify events from libpq to Tcl event queue. */
PgNotifyTransferEvents(connid);
}
else
{
/*
* If there is no input but we have read-ready, assume this means
* we lost the connection.
*/
PgConnLossTransferEvents(connid);
}
}
/*
* Start and stop the notify event source for a connection.
*
* We do not bother to run the notifier unless at least one pg_listen
* or pg_on_connection_loss has been executed on the connection. Currently,
* once started the notifier is run until the connection is closed.
*
* FIXME: if PQreset is executed on the underlying PGconn, the active
* socket number could change. How and when should we test for this
* and update the Tcl file handler linkage? (For that matter, we'd
* also have to reissue LISTEN commands for active LISTENs, since the
* new backend won't know about 'em. I'm leaving this problem for
* another day.)
*/
void
PgStartNotifyEventSource(Pg_ConnectionId * connid)
{
/* Start the notify event source if it isn't already running */
if (!connid->notifier_running)
{
int pqsock = PQsocket(connid->conn);
if (pqsock >= 0)
{
#if TCL_MAJOR_VERSION >= 8
Tcl_CreateChannelHandler(connid->notifier_channel,
TCL_READABLE,
Pg_Notify_FileHandler,
(ClientData) connid);
#else
/* In Tcl 7.5 and 7.6, we need to gin up a Tcl_File. */
Tcl_File tclfile = Tcl_GetFile((ClientData) pqsock, TCL_UNIX_FD);
Tcl_CreateFileHandler(tclfile, TCL_READABLE,
Pg_Notify_FileHandler, (ClientData) connid);
connid->notifier_socket = pqsock;
#endif
connid->notifier_running = 1;
}
}
}
void
PgStopNotifyEventSource(Pg_ConnectionId * connid, bool allevents)
{
/* Remove the event source */
if (connid->notifier_running)
{
#if TCL_MAJOR_VERSION >= 8
Tcl_DeleteChannelHandler(connid->notifier_channel,
Pg_Notify_FileHandler,
(ClientData) connid);
#else
/* In Tcl 7.5 and 7.6, we need to gin up a Tcl_File. */
Tcl_File tclfile = Tcl_GetFile((ClientData) connid->notifier_socket,
TCL_UNIX_FD);
Tcl_DeleteFileHandler(tclfile);
#endif
connid->notifier_running = 0;
}
/* Kill queued Tcl events that reference this channel */
if (allevents)
Tcl_DeleteEvents(AllNotifyEventDeleteProc, (ClientData) connid);
else
Tcl_DeleteEvents(NotifyEventDeleteProc, (ClientData) connid);
}

View File

@ -1,64 +0,0 @@
/*-------------------------------------------------------------------------
*
* pgtclId.h
*
* Contains Tcl "channel" interface routines, plus useful routines
* to convert between strings and pointers. These are needed because
* everything in Tcl is a string, but in C, pointers to data structures
* are needed.
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/interfaces/libpgtcl/pgtclId.h,v 1.25 2003/11/29 22:41:25 pgsql Exp $
*
*-------------------------------------------------------------------------
*/
extern void PgSetConnectionId(Tcl_Interp *interp, PGconn *conn);
#if TCL_MAJOR_VERSION == 7 && TCL_MINOR_VERSION == 5
/* Only Tcl 7.5 had drivers with this signature */
#define DRIVER_DEL_PROTO ClientData cData, Tcl_Interp *interp, \
Tcl_File inFile, Tcl_File outFile
#define DRIVER_OUTPUT_PROTO ClientData cData, Tcl_File outFile, char *buf, \
int bufSize, int *errorCodePtr
#define DRIVER_INPUT_PROTO ClientData cData, Tcl_File inFile, char *buf, \
int bufSize, int *errorCodePtr
#else
/* Tcl 7.6 and beyond use this signature */
#define DRIVER_OUTPUT_PROTO ClientData cData, CONST84 char *buf, int bufSize, \
int *errorCodePtr
#define DRIVER_INPUT_PROTO ClientData cData, char *buf, int bufSize, \
int *errorCodePtr
#define DRIVER_DEL_PROTO ClientData cData, Tcl_Interp *interp
#endif
extern PGconn *PgGetConnectionId(Tcl_Interp *interp, CONST84 char *id,
Pg_ConnectionId **);
extern int PgDelConnectionId(DRIVER_DEL_PROTO);
extern int PgOutputProc(DRIVER_OUTPUT_PROTO);
extern int PgInputProc(DRIVER_INPUT_PROTO);
extern int PgSetResultId(Tcl_Interp *interp, CONST84 char *connid,
PGresult *res);
extern PGresult *PgGetResultId(Tcl_Interp *interp, CONST84 char *id);
extern void PgDelResultId(Tcl_Interp *interp, CONST84 char *id);
extern int PgGetConnByResultId(Tcl_Interp *interp, CONST84 char *resid);
extern void PgStartNotifyEventSource(Pg_ConnectionId * connid);
extern void PgStopNotifyEventSource(Pg_ConnectionId * connid, bool allevents);
extern void PgNotifyTransferEvents(Pg_ConnectionId * connid);
extern void PgConnLossTransferEvents(Pg_ConnectionId * connid);
extern void PgNotifyInterpDelete(ClientData clientData, Tcl_Interp *interp);
/* GetFileProc is needed in Tcl 7.6 *only* ... it went away again in 8.0 */
#if TCL_MAJOR_VERSION == 7 && TCL_MINOR_VERSION >= 6
#define HAVE_TCL_GETFILEPROC 1
#else
#define HAVE_TCL_GETFILEPROC 0
#endif
#if HAVE_TCL_GETFILEPROC
extern Tcl_File PgGetFileProc(ClientData cData, int direction);
#endif
extern Tcl_ChannelType Pg_ConnType;

View File

@ -1,201 +0,0 @@
# Microsoft Developer Studio Generated NMAKE File, Based on libpgtcl_REL7_1_STABLE.dsp
!IF "$(CFG)" == ""
CFG=libpgtcl - Win32 Release
!MESSAGE No configuration specified. Defaulting to libpgtcl - Win32 Release.
!ENDIF
!IF "$(CFG)" != "libpgtcl - Win32 Release" && "$(CFG)" != "libpgtcl - Win32 Debug"
!MESSAGE Invalid configuration "$(CFG)" specified.
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "libpgtcl.mak" CFG="libpgtcl - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "libpgtcl - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "libpgtcl - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
!ERROR An invalid configuration is specified.
!ENDIF
!IF "$(OS)" == "Windows_NT"
NULL=
!ELSE
NULL=nul
!ENDIF
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
TCLBASE=\usr\local\tcltk833
PGINCLUDE=/I ..\..\include /I ..\libpq /I $(TCLBASE)\include
!IF "$(CFG)" == "libpgtcl - Win32 Release"
OUTDIR=.\Release
INTDIR=.\Release
# Begin Custom Macros
OutDir=.\Release
# End Custom Macros
ALL : "$(OUTDIR)\libpgtcl.dll" "$(OUTDIR)\libpgtcl.bsc"
CLEAN :
-@erase "$(INTDIR)\pgtcl.obj"
-@erase "$(INTDIR)\pgtcl.sbr"
-@erase "$(INTDIR)\pgtclCmds.obj"
-@erase "$(INTDIR)\pgtclCmds.sbr"
-@erase "$(INTDIR)\pgtclId.obj"
-@erase "$(INTDIR)\pgtclId.sbr"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(OUTDIR)\libpgtcl.dll"
-@erase "$(OUTDIR)\libpgtcl.exp"
-@erase "$(OUTDIR)\libpgtcl.lib"
-@erase "$(OUTDIR)\libpgtcl.bsc"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP_PROJ=/nologo /MT /W3 /GX /O2 $(PGINCLUDE) /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\libpgtcl.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\libpgtcl.bsc"
BSC32_SBRS= \
"$(INTDIR)\pgtcl.sbr" \
"$(INTDIR)\pgtclCmds.sbr" \
"$(INTDIR)\pgtclId.sbr"
"$(OUTDIR)\libpgtcl.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
$(BSC32) @<<
$(BSC32_FLAGS) $(BSC32_SBRS)
<<
LINK32=link.exe
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib tcl83.lib libpq.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\libpgtcl.pdb" /machine:I386 /def:".\libpgtcl.def" /out:"$(OUTDIR)\libpgtcl.dll" /implib:"$(OUTDIR)\libpgtcl.lib" /libpath:"$(TCLBASE)\lib" /libpath:"..\libpq\Release"
DEF_FILE= \
".\libpgtcl.def"
LINK32_OBJS= \
"$(INTDIR)\pgtcl.obj" \
"$(INTDIR)\pgtclCmds.obj" \
"$(INTDIR)\pgtclId.obj"
"$(OUTDIR)\libpgtcl.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ELSEIF "$(CFG)" == "libpgtcl - Win32 Debug"
OUTDIR=.\Debug
INTDIR=.\Debug
# Begin Custom Macros
OutDir=.\Debug
# End Custom Macros
ALL : "$(OUTDIR)\libpgtcl.dll" "$(OUTDIR)\libpgtcl.bsc"
CLEAN :
-@erase "$(INTDIR)\pgtcl.obj"
-@erase "$(INTDIR)\pgtcl.sbr"
-@erase "$(INTDIR)\pgtclCmds.obj"
-@erase "$(INTDIR)\pgtclCmds.sbr"
-@erase "$(INTDIR)\pgtclId.obj"
-@erase "$(INTDIR)\pgtclId.sbr"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(INTDIR)\vc60.pdb"
-@erase "$(OUTDIR)\libpgtcl.dll"
-@erase "$(OUTDIR)\libpgtcl.exp"
-@erase "$(OUTDIR)\libpgtcl.ilk"
-@erase "$(OUTDIR)\libpgtcl.lib"
-@erase "$(OUTDIR)\libpgtcl.pdb"
-@erase "$(OUTDIR)\libpgtcl.bsc"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od $(PGINCLUDE) /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\libpgtcl.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\libpgtcl.bsc"
BSC32_SBRS= \
"$(INTDIR)\pgtcl.sbr" \
"$(INTDIR)\pgtclCmds.sbr" \
"$(INTDIR)\pgtclId.sbr"
"$(OUTDIR)\libpgtcl.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
$(BSC32) @<<
$(BSC32_FLAGS) $(BSC32_SBRS)
<<
LINK32=link.exe
LINK32_FLAGS=tcl83.lib libpq.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\libpgtcl.pdb" /debug /machine:I386 /def:".\libpgtcl.def" /out:"$(OUTDIR)\libpgtcl.dll" /implib:"$(OUTDIR)\libpgtcl.lib" /pdbtype:sept /libpath:"$(TCLBASE)\lib" /libpath:"..\libpq\Debug"
DEF_FILE= \
".\libpgtcl.def"
LINK32_OBJS= \
"$(INTDIR)\pgtcl.obj" \
"$(INTDIR)\pgtclCmds.obj" \
"$(INTDIR)\pgtclId.obj"
"$(OUTDIR)\libpgtcl.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ENDIF
.c{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.c{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
!IF "$(CFG)" == "libpgtcl - Win32 Release" || "$(CFG)" == "libpgtcl - Win32 Debug"
SOURCE=pgtcl.c
"$(INTDIR)\pgtcl.obj" "$(INTDIR)\pgtcl.sbr" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=pgtclCmds.c
"$(INTDIR)\pgtclCmds.obj" "$(INTDIR)\pgtclCmds.sbr" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=pgtclId.c
"$(INTDIR)\pgtclId.obj" "$(INTDIR)\pgtclId.sbr" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
!ENDIF