archie/tcl7.6/generic/tclFHandle.c
2024-05-27 16:40:40 +02:00

260 lines
6.3 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* tclFHandle.c --
*
* This file contains functions for manipulating Tcl file handles.
*
* Copyright (c) 1995 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* SCCS: @(#) tclFHandle.c 1.9 96/07/01 15:41:26
*/
#include "tcl.h"
#include "tclInt.h"
#include "tclPort.h"
/*
* The FileHashKey structure is used to associate the OS file handle and type
* with the corresponding notifier data in a FileHandle.
*/
typedef struct FileHashKey {
int type; /* File handle type. */
ClientData osHandle; /* Platform specific OS file handle. */
} FileHashKey;
typedef struct FileHandle {
FileHashKey key; /* Hash key for a given file. */
ClientData data; /* Platform specific notifier data. */
Tcl_FileFreeProc *proc; /* Callback to invoke when file is freed. */
} FileHandle;
/*
* Static variables used in this file:
*/
static Tcl_HashTable fileTable; /* Hash table containing file handles. */
static int initialized = 0; /* 1 if this module has been initialized. */
/*
* Static procedures used in this file:
*/
static void FileExitProc _ANSI_ARGS_((ClientData clientData));
/*
*----------------------------------------------------------------------
*
* Tcl_GetFile --
*
* This function retrieves the file handle associated with a
* platform specific file handle of the given type. It creates
* a new file handle if needed.
*
* Results:
* Returns the file handle associated with the file descriptor.
*
* Side effects:
* Initializes the file handle table if necessary.
*
*----------------------------------------------------------------------
*/
Tcl_File
Tcl_GetFile(osHandle, type)
ClientData osHandle; /* Platform specific file handle. */
int type; /* Type of file handle. */
{
FileHashKey key;
Tcl_HashEntry *entryPtr;
int new;
if (!initialized) {
Tcl_InitHashTable(&fileTable, sizeof(FileHashKey)/sizeof(int));
Tcl_CreateExitHandler(FileExitProc, 0);
initialized = 1;
}
key.osHandle = osHandle;
key.type = type;
entryPtr = Tcl_CreateHashEntry(&fileTable, (char *) &key, &new);
if (new) {
FileHandle *newHandlePtr;
newHandlePtr = (FileHandle *) ckalloc(sizeof(FileHandle));
newHandlePtr->key = key;
newHandlePtr->data = NULL;
newHandlePtr->proc = NULL;
Tcl_SetHashValue(entryPtr, newHandlePtr);
}
return (Tcl_File) Tcl_GetHashValue(entryPtr);
}
/*
*----------------------------------------------------------------------
*
* Tcl_FreeFile --
*
* Deallocates an entry in the file handle table.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
Tcl_FreeFile(handle)
Tcl_File handle;
{
Tcl_HashEntry *entryPtr;
FileHandle *handlePtr = (FileHandle *) handle;
/*
* Invoke free procedure, then delete the handle.
*/
if (handlePtr->proc) {
(*handlePtr->proc)(handlePtr->data);
}
/*
* Tcl_File structures may be freed as a result of running the
* channel table exit handler. The file table is freed by the file
* table exit handler, which may run before the channel table exit
* handler. The file table exit handler sets the "initialized"
* variable back to zero, so that the Tcl_FreeFile (when invoked
* from the channel table exit handler) can notice that the file
* table has already been destroyed. Otherwise, accessing a
* deleted hash table would cause a panic.
*/
if (initialized) {
entryPtr = Tcl_FindHashEntry(&fileTable, (char *) &handlePtr->key);
if (entryPtr) {
Tcl_DeleteHashEntry(entryPtr);
}
}
ckfree((char *) handlePtr);
}
/*
*----------------------------------------------------------------------
*
* Tcl_GetFileInfo --
*
* This function retrieves the platform specific file data and
* type from the file handle.
*
* Results:
* If typePtr is not NULL, sets *typePtr to the type of the file.
* Returns the platform specific file data.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
ClientData
Tcl_GetFileInfo(handle, typePtr)
Tcl_File handle;
int *typePtr;
{
FileHandle *handlePtr = (FileHandle *) handle;
if (typePtr) {
*typePtr = handlePtr->key.type;
}
return handlePtr->key.osHandle;
}
/*
*----------------------------------------------------------------------
*
* Tcl_SetNotifierData --
*
* This function is used by the notifier to associate platform
* specific notifier information and a deletion procedure with
* a file handle.
*
* Results:
* None.
*
* Side effects:
* Updates the data and delProc slots in the file handle.
*
*----------------------------------------------------------------------
*/
void
Tcl_SetNotifierData(handle, proc, data)
Tcl_File handle;
Tcl_FileFreeProc *proc;
ClientData data;
{
FileHandle *handlePtr = (FileHandle *) handle;
handlePtr->proc = proc;
handlePtr->data = data;
}
/*
*----------------------------------------------------------------------
*
* Tcl_GetNotifierData --
*
* This function is used by the notifier to retrieve the platform
* specific notifier information associated with a file handle.
*
* Results:
* Returns the data stored in a file handle by a previous call to
* Tcl_SetNotifierData, and places a pointer to the free proc
* in the location referred to by procPtr.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
ClientData
Tcl_GetNotifierData(handle, procPtr)
Tcl_File handle;
Tcl_FileFreeProc **procPtr;
{
FileHandle *handlePtr = (FileHandle *) handle;
if (procPtr != NULL) {
*procPtr = handlePtr->proc;
}
return handlePtr->data;
}
/*
*----------------------------------------------------------------------
*
* FileExitProc --
*
* This function an exit handler that frees any memory allocated
* for the file handle table.
*
* Results:
* None.
*
* Side effects:
* Cleans up the file handle table.
*
*----------------------------------------------------------------------
*/
static void
FileExitProc(clientData)
ClientData clientData; /* Not used. */
{
Tcl_DeleteHashTable(&fileTable);
initialized = 0;
}