From 37c0b648759bb24ebf17831abc35533f356be7c4 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Thu, 6 Sep 2001 02:54:56 +0000
Subject: [PATCH] Below is the patch against current cvs for libpgtcl and two
 additional files win32.mak and libpgtcl.def. This patch allows to compile
 libpgtcl.dll on Windows with tcl > 8.0. I've tested it on WinNT (VC6.0), SUSE
 Linux (7.0) and Solaris 2.6 with tcl 8.3.3.

Mikhail Terekhov
---
 src/interfaces/libpgtcl.def         |   8 ++
 src/interfaces/libpgtcl/pgtclCmds.c |  10 +-
 src/interfaces/libpgtcl/pgtclCmds.h |   6 +-
 src/interfaces/libpgtcl/pgtclId.c   |  23 ++--
 src/interfaces/libpq/fe-exec.c      |  16 ++-
 src/interfaces/libpq/libpq-fe.h     |   3 +-
 src/interfaces/libpq/libpqdll.def   |   2 +-
 src/interfaces/win32.mak            | 201 ++++++++++++++++++++++++++++
 8 files changed, 255 insertions(+), 14 deletions(-)
 create mode 100644 src/interfaces/libpgtcl.def
 create mode 100644 src/interfaces/win32.mak

diff --git a/src/interfaces/libpgtcl.def b/src/interfaces/libpgtcl.def
new file mode 100644
index 00000000000..0ecc5ea0319
--- /dev/null
+++ b/src/interfaces/libpgtcl.def
@@ -0,0 +1,8 @@
+;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
diff --git a/src/interfaces/libpgtcl/pgtclCmds.c b/src/interfaces/libpgtcl/pgtclCmds.c
index a87cb1842cb..8fef8732fd6 100644
--- a/src/interfaces/libpgtcl/pgtclCmds.c
+++ b/src/interfaces/libpgtcl/pgtclCmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.56 2001/08/10 22:50:10 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.57 2001/09/06 02:54:56 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -403,6 +403,8 @@ Pg_connect(ClientData cData, Tcl_Interp *interp, int argc, char *argv[])
 int
 Pg_disconnect(ClientData cData, Tcl_Interp *interp, int argc, char *argv[])
 {
+	Pg_ConnectionId *connid;
+	PGconn	   *conn;
 	Tcl_Channel conn_chan;
 
 	if (argc != 2)
@@ -419,6 +421,12 @@ Pg_disconnect(ClientData cData, Tcl_Interp *interp, int argc, char *argv[])
 		return TCL_ERROR;
 	}
 
+#if TCL_MAJOR_VERSION >= 8
+	conn = PgGetConnectionId(interp, argv[1], &connid);
+	if (connid->notifier_channel != NULL)
+		Tcl_UnregisterChannel(interp, connid->notifier_channel);
+#endif
+
 	return Tcl_UnregisterChannel(interp, conn_chan);
 }
 
diff --git a/src/interfaces/libpgtcl/pgtclCmds.h b/src/interfaces/libpgtcl/pgtclCmds.h
index 69ae93015e9..6b40ea63c67 100644
--- a/src/interfaces/libpgtcl/pgtclCmds.h
+++ b/src/interfaces/libpgtcl/pgtclCmds.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pgtclCmds.h,v 1.21 2001/03/22 04:01:24 momjian Exp $
+ * $Id: pgtclCmds.h,v 1.22 2001/09/06 02:54:56 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -64,7 +64,11 @@ typedef struct Pg_ConnectionId_s
 
 	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 */
diff --git a/src/interfaces/libpgtcl/pgtclId.c b/src/interfaces/libpgtcl/pgtclId.c
index f4acde2fc47..af58f66247b 100644
--- a/src/interfaces/libpgtcl/pgtclId.c
+++ b/src/interfaces/libpgtcl/pgtclId.c
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.25 2001/02/10 02:31:29 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.26 2001/09/06 02:54:56 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -174,10 +174,16 @@ PgSetConnectionId(Tcl_Interp *interp, PGconn *conn)
 		connid->results[i] = NULL;
 	connid->notify_list = NULL;
 	connid->notifier_running = 0;
-	connid->notifier_socket = -1;
 
 	sprintf(connid->id, "pgsql%d", PQsocket(conn));
 
+#if TCL_MAJOR_VERSION >= 8
+	connid->notifier_channel = Tcl_MakeTcpClientChannel((ClientData) PQsocket(conn));
+	Tcl_RegisterChannel(interp, 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);
@@ -581,7 +587,7 @@ PgNotifyTransferEvents(Pg_ConnectionId * connid)
 		event->info = *notify;
 		event->connid = connid;
 		Tcl_QueueEvent((Tcl_Event *) event, TCL_QUEUE_TAIL);
-		free(notify);
+		PQfreeNotify(notify);
 	}
 
 	/*
@@ -688,18 +694,17 @@ PgStartNotifyEventSource(Pg_ConnectionId * connid)
 		if (pqsock >= 0)
 		{
 #if TCL_MAJOR_VERSION >= 8
-			/* In Tcl 8, Tcl_CreateFileHandler takes a socket directly. */
-			Tcl_CreateFileHandler(pqsock, TCL_READABLE,
-							 Pg_Notify_FileHandler, (ClientData) connid);
+			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;
-			connid->notifier_socket = pqsock;
 		}
 	}
 }
@@ -711,8 +716,8 @@ PgStopNotifyEventSource(Pg_ConnectionId * connid)
 	if (connid->notifier_running)
 	{
 #if TCL_MAJOR_VERSION >= 8
-		/* In Tcl 8, Tcl_DeleteFileHandler takes a socket directly. */
-		Tcl_DeleteFileHandler(connid->notifier_socket);
+		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,
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index d02b74490e7..4b67bdcf52a 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.108 2001/08/21 20:39:53 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.109 2001/09/06 02:54:56 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1345,6 +1345,20 @@ PQnotifies(PGconn *conn)
 	return event;
 }
 
+/*
+ * PQfreeNotify - free's the memory associated with a PGnotify
+ *
+ * This function is needed on Windows when using libpq.dll and
+ * for example libpgtcl.dll: All memory allocated inside a dll
+ * should be freed in the context of the same dll.
+ *
+ */
+void
+PQfreeNotify(PGnotify *notify)
+{
+	free(notify);
+}
+
 /*
  * PQgetline - gets a newline-terminated string from the backend.
  *
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index 79166533e99..5faa576c087 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq-fe.h,v 1.72 2001/08/21 20:39:54 momjian Exp $
+ * $Id: libpq-fe.h,v 1.73 2001/09/06 02:54:56 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -254,6 +254,7 @@ extern		"C"
 	/* Simple synchronous query */
 	extern PGresult *PQexec(PGconn *conn, const char *query);
 	extern PGnotify *PQnotifies(PGconn *conn);
+	extern void      PQfreeNotify(PGnotify *notify);
 
 	/* Interface for multiple-result or asynchronous queries */
 	extern int	PQsendQuery(PGconn *conn, const char *query);
diff --git a/src/interfaces/libpq/libpqdll.def b/src/interfaces/libpq/libpqdll.def
index a8b24c96be8..059707f87ea 100644
--- a/src/interfaces/libpq/libpqdll.def
+++ b/src/interfaces/libpq/libpqdll.def
@@ -87,4 +87,4 @@ EXPORTS
 	PQresetStart		@ 84
 	PQsetClientEncoding	@ 85
 	PQsetnonblocking	@ 86
-
+	PQfreeNotify		@ 87
diff --git a/src/interfaces/win32.mak b/src/interfaces/win32.mak
new file mode 100644
index 00000000000..bbd11b2c33c
--- /dev/null
+++ b/src/interfaces/win32.mak
@@ -0,0 +1,201 @@
+# 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 
+
-- 
GitLab