~hilaire-fernandes/drgeo/trunk

« back to all changes in this revision

Viewing changes to VMs/iPad/source/iOS/vm/OSX/sqMacUnixExternalPrims.m

  • Committer: Hilaire Fernandes
  • Date: 2012-01-27 21:15:40 UTC
  • Revision ID: hilaire.fernandes@gmail.com-20120127211540-912spf97bhpx6mve
Initial additions

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
//  Created by John M McIntosh on 09-11-27.
 
3
//  This file orginally comes from the sqUnixExternalPrims.c written by Ian Piumarta
 
4
//  With additional work for the 3.x and 4.x series of macintosh carbon vms
 
5
//  To preserve the behavior, bugs, etc I decided to copy the code versus a new re-write
 
6
 
 
7
/* sqUnixExternalPrims.c -- Unix named primitives and loadable modules
 
8
 * 
 
9
 *   Copyright (C) 1996-2009 by Ian Piumarta
 
10
 *   All rights reserved.
 
11
 *   
 
12
 *   This file is part of Unix Squeak.
 
13
 * 
 
14
 *   Permission is hereby granted, free of charge, to any person obtaining a copy
 
15
 *   of this software and associated documentation files (the "Software"), to deal
 
16
 *   in the Software without restriction, including without limitation the rights
 
17
 *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
18
 *   copies of the Software, and to permit persons to whom the Software is
 
19
 *   furnished to do so, subject to the following conditions:
 
20
 * 
 
21
 *   The above copyright notice and this permission notice shall be included in
 
22
 *   all copies or substantial portions of the Software.
 
23
 * 
 
24
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
25
 *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
26
 *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
27
 *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
28
 *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
29
 *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 
30
 *   SOFTWARE.
 
31
 */
 
32
 
 
33
 /* Author: Ian.Piumarta@INRIA.Fr
 
34
 *
 
35
 * Last edited: 2005-04-06 06:09:36 by piumarta on pauillac.hpl.hp.com
 
36
        
 
37
 * Altered by John M McIntosh johnmci@smalltalkconsulting.com Feb 24th, 2006 for os-x carbon support
 
38
 3.8.11b2 load from resource location first, avoid plugins external directory because of intel migration effort issues.
 
39
 3.8.17b1 April 25, 2007, JMM rework for 10.2.8 backwards support using Ian's dl* logic. 
 
40
 5.0.0b6  Nov 27, 2009, JMM rework for the 32/64bit 5.0 VM
 
41
  
 
42
 */
 
43
#import "sqSqueakOSXInfoPlistInterface.h"
 
44
#import "SqueakOSXAppDelegate.h"
 
45
#import "sq.h"
 
46
 
 
47
extern SqueakOSXAppDelegate *gDelegateApp;
 
48
 
 
49
# define dprintf(ARGS) if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakDebug) fprintf ARGS
 
50
 
 
51
#if defined(HAVE_LIBDL) /* non-starter without this! */
 
52
 
 
53
#include <dlfcn.h> 
 
54
#include <sys/param.h>
 
55
#include <sys/stat.h>
 
56
 
 
57
/* get a value for RTLD_NOW, with increasing levels of desperation... */
 
58
 
 
59
#if !defined(RTLD_NOW)
 
60
# if defined(DL_NOW)
 
61
#   define RTLD_NOW DL_NOW
 
62
# elif defined(RTLD_LAZY)
 
63
#   define RTLD_NOW RTLD_LAZY
 
64
# elif defined(DL_LAZY)
 
65
#   define RTLD_NOW DL_LAZY
 
66
# else
 
67
#   warning: defining RTLD_NOW as 1
 
68
#   define RTLD_NOW 1
 
69
# endif
 
70
#endif
 
71
 
 
72
#if !defined(RTLD_GLOBAL)
 
73
# define RTLD_GLOBAL 0
 
74
#endif
 
75
 
 
76
#endif
 
77
 
 
78
 
 
79
/*** local functions ***/
 
80
void *ioLoadModuleRaw(char *pluginName);
 
81
 
 
82
/*  Attempt to load the shared library named by the concatenation of prefix,
 
83
 *  moduleName and suffix.  Answer the new module entry, or 0 if the shared
 
84
 *  library could not be loaded.
 
85
 */
 
86
static void *tryLoadingInternals(NSString *libNameString) {     
 
87
        struct stat buf;
 
88
        int         err;
 
89
        void        *handle = NULL;
 
90
        const char* libName = [libNameString fileSystemRepresentation];
 
91
        
 
92
        if ((!(err= stat(libName, &buf))) && S_ISDIR(buf.st_mode)) {
 
93
                dprintf((stderr, "ignoring directory: %s\n", libName));
 
94
        } else {
 
95
            dprintf((stderr, "tryLoading %s\n", libName));
 
96
                handle= dlopen(libName, RTLD_NOW | RTLD_GLOBAL);
 
97
            if (handle == NULL) {
 
98
                        const char* why = dlerror();
 
99
                        if ((!err) && (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakDebug))
 
100
                                fprintf(stderr, "ioLoadModule(%s):\n  %s\n", libName, why);
 
101
                } else {
 
102
                    return handle;
 
103
                }
 
104
        }
 
105
        return NULL;
 
106
}
 
107
 
 
108
static void *tryLoading(NSString *dirNameString, char *moduleName)
 
109
{
 
110
        void        *handle= NULL;
 
111
        NSString    *libName;
 
112
        
 
113
        libName = [dirNameString stringByAppendingPathComponent: [NSString stringWithUTF8String: moduleName]];
 
114
        libName = [libName stringByAppendingPathExtension: @"bundle/Contents/MacOS/"];
 
115
        libName = [libName stringByAppendingPathComponent: [NSString stringWithUTF8String: moduleName]];
 
116
        handle = tryLoadingInternals(libName);
 
117
        if (handle) 
 
118
                return handle;
 
119
        
 
120
        libName = [dirNameString stringByAppendingPathComponent: [NSString stringWithUTF8String: moduleName]];
 
121
        handle = tryLoadingInternals(libName);
 
122
        if (handle) 
 
123
                return handle;
 
124
        
 
125
        if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakPluginsBuiltInOrLocalOnly)
 
126
                return NULL;
 
127
        
 
128
        static char *prefixes[]= { "", "lib", 0 };
 
129
        static char *suffixes[]= { "", "so", "dylib",0 };
 
130
        char         **prefix= NULL, **suffix= NULL;
 
131
 
 
132
        for (prefix= prefixes;  *prefix;  ++prefix)
 
133
                for (suffix= suffixes;  *suffix;  ++suffix)             {
 
134
                        libName = [dirNameString stringByAppendingPathComponent: [NSString stringWithUTF8String: *prefix]];
 
135
                        libName = [libName stringByAppendingString: [NSString stringWithUTF8String: moduleName]];
 
136
                        libName = [libName stringByAppendingPathExtension: [NSString stringWithUTF8String: *suffix]];
 
137
 
 
138
                        handle = tryLoadingInternals(libName);
 
139
                        if (handle) 
 
140
                                return handle;
 
141
                }
 
142
        return NULL;
 
143
}
 
144
 
 
145
 
 
146
/*  Find and load the named module.  Answer 0 if not found (do NOT fail
 
147
 *  the primitive!).
 
148
 */
 
149
void *ioLoadModule(char *pluginName) {
 
150
        NSAutoreleasePool * pool = [NSAutoreleasePool new];
 
151
        void* result = ioLoadModuleRaw(pluginName);
 
152
        [pool drain];
 
153
        return result;
 
154
}
 
155
        
 
156
void *ioLoadModuleRaw(char *pluginName)
 
157
{
 
158
        void *handle= null;
 
159
 
 
160
        if ((pluginName == null) || (pluginName[0] == 0x00)) {
 
161
                handle = dlopen(0, RTLD_NOW | RTLD_GLOBAL);
 
162
                if (handle == null) {
 
163
                        char * why = dlerror();
 
164
                        dprintf((stderr, "ioLoadModule(<intrinsic>): %s\n", why));
 
165
                } else {
 
166
                        dprintf((stderr, "loaded: <intrinsic>\n"));
 
167
                        return handle;
 
168
                }
 
169
    }
 
170
        
 
171
        /* first, look in the "<Squeak VM directory>Plugins" directory for the library */
 
172
        NSString *pluginDirPath = [[gDelegateApp.squeakApplication.vmPathStringURL path] stringByAppendingPathComponent: @"Plugins/"];
 
173
        NSString *vmDirPath = [[NSBundle mainBundle] resourcePath];
 
174
 
 
175
        if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakPluginsBuiltInOrLocalOnly) {
 
176
          if ( (handle= tryLoading( vmDirPath, pluginName)) || (handle= tryLoading( pluginDirPath,      pluginName)))
 
177
                        return handle;
 
178
    } else {
 
179
                  if ((   handle= tryLoading( pluginDirPath,    pluginName))
 
180
                          || (handle= tryLoading( @"./",                        pluginName))
 
181
                          || (handle= tryLoading( vmDirPath,            pluginName))
 
182
                          || (handle= tryLoading( @"",                          pluginName))
 
183
                          )
 
184
                        return handle;
 
185
        }
 
186
 
 
187
        // the following is needed so that, for example, the FFI can pick up
 
188
        // things like <cdecl: 'xyz' module: 'CoreServices'>
 
189
        {
 
190
                static char *frameworks[]=
 
191
                {
 
192
                        "",
 
193
                        "/CoreServices.framework/Frameworks",
 
194
                        "/ApplicationServices.framework/Frameworks",
 
195
                        "/Carbon.framework/Frameworks",
 
196
                        0
 
197
                };
 
198
                
 
199
                static NSString *systemFolder = NULL;
 
200
                char **framework= NULL;
 
201
                char workingData[PATH_MAX+1];
 
202
                size_t pluginNameLength;
 
203
                NSString *path,*path2;
 
204
                
 
205
                if (!systemFolder) {
 
206
                        struct FSRef frameworksFolderRef;
 
207
                        OSErr err = FSFindFolder(kSystemDomain, kFrameworksFolderType, false, &frameworksFolderRef);
 
208
#pragma unused(err)
 
209
                        NSURL *myURLRef = (NSURL *) CFURLCreateFromFSRef(kCFAllocatorDefault, &frameworksFolderRef);
 
210
                        systemFolder = [[myURLRef path] retain];
 
211
                        CFRelease(myURLRef);
 
212
                }
 
213
                
 
214
                pluginNameLength = strlen(pluginName);
 
215
                if (pluginNameLength > 10) {
 
216
                        strncpy(workingData,pluginName+pluginNameLength-10,10);
 
217
                        workingData[10] = 0x00;
 
218
                        if (strcmp(workingData,".framework") == 0) {
 
219
                                strncpy(workingData,pluginName,pluginNameLength-10);
 
220
                                workingData[pluginNameLength-10] = 0x00;
 
221
                                path = [vmDirPath stringByAppendingPathComponent: [NSString stringWithUTF8String: pluginName]];
 
222
                                if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakPluginsBuiltInOrLocalOnly) {
 
223
                                        path2 = [path stringByAppendingPathComponent: [NSString stringWithUTF8String: workingData]];
 
224
                                        if ((handle = tryLoadingInternals(path2)))
 
225
                                                return handle;
 
226
                                } else {
 
227
                                        if ((handle= tryLoading(path, workingData)))
 
228
                                                return handle;
 
229
                                }
 
230
                                path = [pluginDirPath stringByAppendingPathComponent: [NSString stringWithUTF8String: pluginName]];
 
231
 
 
232
                                if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakPluginsBuiltInOrLocalOnly) {
 
233
                                        path2 = [path stringByAppendingPathComponent: [NSString stringWithUTF8String: workingData]];
 
234
                                        if ((handle = tryLoadingInternals(path2)))
 
235
                                                return handle;
 
236
                                } else {
 
237
                                        if ((handle= tryLoading(path, workingData)))
 
238
                                                return handle;
 
239
                                }
 
240
 
 
241
                                path = [systemFolder stringByAppendingPathComponent: [NSString stringWithUTF8String: pluginName]];
 
242
                                if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakPluginsBuiltInOrLocalOnly) {
 
243
                                        path2 = [path stringByAppendingPathComponent: [NSString stringWithUTF8String: workingData]];
 
244
                                        if ((handle = tryLoadingInternals(path2)))
 
245
                                                return handle;
 
246
                                } else {
 
247
                                        if ((handle= tryLoading(path, workingData)))
 
248
                                                return handle;
 
249
                                }
 
250
                        }
 
251
                }
 
252
                
 
253
                if (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakPluginsBuiltInOrLocalOnly)
 
254
                        return NULL;
 
255
                
 
256
                for (framework= frameworks;  *framework;  ++framework) {
 
257
                        path = [[systemFolder stringByAppendingPathComponent: [NSString stringWithUTF8String: *framework]]
 
258
                                        stringByAppendingPathComponent: [NSString stringWithUTF8String: pluginName]];
 
259
                        if ((handle= tryLoading(path, pluginName)))
 
260
                                return handle;
 
261
                        
 
262
                        path = [systemFolder stringByAppendingPathComponent: [NSString stringWithUTF8String: *framework]];
 
263
                        path = [path stringByAppendingPathComponent: [NSString stringWithUTF8String: pluginName]];
 
264
                        path = [path stringByAppendingPathExtension: @"framework"];
 
265
                        
 
266
                        if ((handle= tryLoading(path, pluginName)))
 
267
                                return handle;
 
268
                }
 
269
        }
 
270
        
 
271
        return NULL;
 
272
}
 
273
 
 
274
 
 
275
/*  Find a function in a loaded module.  Answer 0 if not found (do NOT
 
276
 *  fail the primitive!).
 
277
 */
 
278
void *ioFindExternalFunctionIn(char *lookupName, void *moduleHandle)
 
279
{
 
280
  char buf[NAME_MAX+1];
 
281
 
 
282
  snprintf(buf, sizeof(buf), "%s", lookupName);
 
283
  void *fn = dlsym(moduleHandle, buf);
 
284
 
 
285
  dprintf((stderr, "ioFindExternalFunctionIn(%s, %ld)\n",lookupName, (long) moduleHandle));
 
286
 
 
287
  if ((fn == NULL) && (((sqSqueakOSXInfoPlistInterface*) gDelegateApp.squeakApplication.infoPlistInterfaceLogic).SqueakDebug)
 
288
      && strcmp(lookupName, "initialiseModule")
 
289
      && strcmp(lookupName, "shutdownModule")
 
290
      && strcmp(lookupName, "setInterpreter")
 
291
      && strcmp(lookupName, "getModuleName")) {
 
292
        char *why = dlerror();
 
293
    fprintf(stderr, "ioFindExternalFunctionIn(%s, %p):\n  %s\n",lookupName, moduleHandle, why);
 
294
        }
 
295
 
 
296
  return fn;
 
297
}
 
298
 
 
299
/*  Free the module with the associated handle.  Answer 0 on error (do
 
300
 *  NOT fail the primitive!).
 
301
*/
 
302
sqInt ioFreeModule(void *moduleHandle)
 
303
{
 
304
  int results = dlclose(moduleHandle);
 
305
        
 
306
  if (results) {
 
307
          char* why = dlerror();
 
308
      dprintf((stderr, "ioFreeModule(%ld): %s\n", (long) moduleHandle, why));
 
309
      return 0;
 
310
    }
 
311
  return 1;
 
312
}
 
 
b'\\ No newline at end of file'