harec

[hare] Hare compiler, written in C11 for POSIX OSs
Log | Files | Refs | README | LICENSE

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 };