#line 514 "/home/travis/build/felix-lang/felix/src/packages/program.fdoc"
  
  class Win32Process {
    open Win32Signal;
  
    instance Process_class[Win32, process_status_t]
    {
      gen popen_in: string -> Cstdio::ifile = '_popen($1.c_str(), "r")' requires C89_headers::stdio_h;
      gen pclose: Cstdio::ifile -> process_status_t = "_pclose($1)" requires C89_headers::stdio_h;
    }
    inherit Process_class[Win32, process_status_t];
    type process_status_t = "intptr_t";
    ctor intptr:process_status_t = "$1";
    ctor int:process_status_t = "int($1)";
    ctor process_status_t : intptr = "$1";
    fun int_of_process_status_t: process_status_t -> int = "(int)$1";
  
  /*
  
    fun WIFCONTINUED: process_status_t -> bool = "WIFCONTINUED($1)!=0";
    fun WIFEXITED: process_status_t -> bool = "WIFEXITED($1)!=0";
    fun WIFSIGNALED: process_status_t -> bool = "WIFSIGNALED($1)!=0";
    fun WIFSTOPPED: process_status_t -> bool = "WIFSTOPPED($1)!=0";
  
    fun WEXITSTATUS: process_status_t -> int = "WEXITSTATUS($1)";
    fun WTERMSIG: process_status_t -> signal_t = "WTERMSIG($1)";
    fun WSTOPSIG: process_status_t -> signal_t = "WSTOPSIG($1)";
  
    // OSX only, not in Posix
    fun  WCOREDUMP: process_status_t -> int = "WCOREDUMP($1)";
  
  
    fun str(x:process_status_t) = {
      if WIFEXITED x do
         val e = x.WEXITSTATUS;
         return "Exit " + str e + ": " +e.errno_t.strerror;
      elif WIFSIGNALED x do
         val s = x.WTERMSIG;
         return "SIGNAL " + s.int.str + ": " + s.str;
      else
         return "Unknown temination status " + x.int.str;
      done
    }
  */
    const environ: + (+char) = "environ" requires Posix_headers::unistd_h;
  
    type exec_result_t = "intptr_t";
    const bad_exec: exec_result_t = "intptr_t(-1)";
    fun == : exec_result_t * exec_result_t -> bool= "$1==$2";
  
    gen execv:+char *  + (+char) -> exec_result_t = "_execv($1, $2)" requires Win32_headers::process_h;
    gen execvp:+char *  + (+char) -> exec_result_t = "_execvp($1, $2)" requires Win32_headers::process_h;
    gen execve:+char *  + (+char) * + (+char) -> exec_result_t = "_execve($1, $2, $3)" requires Win32_headers::process_h;
  
    // do NOT try to fork Felix programs, it doesn't work
    // because of threads already running. We use fork only
    // to preceed exec() calls.
    type pid_t = "intptr_t" requires Posix_headers::unistd_h;
    ctor intptr: pid_t = "($1)";
    const bad_process : pid_t = "intptr_t(-1)";
    fun == : pid_t * pid_t -> bool= "$1==$2";
  
    instance Str[pid_t] {
      fun str: pid_t -> string = "::flx::rtl::strutil::str<intptr_t>($1)" requires package "flx_strutil";
    }
  
    union spawn_result_t =
    // returned to parent process
    | BadFork of errno_t
    | ProcessId of pid_t
  
    // returned to child proces (can't happen on Windows)
    | BadExec of errno_t
    | BadSetup of int
    ;
  
    gen spawnv:+char *  + (+char) -> pid_t = "_spawn(_P_NOWAIT,$1, $2)" requires Win32_headers::process_h;
    gen spawnvp:+char *  + (+char) -> pid_t = "_spawnvp(_P_NOWAIT,$1, $2)" requires Win32_headers::process_h;
    gen spawnve:+char *  + (+char) * + (+char) -> pid_t = "_spawnve(_P_NOWAIT,$1, $2, $3)" requires Win32_headers::process_h;
  
    gen spawnv(file: string, argv:+ (+char), setup:1->int) : spawn_result_t = {
      var x = spawnv(file.cstr, argv);
      if x == bad_process do // PARENT
        return BadFork errno;
      else
        return ProcessId x;
      done
    }
  
    gen spawnvp(file: string, argv:+ (+char), setup:1->int) : spawn_result_t = {
      var x = spawnvp(file.cstr, argv);
      if x == bad_process do  // PARENT
        return BadFork errno;
      else
        return ProcessId x;
      done
    }
  
    gen spawnve(file: string, argv:+ (+char), env: + (+char), setup:1->int) : spawn_result_t = {
      var x = spawnve(file.cstr, argv, env);
      if x == bad_process do // PARENT
        return BadFork errno;
      else
        return ProcessId x;
      done
    }
  /*
    type process_status_options_t = "int";
    const WCONTINUED: process_status_options_t;
    const WNOHANG: process_status_options_t;
    const WUNTRACED: process_status_options_t;
    const WNONE: process_status_options_t="0";
    fun \| : process_status_options_t * process_status_options_t -> process_status_options_t = "$1|$2";
  
    // Use WaitForSingleObject
    gen waitpid: pid_t * &process_status_t * process_status_options_t -> pid_t requires Posix_headers::sys_wait_h;
  
    gen waitpid(pid:pid_t) = {
      var status: process_status_t;
      var pid' = waitpid(pid,&status,WNONE);
      if pid' == bad_process do
        println$ "Waitpid failed .. fix me!";
        System::exit 1;
      else
        return status;
      done
    }
  
    union ProcesStatus= | Running | Stopped of process_status_t;
  
    gen checkpid(pid:pid_t) = {
      var status: process_status_t;
      var pid' = waitpid(pid,&status,WNOHANG);
      if pid' == bad_process do
        println$ "Waitpid failed .. fix me!";
        System::exit 1;
      elif pid'.int == 0 do
        return Running;
      else
        return Stopped status;
      done
    }
  
    gen kill: pid_t * signal_t -> int;
    const OUR_PROCESS_GROUP: pid_t = "0";
  */
  }