/source/core/DynamicLoader.ooc
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