compile.ha (1563B)
1 export type exited = int, signaled = int; 2 export type exit_status = (exited | signaled); 3 4 export type typedef = str; 5 export type define = str; 6 export type compileflag = (typedef | define); 7 8 // Runs the Hare compiler and returns the exit status. 9 export fn compile(src: const str, flags: compileflag...) exit_status = { 10 let status = 0; 11 let pipefd = [-1, -1]; 12 assert(pipe2(&pipefd, 0) == 0); 13 14 const child = fork(); 15 if (child == 0) { 16 close(pipefd[1]); 17 dup2(pipefd[0], 0); 18 close(1); 19 close(2); 20 21 const path = "./harec\0"; 22 let argv: []nullable *const char = []; 23 append(argv, constchar(path)); 24 for (let i = 0z; i < len(flags); i += 1) { 25 match (flags[i]) { 26 case let d: define => 27 append(argv, constchar("-D\0")); 28 append(argv, alloc_constchar(d)); 29 case let t: typedef => 30 append(argv, constchar("-t\0")); 31 append(argv, alloc_constchar(t)); 32 }; 33 }; 34 append(argv, constchar("-\0")); 35 append(argv, null); 36 37 const envp: [_]nullable *const char = [ 38 constchar("HARECACHE=mod\0"), 39 null 40 ]; 41 execve(constchar(path), *(&argv: **[*]nullable *const char), &envp); 42 abort(); 43 } else { 44 assert(child != -1, "fork(2) failed"); 45 close(pipefd[0]); 46 47 const buf = constchar(src): *const [*]u8; 48 for (let n = 0z; n < len(src)) { 49 let m = write(pipefd[1], &buf[n], len(src) - n); 50 assert(m > 0, "write(2) failed"); 51 n += m; 52 }; 53 54 close(pipefd[1]); 55 wait4(child, &status, 0, null); 56 }; 57 58 return if (wifexited(status)) wexitstatus(status): exited 59 else if (wifsignaled(status)) wtermsig(status): signaled 60 else abort(); 61 };