summaryrefslogtreecommitdiffstats
path: root/mac/tclMacLoad.c
diff options
context:
space:
mode:
Diffstat (limited to 'mac/tclMacLoad.c')
-rw-r--r--mac/tclMacLoad.c186
1 files changed, 116 insertions, 70 deletions
diff --git a/mac/tclMacLoad.c b/mac/tclMacLoad.c
index e767651..a36e151 100644
--- a/mac/tclMacLoad.c
+++ b/mac/tclMacLoad.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclMacLoad.c,v 1.12 2002/01/27 11:09:58 das Exp $
+ * RCS: @(#) $Id: tclMacLoad.c,v 1.13 2002/07/17 20:00:46 vincentdarley Exp $
*/
#include <CodeFragments.h>
@@ -76,6 +76,16 @@ struct CfrgItem {
Str255 name; /* This is actually variable sized. */
};
typedef struct CfrgItem CfrgItem;
+
+typedef struct TclMacLoadInfo {
+ int loaded;
+ CFragConnectionID connID;
+ FSSpec fileSpec;
+} TclMacLoadInfo;
+
+static int TryToLoad(Tcl_Interp *interp, TclMacLoadInfo *loadInfo,
+ CONST char *sym /* native */)
+
/*
*----------------------------------------------------------------------
@@ -97,18 +107,11 @@ typedef struct CfrgItem CfrgItem;
*/
int
-TclpLoadFile(
- Tcl_Interp *interp, /* Used for error reporting. */
- Tcl_Obj *pathPtr, /* Name of the file containing the desired
- * code. */
- CONST char *sym1,
- CONST char *sym2, /* Names of two procedures to look up in
- * the file's symbol table. */
- Tcl_PackageInitProc **proc1Ptr,
- Tcl_PackageInitProc **proc2Ptr,
- /* Where to return the addresses corresponding
- * to sym1 and sym2. */
- ClientData *clientDataPtr, /* Filled with token for dynamically loaded
+TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
+ Tcl_Interp *interp; /* Used for error reporting. */
+ Tcl_Obj *pathPtr; /* Name of the file containing the desired
+ * code (UTF-8). */
+ TclLoadHandle *loadHandle; /* Filled with token for dynamically loaded
* file which will be passed back to
* (*unloadProcPtr)() to unload the file. */
Tcl_FSUnloadFileProc **unloadProcPtr)
@@ -116,19 +119,11 @@ TclpLoadFile(
* function which should be used for
* this file. */
{
- CFragConnectionID connID;
- Ptr dummy;
OSErr err;
- CFragSymbolClass symClass;
FSSpec fileSpec;
- short fragFileRef, saveFileRef;
- Handle fragResource;
- UInt32 offset = 0;
- UInt32 length = kCFragGoesToEOF;
- StringPtr fragName=NULL;
- Str255 errName, symbolName;
Tcl_DString ds;
CONST char *native;
+ TclMacLoadInfo *loadInfo;
native = Tcl_FSGetNativePath(pathPtr);
err = FSpLocationFromPath(strlen(native), native, &fileSpec);
@@ -138,15 +133,37 @@ TclpLoadFile(
return TCL_ERROR;
}
- /*
- * First thing we must do is infer the package name from the sym1
- * variable (by removing the "_Init" suffix). This is kind of dumb
- * since the caller actually knows this value, it just doesn't give
- * it to us.
- */
- native = Tcl_UtfToExternalDString(NULL, sym1, -1, &ds);
- Tcl_DStringSetLength(&ds, Tcl_DStringLength(&ds) - 5);
+ loadInfo = (TclMacLoadInfo *) ckalloc(sizeof(TclMacLoadInfo));
+ loadInfo->loaded = 0;
+ loadInfo->fileSpec = fileSpec;
+ loadInfo->connID = NULL;
+ if (TryToLoad(interp, loadInfo, NULL) != TCL_OK) {
+ ckfree(loadInfo);
+ return TCL_ERROR;
+ }
+
+ *loadHandle = (TclLoadHandle)loadInfo;
+ *unloadProcPtr = &TclpUnloadFile;
+ return TCL_OK;
+}
+static int
+TryToLoad(Tcl_Interp *interp, TclMacLoadInfo *loadInfo,
+ CONST char *sym /* native */)
+{
+ CFragConnectionID connID;
+ Ptr dummy;
+ short fragFileRef, saveFileRef;
+ Handle fragResource;
+ UInt32 offset = 0;
+ UInt32 length = kCFragGoesToEOF;
+ Str255 errName;
+ StringPtr fragName=NULL;
+
+ if (loadInfo->loaded == 1) {
+ return TCL_OK;
+ }
+
/*
* See if this fragment has a 'cfrg' resource. It will tell us where
* to look for the fragment in the file. If it doesn't exist we will
@@ -160,25 +177,27 @@ TclpLoadFile(
fragFileRef = FSpOpenResFile(&fileSpec, fsRdPerm);
SetResLoad(true);
if (fragFileRef != -1) {
- UseResFile(fragFileRef);
- fragResource = Get1Resource(kCFragResourceType, kCFragResourceID);
- HLock(fragResource);
- if (ResError() == noErr) {
- CfrgItem* srcItem;
- long itemCount, index;
- Ptr itemStart;
+ if (sym != NULL) {
+ UseResFile(fragFileRef);
+ fragResource = Get1Resource(kCFragResourceType, kCFragResourceID);
+ HLock(fragResource);
+ if (ResError() == noErr) {
+ CfrgItem* srcItem;
+ long itemCount, index;
+ Ptr itemStart;
- itemCount = (*(CfrgHeaderPtrHand)fragResource)->itemCount;
- itemStart = &(*(CfrgHeaderPtrHand)fragResource)->arrayStart;
- for (index = 0; index < itemCount;
- index++, itemStart += srcItem->itemSize) {
- srcItem = (CfrgItem*)itemStart;
- if (srcItem->archType != OUR_ARCH_TYPE) continue;
- if (!strncasecmp(native, (char *) srcItem->name + 1,
- strlen(native))) {
- offset = srcItem->codeOffset;
- length = srcItem->codeLength;
- fragName=srcItem->name;
+ itemCount = (*(CfrgHeaderPtrHand)fragResource)->itemCount;
+ itemStart = &(*(CfrgHeaderPtrHand)fragResource)->arrayStart;
+ for (index = 0; index < itemCount;
+ index++, itemStart += srcItem->itemSize) {
+ srcItem = (CfrgItem*)itemStart;
+ if (srcItem->archType != OUR_ARCH_TYPE) continue;
+ if (!strncasecmp(sym, (char *) srcItem->name + 1,
+ strlen(sym))) {
+ offset = srcItem->codeOffset;
+ length = srcItem->codeLength;
+ fragName=srcItem->name;
+ }
}
}
}
@@ -191,20 +210,21 @@ TclpLoadFile(
ReleaseResource(fragResource);
CloseResFile(fragFileRef);
UseResFile(saveFileRef);
+ if (sym == NULL) {
+ /* We just return */
+ return TCL_OK;
+ }
}
- Tcl_DStringFree(&ds);
/*
- * Now we can attempt to load the fragement using the offset & length
+ * Now we can attempt to load the fragment using the offset & length
* obtained from the resource. We don't worry about the main entry point
* as we are going to search for specific entry points passed to us.
*/
err = GetDiskFragment(&fileSpec, offset, length, fragName,
kLoadCFrag, &connID, &dummy, errName);
-
- *clientDataPtr = (ClientData) connID;
-
+
if (err != fragNoErr) {
p2cstr(errName);
Tcl_AppendResult(interp, "couldn't load file \"",
@@ -212,31 +232,53 @@ TclpLoadFile(
"\": ", errName, (char *) NULL);
return TCL_ERROR;
}
-
- *unloadProcPtr = &TclpUnloadFile;
+
+ loadInfo->connID = connID;
+ loadInfo->loaded = 1;
+
+ return TCL_OK;
+}
+
+Tcl_PackageInitProc*
+TclpFindSymbol(interp, loadHandle, symbol)
+ Tcl_Interp *interp;
+ TclLoadHandle loadHandle;
+ CONST char *symbol;
+{
+ Tcl_DString ds;
+ Tcl_PackageInitProc *proc=NULL;
+ TclMacLoadInfo *loadInfo = (TclMacLoadInfo *)loadHandle;
+ Str255 symbolName;
+ CFragSymbolClass symClass;
+ OSErr err;
- Tcl_UtfToExternalDString(NULL, sym1, -1, &ds);
+ if (loadInfo->loaded == 0) {
+ int res;
+ /*
+ * First thing we must do is infer the package name from the
+ * sym variable. We do this by removing the '_Init'.
+ */
+ Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
+ Tcl_DStringSetLength(&ds, Tcl_DStringLength(&ds) - 5);
+ res = TryToLoad(interp, loadInfo, Tcl_DStringValue(&ds));
+ Tcl_DStringFree(&ds);
+ if (res != TCL_OK) {
+ return NULL;
+ }
+ }
+
+ Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
strcpy((char *) symbolName + 1, Tcl_DStringValue(&ds));
symbolName[0] = (unsigned) Tcl_DStringLength(&ds);
- err = FindSymbol(connID, symbolName, (Ptr *) proc1Ptr, &symClass);
+ err = FindSymbol(loadInfo->connID, symbolName, (Ptr *) &proc, &symClass);
Tcl_DStringFree(&ds);
if (err != fragNoErr || symClass == kDataCFragSymbol) {
Tcl_SetResult(interp,
"could not find Initialization routine in library",
TCL_STATIC);
- return TCL_ERROR;
+ return NULL;
}
-
- Tcl_UtfToExternalDString(NULL, sym2, -1, &ds);
- strcpy((char *) symbolName + 1, Tcl_DStringValue(&ds));
- symbolName[0] = (unsigned) Tcl_DStringLength(&ds);
- err = FindSymbol(connID, symbolName, (Ptr *) proc2Ptr, &symClass);
- Tcl_DStringFree(&ds);
- if (err != fragNoErr || symClass == kDataCFragSymbol) {
- *proc2Ptr = NULL;
- }
-
- return TCL_OK;
+ return proc;
}
/*
@@ -264,7 +306,11 @@ TclpUnloadFile(clientData)
* a token that represents the loaded
* file. */
{
- CloseConnection((CFragConnectionID*) &clientData);
+ TclMacLoadInfo *loadInfo = (TclMacLoadInfo *)clientData;
+ if (loadInfo->loaded) {
+ CloseConnection((CFragConnectionID*) &(loadInfo->connID));
+ }
+ ckfree(loadInfo);
}
/*