1 37 package org.jruby; 38 39 import java.io.InputStream ; 40 import java.io.PrintStream ; 41 import java.io.Reader ; 42 import java.util.Iterator ; 43 44 import org.jruby.ast.Node; 45 import org.jruby.exceptions.JumpException; 46 import org.jruby.exceptions.MainExitException; 47 import org.jruby.exceptions.RaiseException; 48 import org.jruby.internal.runtime.ValueAccessor; 49 import org.jruby.javasupport.JavaUtil; 50 import org.jruby.parser.ParserSupport; 51 import org.jruby.runtime.Block; 52 import org.jruby.runtime.Constants; 53 import org.jruby.runtime.IAccessor; 54 import org.jruby.runtime.builtin.IRubyObject; 55 import org.jruby.util.CommandlineParser; 56 import org.jruby.ast.executable.YARVCompiledRunner; 57 58 67 public class Main { 68 private CommandlineParser commandline; 69 private boolean hasPrintedUsage = false; 70 private RubyInstanceConfig config; 71 private PrintStream out; 73 private PrintStream err; 74 75 public Main(RubyInstanceConfig config) { 76 this.config = config; 77 this.out = config.getOutput(); 78 this.err = config.getError(); 79 } 80 81 public Main(final InputStream in, final PrintStream out, final PrintStream err) { 82 this(new RubyInstanceConfig(){{ 83 setInput(in); 84 setOutput(out); 85 setError(err); 86 }}); 87 } 88 89 public Main() { 90 this(new RubyInstanceConfig()); 91 } 92 93 public static void main(String [] args) { 94 Main main = new Main(); 95 int status = main.run(args); 96 if (status != 0) { 97 System.exit(status); 98 } 99 } 100 101 public int run(String [] args) { 102 commandline = new CommandlineParser(this, args); 103 104 if (commandline.isShowVersion()) { 105 showVersion(); 106 } 107 108 if (! commandline.shouldRunInterpreter()) { 109 return 0; 110 } 111 112 long now = -1; 113 if (commandline.isBenchmarking()) { 114 now = System.currentTimeMillis(); 115 } 116 117 int status; 118 119 try { 120 status = runInterpreter(commandline); 121 } catch (MainExitException mee) { 122 err.println(mee.getMessage()); 123 if (mee.isUsageError()) { 124 printUsage(); 125 } 126 status = mee.getStatus(); 127 } 128 129 if (commandline.isBenchmarking()) { 130 out.println("Runtime: " + (System.currentTimeMillis() - now) + " ms"); 131 } 132 133 return status; 134 } 135 136 private void showVersion() { 137 out.print("ruby "); 138 out.print(Constants.RUBY_VERSION); 139 out.print(" ("); 140 out.print(Constants.COMPILE_DATE); 141 out.print(") ["); 142 out.print("java-jruby" + Constants.VERSION); 143 out.println("]"); 144 } 145 146 public void printUsage() { 147 if (!hasPrintedUsage) { 148 out.println("Usage: jruby [switches] [--] [rubyfile.rb] [arguments]"); 149 out.println(" -e 'command' one line of script. Several -e's allowed. Omit [programfile]"); 150 out.println(" -b benchmark mode, times the script execution"); 151 out.println(" -Idirectory specify $LOAD_PATH directory (may be used more than once)"); 152 out.println(" -- optional -- before rubyfile.rb for compatibility with ruby"); 153 out.println(" -d set debugging flags (set $DEBUG to true)"); 154 out.println(" -v print version number, then turn on verbose mode"); 155 out.println(" -O run with ObjectSpace disabled (improves performance)"); 156 out.println(" -S cmd run the specified command in JRuby's bin dir"); 157 out.println(" -C pre-compile scripts before running (EXPERIMENTAL)"); 158 out.println(" -y read a YARV-compiled Ruby script and run that (EXPERIMENTAL)"); 159 out.println(" -Y compile a Ruby script into YARV bytecodes and run this (EXPERIMENTAL)"); 160 out.println(" --command word Execute ruby-related shell command (i.e., irb, gem)"); 161 hasPrintedUsage = true; 162 } 163 } 164 165 private int runInterpreter(CommandlineParser commandline) { 166 Reader reader = commandline.getScriptSource(); 167 String filename = commandline.displayedFileName(); 168 config.updateWithCommandline(commandline); 169 final Ruby runtime = Ruby.newInstance(config); 170 runtime.setKCode(commandline.getKCode()); 171 172 Runtime.getRuntime().addShutdownHook(new Thread () { 176 public void run() { 177 if (!runtime.getRuntimeInformation().isEmpty()) { 178 System.err.println("Runtime information dump:"); 179 180 for (Iterator iter = runtime.getRuntimeInformation().keySet().iterator(); iter.hasNext();) { 181 Object key = iter.next(); 182 System.err.println("[" + key + "]: " + runtime.getRuntimeInformation().get(key)); 183 } 184 } 185 } 186 }); 187 188 try { 189 runInterpreter(runtime, reader, filename); 190 return 0; 191 } catch (JumpException je) { 192 if (je.getJumpType() == JumpException.JumpType.RaiseJump) { 193 RubyException raisedException = ((RaiseException)je).getException(); 194 if (raisedException.isKindOf(runtime.getClass("SystemExit"))) { 195 RubyFixnum status = (RubyFixnum)raisedException.getInstanceVariable("status"); 196 197 if (status != null) { 198 return RubyNumeric.fix2int(status); 199 } else { 200 return 0; 201 } 202 } else { 203 runtime.printError(raisedException); 204 return 1; 205 } 206 } else if (je.getJumpType() == JumpException.JumpType.ThrowJump) { 207 return 1; 208 } else { 209 throw je; 210 } 211 } catch(MainExitException e) { 212 if(e.isAborted()) { 213 return e.getStatus(); 214 } else { 215 throw e; 216 } 217 } 218 } 219 220 private void runInterpreter(Ruby runtime, Reader reader, String filename) { 221 try { 222 initializeRuntime(runtime, filename); 223 if(commandline.isYARVEnabled()) { 224 new YARVCompiledRunner(runtime,reader,filename).run(); 225 } else { 226 Node parsedScript = getParsedScript(runtime, reader, filename); 227 if (commandline.isCompilerEnabled()) { 228 runtime.compileAndRun(parsedScript); 229 } else if(commandline.isYARVCompileEnabled()) { 230 runtime.ycompileAndRun(parsedScript); 231 } else { 232 runtime.eval(parsedScript); 233 } 234 } 235 } finally { 236 runtime.tearDown(); 237 } 238 } 239 240 private Node getParsedScript(Ruby runtime, Reader reader, String filename) { 241 Node result = runtime.parse(reader, filename, runtime.getCurrentContext().getCurrentScope()); 243 if (commandline.isAssumePrinting()) { 244 result = new ParserSupport().appendPrintToBlock(result); 245 } 246 if (commandline.isAssumeLoop()) { 247 result = new ParserSupport().appendWhileLoopToBlock(result, commandline.isProcessLineEnds(), commandline.isSplit()); 248 } 249 return result; 250 } 251 252 private void initializeRuntime(final Ruby runtime, String filename) { 253 IRubyObject argumentArray = runtime.newArrayNoCopy(JavaUtil.convertJavaArrayToRuby(runtime, commandline.getScriptArguments())); 254 runtime.setVerbose(runtime.newBoolean(commandline.isVerbose())); 255 runtime.setDebug(runtime.newBoolean(commandline.isDebug())); 256 257 defineGlobalVERBOSE(runtime); 258 defineGlobalDEBUG(runtime); 259 260 runtime.getObject().setConstant("$VERBOSE", 261 commandline.isVerbose() ? runtime.getTrue() : runtime.getNil()); 262 runtime.defineGlobalConstant("ARGV", argumentArray); 263 264 defineGlobal(runtime, "$-p", commandline.isAssumePrinting()); 265 defineGlobal(runtime, "$-n", commandline.isAssumeLoop()); 266 defineGlobal(runtime, "$-a", commandline.isSplit()); 267 defineGlobal(runtime, "$-l", commandline.isProcessLineEnds()); 268 runtime.getGlobalVariables().defineReadonly("$*", new ValueAccessor(argumentArray)); 269 runtime.getGlobalVariables().defineReadonly("$$", new ValueAccessor(runtime.newFixnum(runtime.hashCode()))); 271 272 IAccessor d = new ValueAccessor(runtime.newString(filename)); 273 runtime.getGlobalVariables().define("$PROGRAM_NAME", d); 274 runtime.getGlobalVariables().define("$0", d); 275 276 runtime.getLoadService().init(commandline.loadPaths()); 277 Iterator iter = commandline.requiredLibraries().iterator(); 278 while (iter.hasNext()) { 279 String scriptName = (String ) iter.next(); 280 RubyKernel.require(runtime.getTopSelf(), runtime.newString(scriptName), Block.NULL_BLOCK); 281 } 282 } 283 284 private void defineGlobalVERBOSE(final Ruby runtime) { 285 runtime.getGlobalVariables().define("$VERBOSE", new IAccessor() { 287 public IRubyObject getValue() { 288 return runtime.getVerbose(); 289 } 290 291 public IRubyObject setValue(IRubyObject newValue) { 292 if (newValue.isNil()) { 293 runtime.setVerbose(newValue); 294 } else { 295 runtime.setVerbose(runtime.newBoolean(newValue != runtime.getFalse())); 296 } 297 298 return newValue; 299 } 300 }); 301 } 302 303 private void defineGlobalDEBUG(final Ruby runtime) { 304 IAccessor d = new IAccessor() { 305 public IRubyObject getValue() { 306 return runtime.getDebug(); 307 } 308 309 public IRubyObject setValue(IRubyObject newValue) { 310 if (newValue.isNil()) { 311 runtime.setDebug(newValue); 312 } else { 313 runtime.setDebug(runtime.newBoolean(newValue != runtime.getFalse())); 314 } 315 316 return newValue; 317 } 318 }; 319 runtime.getGlobalVariables().define("$DEBUG", d); 320 runtime.getGlobalVariables().define("$-d", d); 321 } 322 323 private void defineGlobal(Ruby runtime, String name, boolean value) { 324 runtime.getGlobalVariables().defineReadonly(name, new ValueAccessor(value ? runtime.getTrue() : runtime.getNil())); 325 } 326 } 327 | Popular Tags |