RunnerDriver.swift 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. //
  2. // RunnerDriver.swift
  3. // RunCScriptCommandHandler
  4. //
  5. // Created by 邢铖 on 2022/7/7.
  6. // Copyright © 2022 xcbosa. All rights reserved.
  7. //
  8. import Foundation
  9. public struct CodeFile {
  10. public var fileName, content: String
  11. }
  12. public struct CodeEnvironment {
  13. public var files: [CodeFile]
  14. public var startIndex: Int
  15. }
  16. public class RunnerDriver {
  17. var processThread: Thread?
  18. public func runCodeAsync(inEnvironment env: CodeEnvironment) {
  19. sf_receiver_putchar = bridgePutchar(_:)
  20. sf_ccd_io_fopen = bridgeFopen(_:_:)
  21. sf_ccd_io_fclose = bridgeFclose(_:)
  22. sf_ccd_io_fflush = bridgeFflush(_:)
  23. sf_ccd_io_fputc = bridgeFputc(_:_:)
  24. sf_ccd_io_fgetc = bridgeFgetc(_:)
  25. sf_ccd_io_fsetpos = bridgeFsetpos(_:_:)
  26. sf_ccd_io_fgetpos = bridgeFgetpos(_:)
  27. sf_ccd_io_fungetc = bridgeFungetc(_:_:)
  28. sf_ccd_system_clear = bridgeClear
  29. sf_setup_pid = Self.setup(forPid:)
  30. sf_cleanup_pid = Self.cleanUp(forPid:)
  31. TreeObjectWrapper.initWrapper()
  32. pthread_cancel_p = 0
  33. processThread = Thread {
  34. print("Process started.")
  35. CCDPrepareCompile()
  36. for it in env.files.filter({ $0.fileName != env.files[env.startIndex].fileName }) {
  37. let unsafeFileName = UnsafeMutablePointer<Int8>(mutating: (it.fileName as NSString).utf8String)
  38. let unsafeCode = UnsafeMutablePointer<Int8>(mutating: (it.content as NSString).utf8String)
  39. CCDAddFile(unsafeFileName, unsafeCode)
  40. }
  41. let unsafe_predefinedStdin = UnsafeMutablePointer<Int8>(mutating: ("" as NSString).utf8String)
  42. setPredefinedStdin(unsafe_predefinedStdin!)
  43. let unsafeArgs = UnsafeMutablePointer<Int8>(mutating: ("notebook" as NSString).utf8String)
  44. mainInvokerSetArgs(unsafeArgs!)
  45. let entryFile = UnsafeMutablePointer<Int8>(mutating: (env.files[env.startIndex].content as NSString).utf8String)!
  46. CCDInterpretInline(entryFile)
  47. }
  48. Thread {
  49. [weak self] in
  50. while (true) {
  51. guard let self = self, let processThread = self.processThread else {
  52. return
  53. }
  54. if (ccd_state == 1) {
  55. ccd_state = 10
  56. }
  57. if (ui_stdin_needed == 1) {
  58. let ch = fgetc(stdin)
  59. stdin_putch_u(UInt8(ch))
  60. } else if (ui_stdin_needed == 0) {
  61. }
  62. if processThread.isExecuting {
  63. } else {
  64. print("\nProcess terminated.")
  65. self.processThread = nil
  66. return
  67. }
  68. usleep(1000)
  69. }
  70. }.start()
  71. processThread?.start()
  72. }
  73. public func waitForEnd() {
  74. while self.processThread != nil {
  75. usleep(20000)
  76. }
  77. }
  78. public func runCode(inEnvironment env: CodeEnvironment, notify: (() -> Void)? = nil) {
  79. runCodeAsync(inEnvironment: env)
  80. if let notify = notify {
  81. DispatchQueue.global(qos: .utility).async {
  82. self.waitForEnd()
  83. notify()
  84. }
  85. } else {
  86. waitForEnd()
  87. }
  88. }
  89. public private(set) var stdout: String = ""
  90. private func bridgePutchar(_ ch: UnsafeMutablePointer<Int8>?) {
  91. guard let ch = ch else {
  92. return
  93. }
  94. if let scalar = Unicode.Scalar(UInt32(ch.pointee)) {
  95. stdout.append(Character(scalar))
  96. }
  97. }
  98. private func bridgeClear() {
  99. print("## Clear Screen")
  100. }
  101. public func stopCode() {
  102. pthread_cancel_p = 1
  103. }
  104. }
  105. extension RunnerDriver {
  106. private class func setup(forPid pid: Int32) {
  107. TreeObjectWrapper.setup(forPid: pid)
  108. }
  109. private class func cleanUp(forPid pid: Int32) {
  110. TreeObjectWrapper.cleanUp(forPid: pid)
  111. }
  112. private func bridgeFopen(_ file: UnsafeMutablePointer<CChar>, _ openMode: UnsafeMutablePointer<CChar>) -> Int32 {
  113. return 0
  114. }
  115. private func bridgeFclose(_ fd: Int32) {
  116. }
  117. private func bridgeFflush(_ fd: Int32) {
  118. }
  119. private func bridgeFputc(_ fd: Int32, _ ch: CChar) {
  120. }
  121. private func bridgeFgetc(_ fd: Int32) -> Int8 {
  122. return 0
  123. }
  124. private func bridgeFsetpos(_ fd: Int32, _ pos: Int32) {
  125. }
  126. private func bridgeFgetpos(_ fd: Int32) -> Int32 {
  127. return 0
  128. }
  129. private func bridgeFungetc(_ fd: Int32, _ c: UInt8) {
  130. }
  131. }