PageRenderTime 27ms CodeModel.GetById 24ms app.highlight 1ms RepoModel.GetById 1ms app.codeStats 0ms

/source/core/DynamicLoader.ooc

http://github.com/nddrylliog/oc
Unknown | 145 lines | 116 code | 29 blank | 0 comment | 0 complexity | 531964a6ebf14309a6772f31720f804f MD5 | raw file
  1
  2import io/File
  3
  4import backend/Backend
  5import frontend/BuildParams
  6
  7import frontend/[ParsingPool, Frontend]
  8
  9DynamicLoader: class {
 10    
 11    plugins: static File
 12
 13    init: static func (params: BuildParams) {
 14        plugins = File new(params home, "plugins")
 15        if(!plugins exists?()) {
 16            "Couldn't locate oc plugins in %s - please set the OC_DIST environment variable" printfln(plugins path)
 17            exit(1)
 18        }
 19        
 20        params backend = loadBackend(params backendString, params)
 21        if(!params backend) {
 22            "Couldn't load backend '%s', bailing out!" printfln(params backendString)
 23            exit(1)
 24        }
 25        
 26        if(params verbose > 0) {
 27            "oc v%s  sourcepath = %s  outpath = %s  backend is %s" printfln(params VERSION, params sourcepath join(":"), params outpath, params backend class name)
 28            "-----------------------------------------------------------------------"
 29        }
 30    }
 31    
 32    exit: static func {
 33        // So here's the fun thing: we can't unload core nor sdk
 34        // without making the application crash. However, simply exiting
 35        // seems to clean up stuff cleanly AND not crash!
 36        exit(0)
 37    }
 38    
 39    findPlugin: static func (name: String, params: BuildParams, callback: Func (LibHandle)) {
 40        plugins getChildren() each(|child|
 41            if(child name() startsWith?(name)) {
 42                if(params verbose > 0) "Found plug-in %s in %s" printfln(name, child path)
 43                
 44                handle := dlopen(child path, RTLD_LAZY)
 45                if(handle) {
 46                    callback(handle)
 47                } else {
 48                    "Error while opening plug-in %s: %s" printfln(child path, dlerror())
 49                }
 50            } else {
 51                if(params verbose > 0) "Ignoring %s" printfln(child path)
 52            }
 53        )
 54    }
 55    
 56    loadBackend: static func (name: String, params: BuildParams) -> Backend {
 57        backend: Backend = null
 58        This findPlugin(name + "_backend", params, |handle|
 59            classPrefix := "backend_%s_Backend_" format(name)
 60        
 61            // call load
 62            loadAddress := dlsym(handle, classPrefix + "load")
 63            if(!loadAddress) {
 64                "Symbol '%s' not found in %s" printfln(classPrefix + "load", name)
 65                dlclose(handle)
 66                return null
 67            }
 68            
 69            callableLoad: Closure 
 70            callableLoad thunk = loadAddress
 71            (callableLoad as Func)()
 72            
 73            classPrefix = "backend_%s_Backend__%s_" format(name, name)
 74            
 75            // call constructor
 76            constructorAddress := dlsym(handle, classPrefix + "Backend_new")
 77            if(!constructorAddress) {
 78                "Symbol '%s' not found in %s" printfln(classPrefix + "Backend_new", name)
 79                dlclose(handle)
 80                return null
 81            }
 82            
 83            callableConstructor: Closure
 84            callableConstructor thunk = constructorAddress
 85            
 86            backend = (callableConstructor as Func -> Backend)()
 87            if(!backend) {
 88                "Couldn't instantiate backend for '%s', please report this bug to backend maintainers" printfln(name)
 89            }
 90            if(params verbose > 0) "Got backend %s" printfln(backend class name)
 91        )
 92        backend
 93    }
 94    
 95    loadFrontend: static func (name: String, params: BuildParams, pool: ParsingPool) -> FrontendFactory {
 96        factory: FrontendFactory = null
 97        This findPlugin(name + "_frontend", params, |handle|
 98            classPrefix := "frontend_%s_Frontend_" format(name)
 99        
100            // call load
101            loadAddress := dlsym(handle, classPrefix + "load")
102            if(!loadAddress) {
103                "Symbol '%s' not found in %s" printfln(classPrefix + "load", name)
104                dlclose(handle)
105                return null
106            }
107            
108            callableLoad: Closure 
109            callableLoad thunk = loadAddress
110            (callableLoad as Func)()
111            
112            classPrefix = "frontend_%s_Frontend__%s_FrontendFactory_" format(name, name)
113            
114            // call constructor
115            constructorAddress := dlsym(handle, classPrefix + "new")
116            if(!constructorAddress) {
117                "Symbol '%s' not found in %s" printfln(classPrefix + "new", name)
118                dlclose(handle)
119                return null
120            }
121            
122            callableConstructor: Closure
123            callableConstructor thunk = constructorAddress
124            
125            factory = (callableConstructor as Func -> FrontendFactory)()
126            if(!factory) {
127                "Couldn't instantiate frontend for '%s', please report this bug to frontend maintainers" printfln(name)
128            }
129            if(params verbose > 0) "Got frontend %s" printfln(factory class name)
130        )
131        factory
132    }
133    
134}
135
136/* C binding part */
137use dl
138
139LibHandle: cover from Pointer {}
140RTLD_LAZY, RTLD_NOW, RTLD_GLOBAL: extern Int
141
142dlopen  : extern func (fileName: CString, flag: Int) -> LibHandle
143dlsym   : extern func (handle: LibHandle, symbolName: CString) -> Pointer
144dlclose : extern func (handle: LibHandle) -> Int
145dlerror : extern func -> CString