# This patch file was generated by NetBeans IDE
# Following Index: paths are relative to: /Users/mh124079/Development/Ruby/jruby/src/org/jruby
# This patch can be applied using context Tools: Patch action on respective folder.
# It uses platform neutral UTF-8 encoding and \n newlines.
# Above lines and this line are ignored by the patching process.
Index: RubyKernel.java
*** /Users/mh124079/Development/Ruby/jruby/src/org/jruby/RubyKernel.java Base (1.45)
--- /Users/mh124079/Development/Ruby/jruby/src/org/jruby/RubyKernel.java Locally Modified (Based On 1.45)
***************
*** 35,49 ****
   ***** END LICENSE BLOCK *****/
  package org.jruby;
  
! import java.io.BufferedReader;
  import java.io.File;
  import java.io.IOException;
! import java.io.InputStreamReader;
  import java.util.Iterator;
  import java.util.StringTokenizer;
  import java.util.regex.Pattern;
  
--- 35,50 ----
   ***** END LICENSE BLOCK *****/
  package org.jruby;
  
! import java.io.ByteArrayOutputStream;
  import java.io.File;
  import java.io.IOException;
! import java.io.InputStream;
! import java.io.OutputStream;
! import java.io.PrintStream;
  import java.util.Iterator;
+ import java.util.Stack;
  import java.util.StringTokenizer;
+ import java.util.Vector;
  import java.util.regex.Pattern;
  
  import org.jruby.ast.util.ArgsUtil;
***************
*** 683,693 ****
      }
  
      public static IRubyObject backquote(IRubyObject recv, IRubyObject aString) {
-         StringBuffer output = new StringBuffer();
          IRuby runtime = recv.getRuntime();
!         runtime.getGlobalVariables().set("$?", runtime.newFixnum(
!             runInShell(runtime, aString.toString(), output)));
!         
          return recv.getRuntime().newString(output.toString());
      }
      
--- 687,696 ----
      }
  
      public static IRubyObject backquote(IRubyObject recv, IRubyObject aString) {
          IRuby runtime = recv.getRuntime();
!         ByteArrayOutputStream output = new ByteArrayOutputStream();
!         int resultCode = runInShell(runtime, new IRubyObject[] {aString}, output);
!         recv.getRuntime().getGlobalVariables().set("$?", runtime.newFixnum(resultCode));
          return recv.getRuntime().newString(output.toString());
      }
      
***************
*** 702,797 ****
       * @return The "fixed" full command line
       */
      private static String repairDirSeps(String command) {
!         // TODO: This could be improved and optimized
!         StringTokenizer toker = new StringTokenizer(command, " ");
!         StringBuffer executable = new StringBuffer();
          
!         boolean insideQuotes = false;
!         char quoteChar = 0;
!         loop: while (true) {
!             String token = toker.nextToken();
              
!             if (!insideQuotes) {
!                 char first = token.charAt(0);
!                 switch (first) {
!                     case '"':
!                     case '\'':
!                         insideQuotes = true;
!                         quoteChar = first;
!                         executable.append(token + " ");
!                         break;
!                     default:
!                         executable.append(token);
!                         break loop;
                  }
              } else {
!                 char last = token.charAt(token.length() - 1);
!                 executable.append(token);
!                 if (last == quoteChar) {
!                     insideQuotes = false;
!                     break loop;
!                 } else {
!                     executable.append(" ");
                  }
              }
          }
          
!         String remainder = command.substring(executable.length());
          
!         // Matcher.replaceAll treats backslashes in the replacement string as escaped characters
!         String replacement = File.separator;
!         if (File.separatorChar == '\\') replacement = "\\\\";
          
!         return PATH_SEPARATORS.matcher(executable).replaceAll(replacement) + remainder;
      }
  
!     private static int runInShell(IRuby runtime, String command, StringBuffer output) {
          try {
              String shell = System.getProperty("jruby.shell");
!             Process aProcess;
!             String shellSwitch = "-c";
              
!             command = repairDirSeps(command);
              
!             if (shell != null) {
!                 if (!shell.endsWith("sh")) {
!                     shellSwitch = "/c";
                  }
!                 aProcess = Runtime.getRuntime().exec(new String[] { shell, shellSwitch, command });
              } else {
!                 aProcess = Runtime.getRuntime().exec(command);
              }
  
!             final BufferedReader reader = new BufferedReader(new InputStreamReader(aProcess.getInputStream()));
  
              // Fairly innefficient impl, but readLine is unable to tell 
              // whether the last line in a process ended with a newline or not.
!             int c;
              boolean crSeen = false;
!             while ((c = reader.read()) != -1) {
!             	if (c == '\r') {
              		crSeen = true;
              	} else {
              		if (crSeen) {
!             			if (c != '\n') {
!             				output.append('\r');
              			}
              			crSeen = false;
              		}
!             		output.append((char)c);
              	}
              }
              if (crSeen) {
!             	output.append('\r');
              }
              aProcess.getErrorStream().close();
              aProcess.getOutputStream().close();
!             reader.close();
              
              return aProcess.waitFor();
          } catch (IOException e) {
              throw runtime.newIOErrorFromException(e);
--- 705,881 ----
       * @return The "fixed" full command line
       */
      private static String repairDirSeps(String command) {
!         String executable = "", remainder = "";
!         command = command.trim();
!         if (command.startsWith("'")) {
!             String [] tokens = command.split("'", 3);
!             executable = "'"+tokens[1]+"'";
!             if (tokens.length > 2)
!                 remainder = tokens[2];
!         } else if (command.startsWith("\"")) {
!             String [] tokens = command.split("\"", 3);
!             executable = "\""+tokens[1]+"\"";
!             if (tokens.length > 2)
!                 remainder = tokens[2];
!         } else {
!             String [] tokens = command.split(" ", 2);
!             executable = tokens[0];
!             if (tokens.length > 1)
!                 remainder = " "+tokens[1];
!         }
          
!         // Matcher.replaceAll treats backslashes in the replacement string as escaped characters
!         String replacement = File.separator;
!         if (File.separatorChar == '\\')
!             replacement = "\\\\";
          
!         return PATH_SEPARATORS.matcher(executable).replaceAll(replacement) + remainder;
      }
+ 
+     private static Vector parseCommandLine(IRubyObject[] rawArgs) {
+         // first parse the first element of rawArgs since this may contain
+         // the whole command line
+         String command = rawArgs[0].toString();
+         Stack args = new Stack();
+         StringTokenizer st = new StringTokenizer(command, " ");
+         String quoteChar = null;
+ 
+         while (st.hasMoreTokens()) {
+             String token = st.nextToken();
+             if (quoteChar == null) {
+                 // not currently in the middle of a quoted token
+                 if (token.startsWith("'") || token.startsWith("\"")) {
+                     // note quote char and remove from beginning of token
+                     quoteChar = token.substring(0, 1);
+                     token = token.substring(1);
+                 }
+                 if (quoteChar!=null && token.endsWith(quoteChar)) {
+                     // quoted token self contained, remove from end of token
+                     token = token.substring(0, token.length()-1);
+                     quoteChar = null;
+                 }
+                 // add new token to list
+                 args.push(token);
              } else {
!                 // in the middle of quoted token
!                 if (token.endsWith(quoteChar)) {
!                     // end of quoted token
!                     token = token.substring(0, token.length()-1);
!                     quoteChar = null;
                  }
+                 // update token at end of list
+                 token = args.pop() + " " + token;
+                 args.push(token);
              }
          }
          
!         // now append the remaining raw args to the cooked arg list
!         for (int i=1;i<rawArgs.length;i++) {
!             args.push(rawArgs[i].toString());
!         }
          
!         return args;
!     }
      
!     private static boolean isRubyCommand(String command) {
!         command = command.trim();
!         String [] spaceDelimitedTokens = command.split(" ", 2);
!         String [] slashDelimitedTokens = spaceDelimitedTokens[0].split("/");
!         String finalToken = slashDelimitedTokens[slashDelimitedTokens.length-1];
!         if (finalToken.contains("ruby") || finalToken.endsWith(".rb"))
!             return true;
!         else
!             return false;
      }
      
!     private static int runInShell(IRuby runtime, IRubyObject[] rawArgs, OutputStream output) {
          try {
+             // startup scripts set jruby.shell to /bin/sh for Unix, cmd.exe for Windows
              String shell = System.getProperty("jruby.shell");
!             rawArgs[0] = runtime.newString(repairDirSeps(rawArgs[0].toString()));
!             Process aProcess = null;
              
!             if (isRubyCommand(rawArgs[0].toString())) {
!                 final Vector args = parseCommandLine(rawArgs);
!                 final String command = (String)args.get(0);            
!                 Thread t = new Thread() {
!                     public void run() {
!                         try {
!                             String[] argArray = new String[args.size()-1];
!                             // snip off ruby or jruby command from list of arguments
!                             // leave alone if the command is the name of a script
!                             int startIndex = command.endsWith(".rb") ? 0 : 1;
!                             args.subList(startIndex,args.size()).toArray(argArray);
!                             org.jruby.Main.main(argArray);
!                         } catch (Throwable t) {
!                         }
!                     }
!                 };
                  
!                 // redirect stdout to output
!                 PrintStream out = System.out;
!                 PrintStream redirect = new PrintStream(output);
!                 System.setOut(redirect);
!                 
!                 // execute ruby command in new thread
!                 t.start();
!                 t.join();
!                 
!                 // reset stdout and stderr back to their orignal values
!                 System.setOut(out);
!             } else if (shell != null && rawArgs.length == 1) {
!                 // execute command with sh -c or cmd.exe /c
!                 // this does shell expansion of wildcards
!                 String shellSwitch = shell.endsWith("sh") ? "-c" : "/c";
!                 String[] argArray = new String[3];
!                 argArray[0] = shell;
!                 argArray[1] = shellSwitch;
!                 argArray[2] = rawArgs[0].toString();
!                 aProcess = Runtime.getRuntime().exec(argArray);
!             } else {
!                 // execute command directly, no wildcard expansion
!                 if (rawArgs.length > 1) {
!                     String[] argArray = new String[rawArgs.length];
!                     for (int i=0;i<rawArgs.length;i++) {
!                         argArray[i] = rawArgs[i].toString();
                      }
!                     aProcess = Runtime.getRuntime().exec(argArray);
                  } else {
!                     aProcess = Runtime.getRuntime().exec(rawArgs[0].toString());
                  }
+             }
  
!             if (aProcess != null) {
!                 InputStream processOutput = aProcess.getInputStream();
                  
                  // Fairly innefficient impl, but readLine is unable to tell
                  // whether the last line in a process ended with a newline or not.
!                 int b;
                  boolean crSeen = false;
!                 while ((b = processOutput.read()) != -1) {
!                     if (b == '\r') {
                          crSeen = true;
                      } else {
                          if (crSeen) {
!                             if (b != '\n') {
!                                 output.write('\r');
                              }
                              crSeen = false;
                          }
!                         output.write(b);
                      }
                  }
                  if (crSeen) {
!                     output.write('\r');
                  }
                  aProcess.getErrorStream().close();
                  aProcess.getOutputStream().close();
!                 processOutput.close();
                  
                  return aProcess.waitFor();
+             } else {
+                 return 0;
+             }
          } catch (IOException e) {
              throw runtime.newIOErrorFromException(e);
          } catch (InterruptedException e) {
***************
*** 839,849 ****
  
      public static RubyBoolean system(IRubyObject recv, IRubyObject[] args) {
          IRuby runtime = recv.getRuntime();
!         if (args.length > 1) {
!             throw runtime.newArgumentError("more arguments not yet supported");
!         }
!         StringBuffer output = new StringBuffer();
!         int resultCode = runInShell(runtime, args[0].toString(), output);
          recv.getRuntime().getGlobalVariables().set("$?", runtime.newFixnum(resultCode));
          return runtime.newBoolean(resultCode == 0);
      }
--- 926,934 ----
  
      public static RubyBoolean system(IRubyObject recv, IRubyObject[] args) {
          IRuby runtime = recv.getRuntime();
!         ByteArrayOutputStream output = new ByteArrayOutputStream();
!         int resultCode = runInShell(runtime, args, output);
!         System.out.println(output.toString());
          recv.getRuntime().getGlobalVariables().set("$?", runtime.newFixnum(resultCode));
          return runtime.newBoolean(resultCode == 0);
      }
