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