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
11 * Copyright (c) 1996 Sun Microsystems, Inc.
13 * See the file "license.terms" for information on usage and redistribution
14 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
20 * Here is another place that we are using the old routine names...
23 #include <CodeFragments.h>
25 #include <Resources.h>
27 #include "tclMacInt.h"
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.
36 OSErr TclMacInitializeFragment _ANSI_ARGS_((
37 struct CFragInitBlock* initBlkPtr));
38 void TclMacTerminateFragment _ANSI_ARGS_((void));
41 * Static functions in this file.
44 static OSErr OpenLibraryResource _ANSI_ARGS_((
45 struct CFragInitBlock* initBlkPtr));
46 static void CloseLibraryResource _ANSI_ARGS_((void));
49 * The refnum of the opened resource fork.
51 static short ourResFile = kResFileNotOpened;
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.
59 #ifdef TCL_REGISTER_LIBRARY
60 static Tcl_Obj *ourResToken;
64 *----------------------------------------------------------------------
66 * TclMacInitializeFragment --
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.
73 * MacOS error code if loading should be canceled.
76 * Opens the resource fork of the shared library file.
78 *----------------------------------------------------------------------
82 TclMacInitializeFragment(
83 struct CFragInitBlock* initBlkPtr) /* Pointer to our library. */
89 extern OSErr __initialize( CFragInitBlock* initBlkPtr);
90 err = __initialize((CFragInitBlock *) initBlkPtr);
94 err = OpenLibraryResource( initBlkPtr);
99 *----------------------------------------------------------------------
101 * TclMacTerminateFragment --
103 * Called by MacOS CFM when the shared library is unloaded.
109 * The resource fork of the code fragment is closed.
111 *----------------------------------------------------------------------
115 TclMacTerminateFragment()
117 CloseLibraryResource();
121 extern void __terminate(void);
128 *----------------------------------------------------------------------
130 * OpenLibraryResource --
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
139 * If you #define TCL_REGISTER_RESOURCE before compiling this resource,
140 * then your library will register its open resource fork with the
144 * It returns noErr on success and a MacOS error code on failure.
147 * The resource fork of the code fragment is opened read-only and
148 * is installed at the head of the resource chain.
150 *----------------------------------------------------------------------
155 struct CFragInitBlock* initBlkPtr)
158 * The 3.0 version of the Universal headers changed CFragInitBlock
159 * to an opaque pointer type. CFragSystem7InitBlock is now the
163 #if !defined(UNIVERSAL_INTERFACES_VERSION) || (UNIVERSAL_INTERFACES_VERSION < 0x0300)
164 struct CFragInitBlock *realInitBlkPtr = initBlkPtr;
166 CFragSystem7InitBlock *realInitBlkPtr = (CFragSystem7InitBlock *) initBlkPtr;
168 FSSpec* fileSpec = NULL;
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;
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.
186 if (fileSpec != NULL) {
187 ourResFile = FSpOpenResFile(fileSpec, fsRdPerm);
188 if (ourResFile == kResFileNotOpened) {
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);
200 SetResFileAttrs(ourResFile, mapReadOnly);
208 *----------------------------------------------------------------------
210 * CloseLibraryResource --
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.
220 * The resource fork of the code fragment is closed.
222 *----------------------------------------------------------------------
226 CloseLibraryResource()
228 if (ourResFile != kResFileNotOpened) {
229 #ifdef TCL_REGISTER_LIBRARY
231 TclMacUnRegisterResourceFork(
232 Tcl_GetStringFromObj(ourResToken, &length),
234 Tcl_DecrRefCount(ourResToken);
236 CloseResFile(ourResFile);
237 ourResFile = kResFileNotOpened;