OSDN Git Service

2003-01-21 Anita Kulkarni <anitak@kpit.com>
[pf3gnuchains/sourceware.git] / tcl / generic / tclFHandle.c
1 /* 
2  * tclFHandle.c --
3  *
4  *      This file contains functions for manipulating Tcl file handles.
5  *
6  * Copyright (c) 1995 Sun Microsystems, Inc.
7  *
8  * See the file "license.terms" for information on usage and redistribution
9  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10  *
11  * SCCS: @(#) tclFHandle.c 1.9 96/07/01 15:41:26
12  */
13
14 #include "tcl.h"
15 #include "tclInt.h"
16 #include "tclPort.h"
17
18 /*
19  * The FileHashKey structure is used to associate the OS file handle and type
20  * with the corresponding notifier data in a FileHandle.
21  */
22
23 typedef struct FileHashKey {
24     int type;                   /* File handle type. */
25     ClientData osHandle;        /* Platform specific OS file handle. */
26 } FileHashKey;
27
28 typedef struct FileHandle {
29     FileHashKey key;            /* Hash key for a given file. */
30     ClientData data;            /* Platform specific notifier data. */
31     Tcl_FileFreeProc *proc;     /* Callback to invoke when file is freed. */
32 } FileHandle;
33
34 /*
35  * Static variables used in this file:
36  */
37
38 static Tcl_HashTable fileTable; /* Hash table containing file handles. */
39 static int initialized = 0;     /* 1 if this module has been initialized. */
40
41 /*
42  * Static procedures used in this file:
43  */
44
45 static void             FileExitProc _ANSI_ARGS_((ClientData clientData));
46 \f
47 /*
48  *----------------------------------------------------------------------
49  *
50  * Tcl_GetFile --
51  *
52  *      This function retrieves the file handle associated with a
53  *      platform specific file handle of the given type.  It creates
54  *      a new file handle if needed.
55  *
56  * Results:
57  *      Returns the file handle associated with the file descriptor.
58  *
59  * Side effects:
60  *      Initializes the file handle table if necessary.
61  *
62  *----------------------------------------------------------------------
63  */
64
65 Tcl_File
66 Tcl_GetFile(osHandle, type)
67     ClientData osHandle;        /* Platform specific file handle. */
68     int type;                   /* Type of file handle. */
69 {
70     FileHashKey key;
71     Tcl_HashEntry *entryPtr;
72     int new;
73
74     if (!initialized) {
75         Tcl_InitHashTable(&fileTable, sizeof(FileHashKey)/sizeof(int));
76         Tcl_CreateExitHandler(FileExitProc, 0);
77         initialized = 1;
78     }
79     key.osHandle = osHandle;
80     key.type = type;
81     entryPtr = Tcl_CreateHashEntry(&fileTable, (char *) &key, &new);
82     if (new) {
83         FileHandle *newHandlePtr;
84         newHandlePtr = (FileHandle *) ckalloc(sizeof(FileHandle));
85         newHandlePtr->key = key;
86         newHandlePtr->data = NULL;
87         newHandlePtr->proc = NULL;
88         Tcl_SetHashValue(entryPtr, newHandlePtr);
89     }
90     
91     return (Tcl_File) Tcl_GetHashValue(entryPtr);
92 }
93 \f
94 /*
95  *----------------------------------------------------------------------
96  *
97  * Tcl_FreeFile --
98  *
99  *      Deallocates an entry in the file handle table.
100  *
101  * Results:
102  *      None.
103  *
104  * Side effects:
105  *      None.
106  *
107  *----------------------------------------------------------------------
108  */
109
110 void
111 Tcl_FreeFile(handle)
112     Tcl_File handle;
113 {
114     Tcl_HashEntry *entryPtr;
115     FileHandle *handlePtr = (FileHandle *) handle;
116     
117     /*
118      * Invoke free procedure, then delete the handle.
119      */
120
121     if (handlePtr->proc) {
122         (*handlePtr->proc)(handlePtr->data);
123     }
124
125     /*
126      * Tcl_File structures may be freed as a result of running the
127      * channel table exit handler. The file table is freed by the file
128      * table exit handler, which may run before the channel table exit
129      * handler. The file table exit handler sets the "initialized"
130      * variable back to zero, so that the Tcl_FreeFile (when invoked
131      * from the channel table exit handler) can notice that the file
132      * table has already been destroyed. Otherwise, accessing a
133      * deleted hash table would cause a panic.
134      */
135      
136     if (initialized) {
137         entryPtr = Tcl_FindHashEntry(&fileTable, (char *) &handlePtr->key);
138         if (entryPtr) {
139             Tcl_DeleteHashEntry(entryPtr);
140         }
141     }
142     ckfree((char *) handlePtr);
143 }
144 \f
145 /*
146  *----------------------------------------------------------------------
147  *
148  * Tcl_GetFileInfo --
149  *
150  *      This function retrieves the platform specific file data and
151  *      type from the file handle.
152  *
153  * Results:
154  *      If typePtr is not NULL, sets *typePtr to the type of the file.
155  *      Returns the platform specific file data.
156  *
157  * Side effects:
158  *      None.
159  *
160  *----------------------------------------------------------------------
161  */
162
163 ClientData
164 Tcl_GetFileInfo(handle, typePtr)
165     Tcl_File handle;
166     int *typePtr;
167 {
168     FileHandle *handlePtr = (FileHandle *) handle;
169
170     if (typePtr) {
171         *typePtr = handlePtr->key.type;
172     }
173     return handlePtr->key.osHandle;
174 }
175 \f
176 /*
177  *----------------------------------------------------------------------
178  *
179  * Tcl_SetNotifierData --
180  *
181  *      This function is used by the notifier to associate platform
182  *      specific notifier information and a deletion procedure with
183  *      a file handle.
184  *
185  * Results:
186  *      None.
187  *
188  * Side effects:
189  *      Updates the data and delProc slots in the file handle.
190  *
191  *----------------------------------------------------------------------
192  */
193
194 void
195 Tcl_SetNotifierData(handle, proc, data)
196     Tcl_File handle;
197     Tcl_FileFreeProc *proc;
198     ClientData data;
199 {
200     FileHandle *handlePtr = (FileHandle *) handle;
201     handlePtr->proc = proc;
202     handlePtr->data = data;
203 }
204 \f
205 /*
206  *----------------------------------------------------------------------
207  *
208  * Tcl_GetNotifierData --
209  *
210  *      This function is used by the notifier to retrieve the platform
211  *      specific notifier information associated with a file handle.
212  *
213  * Results:
214  *      Returns the data stored in a file handle by a previous call to
215  *      Tcl_SetNotifierData, and places a pointer to the free proc
216  *      in the location referred to by procPtr.
217  *
218  * Side effects:
219  *      None.
220  *
221  *----------------------------------------------------------------------
222  */
223
224 ClientData
225 Tcl_GetNotifierData(handle, procPtr)
226     Tcl_File handle;
227     Tcl_FileFreeProc **procPtr;
228 {
229     FileHandle *handlePtr = (FileHandle *) handle;
230     if (procPtr != NULL) {
231         *procPtr = handlePtr->proc;
232     }
233     return handlePtr->data;
234 }
235 \f
236 /*
237  *----------------------------------------------------------------------
238  *
239  * FileExitProc --
240  *
241  *      This function an exit handler that frees any memory allocated
242  *      for the file handle table.
243  *
244  * Results:
245  *      None.
246  *
247  * Side effects:
248  *      Cleans up the file handle table.
249  *
250  *----------------------------------------------------------------------
251  */
252
253 static void
254 FileExitProc(clientData)
255     ClientData clientData;      /* Not used. */
256 {
257     Tcl_DeleteHashTable(&fileTable);
258     initialized = 0;
259 }