#line 839 "/home/travis/build/felix-lang/felix/src/packages/program.fdoc"
  
  // Note: shell functions here only work with Bash.
  // However, the system() function always calls sh,
  // and sh is always an ash, which is almost always bash
  
  /* GNU Bash 3-2 Man page
  QUOTING
         Quoting  is  used  to  remove  the  special meaning of certain characters or words to the shell.
         Quoting can be used to disable special treatment for special  characters,  to  prevent  reserved
         words from being recognized as such, and to prevent parameter expansion.
  
         Each  of  the metacharacters listed above under DEFINITIONS has special meaning to the shell and
         must be quoted if it is to represent itself.
  
         When the command history expansion facilities are being used (see HISTORY EXPANSION below),  the
         history expansion character, usually !, must be quoted to prevent history expansion.
  
         There are three quoting mechanisms: the escape character, single quotes, and double quotes.
  
         A  non-quoted backslash (\) is the escape character.  It preserves the literal value of the next
         character that follows, with the exception of <newline>.  If a \<newline> pair appears, and  the
         backslash is not itself quoted, the \<newline> is treated as a line continuation (that is, it is
         removed from the input stream and effectively ignored).
  
         Enclosing characters in single quotes preserves the literal value of each character  within  the
         quotes.   A single quote may not occur between single quotes, even when preceded by a backslash.
  
         Enclosing characters in double quotes preserves the literal value of all characters  within  the
         quotes,  with  the exception of $, `, \, and, when history expansion is enabled, !.  The charac-
         ters $ and ` retain their special meaning within double quotes.  The backslash retains its  spe-
         cial meaning only when followed by one of the following characters: $, `, ", \, or <newline>.  A
         double quote may be quoted within double quotes by preceding it with a backslash.   If  enabled,
         history  expansion  will be performed unless an !  appearing in double quotes is escaped using a
         backslash.  The backslash preceding the !  is not removed.
  
         The special parameters * and @ have special  meaning  when  in  double  quotes  (see  PARAMETERS
         below).
  
         Words  of the form $'string' are treated specially.  The word expands to string, with backslash-
         escaped characters replaced as specified by the ANSI C standard.  Backslash escape sequences, if
         present, are decoded as follows:
                \a     alert (bell)
                \b     backspace
                \e     an escape character
                \f     form feed
                \n     new line
                \r     carriage return
                \t     horizontal tab
                \v     vertical tab
                \\     backslash
                \'     single quote
                \nnn   the eight-bit character whose value is the octal value nnn (one to three digits)
                \xHH   the  eight-bit  character  whose value is the hexadecimal value HH (one or two hex
                       digits)
                \cx    a control-x character
  
         The expanded result is single-quoted, as if the dollar sign had not been present.
  
         A double-quoted string preceded by a dollar sign ($) will cause  the  string  to  be  translated
         according  to  the  current  locale.   If  the  current locale is C or POSIX, the dollar sign is
         ignored.  If the string is translated and replaced, the replacement is double-quoted.
  
  */
  
  class Bash {
  
    instance Shell_class[Posix, PosixProcess::process_status_t] {
      // we can't use single quotes becase there's no way to represent a '
      // in a single quoted string .. so we have to use double quotes and
      // backslash the 4 special characters: " $ \ `
      // I think this is all ..
      fun quote_arg(s:string):string= {
        var r = "";
        for ch in s do
          if ch in "\\\"" do   // leave $ and ` in there, unquoted.
            r += "\\"+ str ch;
          else
            r+= ch;
          done
        done
        return '"'+r+'"';
      }
      fun quote_line_for_system (s:string) => s;
      fun quote_line_for_popen (s:string) => s + " ";
  
      gen raw_get_stdout(x:string) = {
          var fout = PosixProcess::popen_in(x+" ");
          if valid fout do
            var output = load fout;
  
            var result = PosixProcess::pclose fout;
            return PosixProcess::WEXITSTATUS result, output;
          else
            println$ "Unable to run command '" + x "'";
            return -1,"";
          done
      }
  
      //$ Parse a bash command line into words.
      fun parse (s:string) : list[string] =
      {
        var args = Empty[string];
        var current = "";
        union mode_t = | copy | skip | quote | dquote | escape-copy | escape-dquote;
        var mode = skip;
        for ch in s do
          match mode with
          | #skip =>
            if ch == char "\\" do
              mode = escape-copy;
            elif ch == char "'" do
              mode = quote;
            elif ch == char '"' do
              mode = dquote;
            elif ord ch > ord (char ' ') do
              current += ch;
              mode = copy;
            done
  
          | #copy =>
            if ch == char "\\" do
              mode = escape-copy;
            elif ord ch <= ord (char ' ') do
              mode = skip;
              args += current;
              current = "";
            elif ch == char "'" do
               mode = quote;
            elif ch == char '"' do
              mode = dquote;
            else
              current += ch;
            done
  
          | #escape-copy =>
            current += ch;
            mode = copy;
  
          | #escape-dquote =>
            mode = dquote;
            if ch in '"\\$`' do
              current += ch;
            elif ch == char "'n" do ;
            else
              current += "\\" + ch;
            done
  
          | #dquote =>
            if ch == char '"' do
              mode = copy;
            elif ch == char "\\" do
              mode = escape-dquote;
            else
              current += ch;
            done
          | #quote =>
            if ch == char "'" do
              mode = copy;
            else
              current += ch;
            done
          endmatch;
        done
        match mode with
        | #skip => ;
        | _ => args += current;
        endmatch;
        return args;
      }
    }
    inherit Shell_class[Posix, PosixProcess::process_status_t];
  }