0001: /*
0002: * InfoCmd.java
0003: *
0004: * Copyright (c) 1997 Cornell University.
0005: * Copyright (c) 1997 Sun Microsystems, Inc.
0006: *
0007: * See the file "license.terms" for information on usage and
0008: * redistribution of this file, and for a DISCLAIMER OF ALL
0009: * WARRANTIES.
0010: *
0011: * RCS: @(#) $Id: InfoCmd.java,v 1.15 2006/03/27 00:06:42 mdejong Exp $
0012: *
0013: */
0014:
0015: package tcl.lang;
0016:
0017: import java.util.*;
0018: import java.net.InetAddress;
0019: import java.net.UnknownHostException;
0020:
0021: /**
0022: * This class implements the built-in "info" command in Tcl.
0023: */
0024:
0025: class InfoCmd implements Command {
0026: static final private String validCmds[] = { "args", "body",
0027: "cmdcount", "commands", "complete", "default", "exists",
0028: "globals", "hostname", "level", "library", "loaded",
0029: "locals", "nameofexecutable", "patchlevel", "procs",
0030: "script", "sharedlibextension", "tclversion", "vars" };
0031:
0032: static final int OPT_ARGS = 0;
0033: static final int OPT_BODY = 1;
0034: static final int OPT_CMDCOUNT = 2;
0035: static final int OPT_COMMANDS = 3;
0036: static final int OPT_COMPLETE = 4;
0037: static final int OPT_DEFAULT = 5;
0038: static final int OPT_EXISTS = 6;
0039: static final int OPT_GLOBALS = 7;
0040: static final int OPT_HOSTNAME = 8;
0041: static final int OPT_LEVEL = 9;
0042: static final int OPT_LIBRARY = 10;
0043: static final int OPT_LOADED = 11;
0044: static final int OPT_LOCALS = 12;
0045: static final int OPT_NAMEOFEXECUTABLE = 13;
0046: static final int OPT_PATCHLEVEL = 14;
0047: static final int OPT_PROCS = 15;
0048: static final int OPT_SCRIPT = 16;
0049: static final int OPT_SHAREDLIBEXTENSION = 17;
0050: static final int OPT_TCLVERSION = 18;
0051: static final int OPT_VARS = 19;
0052:
0053: /**
0054: * Tcl_InfoObjCmd -> InfoCmd.cmdProc
0055: *
0056: * This procedure is invoked to process the "info" Tcl command.
0057: * See the user documentation for details on what it does.
0058: *
0059: * @param interp the current interpreter.
0060: * @param argv command arguments.
0061: * @exception TclException if wrong # of args or invalid argument(s).
0062: */
0063: public void cmdProc(Interp interp, TclObject[] objv)
0064: throws TclException {
0065: int index;
0066:
0067: if (objv.length < 2) {
0068: throw new TclNumArgsException(interp, 1, objv,
0069: "option ?arg arg ...?");
0070: }
0071: index = TclIndex.get(interp, objv[1], validCmds, "option", 0);
0072:
0073: switch (index) {
0074: case OPT_ARGS:
0075: InfoArgsCmd(interp, objv);
0076: break;
0077: case OPT_BODY:
0078: InfoBodyCmd(interp, objv);
0079: break;
0080: case OPT_CMDCOUNT:
0081: InfoCmdCountCmd(interp, objv);
0082: break;
0083: case OPT_COMMANDS:
0084: InfoCommandsCmd(interp, objv);
0085: break;
0086: case OPT_COMPLETE:
0087: InfoCompleteCmd(interp, objv);
0088: break;
0089: case OPT_DEFAULT:
0090: InfoDefaultCmd(interp, objv);
0091: break;
0092: case OPT_EXISTS:
0093: InfoExistsCmd(interp, objv);
0094: break;
0095: case OPT_GLOBALS:
0096: InfoGlobalsCmd(interp, objv);
0097: break;
0098: case OPT_HOSTNAME:
0099: InfoHostnameCmd(interp, objv);
0100: break;
0101: case OPT_LEVEL:
0102: InfoLevelCmd(interp, objv);
0103: break;
0104: case OPT_LIBRARY:
0105: InfoLibraryCmd(interp, objv);
0106: break;
0107: case OPT_LOADED:
0108: InfoLoadedCmd(interp, objv);
0109: break;
0110: case OPT_LOCALS:
0111: InfoLocalsCmd(interp, objv);
0112: break;
0113: case OPT_NAMEOFEXECUTABLE:
0114: InfoNameOfExecutableCmd(interp, objv);
0115: break;
0116: case OPT_PATCHLEVEL:
0117: InfoPatchLevelCmd(interp, objv);
0118: break;
0119: case OPT_PROCS:
0120: InfoProcsCmd(interp, objv);
0121: break;
0122: case OPT_SCRIPT:
0123: InfoScriptCmd(interp, objv);
0124: break;
0125: case OPT_SHAREDLIBEXTENSION:
0126: InfoSharedlibCmd(interp, objv);
0127: break;
0128: case OPT_TCLVERSION:
0129: InfoTclVersionCmd(interp, objv);
0130: break;
0131: case OPT_VARS:
0132: InfoVarsCmd(interp, objv);
0133: break;
0134: }
0135: return;
0136: }
0137:
0138: /*
0139: *----------------------------------------------------------------------
0140: *
0141: * InfoArgsCmd --
0142: *
0143: * Called to implement the "info args" command that returns the
0144: * argument list for a procedure. Handles the following syntax:
0145: *
0146: * info args procName
0147: *
0148: * Results:
0149: * Returns if successful, raises TclException otherwise.
0150: *
0151: * Side effects:
0152: * Returns a result in the interpreter's result object.
0153: *
0154: *----------------------------------------------------------------------
0155: */
0156:
0157: private static void InfoArgsCmd(Interp interp, TclObject[] objv)
0158: throws TclException {
0159: String name;
0160: Procedure proc;
0161: TclObject listObj;
0162:
0163: if (objv.length != 3) {
0164: throw new TclNumArgsException(interp, 2, objv, "procname");
0165: }
0166: name = objv[2].toString();
0167: proc = Procedure.findProc(interp, name);
0168: if (proc == null) {
0169: throw new TclException(interp, "\"" + name
0170: + "\" isn't a procedure");
0171: }
0172:
0173: // Build a return list containing the arguments.
0174:
0175: listObj = TclList.newInstance();
0176: for (int i = 0; i < proc.argList.length; i++) {
0177: TclObject s = TclString.newInstance(proc.argList[i][0]);
0178: TclList.append(interp, listObj, s);
0179: }
0180: interp.setResult(listObj);
0181: return;
0182: }
0183:
0184: /*
0185: *----------------------------------------------------------------------
0186: *
0187: * InfoBodyCmd --
0188: *
0189: * Called to implement the "info body" command that returns the body
0190: * for a procedure. Handles the following syntax:
0191: *
0192: * info body procName
0193: *
0194: * Results:
0195: * Returns if successful, raises TclException otherwise.
0196: *
0197: * Side effects:
0198: * Returns a result in the interpreter's result object.
0199: *
0200: *----------------------------------------------------------------------
0201: */
0202:
0203: private static void InfoBodyCmd(Interp interp, TclObject[] objv)
0204: throws TclException {
0205: String name;
0206: Procedure proc;
0207: TclObject body, result;
0208:
0209: if (objv.length != 3) {
0210: throw new TclNumArgsException(interp, 2, objv, "procname");
0211: }
0212: name = objv[2].toString();
0213: proc = Procedure.findProc(interp, name);
0214: if (proc == null) {
0215: throw new TclException(interp, "\"" + name
0216: + "\" isn't a procedure");
0217: }
0218:
0219: interp.setResult(proc.body.toString());
0220: return;
0221: }
0222:
0223: /*
0224: *----------------------------------------------------------------------
0225: *
0226: * InfoCmdCountCmd --
0227: *
0228: * Called to implement the "info cmdcount" command that returns the
0229: * number of commands that have been executed. Handles the following
0230: * syntax:
0231: *
0232: * info cmdcount
0233: *
0234: * Results:
0235: * Returns if successful, raises TclException otherwise.
0236: *
0237: * Side effects:
0238: * Returns a result in the interpreter's result object.
0239: *
0240: *----------------------------------------------------------------------
0241: */
0242:
0243: private static void InfoCmdCountCmd(Interp interp, TclObject[] objv)
0244: throws TclException {
0245: if (objv.length != 2) {
0246: throw new TclNumArgsException(interp, 2, objv, null);
0247: }
0248: interp.setResult(interp.cmdCount);
0249: return;
0250: }
0251:
0252: /*
0253: *----------------------------------------------------------------------
0254: *
0255: * InfoCommandsCmd --
0256: *
0257: * Called to implement the "info commands" command that returns the
0258: * list of commands in the interpreter that match an optional pattern.
0259: * The pattern, if any, consists of an optional sequence of namespace
0260: * names separated by "::" qualifiers, which is followed by a
0261: * glob-style pattern that restricts which commands are returned.
0262: * Handles the following syntax:
0263: *
0264: * info commands ?pattern?
0265: *
0266: * Results:
0267: * Returns if successful, raises TclException otherwise.
0268: *
0269: * Side effects:
0270: * Returns a result in the interpreter's result object.
0271: *
0272: *----------------------------------------------------------------------
0273: */
0274:
0275: private static void InfoCommandsCmd(Interp interp, TclObject[] objv)
0276: throws TclException {
0277: String cmdName, pattern, simplePattern;
0278: Namespace ns;
0279: Namespace globalNs = Namespace.getGlobalNamespace(interp);
0280: Namespace currNs = Namespace.getCurrentNamespace(interp);
0281: TclObject list, elemObj;
0282: boolean specificNsInPattern = false; // Init. to avoid compiler warning.
0283: WrappedCommand cmd;
0284:
0285: // Get the pattern and find the "effective namespace" in which to
0286: // list commands.
0287:
0288: if (objv.length == 2) {
0289: simplePattern = null;
0290: ns = currNs;
0291: specificNsInPattern = false;
0292: } else if (objv.length == 3) {
0293: // From the pattern, get the effective namespace and the simple
0294: // pattern (no namespace qualifiers or ::'s) at the end. If an
0295: // error was found while parsing the pattern, return it. Otherwise,
0296: // if the namespace wasn't found, just leave ns NULL: we will
0297: // return an empty list since no commands there can be found.
0298:
0299: pattern = objv[2].toString();
0300:
0301: Namespace.GetNamespaceForQualNameResult gnfqnr = interp.getnfqnResult;
0302: Namespace.getNamespaceForQualName(interp, pattern, null, 0,
0303: gnfqnr);
0304: ns = gnfqnr.ns;
0305: simplePattern = gnfqnr.simpleName;
0306:
0307: if (ns != null) { // we successfully found the pattern's ns
0308: specificNsInPattern = (simplePattern.compareTo(pattern) != 0);
0309: }
0310: } else {
0311: throw new TclNumArgsException(interp, 2, objv, "?pattern?");
0312: }
0313:
0314: // Scan through the effective namespace's command table and create a
0315: // list with all commands that match the pattern. If a specific
0316: // namespace was requested in the pattern, qualify the command names
0317: // with the namespace name.
0318:
0319: list = TclList.newInstance();
0320:
0321: if (ns != null) {
0322: for (Iterator iter = ns.cmdTable.entrySet().iterator(); iter
0323: .hasNext();) {
0324: Map.Entry entry = (Map.Entry) iter.next();
0325: cmdName = (String) entry.getKey();
0326:
0327: if ((simplePattern == null)
0328: || Util.stringMatch(cmdName, simplePattern)) {
0329: if (specificNsInPattern) {
0330: cmd = (WrappedCommand) entry.getValue();
0331: elemObj = TclString.newInstance(interp
0332: .getCommandFullName(cmd));
0333: } else {
0334: elemObj = TclString.newInstance(cmdName);
0335: }
0336: TclList.append(interp, list, elemObj);
0337: }
0338: }
0339:
0340: // If the effective namespace isn't the global :: namespace, and a
0341: // specific namespace wasn't requested in the pattern, then add in
0342: // all global :: commands that match the simple pattern. Of course,
0343: // we add in only those commands that aren't hidden by a command in
0344: // the effective namespace.
0345:
0346: if ((ns != globalNs) && !specificNsInPattern) {
0347: for (Iterator iter = globalNs.cmdTable.entrySet()
0348: .iterator(); iter.hasNext();) {
0349: Map.Entry entry = (Map.Entry) iter.next();
0350: cmdName = (String) entry.getKey();
0351: if ((simplePattern == null)
0352: || Util.stringMatch(cmdName, simplePattern)) {
0353: if (ns.cmdTable.get(cmdName) == null) {
0354: TclList.append(interp, list, TclString
0355: .newInstance(cmdName));
0356: }
0357: }
0358: }
0359: }
0360: }
0361:
0362: interp.setResult(list);
0363: return;
0364: }
0365:
0366: /*
0367: *----------------------------------------------------------------------
0368: *
0369: * InfoCompleteCmd --
0370: *
0371: * Called to implement the "info complete" command that determines
0372: * whether a string is a complete Tcl command. Handles the following
0373: * syntax:
0374: *
0375: * info complete command
0376: *
0377: * Results:
0378: * Returns if successful, raises TclException otherwise.
0379: *
0380: * Side effects:
0381: * Returns a result in the interpreter's result object.
0382: *
0383: *----------------------------------------------------------------------
0384: */
0385:
0386: private static void InfoCompleteCmd(Interp interp, TclObject[] objv)
0387: throws TclException {
0388: if (objv.length != 3) {
0389: throw new TclNumArgsException(interp, 2, objv, "command");
0390: }
0391:
0392: interp.setResult(Interp.commandComplete(objv[2].toString()));
0393: return;
0394: }
0395:
0396: /*
0397: *----------------------------------------------------------------------
0398: *
0399: * InfoDefaultCmd --
0400: *
0401: * Called to implement the "info default" command that returns the
0402: * default value for a procedure argument. Handles the following
0403: * syntax:
0404: *
0405: * info default procName arg varName
0406: *
0407: * Results:
0408: * Returns if successful, raises TclException otherwise.
0409: *
0410: * Side effects:
0411: * Returns a result in the interpreter's result object.
0412: *
0413: *----------------------------------------------------------------------
0414: */
0415:
0416: private static void InfoDefaultCmd(Interp interp, TclObject[] objv)
0417: throws TclException {
0418: String procName, argName, varName;
0419: Procedure proc;
0420: TclObject valueObj;
0421:
0422: if (objv.length != 5) {
0423: throw new TclNumArgsException(interp, 2, objv,
0424: "procname arg varname");
0425: }
0426:
0427: procName = objv[2].toString();
0428: argName = objv[3].toString();
0429: proc = Procedure.findProc(interp, procName);
0430: if (proc == null) {
0431: throw new TclException(interp, "\"" + procName
0432: + "\" isn't a procedure");
0433: }
0434:
0435: for (int i = 0; i < proc.argList.length; i++) {
0436: if (argName.equals(proc.argList[i][0].toString())) {
0437: varName = objv[4].toString();
0438: try {
0439: if (proc.argList[i][1] != null) {
0440: interp.setVar(varName, proc.argList[i][1], 0);
0441: interp.setResult(1);
0442: } else {
0443: interp.setVar(varName, "", 0);
0444: interp.setResult(0);
0445: }
0446: } catch (TclException excp) {
0447: throw new TclException(interp,
0448: "couldn't store default value in variable \""
0449: + varName + "\"");
0450: }
0451: return;
0452: }
0453: }
0454: throw new TclException(interp, "procedure \"" + procName
0455: + "\" doesn't have an argument \"" + argName + "\"");
0456: }
0457:
0458: /*
0459: *----------------------------------------------------------------------
0460: *
0461: * InfoExistsCmd --
0462: *
0463: * Called to implement the "info exists" command that determines
0464: * whether a variable exists. Handles the following syntax:
0465: *
0466: * info exists varName
0467: *
0468: * Results:
0469: * Returns if successful, raises TclException otherwise.
0470: *
0471: * Side effects:
0472: * Returns a result in the interpreter's result object.
0473: *
0474: *----------------------------------------------------------------------
0475: */
0476:
0477: private static void InfoExistsCmd(Interp interp, TclObject[] objv)
0478: throws TclException {
0479: String varName;
0480: Var var = null;
0481:
0482: if (objv.length != 3) {
0483: throw new TclNumArgsException(interp, 2, objv, "varName");
0484: }
0485:
0486: varName = objv[2].toString();
0487: Var[] result = Var.lookupVar(interp, varName, null, 0,
0488: "access", false, false);
0489: if (result != null) {
0490: var = result[0];
0491: }
0492:
0493: if ((var != null) && !var.isVarUndefined()) {
0494: interp.setResult(true);
0495: } else {
0496: interp.setResult(false);
0497: }
0498:
0499: return;
0500: }
0501:
0502: /*
0503: *----------------------------------------------------------------------
0504: *
0505: * InfoGlobalsCmd --
0506: *
0507: * Called to implement the "info globals" command that returns the list
0508: * of global variables matching an optional pattern. Handles the
0509: * following syntax:
0510: *
0511: * info globals ?pattern?*
0512: *
0513: * Results:
0514: * Returns if successful, raises TclException otherwise.
0515: *
0516: * Side effects:
0517: * Returns a result in the interpreter's result object.
0518: *
0519: *----------------------------------------------------------------------
0520: */
0521:
0522: private static void InfoGlobalsCmd(Interp interp, TclObject[] objv)
0523: throws TclException {
0524: String varName, pattern;
0525: Namespace globalNs = Namespace.getGlobalNamespace(interp);
0526: Var var;
0527: TclObject list;
0528:
0529: if (objv.length == 2) {
0530: pattern = null;
0531: } else if (objv.length == 3) {
0532: pattern = objv[2].toString();
0533: } else {
0534: throw new TclNumArgsException(interp, 2, objv, "?pattern?");
0535: }
0536:
0537: // Scan through the global :: namespace's variable table and create a
0538: // list of all global variables that match the pattern.
0539:
0540: list = TclList.newInstance();
0541:
0542: for (Iterator iter = globalNs.varTable.entrySet().iterator(); iter
0543: .hasNext();) {
0544: Map.Entry entry = (Map.Entry) iter.next();
0545: varName = (String) entry.getKey();
0546: var = (Var) entry.getValue();
0547: if (var.isVarUndefined()) {
0548: continue;
0549: }
0550: if ((pattern == null) || Util.stringMatch(varName, pattern)) {
0551: TclList.append(interp, list, TclString
0552: .newInstance(varName));
0553: }
0554: }
0555:
0556: interp.setResult(list);
0557: return;
0558: }
0559:
0560: /*
0561: *----------------------------------------------------------------------
0562: *
0563: * InfoHostnameCmd --
0564: *
0565: * Called to implement the "info hostname" command that returns the
0566: * host name. Handles the following syntax:
0567: *
0568: * info hostname
0569: *
0570: * Results:
0571: * Returns if successful, raises TclException otherwise.
0572: *
0573: * Side effects:
0574: * Returns a result in the interpreter's result object.
0575: *
0576: *----------------------------------------------------------------------
0577: */
0578:
0579: private static void InfoHostnameCmd(Interp interp, TclObject[] objv)
0580: throws TclException {
0581: String name = null;
0582:
0583: if (objv.length != 2) {
0584: throw new TclNumArgsException(interp, 2, objv, null);
0585: }
0586:
0587: try {
0588: name = InetAddress.getLocalHost().getHostName();
0589: } catch (UnknownHostException ex) {
0590: }
0591:
0592: if (name != null) {
0593: interp.setResult(name);
0594: return;
0595: } else {
0596: interp.setResult("unable to determine name of host");
0597: return;
0598: }
0599: }
0600:
0601: /*
0602: *----------------------------------------------------------------------
0603: *
0604: * InfoLevelCmd --
0605: *
0606: * Called to implement the "info level" command that returns
0607: * information about the call stack. Handles the following syntax:
0608: *
0609: * info level ?number?
0610: *
0611: * Results:
0612: * Returns if successful, raises TclException otherwise.
0613: *
0614: * Side effects:
0615: * Returns a result in the interpreter's result object.
0616: *
0617: *----------------------------------------------------------------------
0618: */
0619:
0620: private static void InfoLevelCmd(Interp interp, TclObject[] objv)
0621: throws TclException {
0622: int level;
0623: CallFrame frame;
0624: TclObject list;
0625:
0626: if (objv.length == 2) { // just "info level"
0627: if (interp.varFrame == null) {
0628: interp.setResult(0);
0629: } else {
0630: interp.setResult(interp.varFrame.level);
0631: }
0632: return;
0633: } else if (objv.length == 3) {
0634: level = TclInteger.get(interp, objv[2]);
0635:
0636: if (level <= 0) {
0637: if (interp.varFrame == null) {
0638: throw new TclException(interp, "bad level \""
0639: + objv[2].toString() + "\"");
0640: }
0641:
0642: level += interp.varFrame.level;
0643: }
0644:
0645: for (frame = interp.varFrame; frame != null; frame = frame.callerVar) {
0646: if (frame.level == level) {
0647: break;
0648: }
0649: }
0650: if ((frame == null) || frame.objv == null) {
0651: throw new TclException(interp, "bad level \""
0652: + objv[2].toString() + "\"");
0653: }
0654:
0655: list = TclList.newInstance();
0656: for (int i = 0; i < frame.objv.length; i++) {
0657: TclList.append(interp, list, TclString
0658: .newInstance(frame.objv[i]));
0659: }
0660: interp.setResult(list);
0661: return;
0662: }
0663:
0664: throw new TclNumArgsException(interp, 2, objv, "?number?");
0665: }
0666:
0667: /*
0668: *----------------------------------------------------------------------
0669: *
0670: * InfoLibraryCmd --
0671: *
0672: * Called to implement the "info library" command that returns the
0673: * library directory for the Tcl installation. Handles the following
0674: * syntax:
0675: *
0676: * info library
0677: *
0678: * Results:
0679: * Returns if successful, raises TclException otherwise.
0680: *
0681: * Side effects:
0682: * Returns a result in the interpreter's result object.
0683: *
0684: *----------------------------------------------------------------------
0685: */
0686:
0687: private static void InfoLibraryCmd(Interp interp, TclObject[] objv)
0688: throws TclException {
0689: if (objv.length != 2) {
0690: throw new TclNumArgsException(interp, 2, objv, null);
0691: }
0692: try {
0693: interp.setResult(interp.getVar("tcl_library",
0694: TCL.GLOBAL_ONLY));
0695: return;
0696: } catch (TclException e) {
0697: // If the variable has not been defined
0698: throw new TclException(interp,
0699: "no library has been specified for Tcl");
0700: }
0701: }
0702:
0703: /*
0704: *----------------------------------------------------------------------
0705: *
0706: * InfoLoadedCmd --
0707: *
0708: * Called to implement the "info loaded" command that returns the
0709: * packages that have been loaded into an interpreter. Handles the
0710: * following syntax:
0711: *
0712: * info loaded ?interp?
0713: *
0714: * Results:
0715: * Returns if successful, raises TclException otherwise.
0716: *
0717: * Side effects:
0718: * Returns a result in the interpreter's result object.
0719: *
0720: *----------------------------------------------------------------------
0721: */
0722:
0723: private static void InfoLoadedCmd(Interp interp, TclObject[] objv)
0724: throws TclException {
0725: if (objv.length != 2 && objv.length != 3) {
0726: throw new TclNumArgsException(interp, 2, objv, "?interp?");
0727: }
0728: // FIXME : what should "info loaded" return?
0729: throw new TclException(interp, "info loaded not implemented");
0730: }
0731:
0732: /*
0733: *----------------------------------------------------------------------
0734: *
0735: * InfoLocalsCmd --
0736: *
0737: * Called to implement the "info locals" command to return a list of
0738: * local variables that match an optional pattern. Handles the
0739: * following syntax:
0740: *
0741: * info locals ?pattern?
0742: *
0743: * Results:
0744: * Returns if successful, raises TclException otherwise.
0745: *
0746: * Side effects:
0747: * Returns a result in the interpreter's result object.
0748: *
0749: *----------------------------------------------------------------------
0750: */
0751:
0752: private static void InfoLocalsCmd(Interp interp, TclObject[] objv)
0753: throws TclException {
0754: String pattern;
0755: TclObject list;
0756:
0757: if (objv.length == 2) {
0758: pattern = null;
0759: } else if (objv.length == 3) {
0760: pattern = objv[2].toString();
0761: } else {
0762: throw new TclNumArgsException(interp, 2, objv, "?pattern?");
0763: }
0764:
0765: if (interp.varFrame == null || !interp.varFrame.isProcCallFrame) {
0766: return;
0767: }
0768:
0769: // Return a list containing names of first the compiled locals (i.e. the
0770: // ones stored in the call frame), then the variables in the local hash
0771: // table (if one exists).
0772:
0773: list = TclList.newInstance();
0774: Var.AppendLocals(interp, list, pattern, false);
0775: interp.setResult(list);
0776: return;
0777: }
0778:
0779: /*
0780: *----------------------------------------------------------------------
0781: *
0782: * InfoNameOfExecutableCmd --
0783: *
0784: * Called to implement the "info nameofexecutable" command that returns
0785: * the name of the binary file running this application. Handles the
0786: * following syntax:
0787: *
0788: * info nameofexecutable
0789: *
0790: * Results:
0791: * Returns if successful, raises TclException otherwise.
0792: *
0793: * Side effects:
0794: * Returns a result in the interpreter's result object.
0795: *
0796: *----------------------------------------------------------------------
0797: */
0798:
0799: private static void InfoNameOfExecutableCmd(Interp interp,
0800: TclObject[] objv) throws TclException {
0801:
0802: if (objv.length != 2) {
0803: throw new TclNumArgsException(interp, 2, objv, null);
0804: }
0805:
0806: // We depend on a user defined property named "JAVA" since
0807: // the JDK provides no means to learn the name of the executable
0808: // that launched the application.
0809:
0810: String nameOfExecutable = System.getProperty("JAVA");
0811:
0812: if (nameOfExecutable != null) {
0813: TclObject result = TclList.newInstance();
0814: TclList.append(interp, result, TclString
0815: .newInstance(nameOfExecutable));
0816: TclList.append(interp, result, TclString
0817: .newInstance("tcl.lang.Shell"));
0818: interp.setResult(result);
0819: }
0820:
0821: return;
0822: }
0823:
0824: /*
0825: *----------------------------------------------------------------------
0826: *
0827: * InfoPatchLevelCmd --
0828: *
0829: * Called to implement the "info patchlevel" command that returns the
0830: * default value for an argument to a procedure. Handles the following
0831: * syntax:
0832: *
0833: * info patchlevel
0834: *
0835: * Results:
0836: * Returns if successful, raises TclException otherwise.
0837: *
0838: * Side effects:
0839: * Returns a result in the interpreter's result object.
0840: *
0841: *----------------------------------------------------------------------
0842: */
0843:
0844: private static void InfoPatchLevelCmd(Interp interp,
0845: TclObject[] objv) throws TclException {
0846: if (objv.length != 2) {
0847: throw new TclNumArgsException(interp, 2, objv, null);
0848: }
0849:
0850: interp.setResult(interp.getVar("tcl_patchLevel",
0851: TCL.GLOBAL_ONLY));
0852: return;
0853: }
0854:
0855: /*
0856: *----------------------------------------------------------------------
0857: *
0858: * InfoProcsCmd --
0859: *
0860: * Called to implement the "info procs" command that returns the
0861: * procedures in the current namespace that match an optional pattern.
0862: * Handles the following syntax:
0863: *
0864: * info procs ?pattern?
0865: *
0866: * Results:
0867: * Returns if successful, raises TclException otherwise.
0868: *
0869: * Side effects:
0870: * Returns a result in the interpreter's result object.
0871: *
0872: *----------------------------------------------------------------------
0873: */
0874:
0875: private static void InfoProcsCmd(Interp interp, TclObject[] objv)
0876: throws TclException {
0877: String cmdName, pattern;
0878: Namespace currNs = Namespace.getCurrentNamespace(interp);
0879: WrappedCommand cmd, realCmd;
0880: TclObject list;
0881:
0882: if (objv.length == 2) {
0883: pattern = null;
0884: } else if (objv.length == 3) {
0885: pattern = objv[2].toString();
0886: } else {
0887: throw new TclNumArgsException(interp, 2, objv, "?pattern?");
0888: }
0889:
0890: // Scan through the current namespace's command table and return a list
0891: // of all procs that match the pattern.
0892:
0893: list = TclList.newInstance();
0894: for (Iterator iter = currNs.cmdTable.entrySet().iterator(); iter
0895: .hasNext();) {
0896: Map.Entry entry = (Map.Entry) iter.next();
0897: cmdName = (String) entry.getKey();
0898: cmd = (WrappedCommand) entry.getValue();
0899:
0900: // If the command isn't itself a proc, it still might be an
0901: // imported command that points to a "real" proc in a different
0902: // namespace.
0903:
0904: realCmd = Namespace.getOriginalCommand(cmd);
0905:
0906: if (Procedure.isProc(cmd)
0907: || ((realCmd != null) && Procedure.isProc(realCmd))) {
0908: if ((pattern == null)
0909: || Util.stringMatch(cmdName, pattern)) {
0910: TclList.append(interp, list, TclString
0911: .newInstance(cmdName));
0912: }
0913: }
0914: }
0915:
0916: interp.setResult(list);
0917: return;
0918: }
0919:
0920: /*
0921: *----------------------------------------------------------------------
0922: *
0923: * InfoScriptCmd --
0924: *
0925: * Called to implement the "info script" command that returns the
0926: * script file that is currently being evaluated. Handles the
0927: * following syntax:
0928: *
0929: * info script
0930: *
0931: * Results:
0932: * Returns if successful, raises TclException otherwise.
0933: *
0934: * Side effects:
0935: * Returns a result in the interpreter's result object.
0936: *
0937: *----------------------------------------------------------------------
0938: */
0939:
0940: private static void InfoScriptCmd(Interp interp, TclObject[] objv)
0941: throws TclException {
0942: if (objv.length != 2) {
0943: throw new TclNumArgsException(interp, 2, objv, null);
0944: }
0945:
0946: interp.setResult(interp.scriptFile);
0947: return;
0948: }
0949:
0950: /*
0951: *----------------------------------------------------------------------
0952: *
0953: * InfoSharedlibCmd --
0954: *
0955: * Called to implement the "info sharedlibextension" command that
0956: * returns the file extension used for shared libraries. Handles the
0957: * following syntax:
0958: *
0959: * info sharedlibextension
0960: *
0961: * Results:
0962: * Returns if successful, raises TclException otherwise.
0963: *
0964: * Side effects:
0965: * Returns a result in the interpreter's result object.
0966: *
0967: *----------------------------------------------------------------------
0968: */
0969:
0970: private static void InfoSharedlibCmd(Interp interp, TclObject[] objv)
0971: throws TclException {
0972: if (objv.length != 2) {
0973: throw new TclNumArgsException(interp, 2, objv, null);
0974: }
0975: interp.setResult(".jar");
0976: return;
0977: }
0978:
0979: /*
0980: *----------------------------------------------------------------------
0981: *
0982: * InfoTclVersionCmd --
0983: *
0984: * Called to implement the "info tclversion" command that returns the
0985: * version number for this Tcl library. Handles the following syntax:
0986: *
0987: * info tclversion
0988: *
0989: * Results:
0990: * Returns if successful, raises TclException otherwise.
0991: *
0992: * Side effects:
0993: * Returns a result in the interpreter's result object.
0994: *
0995: *----------------------------------------------------------------------
0996: */
0997:
0998: private static void InfoTclVersionCmd(Interp interp,
0999: TclObject[] objv) throws TclException {
1000: if (objv.length != 2) {
1001: throw new TclNumArgsException(interp, 2, objv, null);
1002: }
1003:
1004: interp.setResult(interp.getVar("tcl_version", TCL.GLOBAL_ONLY));
1005: return;
1006: }
1007:
1008: /*
1009: *----------------------------------------------------------------------
1010: *
1011: * InfoVarsCmd --
1012: *
1013: * Called to implement the "info vars" command that returns the
1014: * list of variables in the interpreter that match an optional pattern.
1015: * The pattern, if any, consists of an optional sequence of namespace
1016: * names separated by "::" qualifiers, which is followed by a
1017: * glob-style pattern that restricts which variables are returned.
1018: * Handles the following syntax:
1019: *
1020: * info vars ?pattern?
1021: *
1022: * Results:
1023: * Returns if successful, raises TclException otherwise.
1024: *
1025: * Side effects:
1026: * Returns a result in the interpreter's result object.
1027: *
1028: *----------------------------------------------------------------------
1029: */
1030:
1031: private static void InfoVarsCmd(Interp interp, TclObject[] objv)
1032: throws TclException {
1033: String varName, pattern, simplePattern;
1034: Var var;
1035: Namespace ns;
1036: Namespace globalNs = Namespace.getGlobalNamespace(interp);
1037: Namespace currNs = Namespace.getCurrentNamespace(interp);
1038: TclObject list, elemObj;
1039: boolean specificNsInPattern = false; // Init. to avoid compiler warning.
1040:
1041: // Get the pattern and find the "effective namespace" in which to
1042: // list variables. We only use this effective namespace if there's
1043: // no active Tcl procedure frame.
1044:
1045: if (objv.length == 2) {
1046: simplePattern = null;
1047: ns = currNs;
1048: specificNsInPattern = false;
1049: } else if (objv.length == 3) {
1050: // From the pattern, get the effective namespace and the simple
1051: // pattern (no namespace qualifiers or ::'s) at the end. If an
1052: // error was found while parsing the pattern, return it. Otherwise,
1053: // if the namespace wasn't found, just leave ns = null: we will
1054: // return an empty list since no variables there can be found.
1055:
1056: pattern = objv[2].toString();
1057:
1058: Namespace.GetNamespaceForQualNameResult gnfqnr = interp.getnfqnResult;
1059: Namespace.getNamespaceForQualName(interp, pattern, null, 0,
1060: gnfqnr);
1061: ns = gnfqnr.ns;
1062: simplePattern = gnfqnr.simpleName;
1063:
1064: if (ns != null) { // we successfully found the pattern's ns
1065: specificNsInPattern = (simplePattern.compareTo(pattern) != 0);
1066: }
1067: } else {
1068: throw new TclNumArgsException(interp, 2, objv, "?pattern?");
1069: }
1070:
1071: // If the namespace specified in the pattern wasn't found, just return.
1072:
1073: if (ns == null) {
1074: return;
1075: }
1076:
1077: list = TclList.newInstance();
1078:
1079: if ((interp.varFrame == null)
1080: || !interp.varFrame.isProcCallFrame
1081: || specificNsInPattern) {
1082: // There is no frame pointer, the frame pointer was pushed only
1083: // to activate a namespace, or we are in a procedure call frame
1084: // but a specific namespace was specified. Create a list containing
1085: // only the variables in the effective namespace's variable table.
1086:
1087: for (Iterator iter = ns.varTable.entrySet().iterator(); iter
1088: .hasNext();) {
1089: Map.Entry entry = (Map.Entry) iter.next();
1090: varName = (String) entry.getKey();
1091: var = (Var) entry.getValue();
1092:
1093: if (!var.isVarUndefined() || var.isVarNamespace()) {
1094: if ((simplePattern == null)
1095: || Util.stringMatch(varName, simplePattern)) {
1096: if (specificNsInPattern) {
1097: elemObj = TclString.newInstance(Var
1098: .getVariableFullName(interp, var));
1099: } else {
1100: elemObj = TclString.newInstance(varName);
1101: }
1102: TclList.append(interp, list, elemObj);
1103: }
1104: }
1105: }
1106:
1107: // If the effective namespace isn't the global :: namespace, and a
1108: // specific namespace wasn't requested in the pattern (i.e., the
1109: // pattern only specifies variable names), then add in all global ::
1110: // variables that match the simple pattern. Of course, add in only
1111: // those variables that aren't hidden by a variable in the effective
1112: // namespace.
1113:
1114: if ((ns != globalNs) && !specificNsInPattern) {
1115: for (Iterator iter = globalNs.varTable.entrySet()
1116: .iterator(); iter.hasNext();) {
1117: Map.Entry entry = (Map.Entry) iter.next();
1118: varName = (String) entry.getKey();
1119: var = (Var) entry.getValue();
1120:
1121: if (!var.isVarUndefined() || var.isVarNamespace()) {
1122: if ((simplePattern == null)
1123: || Util.stringMatch(varName,
1124: simplePattern)) {
1125:
1126: // Skip vars defined in current namespace
1127: if (ns.varTable.get(varName) == null) {
1128: TclList.append(interp, list, TclString
1129: .newInstance(varName));
1130: }
1131: }
1132: }
1133: }
1134: }
1135: } else {
1136: Var.AppendLocals(interp, list, simplePattern, true);
1137: }
1138:
1139: interp.setResult(list);
1140: return;
1141: }
1142: }
|