module exec;

import StdEnv;

load_long :: !Int -> Int;
load_long n = code {
		instruction 139
		instruction 0	| movl (%eax),%eax
	} 

store_long :: !Int !Int -> Int;
store_long p n = code {
		instruction 137
		instruction 3	| movl %eax,(%ebx)
		pop_b 1
	}

store_byte :: !Int !Int -> Int;
store_byte p n = code {
		instruction 136
		instruction 3	| movb %al,(%ebx)
		pop_b 1
	}

malloc :: !Int -> Int;
malloc n = code {
		ccall malloc "I:I"
	}

calloc :: !Int !Int -> Int;
calloc s n = code {
		ccall calloc "II:I"
	}

free :: !Int !Int -> Int;
free p r = code { 
		ccall free "I:V:I" 
	}

execv :: !{#Char} !Int -> Int;
execv file_name argv = code { 
		ccall execv "sI:I" 
	}

fork :: Int;
fork = code { 
		ccall fork ":I" 
	}

wait :: (!Int,!Int);
wait = code { 
		ccall wait ":II" 
	}

sigaddset :: !Int !Int -> Int;
sigaddset sigset_p signal = code {
		ccall sigaddset "II:I"
	}

sigprocmask :: !Int !Int !Int -> Int;
sigprocmask how set old_set = code { 
		ccall sigprocmask "III:I"
	}

exec_ file_name args
	# sigset=calloc 4 1;
	| sigset<>0 && sigaddset sigset 14==0 && sigprocmask 0 sigset 0==0
		#! (r,s) = exec file_name args;
		| sigprocmask 1 sigset 0==0 && free sigset 0==0
			= (r,s);
			= abort "exec_";

exec :: !{#Char} ![{#Char}] -> (!Bool,!Int);
exec file_name args
	# args=[file_name:args];
	# n_args = length args;
	# argv_size = 6+5*n_args+sum (map size args);
	# argv = malloc argv_size;
	| argv==0
		= abort "malloc failed";
	# argv = fill_arguments args argv (argv+((n_args+1)<<2));
	  with {
		fill_arguments [] argp argsp
			|  store_long argp 0==0 && store_byte argsp 0==0 && store_byte (argsp+1) 0==0
				= argv;
		fill_arguments [arg:args] argp argsp
			|  store_long argp argsp==argsp && store_zstring 0==0
				= fill_arguments args (argp+4) (argsp+size arg+1);
				= fill_arguments args (argp+4) (argsp+size arg+1);
			{}{
				store_zstring i
					| i==size arg
						= store_byte (argsp+i) 0;
					# v=toInt arg.[i];
					| store_byte (argsp+i) v==v
						= store_zstring (i+1);
			}
		}
	# (r,s) = fork_exec_wait (file_name+++"\0") argv;
	  with {
		fork_exec_wait :: !{#Char} !Int -> (!Bool,!Int);
		fork_exec_wait file_name0 argv
			# pid=fork;
			| pid==(-1)
				= (False,-1);
			| pid<>0
				# (pid,r) = wait;
				= abort ("wait "+++toString r+++" "+++toString pid+++"\n");
				// = (True,r);
				# r = execv file_name0 argv;
				= (False,r);
	  }
	| free argv s==s
		= (r,s);

Start = exec "/bin/ls" ["-l","-t","."];

