1 /*
2  * Copyright (C) 2007 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #import <wtf/Assertions.h>
30 #import <dlfcn.h>
31 
32 #define SOFT_LINK_LIBRARY(lib) \
33     static void* lib##Library() \
34     { \
35         static void* dylib = dlopen("/usr/lib/" #lib ".dylib", RTLD_NOW); \
36         ASSERT(dylib); \
37         return dylib; \
38     }
39 
40 #define SOFT_LINK_FRAMEWORK(framework) \
41     static void* framework##Library() \
42     { \
43         static void* frameworkLibrary = dlopen("/System/Library/Frameworks/" #framework ".framework/" #framework, RTLD_NOW); \
44         ASSERT(frameworkLibrary); \
45         return frameworkLibrary; \
46     }
47 
48 #define SOFT_LINK_FRAMEWORK_IN_CORESERVICES_UMBRELLA(framework) \
49     static void* framework##Library() \
50     { \
51         static void* frameworkLibrary = dlopen("/System/Library/Frameworks/CoreServices.framework/Frameworks/" #framework ".framework/" #framework, RTLD_NOW); \
52         ASSERT(frameworkLibrary); \
53         return frameworkLibrary; \
54     }
55 
56 #define SOFT_LINK(framework, functionName, resultType, parameterDeclarations, parameterNames) \
57     static resultType init##functionName parameterDeclarations; \
58     static resultType (*softLink##functionName) parameterDeclarations = init##functionName; \
59     \
60     static resultType init##functionName parameterDeclarations \
61     { \
62         softLink##functionName = (resultType (*) parameterDeclarations) dlsym(framework##Library(), #functionName); \
63         ASSERT(softLink##functionName); \
64         return softLink##functionName parameterNames; \
65     }\
66     \
67     inline resultType functionName parameterDeclarations \
68     {\
69         return softLink##functionName parameterNames; \
70     }
71 
72 /* callingConvention is unused on Mac but is here to keep the macro prototype the same between Mac and Windows. */
73 #define SOFT_LINK_OPTIONAL(framework, functionName, resultType, callingConvention, parameterDeclarations) \
74     typedef resultType (*functionName##PtrType) parameterDeclarations; \
75     \
76     static functionName##PtrType functionName##Ptr() \
77     { \
78         static functionName##PtrType ptr = reinterpret_cast<functionName##PtrType>(dlsym(framework##Library(), #functionName)); \
79         return ptr; \
80     }
81 
82 #define SOFT_LINK_CLASS(framework, className) \
83     static Class init##className(); \
84     static Class (*get##className##Class)() = init##className; \
85     static Class class##className; \
86     \
87     static Class className##Function() \
88     { \
89         return class##className; \
90     }\
91     \
92     static Class init##className() \
93     { \
94         framework##Library(); \
95         class##className = objc_getClass(#className); \
96         ASSERT(class##className); \
97         get##className##Class = className##Function; \
98         return class##className; \
99     }
100 
101 #define SOFT_LINK_POINTER(framework, name, type) \
102     static type init##name(); \
103     static type (*get##name)() = init##name; \
104     static type pointer##name; \
105     \
106     static type name##Function() \
107     { \
108         return pointer##name; \
109     }\
110     \
111     static type init##name() \
112     { \
113         void** pointer = static_cast<void**>(dlsym(framework##Library(), #name)); \
114         ASSERT(pointer); \
115         pointer##name = static_cast<type>(*pointer); \
116         get##name = name##Function; \
117         return pointer##name; \
118     }
119 
120 #define SOFT_LINK_CONSTANT(framework, name, type) \
121     static type init##name(); \
122     static type (*get##name)() = init##name; \
123     static type constant##name; \
124     \
125     static type name##Function() \
126     { \
127         return constant##name; \
128     }\
129     \
130     static type init##name() \
131     { \
132         void* constant = dlsym(framework##Library(), #name); \
133         ASSERT(constant); \
134         constant##name = *static_cast<type*>(constant); \
135         get##name = name##Function; \
136         return constant##name; \
137     }
138