#line 744 "/home/travis/build/felix-lang/felix/src/packages/program.fdoc"
  
  // Note Shell_class interface doesn't use process_status_t
  // but the implementation does.
  
  class Shell_class[OS, process_status_t]
  {
    // Quote a single argument.
    // Note: kills Bash wildcard replacement.
    virtual fun quote_arg:string->string;
    fun quote_args (s:list[string]) : string => catmap[string] ' ' quote_arg s;
  
    // Mainly for Windows we need a way to quote command line strings too.
    virtual fun quote_line_for_system: string->string;
  
    virtual fun parse: string -> list[string];
  
    //------------------------------------------------------------
    // system() function
  
    System command is ISO C and C++ standard.
    gen raw_system: string -> int = "::std::system($1.c_str())"
      requires Cxx_headers::cstdlib
    ;
    basic command with line quoting.
    gen basic_system (cmd: string) :int =>
      cmd.quote_line_for_system.raw_system
    ;
  
    // string argument
    gen system (cmd:string) = {
      if Env::getenv "FLX_SHELL_ECHO" != "" do
        eprintln$ "[system] " + cmd;
      done
      return basic_system cmd;
    }
  
    // list of string argument
    gen system (args:list[string]) : int =>
      args.quote_args.system
    ;
  
    gen system[T with Iterable[T,string]] (args:T) : int =
    {
      var lst = Empty[string];
      for arg in args do
        lst = lst + arg;
      done
      return system lst;
    }
  
    //------------------------------------------------------------
    // popen() function (get_stdout)
  
    virtual fun quote_line_for_popen: string -> string;
  
    get_stdout is a synchronous version of popen_in/pclose pair.
    virtual gen raw_get_stdout : string -> int * string;
  
    gen basic_get_stdout (cmd: string) : int * string =>
      cmd.quote_line_for_popen.raw_get_stdout
    ;
  
    gen get_stdout (cmd:string) : int * string = {
      if Env::getenv "FLX_SHELL_ECHO" != "" do
        eprintln$ "[get_stdout] " + cmd;
      done
      return basic_get_stdout cmd;
    }
  
    // arbitrary Streamable argument
    gen get_stdout (args:list[string]) : int * string =>
      args.quote_args.get_stdout
    ;
  
    gen get_stdout[T with Iterable[T,string]] (args:T) : int * string =
    {
      var lst = Empty[string];
      for arg in args do
        lst = lst + arg;
      done
      return get_stdout lst;
    }
  
  }
  
  class Shell {
  if PLAT_WIN32 do
    inherit CmdExe;
  else
    inherit Bash;
  done
  }