0001: /***** BEGIN LICENSE BLOCK *****
0002: * Version: CPL 1.0/GPL 2.0/LGPL 2.1
0003: *
0004: * The contents of this file are subject to the Common Public
0005: * License Version 1.0 (the "License"); you may not use this file
0006: * except in compliance with the License. You may obtain a copy of
0007: * the License at http://www.eclipse.org/legal/cpl-v10.html
0008: *
0009: * Software distributed under the License is distributed on an "AS
0010: * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
0011: * implied. See the License for the specific language governing
0012: * rights and limitations under the License.
0013: *
0014: * Copyright (C) 2001 Chad Fowler <chadfowler@chadfowler.com>
0015: * Copyright (C) 2001 Alan Moore <alan_moore@gmx.net>
0016: * Copyright (C) 2001-2002 Benoit Cerrina <b.cerrina@wanadoo.fr>
0017: * Copyright (C) 2001-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
0018: * Copyright (C) 2002-2006 Thomas E Enebo <enebo@acm.org>
0019: * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
0020: * Copyright (C) 2004-2005 Charles O Nutter <headius@headius.com>
0021: * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
0022: * Copyright (C) 2005 Kiel Hodges <jruby-devel@selfsosoft.com>
0023: * Copyright (C) 2006 Evan Buswell <evan@heron.sytes.net>
0024: * Copyright (C) 2006 Ola Bini <ola@ologix.com>
0025: * Copyright (C) 2006 Michael Studman <codehaus@michaelstudman.com>
0026: * Copyright (C) 2006 Miguel Covarrubias <mlcovarrubias@gmail.com>
0027: * Copyright (C) 2007 Nick Sieger <nicksieger@gmail.com>
0028: *
0029: * Alternatively, the contents of this file may be used under the terms of
0030: * either of the GNU General Public License Version 2 or later (the "GPL"),
0031: * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
0032: * in which case the provisions of the GPL or the LGPL are applicable instead
0033: * of those above. If you wish to allow use of your version of this file only
0034: * under the terms of either the GPL or the LGPL, and not to allow others to
0035: * use your version of this file under the terms of the CPL, indicate your
0036: * decision by deleting the provisions above and replace them with the notice
0037: * and other provisions required by the GPL or the LGPL. If you do not delete
0038: * the provisions above, a recipient may use your version of this file under
0039: * the terms of any one of the CPL, the GPL or the LGPL.
0040: ***** END LICENSE BLOCK *****/package org.jruby;
0041:
0042: import java.io.ByteArrayOutputStream;
0043: import java.io.File;
0044: import java.io.IOException;
0045: import java.math.BigInteger;
0046: import java.util.ArrayList;
0047: import java.util.Calendar;
0048: import java.util.Iterator;
0049:
0050: import org.jruby.ast.util.ArgsUtil;
0051: import org.jruby.exceptions.JumpException;
0052: import org.jruby.exceptions.MainExitException;
0053: import org.jruby.exceptions.RaiseException;
0054: import org.jruby.internal.runtime.methods.DynamicMethod;
0055: import org.jruby.runtime.Arity;
0056: import org.jruby.runtime.Block;
0057: import org.jruby.runtime.CallType;
0058: import org.jruby.runtime.CallbackFactory;
0059: import org.jruby.runtime.MethodIndex;
0060: import org.jruby.runtime.ThreadContext;
0061: import org.jruby.runtime.Visibility;
0062: import org.jruby.runtime.builtin.IRubyObject;
0063: import org.jruby.runtime.load.IAutoloadMethod;
0064: import org.jruby.runtime.load.LoadService;
0065: import org.jruby.util.ShellLauncher;
0066: import org.jruby.util.Sprintf;
0067:
0068: /**
0069: * Note: For CVS history, see KernelModule.java.
0070: *
0071: * @author jpetersen
0072: */
0073: public class RubyKernel {
0074: public final static Class IRUBY_OBJECT = IRubyObject.class;
0075:
0076: public static RubyModule createKernelModule(Ruby runtime) {
0077: RubyModule module = runtime.defineModule("Kernel");
0078: CallbackFactory callbackFactory = runtime
0079: .callbackFactory(RubyKernel.class);
0080: CallbackFactory objectCallbackFactory = runtime
0081: .callbackFactory(RubyObject.class);
0082:
0083: module.defineFastModuleFunction("Array", callbackFactory
0084: .getFastSingletonMethod("new_array", IRUBY_OBJECT));
0085: module.defineFastModuleFunction("Float", callbackFactory
0086: .getFastSingletonMethod("new_float", IRUBY_OBJECT));
0087: module.defineFastModuleFunction("Integer", callbackFactory
0088: .getFastSingletonMethod("new_integer", IRUBY_OBJECT));
0089: module.defineFastModuleFunction("String", callbackFactory
0090: .getFastSingletonMethod("new_string", IRUBY_OBJECT));
0091: module.defineFastModuleFunction("`", callbackFactory
0092: .getFastSingletonMethod("backquote", IRUBY_OBJECT));
0093: module.defineFastModuleFunction("abort", callbackFactory
0094: .getFastOptSingletonMethod("abort"));
0095: module.defineModuleFunction("at_exit", callbackFactory
0096: .getSingletonMethod("at_exit"));
0097: module.defineFastModuleFunction("autoload", callbackFactory
0098: .getFastSingletonMethod("autoload", IRUBY_OBJECT,
0099: IRUBY_OBJECT));
0100: module.defineFastModuleFunction("autoload?", callbackFactory
0101: .getFastSingletonMethod("autoload_p", IRUBY_OBJECT));
0102: module.defineModuleFunction("binding", callbackFactory
0103: .getSingletonMethod("binding"));
0104: module.defineModuleFunction("block_given?", callbackFactory
0105: .getSingletonMethod("block_given"));
0106: module.defineModuleFunction("callcc", callbackFactory
0107: .getOptSingletonMethod("callcc"));
0108: module.defineModuleFunction("caller", callbackFactory
0109: .getOptSingletonMethod("caller"));
0110: module.defineModuleFunction("catch", callbackFactory
0111: .getSingletonMethod("rbCatch", IRUBY_OBJECT));
0112: module.defineFastModuleFunction("chomp", callbackFactory
0113: .getFastOptSingletonMethod("chomp"));
0114: module.defineFastModuleFunction("chomp!", callbackFactory
0115: .getFastOptSingletonMethod("chomp_bang"));
0116: module.defineFastModuleFunction("chop", callbackFactory
0117: .getFastSingletonMethod("chop"));
0118: module.defineFastModuleFunction("chop!", callbackFactory
0119: .getFastSingletonMethod("chop_bang"));
0120: module.defineModuleFunction("eval", callbackFactory
0121: .getOptSingletonMethod("eval"));
0122: module.defineFastModuleFunction("exit", callbackFactory
0123: .getFastOptSingletonMethod("exit"));
0124: module.defineFastModuleFunction("exit!", callbackFactory
0125: .getFastOptSingletonMethod("exit_bang"));
0126: module.defineModuleFunction("fail", callbackFactory
0127: .getOptSingletonMethod("raise"));
0128: // TODO: Implement Kernel#fork
0129: module.defineFastModuleFunction("format", callbackFactory
0130: .getFastOptSingletonMethod("sprintf"));
0131: module.defineFastModuleFunction("gets", callbackFactory
0132: .getFastOptSingletonMethod("gets"));
0133: module.defineFastModuleFunction("global_variables",
0134: callbackFactory
0135: .getFastSingletonMethod("global_variables"));
0136: module.defineModuleFunction("gsub", callbackFactory
0137: .getOptSingletonMethod("gsub"));
0138: module.defineModuleFunction("gsub!", callbackFactory
0139: .getOptSingletonMethod("gsub_bang"));
0140: // TODO: Add deprecation to Kernel#iterator? (maybe formal deprecation mech.)
0141: module.defineModuleFunction("iterator?", callbackFactory
0142: .getSingletonMethod("block_given"));
0143: module.defineModuleFunction("lambda", callbackFactory
0144: .getSingletonMethod("proc"));
0145: module.defineModuleFunction("load", callbackFactory
0146: .getOptSingletonMethod("load"));
0147: module.defineFastModuleFunction("local_variables",
0148: callbackFactory
0149: .getFastSingletonMethod("local_variables"));
0150: module.defineModuleFunction("loop", callbackFactory
0151: .getSingletonMethod("loop"));
0152: // Note: method_missing is documented as being in Object, but ruby appears to stick it in Kernel.
0153: module.defineModuleFunction("method_missing", callbackFactory
0154: .getOptSingletonMethod("method_missing"));
0155: module.defineModuleFunction("open", callbackFactory
0156: .getOptSingletonMethod("open"));
0157: module.defineFastModuleFunction("p", callbackFactory
0158: .getFastOptSingletonMethod("p"));
0159: module.defineFastModuleFunction("print", callbackFactory
0160: .getFastOptSingletonMethod("print"));
0161: module.defineFastModuleFunction("printf", callbackFactory
0162: .getFastOptSingletonMethod("printf"));
0163: module.defineModuleFunction("proc", callbackFactory
0164: .getSingletonMethod("proc"));
0165: // TODO: implement Kernel#putc
0166: module.defineFastModuleFunction("putc", callbackFactory
0167: .getFastSingletonMethod("putc", IRubyObject.class));
0168: module.defineFastModuleFunction("puts", callbackFactory
0169: .getFastOptSingletonMethod("puts"));
0170: module.defineModuleFunction("raise", callbackFactory
0171: .getOptSingletonMethod("raise"));
0172: module.defineFastModuleFunction("rand", callbackFactory
0173: .getFastOptSingletonMethod("rand"));
0174: module.defineFastModuleFunction("readline", callbackFactory
0175: .getFastOptSingletonMethod("readline"));
0176: module.defineFastModuleFunction("readlines", callbackFactory
0177: .getFastOptSingletonMethod("readlines"));
0178: module.defineModuleFunction("require", callbackFactory
0179: .getSingletonMethod("require", IRUBY_OBJECT));
0180: module.defineModuleFunction("scan", callbackFactory
0181: .getSingletonMethod("scan", IRUBY_OBJECT));
0182: module.defineFastModuleFunction("select", callbackFactory
0183: .getFastOptSingletonMethod("select"));
0184: module.defineModuleFunction("set_trace_func", callbackFactory
0185: .getSingletonMethod("set_trace_func", IRUBY_OBJECT));
0186: module.defineModuleFunction("trace_var", callbackFactory
0187: .getOptSingletonMethod("trace_var"));
0188: module.defineModuleFunction("untrace_var", callbackFactory
0189: .getOptSingletonMethod("untrace_var"));
0190: module.defineFastModuleFunction("sleep", callbackFactory
0191: .getFastOptSingletonMethod("sleep"));
0192: module.defineFastModuleFunction("split", callbackFactory
0193: .getFastOptSingletonMethod("split"));
0194: module.defineFastModuleFunction("sprintf", callbackFactory
0195: .getFastOptSingletonMethod("sprintf"));
0196: module.defineFastModuleFunction("srand", callbackFactory
0197: .getFastOptSingletonMethod("srand"));
0198: module.defineModuleFunction("sub", callbackFactory
0199: .getOptSingletonMethod("sub"));
0200: module.defineModuleFunction("sub!", callbackFactory
0201: .getOptSingletonMethod("sub_bang"));
0202: // Skipping: Kernel#syscall (too system dependent)
0203: module.defineFastModuleFunction("system", callbackFactory
0204: .getFastOptSingletonMethod("system"));
0205: // TODO: Implement Kernel#exec differently?
0206: module.defineFastModuleFunction("exec", callbackFactory
0207: .getFastOptSingletonMethod("system"));
0208: module.defineFastModuleFunction("test", callbackFactory
0209: .getFastOptSingletonMethod("test"));
0210: module.defineModuleFunction("throw", callbackFactory
0211: .getOptSingletonMethod("rbThrow"));
0212: // TODO: Implement Kernel#trace_var
0213: module.definePublicModuleFunction("trap", callbackFactory
0214: .getOptSingletonMethod("trap"));
0215: // TODO: Implement Kernel#untrace_var
0216: module.defineFastModuleFunction("warn", callbackFactory
0217: .getFastSingletonMethod("warn", IRUBY_OBJECT));
0218:
0219: // Defined p411 Pickaxe 2nd ed.
0220: module.defineModuleFunction("singleton_method_added",
0221: callbackFactory.getSingletonMethod(
0222: "singleton_method_added", IRUBY_OBJECT));
0223: module.defineModuleFunction("singleton_method_removed",
0224: callbackFactory.getSingletonMethod(
0225: "singleton_method_removed", IRUBY_OBJECT));
0226: module.defineModuleFunction("singleton_method_undefined",
0227: callbackFactory.getSingletonMethod(
0228: "singleton_method_undefined", IRUBY_OBJECT));
0229:
0230: // Object methods
0231: module.defineFastPublicModuleFunction("==",
0232: objectCallbackFactory.getFastMethod("obj_equal",
0233: IRUBY_OBJECT));
0234: module.defineFastPublicModuleFunction("eql?",
0235: objectCallbackFactory.getFastMethod("obj_equal",
0236: IRUBY_OBJECT));
0237: module.defineFastPublicModuleFunction("equal?",
0238: objectCallbackFactory.getFastMethod("obj_equal",
0239: IRUBY_OBJECT));
0240:
0241: module.defineFastPublicModuleFunction("===",
0242: objectCallbackFactory.getFastMethod("equal",
0243: IRUBY_OBJECT));
0244:
0245: module.defineFastPublicModuleFunction("to_s",
0246: objectCallbackFactory.getFastMethod("to_s"));
0247: module.defineFastPublicModuleFunction("nil?",
0248: objectCallbackFactory.getFastMethod("nil_p"));
0249: module.defineFastPublicModuleFunction("to_a", callbackFactory
0250: .getFastSingletonMethod("to_a"));
0251: module.defineFastPublicModuleFunction("hash",
0252: objectCallbackFactory.getFastMethod("hash"));
0253: module.defineFastPublicModuleFunction("id",
0254: objectCallbackFactory.getFastMethod("id_deprecated"));
0255: module.defineFastPublicModuleFunction("object_id",
0256: objectCallbackFactory.getFastMethod("id"));
0257: module.defineAlias("__id__", "object_id");
0258: module.defineFastPublicModuleFunction("is_a?",
0259: objectCallbackFactory.getFastMethod("kind_of",
0260: IRUBY_OBJECT));
0261: module.defineAlias("kind_of?", "is_a?");
0262: module.defineFastPublicModuleFunction("dup",
0263: objectCallbackFactory.getFastMethod("dup"));
0264: module.defineFastPublicModuleFunction("type",
0265: objectCallbackFactory.getFastMethod("type_deprecated"));
0266: module.defineFastPublicModuleFunction("class",
0267: objectCallbackFactory.getFastMethod("type"));
0268: module.defineFastPublicModuleFunction("inspect",
0269: objectCallbackFactory.getFastMethod("inspect"));
0270: module.defineFastPublicModuleFunction("=~",
0271: objectCallbackFactory.getFastMethod("match",
0272: IRUBY_OBJECT));
0273: module.definePublicModuleFunction("clone",
0274: objectCallbackFactory.getMethod("rbClone"));
0275: module.defineFastPublicModuleFunction("display",
0276: objectCallbackFactory.getFastOptMethod("display"));
0277: module.defineFastPublicModuleFunction("extend",
0278: objectCallbackFactory.getFastOptMethod("extend"));
0279: module.defineFastPublicModuleFunction("freeze",
0280: objectCallbackFactory.getFastMethod("freeze"));
0281: module.defineFastPublicModuleFunction("frozen?",
0282: objectCallbackFactory.getFastMethod("frozen"));
0283: module.defineFastModuleFunction("initialize_copy",
0284: objectCallbackFactory.getFastMethod("initialize_copy",
0285: IRUBY_OBJECT));
0286: module.definePublicModuleFunction("instance_eval",
0287: objectCallbackFactory.getOptMethod("instance_eval"));
0288: module.definePublicModuleFunction("instance_exec",
0289: objectCallbackFactory.getOptMethod("instance_exec"));
0290: module.defineFastPublicModuleFunction("instance_of?",
0291: objectCallbackFactory.getFastMethod("instance_of",
0292: IRUBY_OBJECT));
0293: module.defineFastPublicModuleFunction("instance_variables",
0294: objectCallbackFactory
0295: .getFastMethod("instance_variables"));
0296: module.defineFastPublicModuleFunction("instance_variable_get",
0297: objectCallbackFactory.getFastMethod(
0298: "instance_variable_get", IRUBY_OBJECT));
0299: module.defineFastPublicModuleFunction("instance_variable_set",
0300: objectCallbackFactory.getFastMethod(
0301: "instance_variable_set", IRUBY_OBJECT,
0302: IRUBY_OBJECT));
0303: module.defineFastPublicModuleFunction("method",
0304: objectCallbackFactory.getFastMethod("method",
0305: IRUBY_OBJECT));
0306: module.defineFastPublicModuleFunction("methods",
0307: objectCallbackFactory.getFastOptMethod("methods"));
0308: module.defineFastPublicModuleFunction("private_methods",
0309: objectCallbackFactory
0310: .getFastOptMethod("private_methods"));
0311: module.defineFastPublicModuleFunction("protected_methods",
0312: objectCallbackFactory
0313: .getFastOptMethod("protected_methods"));
0314: module.defineFastPublicModuleFunction("public_methods",
0315: objectCallbackFactory
0316: .getFastOptMethod("public_methods"));
0317: module.defineFastModuleFunction("remove_instance_variable",
0318: objectCallbackFactory.getMethod(
0319: "remove_instance_variable", IRUBY_OBJECT));
0320: module.defineFastPublicModuleFunction("respond_to?",
0321: objectCallbackFactory.getFastOptMethod("respond_to"));
0322: module.definePublicModuleFunction("send", objectCallbackFactory
0323: .getOptMethod("send"));
0324: module.defineAlias("__send__", "send");
0325: module.defineFastPublicModuleFunction("singleton_methods",
0326: objectCallbackFactory
0327: .getFastOptMethod("singleton_methods"));
0328: module.defineFastPublicModuleFunction("taint",
0329: objectCallbackFactory.getFastMethod("taint"));
0330: module.defineFastPublicModuleFunction("tainted?",
0331: objectCallbackFactory.getFastMethod("tainted"));
0332: module.defineFastPublicModuleFunction("untaint",
0333: objectCallbackFactory.getFastMethod("untaint"));
0334:
0335: runtime.setRespondToMethod(module.searchMethod("respond_to?"));
0336:
0337: return module;
0338: }
0339:
0340: public static IRubyObject at_exit(IRubyObject recv, Block block) {
0341: return recv.getRuntime().pushExitBlock(
0342: recv.getRuntime().newProc(false, block));
0343: }
0344:
0345: public static IRubyObject autoload_p(final IRubyObject recv,
0346: IRubyObject symbol) {
0347: RubyModule module = recv instanceof RubyModule ? (RubyModule) recv
0348: : recv.getRuntime().getObject();
0349: String name = module.getName() + "::" + symbol.asSymbol();
0350:
0351: IAutoloadMethod autoloadMethod = recv.getRuntime()
0352: .getLoadService().autoloadFor(name);
0353: if (autoloadMethod == null)
0354: return recv.getRuntime().getNil();
0355:
0356: return recv.getRuntime().newString(autoloadMethod.file());
0357: }
0358:
0359: public static IRubyObject autoload(final IRubyObject recv,
0360: IRubyObject symbol, final IRubyObject file) {
0361: Ruby runtime = recv.getRuntime();
0362: final LoadService loadService = runtime.getLoadService();
0363: final String baseName = symbol.asSymbol();
0364: final RubyModule module = recv instanceof RubyModule ? (RubyModule) recv
0365: : runtime.getObject();
0366: String nm = module.getName() + "::" + baseName;
0367:
0368: IRubyObject undef = runtime.getUndef();
0369: IRubyObject existingValue = module
0370: .getInstanceVariable(baseName);
0371: if (existingValue != null && existingValue != undef)
0372: return runtime.getNil();
0373:
0374: module.setInstanceVariable(baseName, undef);
0375:
0376: loadService.addAutoload(nm, new IAutoloadMethod() {
0377: public String file() {
0378: return file.toString();
0379: }
0380:
0381: /**
0382: * @see org.jruby.runtime.load.IAutoloadMethod#load(Ruby, String)
0383: */
0384: public IRubyObject load(Ruby runtime, String name) {
0385: boolean required = loadService.require(file.toString());
0386:
0387: // File to be loaded by autoload has already been or is being loaded.
0388: if (!required)
0389: return null;
0390:
0391: return module.getConstant(baseName);
0392: }
0393: });
0394: return runtime.getNil();
0395: }
0396:
0397: public static IRubyObject method_missing(IRubyObject recv,
0398: IRubyObject[] args, Block block) {
0399: Ruby runtime = recv.getRuntime();
0400:
0401: if (args.length == 0 || !(args[0] instanceof RubySymbol))
0402: throw runtime.newArgumentError("no id given");
0403:
0404: String name = args[0].asSymbol();
0405: ThreadContext context = runtime.getCurrentContext();
0406: Visibility lastVis = context.getLastVisibility();
0407: CallType lastCallType = context.getLastCallType();
0408:
0409: String format = null;
0410:
0411: boolean noMethod = true; // NoMethodError
0412:
0413: if (lastVis == Visibility.PRIVATE) {
0414: format = "private method `%s' called for %s";
0415: } else if (lastVis == Visibility.PROTECTED) {
0416: format = "protected method `%s' called for %s";
0417: } else if (lastCallType == CallType.VARIABLE) {
0418: format = "undefined local variable or method `%s' for %s";
0419: noMethod = false; // NameError
0420: } else if (lastCallType == CallType.SUPER) {
0421: format = "super: no superclass method `%s'";
0422: }
0423:
0424: if (format == null)
0425: format = "undefined method `%s' for %s";
0426:
0427: String description = null;
0428:
0429: if (recv.isNil()) {
0430: description = "nil";
0431: } else if (recv instanceof RubyBoolean && recv.isTrue()) {
0432: description = "true";
0433: } else if (recv instanceof RubyBoolean && !recv.isTrue()) {
0434: description = "false";
0435: } else {
0436: if (name.equals("inspect") || name.equals("to_s")) {
0437: description = recv.anyToString().toString();
0438: } else {
0439: IRubyObject d;
0440: try {
0441: d = recv.callMethod(context, "inspect");
0442: if (d.getMetaClass() == recv.getMetaClass()
0443: || (d instanceof RubyString && ((RubyString) d)
0444: .length().getLongValue() > 65)) {
0445: d = recv.anyToString();
0446: }
0447: } catch (JumpException je) {
0448: d = recv.anyToString();
0449: }
0450: description = d.toString();
0451: }
0452: }
0453: if (description.length() == 0
0454: || (description.length() > 0 && description.charAt(0) != '#')) {
0455: description = description + ":"
0456: + recv.getMetaClass().getRealClass().getName();
0457: }
0458:
0459: IRubyObject[] exArgs = new IRubyObject[noMethod ? 3 : 2];
0460:
0461: RubyArray arr = runtime.newArray(args[0], runtime
0462: .newString(description));
0463: RubyString msg = runtime.newString(Sprintf.sprintf(
0464: runtime.newString(format), arr).toString());
0465:
0466: if (recv.isTaint())
0467: msg.setTaint(true);
0468:
0469: exArgs[0] = msg;
0470: exArgs[1] = args[0];
0471:
0472: RubyClass exc;
0473: if (noMethod) {
0474: IRubyObject[] NMEArgs = new IRubyObject[args.length - 1];
0475: System.arraycopy(args, 1, NMEArgs, 0, NMEArgs.length);
0476: exArgs[2] = runtime.newArrayNoCopy(NMEArgs);
0477: exc = runtime.getClass("NoMethodError");
0478: } else {
0479: exc = runtime.getClass("NameError");
0480: }
0481:
0482: throw new RaiseException((RubyException) exc.newInstance(
0483: exArgs, Block.NULL_BLOCK));
0484: }
0485:
0486: public static IRubyObject open(IRubyObject recv,
0487: IRubyObject[] args, Block block) {
0488: Arity.checkArgumentCount(recv.getRuntime(), args, 1, 3);
0489: String arg = args[0].convertToString().toString();
0490: Ruby runtime = recv.getRuntime();
0491:
0492: if (arg.startsWith("|")) {
0493: String command = arg.substring(1);
0494: // exec process, create IO with process
0495: try {
0496: Process p = new ShellLauncher(runtime).run(RubyString
0497: .newString(runtime, command));
0498: RubyIO io = new RubyIO(runtime, p);
0499:
0500: if (block.isGiven()) {
0501: try {
0502: block.yield(recv.getRuntime()
0503: .getCurrentContext(), io);
0504: return runtime.getNil();
0505: } finally {
0506: io.close();
0507: }
0508: }
0509:
0510: return io;
0511: } catch (IOException ioe) {
0512: throw runtime.newIOErrorFromException(ioe);
0513: }
0514: }
0515:
0516: return RubyFile.open(runtime.getClass("File"), args, block);
0517: }
0518:
0519: public static IRubyObject gets(IRubyObject recv, IRubyObject[] args) {
0520: return ((RubyArgsFile) recv.getRuntime().getGlobalVariables()
0521: .get("$<")).gets(args);
0522: }
0523:
0524: public static IRubyObject abort(IRubyObject recv, IRubyObject[] args) {
0525: if (Arity.checkArgumentCount(recv.getRuntime(), args, 0, 1) == 1) {
0526: recv.getRuntime().getGlobalVariables().get("$stderr")
0527: .callMethod(recv.getRuntime().getCurrentContext(),
0528: "puts", args[0]);
0529: }
0530: throw new MainExitException(1, true);
0531: }
0532:
0533: public static IRubyObject new_array(IRubyObject recv,
0534: IRubyObject object) {
0535: IRubyObject value = object.convertToType(recv.getRuntime()
0536: .getArray(), MethodIndex.TO_ARY, "to_ary", false, true,
0537: true);
0538:
0539: if (value.isNil()) {
0540: DynamicMethod method = object.getMetaClass().searchMethod(
0541: "to_a");
0542:
0543: if (method.getImplementationClass() == recv.getRuntime()
0544: .getKernel()) {
0545: return recv.getRuntime().newArray(object);
0546: }
0547:
0548: // Strange that Ruby has custom code here and not convertToTypeWithCheck equivalent.
0549: value = object.callMethod(recv.getRuntime()
0550: .getCurrentContext(), MethodIndex.TO_A, "to_a");
0551: if (value.getMetaClass() != recv.getRuntime().getClass(
0552: "Array")) {
0553: throw recv.getRuntime().newTypeError(
0554: "`to_a' did not return Array");
0555:
0556: }
0557: }
0558:
0559: return value;
0560: }
0561:
0562: public static IRubyObject new_float(IRubyObject recv,
0563: IRubyObject object) {
0564: if (object instanceof RubyFixnum) {
0565: return RubyFloat.newFloat(object.getRuntime(),
0566: ((RubyFixnum) object).getDoubleValue());
0567: } else if (object instanceof RubyFloat) {
0568: return object;
0569: } else if (object instanceof RubyBignum) {
0570: return RubyFloat.newFloat(object.getRuntime(), RubyBignum
0571: .big2dbl((RubyBignum) object));
0572: } else if (object instanceof RubyString) {
0573: if (((RubyString) object).getValue().length() == 0) { // rb_cstr_to_dbl case
0574: throw recv.getRuntime().newArgumentError(
0575: "invalid value for Float(): "
0576: + object.inspect());
0577: }
0578: return RubyNumeric.str2fnum(recv.getRuntime(),
0579: (RubyString) object, true);
0580: } else if (object.isNil()) {
0581: throw recv.getRuntime().newTypeError(
0582: "can't convert nil into Float");
0583: } else {
0584: RubyFloat rFloat = object.convertToFloat();
0585: if (Double.isNaN(rFloat.getDoubleValue())) {
0586: recv.getRuntime().newArgumentError(
0587: "invalid value for Float()");
0588: }
0589: return rFloat;
0590: }
0591: }
0592:
0593: public static IRubyObject new_integer(IRubyObject recv,
0594: IRubyObject object) {
0595: if (object instanceof RubyFloat) {
0596: double val = ((RubyFloat) object).getDoubleValue();
0597: if (val <= (double) RubyFixnum.MAX
0598: && val >= (double) RubyFixnum.MIN) {
0599: IRubyObject tmp = ((RubyObject) object).convertToType(
0600: recv.getRuntime().getClass("Integer"),
0601: MethodIndex.TO_INT, "to_int", false);
0602: if (tmp.isNil())
0603: return ((RubyObject) object).convertToType(recv
0604: .getRuntime().getClass("Integer"),
0605: MethodIndex.TO_I, "to_i", true);
0606: return tmp;
0607: }
0608: return RubyNumeric.dbl2num(recv.getRuntime(),
0609: ((RubyFloat) object).getDoubleValue());
0610: } else if (object instanceof RubyFixnum
0611: || object instanceof RubyBignum) {
0612: return object;
0613: } else if (object instanceof RubyString) {
0614: return RubyNumeric.str2inum(recv.getRuntime(),
0615: (RubyString) object, 0, true);
0616: }
0617:
0618: IRubyObject tmp = ((RubyObject) object).convertToType(recv
0619: .getRuntime().getClass("Integer"), MethodIndex.TO_INT,
0620: "to_int", false);
0621: if (tmp.isNil())
0622: return ((RubyObject) object).convertToType(recv
0623: .getRuntime().getClass("Integer"),
0624: MethodIndex.TO_I, "to_i", true);
0625: return tmp;
0626: }
0627:
0628: public static IRubyObject new_string(IRubyObject recv,
0629: IRubyObject object) {
0630: return object.callMethod(recv.getRuntime().getCurrentContext(),
0631: MethodIndex.TO_S, "to_s");
0632: }
0633:
0634: public static IRubyObject p(IRubyObject recv, IRubyObject[] args) {
0635: IRubyObject defout = recv.getRuntime().getGlobalVariables()
0636: .get("$>");
0637: ThreadContext context = recv.getRuntime().getCurrentContext();
0638:
0639: for (int i = 0; i < args.length; i++) {
0640: if (args[i] != null) {
0641: defout.callMethod(context, "write", args[i].callMethod(
0642: context, "inspect"));
0643: defout.callMethod(context, "write", recv.getRuntime()
0644: .newString("\n"));
0645: }
0646: }
0647: return recv.getRuntime().getNil();
0648: }
0649:
0650: /** rb_f_putc
0651: */
0652: public static IRubyObject putc(IRubyObject recv, IRubyObject ch) {
0653: IRubyObject defout = recv.getRuntime().getGlobalVariables()
0654: .get("$>");
0655: return defout.callMethod(recv.getRuntime().getCurrentContext(),
0656: "putc", ch);
0657: }
0658:
0659: public static IRubyObject puts(IRubyObject recv, IRubyObject[] args) {
0660: IRubyObject defout = recv.getRuntime().getGlobalVariables()
0661: .get("$>");
0662: ThreadContext context = recv.getRuntime().getCurrentContext();
0663:
0664: defout.callMethod(context, "puts", args);
0665:
0666: return recv.getRuntime().getNil();
0667: }
0668:
0669: public static IRubyObject print(IRubyObject recv, IRubyObject[] args) {
0670: IRubyObject defout = recv.getRuntime().getGlobalVariables()
0671: .get("$>");
0672: ThreadContext context = recv.getRuntime().getCurrentContext();
0673:
0674: defout.callMethod(context, "print", args);
0675:
0676: return recv.getRuntime().getNil();
0677: }
0678:
0679: public static IRubyObject printf(IRubyObject recv,
0680: IRubyObject[] args) {
0681: if (args.length != 0) {
0682: IRubyObject defout = recv.getRuntime().getGlobalVariables()
0683: .get("$>");
0684:
0685: if (!(args[0] instanceof RubyString)) {
0686: defout = args[0];
0687: args = ArgsUtil.popArray(args);
0688: }
0689:
0690: ThreadContext context = recv.getRuntime()
0691: .getCurrentContext();
0692:
0693: defout.callMethod(context, "write", RubyKernel.sprintf(
0694: recv, args));
0695: }
0696:
0697: return recv.getRuntime().getNil();
0698: }
0699:
0700: public static IRubyObject readline(IRubyObject recv,
0701: IRubyObject[] args) {
0702: IRubyObject line = gets(recv, args);
0703:
0704: if (line.isNil()) {
0705: throw recv.getRuntime().newEOFError();
0706: }
0707:
0708: return line;
0709: }
0710:
0711: public static RubyArray readlines(IRubyObject recv,
0712: IRubyObject[] args) {
0713: return ((RubyArgsFile) recv.getRuntime().getGlobalVariables()
0714: .get("$<")).readlines(args);
0715: }
0716:
0717: /** Returns value of $_.
0718: *
0719: * @throws TypeError if $_ is not a String or nil.
0720: * @return value of $_ as String.
0721: */
0722: private static RubyString getLastlineString(Ruby runtime) {
0723: IRubyObject line = runtime.getCurrentContext().getLastline();
0724:
0725: if (line.isNil()) {
0726: throw runtime
0727: .newTypeError("$_ value need to be String (nil given).");
0728: } else if (!(line instanceof RubyString)) {
0729: throw runtime.newTypeError("$_ value need to be String ("
0730: + line.getMetaClass().getName() + " given).");
0731: } else {
0732: return (RubyString) line;
0733: }
0734: }
0735:
0736: public static IRubyObject sub_bang(IRubyObject recv,
0737: IRubyObject[] args, Block block) {
0738: return getLastlineString(recv.getRuntime()).sub_bang(args,
0739: block);
0740: }
0741:
0742: public static IRubyObject sub(IRubyObject recv, IRubyObject[] args,
0743: Block block) {
0744: RubyString str = (RubyString) getLastlineString(
0745: recv.getRuntime()).dup();
0746:
0747: if (!str.sub_bang(args, block).isNil()) {
0748: recv.getRuntime().getCurrentContext().setLastline(str);
0749: }
0750:
0751: return str;
0752: }
0753:
0754: public static IRubyObject gsub_bang(IRubyObject recv,
0755: IRubyObject[] args, Block block) {
0756: return getLastlineString(recv.getRuntime()).gsub_bang(args,
0757: block);
0758: }
0759:
0760: public static IRubyObject gsub(IRubyObject recv,
0761: IRubyObject[] args, Block block) {
0762: RubyString str = (RubyString) getLastlineString(
0763: recv.getRuntime()).dup();
0764:
0765: if (!str.gsub_bang(args, block).isNil()) {
0766: recv.getRuntime().getCurrentContext().setLastline(str);
0767: }
0768:
0769: return str;
0770: }
0771:
0772: public static IRubyObject chop_bang(IRubyObject recv) {
0773: return getLastlineString(recv.getRuntime()).chop_bang();
0774: }
0775:
0776: public static IRubyObject chop(IRubyObject recv) {
0777: RubyString str = getLastlineString(recv.getRuntime());
0778:
0779: if (str.getValue().length() > 0) {
0780: str = (RubyString) str.dup();
0781: str.chop_bang();
0782: recv.getRuntime().getCurrentContext().setLastline(str);
0783: }
0784:
0785: return str;
0786: }
0787:
0788: public static IRubyObject chomp_bang(IRubyObject recv,
0789: IRubyObject[] args) {
0790: return getLastlineString(recv.getRuntime()).chomp_bang(args);
0791: }
0792:
0793: public static IRubyObject chomp(IRubyObject recv, IRubyObject[] args) {
0794: RubyString str = getLastlineString(recv.getRuntime());
0795: RubyString dup = (RubyString) str.dup();
0796:
0797: if (dup.chomp_bang(args).isNil()) {
0798: return str;
0799: }
0800:
0801: recv.getRuntime().getCurrentContext().setLastline(dup);
0802: return dup;
0803: }
0804:
0805: public static IRubyObject split(IRubyObject recv, IRubyObject[] args) {
0806: return getLastlineString(recv.getRuntime()).split(args);
0807: }
0808:
0809: public static IRubyObject scan(IRubyObject recv,
0810: IRubyObject pattern, Block block) {
0811: return getLastlineString(recv.getRuntime())
0812: .scan(pattern, block);
0813: }
0814:
0815: public static IRubyObject select(IRubyObject recv,
0816: IRubyObject[] args) {
0817: return RubyIO.select_static(recv.getRuntime(), args);
0818: }
0819:
0820: public static IRubyObject sleep(IRubyObject recv, IRubyObject[] args) {
0821: long milliseconds;
0822:
0823: if (args.length == 0) {
0824: // Zero sleeps forever
0825: milliseconds = 0;
0826: } else {
0827: milliseconds = (long) (args[0].convertToFloat()
0828: .getDoubleValue() * 1000);
0829: if (milliseconds < 0) {
0830: throw recv.getRuntime().newArgumentError(
0831: "time interval must be positive");
0832: } else if (milliseconds == 0) {
0833: // Explicit zero in MRI returns immediately
0834: return recv.getRuntime().newFixnum(0);
0835: }
0836: }
0837: long startTime = System.currentTimeMillis();
0838:
0839: RubyThread rubyThread = recv.getRuntime().getThreadService()
0840: .getCurrentContext().getThread();
0841:
0842: while (milliseconds > 0) {
0843: long loopStartTime = System.currentTimeMillis();
0844: try {
0845: rubyThread.sleep(milliseconds);
0846: } catch (InterruptedException iExcptn) {
0847: }
0848: milliseconds -= (System.currentTimeMillis() - loopStartTime);
0849: }
0850:
0851: return recv
0852: .getRuntime()
0853: .newFixnum(
0854: Math
0855: .round((System.currentTimeMillis() - startTime) / 1000.0));
0856: }
0857:
0858: // FIXME: Add at_exit and finalizers to exit, then make exit_bang not call those.
0859: public static IRubyObject exit(IRubyObject recv, IRubyObject[] args) {
0860: recv.getRuntime().secure(4);
0861:
0862: int status = 1;
0863: if (args.length > 0) {
0864: RubyObject argument = (RubyObject) args[0];
0865: if (argument instanceof RubyFixnum) {
0866: status = RubyNumeric.fix2int(argument);
0867: } else {
0868: status = argument.isFalse() ? 1 : 0;
0869: }
0870: }
0871:
0872: throw recv.getRuntime().newSystemExit(status);
0873: }
0874:
0875: public static IRubyObject exit_bang(IRubyObject recv,
0876: IRubyObject[] args) {
0877: return exit(recv, args);
0878: }
0879:
0880: /** Returns an Array with the names of all global variables.
0881: *
0882: */
0883: public static RubyArray global_variables(IRubyObject recv) {
0884: RubyArray globalVariables = recv.getRuntime().newArray();
0885:
0886: Iterator iter = recv.getRuntime().getGlobalVariables()
0887: .getNames();
0888: while (iter.hasNext()) {
0889: String globalVariableName = (String) iter.next();
0890:
0891: globalVariables.append(recv.getRuntime().newString(
0892: globalVariableName));
0893: }
0894:
0895: return globalVariables;
0896: }
0897:
0898: /** Returns an Array with the names of all local variables.
0899: *
0900: */
0901: public static RubyArray local_variables(IRubyObject recv) {
0902: final Ruby runtime = recv.getRuntime();
0903: RubyArray localVariables = runtime.newArray();
0904:
0905: String[] names = runtime.getCurrentContext().getCurrentScope()
0906: .getAllNamesInScope();
0907: for (int i = 0; i < names.length; i++) {
0908: localVariables.append(runtime.newString(names[i]));
0909: }
0910:
0911: return localVariables;
0912: }
0913:
0914: public static RubyBinding binding(IRubyObject recv, Block block) {
0915: // FIXME: Pass block into binding
0916: return recv.getRuntime().newBinding();
0917: }
0918:
0919: public static RubyBoolean block_given(IRubyObject recv, Block block) {
0920: return recv.getRuntime().newBoolean(
0921: recv.getRuntime().getCurrentContext()
0922: .getPreviousFrame().getBlock().isGiven());
0923: }
0924:
0925: public static IRubyObject sprintf(IRubyObject recv,
0926: IRubyObject[] args) {
0927: if (args.length == 0) {
0928: throw recv.getRuntime().newArgumentError(
0929: "sprintf must have at least one argument");
0930: }
0931:
0932: RubyString str = RubyString.stringValue(args[0]);
0933:
0934: RubyArray newArgs = recv.getRuntime().newArrayNoCopy(args);
0935: newArgs.shift();
0936:
0937: return str.format(newArgs);
0938: }
0939:
0940: public static IRubyObject raise(IRubyObject recv,
0941: IRubyObject[] args, Block block) {
0942: // FIXME: Pass block down?
0943: Arity.checkArgumentCount(recv.getRuntime(), args, 0, 3);
0944: Ruby runtime = recv.getRuntime();
0945:
0946: if (args.length == 0) {
0947: IRubyObject lastException = runtime.getGlobalVariables()
0948: .get("$!");
0949: if (lastException.isNil()) {
0950: throw new RaiseException(runtime, runtime
0951: .getClass("RuntimeError"), "", false);
0952: }
0953: throw new RaiseException((RubyException) lastException);
0954: }
0955:
0956: IRubyObject exception;
0957: ThreadContext context = recv.getRuntime().getCurrentContext();
0958:
0959: if (args.length == 1) {
0960: if (args[0] instanceof RubyString) {
0961: throw new RaiseException((RubyException) runtime
0962: .getClass("RuntimeError").newInstance(args,
0963: block));
0964: }
0965:
0966: if (!args[0].respondsTo("exception")) {
0967: throw runtime
0968: .newTypeError("exception class/object expected");
0969: }
0970: exception = args[0].callMethod(context, "exception");
0971: } else {
0972: if (!args[0].respondsTo("exception")) {
0973: throw runtime
0974: .newTypeError("exception class/object expected");
0975: }
0976:
0977: exception = args[0].callMethod(context, "exception",
0978: args[1]);
0979: }
0980:
0981: if (!exception.isKindOf(runtime.getClass("Exception"))) {
0982: throw runtime.newTypeError("exception object expected");
0983: }
0984:
0985: if (args.length == 3) {
0986: ((RubyException) exception).set_backtrace(args[2]);
0987: }
0988:
0989: throw new RaiseException((RubyException) exception);
0990: }
0991:
0992: /**
0993: * Require.
0994: * MRI allows to require ever .rb files or ruby extension dll (.so or .dll depending on system).
0995: * we allow requiring either .rb files or jars.
0996: * @param recv ruby object used to call require (any object will do and it won't be used anyway).
0997: * @param name the name of the file to require
0998: **/
0999: public static IRubyObject require(IRubyObject recv,
1000: IRubyObject name, Block block) {
1001: if (recv.getRuntime().getLoadService().require(name.toString())) {
1002: return recv.getRuntime().getTrue();
1003: }
1004: return recv.getRuntime().getFalse();
1005: }
1006:
1007: public static IRubyObject load(IRubyObject recv,
1008: IRubyObject[] args, Block block) {
1009: RubyString file = args[0].convertToString();
1010: recv.getRuntime().getLoadService().load(file.toString());
1011: return recv.getRuntime().getTrue();
1012: }
1013:
1014: public static IRubyObject eval(IRubyObject recv,
1015: IRubyObject[] args, Block block) {
1016: if (args == null || args.length == 0) {
1017: throw recv.getRuntime().newArgumentError(args.length, 1);
1018: }
1019:
1020: RubyString src = args[0].convertToString();
1021: IRubyObject scope = null;
1022: String file = "(eval)";
1023:
1024: if (args.length > 1) {
1025: if (!args[1].isNil()) {
1026: scope = args[1];
1027: }
1028:
1029: if (args.length > 2) {
1030: file = args[2].toString();
1031: }
1032: }
1033:
1034: int line = args.length > 3 ? RubyNumeric.fix2int(args[3]) - 1
1035: : 1;
1036:
1037: recv.getRuntime().checkSafeString(src);
1038: ThreadContext context = recv.getRuntime().getCurrentContext();
1039:
1040: if (scope == null) {
1041: scope = RubyBinding.newBindingForEval(recv.getRuntime());
1042: }
1043:
1044: return recv.evalWithBinding(context, src, scope, file, line);
1045: }
1046:
1047: public static IRubyObject callcc(IRubyObject recv,
1048: IRubyObject[] args, Block block) {
1049: Ruby runtime = recv.getRuntime();
1050: runtime
1051: .getWarnings()
1052: .warn(
1053: "Kernel#callcc: Continuations are not implemented in JRuby and will not work");
1054: IRubyObject cc = runtime.getClass("Continuation").callMethod(
1055: runtime.getCurrentContext(), "new");
1056: cc.dataWrapStruct(block);
1057: return block.yield(runtime.getCurrentContext(), cc);
1058: }
1059:
1060: public static IRubyObject caller(IRubyObject recv,
1061: IRubyObject[] args, Block block) {
1062: int level = args.length > 0 ? RubyNumeric.fix2int(args[0]) : 1;
1063:
1064: if (level < 0) {
1065: throw recv.getRuntime().newArgumentError(
1066: "negative level(" + level + ')');
1067: }
1068:
1069: return ThreadContext.createBacktraceFromFrames(recv
1070: .getRuntime(), recv.getRuntime().getCurrentContext()
1071: .createBacktrace(level, false));
1072: }
1073:
1074: public static IRubyObject rbCatch(IRubyObject recv,
1075: IRubyObject tag, Block block) {
1076: ThreadContext context = recv.getRuntime().getCurrentContext();
1077: try {
1078: context.pushCatch(tag.asSymbol());
1079: return block.yield(context, tag);
1080: } catch (JumpException je) {
1081: if (je.getJumpType() == JumpException.JumpType.ThrowJump
1082: && je.getTarget().equals(tag.asSymbol())) {
1083: return (IRubyObject) je.getValue();
1084: }
1085: throw je;
1086: } finally {
1087: context.popCatch();
1088: }
1089: }
1090:
1091: public static IRubyObject rbThrow(IRubyObject recv,
1092: IRubyObject[] args, Block block) {
1093: Ruby runtime = recv.getRuntime();
1094:
1095: String tag = args[0].asSymbol();
1096: ThreadContext context = runtime.getCurrentContext();
1097: String[] catches = context.getActiveCatches();
1098:
1099: String message = "uncaught throw `" + tag + "'";
1100:
1101: //Ordering of array traversal not important, just intuitive
1102: for (int i = catches.length - 1; i >= 0; i--) {
1103: if (tag.equals(catches[i])) {
1104: //Catch active, throw for catch to handle
1105: throw context.prepareJumpException(
1106: JumpException.JumpType.ThrowJump, tag,
1107: args.length > 1 ? args[1] : runtime.getNil());
1108: }
1109: }
1110:
1111: //No catch active for this throw
1112: throw runtime.newNameError(message, tag);
1113: }
1114:
1115: public static IRubyObject trap(IRubyObject recv,
1116: IRubyObject[] args, Block block) {
1117: recv.getRuntime().getLoadService().require("jsignal");
1118: return recv.callMethod(recv.getRuntime().getCurrentContext(),
1119: "trap", args, CallType.FUNCTIONAL, block);
1120: }
1121:
1122: public static IRubyObject warn(IRubyObject recv, IRubyObject message) {
1123: Ruby runtime = recv.getRuntime();
1124: IRubyObject out = runtime.getObject().getConstant("STDERR");
1125: RubyIO io = (RubyIO) out.convertToType(runtime.getClass("IO"),
1126: 0, "to_io", true);
1127:
1128: io.puts(new IRubyObject[] { message });
1129: return recv.getRuntime().getNil();
1130: }
1131:
1132: public static IRubyObject set_trace_func(IRubyObject recv,
1133: IRubyObject trace_func, Block block) {
1134: if (trace_func.isNil()) {
1135: recv.getRuntime().setTraceFunction(null);
1136: } else if (!(trace_func instanceof RubyProc)) {
1137: throw recv.getRuntime().newTypeError(
1138: "trace_func needs to be Proc.");
1139: } else {
1140: recv.getRuntime().setTraceFunction((RubyProc) trace_func);
1141: }
1142: return trace_func;
1143: }
1144:
1145: public static IRubyObject trace_var(IRubyObject recv,
1146: IRubyObject[] args, Block block) {
1147: if (args.length == 0)
1148: throw recv.getRuntime().newArgumentError(0, 1);
1149: RubyProc proc = null;
1150: String var = null;
1151:
1152: if (args.length > 1) {
1153: var = args[0].toString();
1154: }
1155:
1156: if (var.charAt(0) != '$') {
1157: // ignore if it's not a global var
1158: return recv.getRuntime().getNil();
1159: }
1160:
1161: if (args.length == 1) {
1162: proc = RubyProc.newProc(recv.getRuntime(), block, false);
1163: }
1164: if (args.length == 2) {
1165: proc = (RubyProc) args[1].convertToType(recv.getRuntime()
1166: .getClass("Proc"), 0, "to_proc", true);
1167: }
1168:
1169: recv.getRuntime().getGlobalVariables().setTraceVar(var, proc);
1170:
1171: return recv.getRuntime().getNil();
1172: }
1173:
1174: public static IRubyObject untrace_var(IRubyObject recv,
1175: IRubyObject[] args, Block block) {
1176: if (args.length == 0)
1177: throw recv.getRuntime().newArgumentError(0, 1);
1178: String var = null;
1179:
1180: if (args.length >= 1) {
1181: var = args[0].toString();
1182: }
1183:
1184: if (var.charAt(0) != '$') {
1185: // ignore if it's not a global var
1186: return recv.getRuntime().getNil();
1187: }
1188:
1189: if (args.length > 1) {
1190: ArrayList success = new ArrayList();
1191: for (int i = 1; i < args.length; i++) {
1192: if (recv.getRuntime().getGlobalVariables().untraceVar(
1193: var, args[i])) {
1194: success.add(args[i]);
1195: }
1196: }
1197: return RubyArray.newArray(recv.getRuntime(), success);
1198: } else {
1199: recv.getRuntime().getGlobalVariables().untraceVar(var);
1200: }
1201:
1202: return recv.getRuntime().getNil();
1203: }
1204:
1205: public static IRubyObject singleton_method_added(IRubyObject recv,
1206: IRubyObject symbolId, Block block) {
1207: return recv.getRuntime().getNil();
1208: }
1209:
1210: public static IRubyObject singleton_method_removed(
1211: IRubyObject recv, IRubyObject symbolId, Block block) {
1212: return recv.getRuntime().getNil();
1213: }
1214:
1215: public static IRubyObject singleton_method_undefined(
1216: IRubyObject recv, IRubyObject symbolId, Block block) {
1217: return recv.getRuntime().getNil();
1218: }
1219:
1220: public static RubyProc proc(IRubyObject recv, Block block) {
1221: return recv.getRuntime().newProc(true, block);
1222: }
1223:
1224: public static IRubyObject loop(IRubyObject recv, Block block) {
1225: ThreadContext context = recv.getRuntime().getCurrentContext();
1226: while (true) {
1227: try {
1228: block.yield(context, recv.getRuntime().getNil());
1229:
1230: context.pollThreadEvents();
1231: } catch (JumpException je) {
1232: // JRUBY-530, specifically the Kernel#loop case:
1233: // Kernel#loop always takes a block. But what we're looking
1234: // for here is breaking an iteration where the block is one
1235: // used inside loop's block, not loop's block itself. Set the
1236: // appropriate flag on the JumpException if this is the case
1237: // (the FCALLNODE case in EvaluationState will deal with it)
1238: if (je.getJumpType() == JumpException.JumpType.BreakJump) {
1239: if (je.getTarget() != null
1240: && je.getTarget() != block) {
1241: je.setBreakInKernelLoop(true);
1242: }
1243: }
1244:
1245: throw je;
1246: }
1247: }
1248: }
1249:
1250: public static IRubyObject test(IRubyObject recv, IRubyObject[] args) {
1251: Ruby runtime = recv.getRuntime();
1252: if (args.length == 0) {
1253: // MRI message if no args given
1254: throw runtime.newArgumentError("wrong number of arguments");
1255: }
1256: IRubyObject cmdArg = args[0];
1257: int cmd;
1258: if (cmdArg instanceof RubyFixnum) {
1259: cmd = (int) ((RubyFixnum) cmdArg).getLongValue();
1260: } else if (cmdArg instanceof RubyString
1261: && ((RubyString) cmdArg).getByteList().length() > 0) {
1262: // MRI behavior: use first byte of string value if len > 0
1263: cmd = ((RubyString) cmdArg).getByteList().charAt(0);
1264: } else {
1265: cmd = (int) cmdArg.convertToInteger().getLongValue();
1266: }
1267:
1268: // MRI behavior: raise ArgumentError for 'unknown command' before
1269: // checking number of args.
1270: switch (cmd) {
1271:
1272: // implemented commands
1273: case 'C': // ?C | Time | Last change time for file1
1274: case 'd': // ?d | boolean | True if file1 exists and is a directory
1275: case 'e': // ?e | boolean | True if file1 exists
1276: case 'f':
1277: case 'M':
1278: case 's': // ?s | int/nil | If file1 has nonzero size, return the size,
1279: // | | otherwise return nil
1280: case 'z': // ?z | boolean | True if file1 exists and has a zero length
1281: case '=': // ?= | boolean | True if the modification times of file1
1282: // | | and file2 are equal
1283: case '<': // ?< | boolean | True if the modification time of file1
1284: // | | is prior to that of file2
1285: case '>': // ?> | boolean | True if the modification time of file1
1286: // | | is after that of file2
1287: case '-': // ?- | boolean | True if file1 and file2 are identical
1288: break;
1289:
1290: // unimplemented commands
1291:
1292: // FIXME: obviously, these are mostly unimplemented. Raising an
1293: // ArgumentError 'unimplemented command' for them.
1294:
1295: case 'A': // ?A | Time | Last access time for file1
1296: case 'b': // ?b | boolean | True if file1 is a block device
1297: case 'c': // ?c | boolean | True if file1 is a character device
1298: case 'g': // ?g | boolean | True if file1 has the \CF{setgid} bit
1299: case 'G': // ?G | boolean | True if file1 exists and has a group
1300: // | | ownership equal to the caller's group
1301: case 'k': // ?k | boolean | True if file1 exists and has the sticky bit set
1302: case 'l': // ?l | boolean | True if file1 exists and is a symbolic link
1303: case 'o': // ?o | boolean | True if file1 exists and is owned by
1304: // | | the caller's effective uid
1305: case 'O': // ?O | boolean | True if file1 exists and is owned by
1306: // | | the caller's real uid
1307: case 'p': // ?p | boolean | True if file1 exists and is a fifo
1308: case 'r': // ?r | boolean | True if file1 is readable by the effective
1309: // | | uid/gid of the caller
1310: case 'R': // ?R | boolean | True if file is readable by the real
1311: // | | uid/gid of the caller
1312: case 'S': // ?S | boolean | True if file1 exists and is a socket
1313: case 'u': // ?u | boolean | True if file1 has the setuid bit set
1314: case 'w': // ?w | boolean | True if file1 exists and is writable by
1315: case 'W': // ?W | boolean | True if file1 exists and is writable by
1316: // | | the real uid/gid
1317: case 'x': // ?x | boolean | True if file1 exists and is executable by
1318: // | | the effective uid/gid
1319: case 'X': // ?X | boolean | True if file1 exists and is executable by
1320: // | | the real uid/gid
1321: throw runtime.newArgumentError("unimplemented command ?"
1322: + (char) cmd);
1323: default:
1324: // matches MRI message
1325: throw runtime.newArgumentError("unknown command ?"
1326: + (char) cmd);
1327:
1328: }
1329:
1330: // MRI behavior: now check arg count
1331:
1332: switch (cmd) {
1333: case '-':
1334: case '=':
1335: case '<':
1336: case '>':
1337: if (args.length != 3) {
1338: throw runtime.newArgumentError(args.length, 3);
1339: }
1340: break;
1341: default:
1342: if (args.length != 2) {
1343: throw runtime.newArgumentError(args.length, 2);
1344: }
1345: break;
1346: }
1347:
1348: File pwd = new File(runtime.getCurrentDirectory());
1349: File file1 = new File(pwd, args[1].convertToString().toString());
1350: File file2 = null;
1351: Calendar calendar = null;
1352:
1353: switch (cmd) {
1354: case 'C': // ?C | Time | Last change time for file1
1355: return runtime.newFixnum(file1.lastModified());
1356: case 'd': // ?d | boolean | True if file1 exists and is a directory
1357: return runtime.newBoolean(file1.isDirectory());
1358: case 'e': // ?e | boolean | True if file1 exists
1359: return runtime.newBoolean(file1.exists());
1360: case 'f': // ?f | boolean | True if file1 exists and is a regular file
1361: return runtime.newBoolean(file1.isFile());
1362:
1363: case 'M': // ?M | Time | Last modification time for file1
1364: calendar = Calendar.getInstance();
1365: calendar.setTimeInMillis(file1.lastModified());
1366: return RubyTime.newTime(runtime, calendar);
1367: case 's': // ?s | int/nil | If file1 has nonzero size, return the size,
1368: // | | otherwise return nil
1369: long length = file1.length();
1370:
1371: return length == 0 ? runtime.getNil() : runtime
1372: .newFixnum(length);
1373: case 'z': // ?z | boolean | True if file1 exists and has a zero length
1374: return runtime.newBoolean(file1.exists()
1375: && file1.length() == 0);
1376: case '=': // ?= | boolean | True if the modification times of file1
1377: // | | and file2 are equal
1378: file2 = new File(pwd, args[2].convertToString().toString());
1379:
1380: return runtime.newBoolean(file1.lastModified() == file2
1381: .lastModified());
1382: case '<': // ?< | boolean | True if the modification time of file1
1383: // | | is prior to that of file2
1384: file2 = new File(pwd, args[2].convertToString().toString());
1385:
1386: return runtime.newBoolean(file1.lastModified() < file2
1387: .lastModified());
1388: case '>': // ?> | boolean | True if the modification time of file1
1389: // | | is after that of file2
1390: file2 = new File(pwd, args[2].convertToString().toString());
1391:
1392: return runtime.newBoolean(file1.lastModified() > file2
1393: .lastModified());
1394: case '-': // ?- | boolean | True if file1 and file2 are identical
1395: file2 = new File(pwd, args[2].convertToString().toString());
1396:
1397: return runtime.newBoolean(file1.equals(file2));
1398: default:
1399: throw new InternalError("unreachable code reached!");
1400: }
1401: }
1402:
1403: public static IRubyObject backquote(IRubyObject recv,
1404: IRubyObject aString) {
1405: Ruby runtime = recv.getRuntime();
1406: ByteArrayOutputStream output = new ByteArrayOutputStream();
1407:
1408: int resultCode = new ShellLauncher(runtime).runAndWait(
1409: new IRubyObject[] { aString }, output);
1410:
1411: recv.getRuntime().getGlobalVariables().set(
1412: "$?",
1413: RubyProcess.RubyStatus.newProcessStatus(runtime,
1414: resultCode));
1415:
1416: return RubyString.newString(recv.getRuntime(), output
1417: .toByteArray());
1418: }
1419:
1420: public static RubyInteger srand(IRubyObject recv, IRubyObject[] args) {
1421: Ruby runtime = recv.getRuntime();
1422: long oldRandomSeed = runtime.getRandomSeed();
1423:
1424: if (args.length > 0) {
1425: RubyInteger integerSeed = (RubyInteger) args[0]
1426: .convertToType(runtime.getClass("Integer"),
1427: MethodIndex.TO_I, "to_i", true);
1428: runtime.setRandomSeed(integerSeed.getLongValue());
1429: } else {
1430: // Not sure how well this works, but it works much better than
1431: // just currentTimeMillis by itself.
1432: runtime.setRandomSeed(System.currentTimeMillis()
1433: ^ recv.hashCode()
1434: ^ runtime.incrementRandomSeedSequence()
1435: ^ runtime.getRandom().nextInt(
1436: Math.max(1, Math.abs((int) runtime
1437: .getRandomSeed()))));
1438: }
1439: runtime.getRandom().setSeed(runtime.getRandomSeed());
1440: return runtime.newFixnum(oldRandomSeed);
1441: }
1442:
1443: public static RubyNumeric rand(IRubyObject recv, IRubyObject[] args) {
1444: Ruby runtime = recv.getRuntime();
1445: long ceil;
1446: if (args.length == 0) {
1447: ceil = 0;
1448: } else if (args.length == 1) {
1449: if (args[0] instanceof RubyBignum) {
1450: byte[] bytes = new byte[((RubyBignum) args[0])
1451: .getValue().toByteArray().length - 1];
1452:
1453: runtime.getRandom().nextBytes(bytes);
1454:
1455: return new RubyBignum(runtime, new BigInteger(bytes)
1456: .abs());
1457: }
1458:
1459: RubyInteger integerCeil = (RubyInteger) args[0]
1460: .convertToType(runtime.getClass("Integer"),
1461: MethodIndex.TO_I, "to_i", true);
1462: ceil = Math.abs(integerCeil.getLongValue());
1463: } else {
1464: throw runtime.newArgumentError("wrong # of arguments("
1465: + args.length + " for 1)");
1466: }
1467:
1468: if (ceil == 0) {
1469: return RubyFloat.newFloat(runtime, runtime.getRandom()
1470: .nextDouble());
1471: }
1472: if (ceil > Integer.MAX_VALUE) {
1473: return runtime.newFixnum(runtime.getRandom().nextLong()
1474: % ceil);
1475: }
1476:
1477: return runtime.newFixnum(runtime.getRandom()
1478: .nextInt((int) ceil));
1479: }
1480:
1481: public static RubyBoolean system(IRubyObject recv,
1482: IRubyObject[] args) {
1483: Ruby runtime = recv.getRuntime();
1484: int resultCode;
1485: try {
1486: resultCode = new ShellLauncher(runtime).runAndWait(args);
1487: } catch (Exception e) {
1488: resultCode = 127;
1489: }
1490: recv.getRuntime().getGlobalVariables().set(
1491: "$?",
1492: RubyProcess.RubyStatus.newProcessStatus(runtime,
1493: resultCode));
1494: return runtime.newBoolean(resultCode == 0);
1495: }
1496:
1497: public static RubyArray to_a(IRubyObject recv) {
1498: recv.getRuntime().getWarnings().warn(
1499: "default 'to_a' will be obsolete");
1500: return recv.getRuntime().newArray(recv);
1501: }
1502: }
|