OSDN Git Service

a36f3733c1d2b45fadd31e0c820998aae181ed58
[pf3gnuchains/sourceware.git] / tcl / mac / tclMacLibrary.c
1 /*
2  * tclMacLibrary.c --
3  *
4  *      This file should be included in Tcl extensions that want to 
5  *      automatically open their resource forks when the code is linked. 
6  *      These routines should not be exported but should be compiled 
7  *      locally by each fragment.  Many thanks to Jay Lieske
8  *      <lieske@princeton.edu> who provide an initial version of this
9  *      file.
10  *
11  * Copyright (c) 1996 Sun Microsystems, Inc.
12  *
13  * See the file "license.terms" for information on usage and redistribution
14  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15  *
16  * RCS: @(#) $Id$
17  */
18
19 /*
20  * Here is another place that we are using the old routine names...
21  */
22
23 #include <CodeFragments.h>
24 #include <Errors.h>
25 #include <Resources.h>
26 #include <Strings.h>
27 #include "tclMacInt.h"
28
29 /*
30  * These function are not currently defined in any header file.  The
31  * only place they should be used is in the Initialization and
32  * Termination entry points for a code fragment.  The prototypes
33  * are included here to avoid compile errors.
34  */
35
36 OSErr TclMacInitializeFragment _ANSI_ARGS_((
37                         struct CFragInitBlock* initBlkPtr));
38 void TclMacTerminateFragment _ANSI_ARGS_((void));
39
40 /*
41  * Static functions in this file.
42  */
43
44 static OSErr OpenLibraryResource _ANSI_ARGS_((
45                         struct CFragInitBlock* initBlkPtr));
46 static void CloseLibraryResource _ANSI_ARGS_((void));
47
48 /* 
49  * The refnum of the opened resource fork.
50  */
51 static short ourResFile = kResFileNotOpened;
52
53 /*
54  * This is the resource token for the our resource file.
55  * It stores the name we registered with the resource facility.
56  * We only need to use this if we are actually registering ourselves.
57  */
58   
59 #ifdef TCL_REGISTER_LIBRARY
60 static Tcl_Obj *ourResToken;
61 #endif
62 \f
63 /*
64  *----------------------------------------------------------------------
65  *
66  * TclMacInitializeFragment --
67  *
68  *      Called by MacOS CFM when the shared library is loaded. All this
69  *      function really does is give Tcl a chance to open and register
70  *      the resource fork of the library. 
71  *
72  * Results:
73  *      MacOS error code if loading should be canceled.
74  *
75  * Side effects:
76  *      Opens the resource fork of the shared library file.
77  *
78  *----------------------------------------------------------------------
79  */
80
81 OSErr
82 TclMacInitializeFragment(
83     struct CFragInitBlock* initBlkPtr)          /* Pointer to our library. */
84 {
85     OSErr err = noErr;
86
87 #ifdef __MWERKS__
88     {
89         extern OSErr __initialize( CFragInitBlock* initBlkPtr);
90         err = __initialize((CFragInitBlock *) initBlkPtr);
91     }
92 #endif
93     if (err == noErr)
94         err = OpenLibraryResource( initBlkPtr);
95     return err;
96 }
97 \f
98 /*
99  *----------------------------------------------------------------------
100  *
101  * TclMacTerminateFragment --
102  *
103  *      Called by MacOS CFM when the shared library is unloaded.
104  *
105  * Results:
106  *      None.
107  *
108  * Side effects:
109  *      The resource fork of the code fragment is closed.
110  *
111  *----------------------------------------------------------------------
112  */
113
114 void 
115 TclMacTerminateFragment()
116 {
117     CloseLibraryResource();
118
119 #ifdef __MWERKS__
120     {
121         extern void __terminate(void);
122         __terminate();
123     }
124 #endif
125 }
126 \f
127 /*
128  *----------------------------------------------------------------------
129  *
130  * OpenLibraryResource --
131  *
132  *      This routine can be called by a MacOS fragment's initialiation 
133  *      function to open the resource fork of the file.  
134  *      Call it with the same data passed to the initialization function. 
135  *      If the fragment loading should fail if the resource fork can't 
136  *      be opened, then the initialization function can pass on this 
137  *      return value.
138  *
139  *      If you #define TCL_REGISTER_RESOURCE before compiling this resource, 
140  *      then your library will register its open resource fork with the
141  *      resource command.
142  *
143  * Results:
144  *      It returns noErr on success and a MacOS error code on failure.
145  *
146  * Side effects:
147  *      The resource fork of the code fragment is opened read-only and 
148  *      is installed at the head of the resource chain.
149  *
150  *----------------------------------------------------------------------
151  */
152
153 static OSErr 
154 OpenLibraryResource(
155     struct CFragInitBlock* initBlkPtr)
156 {
157     /*
158      * The 3.0 version of the Universal headers changed CFragInitBlock
159      * to an opaque pointer type.  CFragSystem7InitBlock is now the
160      * real pointer.
161      */
162      
163 #if !defined(UNIVERSAL_INTERFACES_VERSION) || (UNIVERSAL_INTERFACES_VERSION < 0x0300)
164     struct CFragInitBlock *realInitBlkPtr = initBlkPtr;
165 #else 
166     CFragSystem7InitBlock *realInitBlkPtr = (CFragSystem7InitBlock *) initBlkPtr;
167 #endif
168     FSSpec* fileSpec = NULL;
169     OSErr err = noErr;
170     
171
172     if (realInitBlkPtr->fragLocator.where == kDataForkCFragLocator) {
173         fileSpec = realInitBlkPtr->fragLocator.u.onDisk.fileSpec;
174     } else if (realInitBlkPtr->fragLocator.where == kResourceCFragLocator) {
175         fileSpec = realInitBlkPtr->fragLocator.u.inSegs.fileSpec;
176     } else {
177         err = resFNotFound;
178     }
179
180     /*
181      * Open the resource fork for this library in read-only mode.  
182      * This will make it the current res file, ahead of the 
183      * application's own resources.
184      */
185     
186     if (fileSpec != NULL) {
187         ourResFile = FSpOpenResFile(fileSpec, fsRdPerm);
188         if (ourResFile == kResFileNotOpened) {
189             err = ResError();
190         } else {
191 #ifdef TCL_REGISTER_LIBRARY
192             ourResToken = Tcl_NewObj();
193             Tcl_IncrRefCount(ourResToken);
194             p2cstr(realInitBlkPtr->libName);
195             Tcl_SetStringObj(ourResToken, (char *) realInitBlkPtr->libName, -1);
196             c2pstr((char *) realInitBlkPtr->libName);
197             TclMacRegisterResourceFork(ourResFile, ourResToken,
198                     TCL_RESOURCE_DONT_CLOSE);
199 #endif
200             SetResFileAttrs(ourResFile, mapReadOnly);
201         }
202     }
203     
204     return err;
205 }
206 \f
207 /*
208  *----------------------------------------------------------------------
209  *
210  * CloseLibraryResource --
211  *
212  *      This routine should be called by a MacOS fragment's termination 
213  *      function to close the resource fork of the file 
214  *      that was opened with OpenLibraryResource.  
215  *
216  * Results:
217  *      None.
218  *
219  * Side effects:
220  *      The resource fork of the code fragment is closed.
221  *
222  *----------------------------------------------------------------------
223  */
224
225 static void
226 CloseLibraryResource()
227 {
228     if (ourResFile != kResFileNotOpened) {
229 #ifdef TCL_REGISTER_LIBRARY
230         int length;
231         TclMacUnRegisterResourceFork(
232                 Tcl_GetStringFromObj(ourResToken, &length),
233                 NULL);
234         Tcl_DecrRefCount(ourResToken);
235 #endif
236         CloseResFile(ourResFile);
237         ourResFile = kResFileNotOpened;
238     }
239 }