1 let pclose (stream : CStream) : int 2 let feof (stream : CStream) : int 3 let fgets (s : MutPtr<CChar> 4 n : int 5 stream : CStream) : MutPtr<CChar> 6 def fclose (stream : CStream) : int 7 8 let kd_get_arg (index : u32) : String 9 let kd_get_current_path () : String 10 11 object Sys = 12 val unprintable_char = '?' 13 val executable_directory = kd_get_current_path 14 |> { s -> if s.contains '\\' 15 then s.replace '\\' '/' 16 else s } 17 18 type Output = 19 val status : i32 20 val stdout : String 21 val stderr : String 22 23 def is_success = status == 0 24 25 type Process @abstract = 26 val output = StringBuilder.new 27 val error = StringBuilder.new 28 var maybe_exit_code : Option<i32> = None 29 30 def is_running : bool 31 def read_streams 32 def close 33 34 def is_success = case maybe_exit_code of 35 None -> false 36 Some exit_code -> exit_code == 0 37 38 def wait = 39 assert maybe_exit_code.is_none 40 41 while is_running do 42 read_streams 43 44 close 45 46 Output status = maybe_exit_code.unwrap 47 stdout = output.create 48 stderr = error.create 49 50 def complete = 51 assert not is_running && maybe_exit_code.is_none 52 53 read_streams 54 close 55 56 let remove_non_ascii (buffer : MutPtr<CChar>) (size : u32) = 57 for i = 0 until size do 58 let c = buffer[i] 59 if c == '\0' then 60 break 61 62 if c as i32 < 0 then 63 buffer[i] = Sys.unprintable_char as CChar 64 65 type CProcess = 66 inherit Process 67 68 val stdout : CStream 69 val stderr : CStream 70 let fd : int 71 72 def Process.is_running = 73 feof stdout == 0 74 75 def Process.read_streams = 76 let max_buffer : int = 256 77 let mut buffer = [CChar; max_buffer]@zero 78 let c_string = CString buffer.as_ptr 79 80 repeat 81 if fgets buffer.as_mut_ptr max_buffer stdout <> null then 82 remove_non_ascii buffer.as_mut_ptr max_buffer.as<u32> 83 output.append c_string 84 else 85 break 86 87 until buffer[0] as i32 == 0 || feof stdout <> 0 88 89 repeat 90 if fgets buffer.as_mut_ptr max_buffer stderr <> null then 91 remove_non_ascii buffer.as_mut_ptr max_buffer.as<u32> 92 error.append c_string 93 else 94 break 95 96 until buffer[0] as i32 == 0 || feof stderr <> 0 97 98 def Process.close = 99 let exit_code = pclose stdout as i32 100 maybe_exit_code = Some exit_code 101 102 fclose stderr 103 close fd |> ignore 104 105 os@ windows 106 107 type WProcessImpl @cpp = 108 fun new (path : String) 109 def is_running : bool 110 def read_from_pipe : MutPtr<CChar> 111 def get_exit_code : i32 112 def close 113 114 let w_max_buffer "WPROCESS_BUFFER_SIZE" : u32 115 116 type WProcess = 117 inherit Process 118 119 let command : String 120 let impl = WProcessImpl command 121 122 def Process.is_running = impl.is_running 123 124 def Process.read_streams = 125 repeat 126 let buffer = impl.read_from_pipe 127 if buffer <> null then 128 remove_non_ascii buffer w_max_buffer 129 let c_string = CString buffer 130 output.append c_string 131 else 132 break 133 134 def Process.close = 135 let exit_code = impl.get_exit_code 136 maybe_exit_code = Some exit_code 137 impl.close 138 139 endos@ 140