Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtdocbook / tcl / tclFHandle.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: tclFHandle.c /main/2 1996/08/08 14:43:54 cde-hp $ */
24 /* 
25  * tclFHandle.c --
26  *
27  *      This file contains functions for manipulating Tcl file handles.
28  *
29  * Copyright (c) 1995 Sun Microsystems, Inc.
30  *
31  * See the file "license.terms" for information on usage and redistribution
32  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
33  *
34  * SCCS: @(#) tclFHandle.c 1.6 96/02/13 16:29:55
35  */
36
37 #include "tcl.h"
38 #include "tclPort.h"
39
40 /*
41  * The FileHashKey structure is used to associate the OS file handle and type
42  * with the corresponding notifier data in a FileHandle.
43  */
44
45 typedef struct FileHashKey {
46     int type;                   /* File handle type. */
47     ClientData osHandle;        /* Platform specific OS file handle. */
48 } FileHashKey;
49
50 typedef struct FileHandle {
51     FileHashKey key;            /* Hash key for a given file. */
52     ClientData data;            /* Platform specific notifier data. */
53     Tcl_FileFreeProc *proc;     /* Callback to invoke when file is freed. */
54 } FileHandle;
55
56 /*
57  * Static variables used in this file:
58  */
59
60 static Tcl_HashTable fileTable; /* Hash table containing file handles. */
61 static int initialized = 0;     /* 1 if this module has been initialized. */
62
63 /*
64  * Static procedures used in this file:
65  */
66
67 static void             FileExitProc _ANSI_ARGS_((ClientData clientData));
68 \f
69 /*
70  *----------------------------------------------------------------------
71  *
72  * Tcl_GetFile --
73  *
74  *      This function retrieves the file handle associated with a
75  *      platform specific file handle of the given type.  It creates
76  *      a new file handle if needed.
77  *
78  * Results:
79  *      Returns the file handle associated with the file descriptor.
80  *
81  * Side effects:
82  *      Initializes the file handle table if necessary.
83  *
84  *----------------------------------------------------------------------
85  */
86
87 Tcl_File
88 Tcl_GetFile(osHandle, type)
89     ClientData osHandle;        /* Platform specific file handle. */
90     int type;                   /* Type of file handle. */
91 {
92     FileHashKey key;
93     Tcl_HashEntry *entryPtr;
94     int new;
95
96     if (!initialized) {
97         Tcl_InitHashTable(&fileTable, sizeof(FileHashKey)/sizeof(int));
98         Tcl_CreateExitHandler(FileExitProc, 0);
99         initialized = 1;
100     }
101     key.osHandle = osHandle;
102     key.type = type;
103     entryPtr = Tcl_CreateHashEntry(&fileTable, (char *) &key, &new);
104     if (new) {
105         FileHandle *newHandlePtr;
106         newHandlePtr = (FileHandle *) ckalloc(sizeof(FileHandle));
107         newHandlePtr->key = key;
108         newHandlePtr->data = NULL;
109         newHandlePtr->proc = NULL;
110         Tcl_SetHashValue(entryPtr, newHandlePtr);
111     }
112     
113     return (Tcl_File) Tcl_GetHashValue(entryPtr);
114 }
115 \f
116 /*
117  *----------------------------------------------------------------------
118  *
119  * Tcl_FreeFile --
120  *
121  *      Deallocates an entry in the file handle table.
122  *
123  * Results:
124  *      None.
125  *
126  * Side effects:
127  *      None.
128  *
129  *----------------------------------------------------------------------
130  */
131
132 void
133 Tcl_FreeFile(handle)
134     Tcl_File handle;
135 {
136     Tcl_HashEntry *entryPtr;
137     FileHandle *handlePtr = (FileHandle *) handle;
138
139     /*
140      * Invoke free procedure, then delete the handle.
141      */
142
143     if (handlePtr->proc) {
144         (*handlePtr->proc)(handlePtr->data);
145     }
146
147     entryPtr = Tcl_FindHashEntry(&fileTable, (char *) &handlePtr->key);
148     if (entryPtr) {
149         Tcl_DeleteHashEntry(entryPtr);
150         ckfree((char *) handlePtr);
151     }
152 }
153 \f
154 /*
155  *----------------------------------------------------------------------
156  *
157  * Tcl_GetFileInfo --
158  *
159  *      This function retrieves the platform specific file data and
160  *      type from the file handle.
161  *
162  * Results:
163  *      If typePtr is not NULL, sets *typePtr to the type of the file.
164  *      Returns the platform specific file data.
165  *
166  * Side effects:
167  *      None.
168  *
169  *----------------------------------------------------------------------
170  */
171
172 ClientData
173 Tcl_GetFileInfo(handle, typePtr)
174     Tcl_File handle;
175     int *typePtr;
176 {
177     FileHandle *handlePtr = (FileHandle *) handle;
178
179     if (typePtr) {
180         *typePtr = handlePtr->key.type;
181     }
182     return handlePtr->key.osHandle;
183 }
184 \f
185 /*
186  *----------------------------------------------------------------------
187  *
188  * Tcl_SetNotifierData --
189  *
190  *      This function is used by the notifier to associate platform
191  *      specific notifier information and a deletion procedure with
192  *      a file handle.
193  *
194  * Results:
195  *      None.
196  *
197  * Side effects:
198  *      Updates the data and delProc slots in the file handle.
199  *
200  *----------------------------------------------------------------------
201  */
202
203 void
204 Tcl_SetNotifierData(handle, proc, data)
205     Tcl_File handle;
206     Tcl_FileFreeProc *proc;
207     ClientData data;
208 {
209     FileHandle *handlePtr = (FileHandle *) handle;
210     handlePtr->proc = proc;
211     handlePtr->data = data;
212 }
213 \f
214 /*
215  *----------------------------------------------------------------------
216  *
217  * Tcl_GetNotifierData --
218  *
219  *      This function is used by the notifier to retrieve the platform
220  *      specific notifier information associated with a file handle.
221  *
222  * Results:
223  *      Returns the data stored in a file handle by a previous call to
224  *      Tcl_SetNotifierData, and places a pointer to the free proc
225  *      in the location referred to by procPtr.
226  *
227  * Side effects:
228  *      None.
229  *
230  *----------------------------------------------------------------------
231  */
232
233 ClientData
234 Tcl_GetNotifierData(handle, procPtr)
235     Tcl_File handle;
236     Tcl_FileFreeProc **procPtr;
237 {
238     FileHandle *handlePtr = (FileHandle *) handle;
239     if (procPtr != NULL) {
240         *procPtr = handlePtr->proc;
241     }
242     return handlePtr->data;
243 }
244 \f
245 /*
246  *----------------------------------------------------------------------
247  *
248  * FileExitProc --
249  *
250  *      This function an exit handler that frees any memory allocated
251  *      for the file handle table.
252  *
253  * Results:
254  *      None.
255  *
256  * Side effects:
257  *      Cleans up the file handle table.
258  *
259  *----------------------------------------------------------------------
260  */
261
262 static void
263 FileExitProc(clientData)
264     ClientData clientData;      /* Not used. */
265 {
266     Tcl_HashSearch search;
267     Tcl_HashEntry *entryPtr;
268
269     entryPtr = Tcl_FirstHashEntry(&fileTable, &search);
270
271     while (entryPtr) {
272         ckfree(Tcl_GetHashValue(entryPtr));
273         entryPtr = Tcl_NextHashEntry(&search);
274     }
275
276     Tcl_DeleteHashTable(&fileTable);
277 }