PageRenderTime 49ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/managed/csharp-sqlite/TCL/src/commands/InfoCmd.cs

https://bitbucket.org/KyanhaLLC/opensim-libs
C# | 1309 lines | 656 code | 164 blank | 489 comment | 169 complexity | 4238318b9485e7932c4592de3d0ec512 MD5 | raw file
Possible License(s): Apache-2.0, BSD-2-Clause, MIT, LGPL-2.1, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, GPL-3.0, BSD-3-Clause
  1. /*
  2. * InfoCmd.java
  3. *
  4. * Copyright (c) 1997 Cornell University.
  5. * Copyright (c) 1997 Sun Microsystems, Inc.
  6. *
  7. * See the file "license.terms" for information on usage and
  8. * redistribution of this file, and for a DISCLAIMER OF ALL
  9. * WARRANTIES.
  10. *
  11. * Included in SQLite3 port to C# for use in testharness only; 2008 Noah B Hart
  12. * $Header$
  13. * RCS @(#) $Id: InfoCmd.java,v 1.8 2001/11/16 23:57:13 mdejong Exp $
  14. *
  15. */
  16. using System;
  17. using System.Collections;
  18. namespace tcl.lang
  19. {
  20. /// <summary> This class implements the built-in "info" command in Tcl.</summary>
  21. class InfoCmd : Command
  22. {
  23. private static readonly string[] validCmds = new string[]{"args", "body", "cmdcount", "commands", "complete", "default", "exists", "globals", "hostname", "level", "library", "loaded", "locals", "nameofexecutable", "patchlevel", "procs", "script", "sharedlibextension", "tclversion", "vars"};
  24. internal const int OPT_ARGS = 0;
  25. internal const int OPT_BODY = 1;
  26. internal const int OPT_CMDCOUNT = 2;
  27. internal const int OPT_COMMANDS = 3;
  28. internal const int OPT_COMPLETE = 4;
  29. internal const int OPT_DEFAULT = 5;
  30. internal const int OPT_EXISTS = 6;
  31. internal const int OPT_GLOBALS = 7;
  32. internal const int OPT_HOSTNAME = 8;
  33. internal const int OPT_LEVEL = 9;
  34. internal const int OPT_LIBRARY = 10;
  35. internal const int OPT_LOADED = 11;
  36. internal const int OPT_LOCALS = 12;
  37. internal const int OPT_NAMEOFEXECUTABLE = 13;
  38. internal const int OPT_PATCHLEVEL = 14;
  39. internal const int OPT_PROCS = 15;
  40. internal const int OPT_SCRIPT = 16;
  41. internal const int OPT_SHAREDLIBEXTENSION = 17;
  42. internal const int OPT_TCLVERSION = 18;
  43. internal const int OPT_VARS = 19;
  44. /// <summary> Tcl_InfoObjCmd -> InfoCmd.cmdProc
  45. ///
  46. /// This procedure is invoked to process the "info" Tcl command.
  47. /// See the user documentation for details on what it does.
  48. ///
  49. /// </summary>
  50. /// <param name="interp">the current interpreter.
  51. /// </param>
  52. /// <param name="argv">command arguments.
  53. /// </param>
  54. /// <exception cref=""> TclException if wrong # of args or invalid argument(s).
  55. /// </exception>
  56. public TCL.CompletionCode cmdProc(Interp interp, TclObject[] objv)
  57. {
  58. int index;
  59. if (objv.Length < 2)
  60. {
  61. throw new TclNumArgsException(interp, 1, objv, "option ?arg arg ...?");
  62. }
  63. index = TclIndex.get(interp, objv[1], validCmds, "option", 0);
  64. switch (index)
  65. {
  66. case OPT_ARGS:
  67. InfoArgsCmd(interp, objv);
  68. break;
  69. case OPT_BODY:
  70. InfoBodyCmd(interp, objv);
  71. break;
  72. case OPT_CMDCOUNT:
  73. InfoCmdCountCmd(interp, objv);
  74. break;
  75. case OPT_COMMANDS:
  76. InfoCommandsCmd(interp, objv);
  77. break;
  78. case OPT_COMPLETE:
  79. InfoCompleteCmd(interp, objv);
  80. break;
  81. case OPT_DEFAULT:
  82. InfoDefaultCmd(interp, objv);
  83. break;
  84. case OPT_EXISTS:
  85. InfoExistsCmd(interp, objv);
  86. break;
  87. case OPT_GLOBALS:
  88. InfoGlobalsCmd(interp, objv);
  89. break;
  90. case OPT_HOSTNAME:
  91. InfoHostnameCmd(interp, objv);
  92. break;
  93. case OPT_LEVEL:
  94. InfoLevelCmd(interp, objv);
  95. break;
  96. case OPT_LIBRARY:
  97. InfoLibraryCmd(interp, objv);
  98. break;
  99. case OPT_LOADED:
  100. InfoLoadedCmd(interp, objv);
  101. break;
  102. case OPT_LOCALS:
  103. InfoLocalsCmd(interp, objv);
  104. break;
  105. case OPT_NAMEOFEXECUTABLE:
  106. InfoNameOfExecutableCmd(interp, objv);
  107. break;
  108. case OPT_PATCHLEVEL:
  109. InfoPatchLevelCmd(interp, objv);
  110. break;
  111. case OPT_PROCS:
  112. InfoProcsCmd(interp, objv);
  113. break;
  114. case OPT_SCRIPT:
  115. InfoScriptCmd(interp, objv);
  116. break;
  117. case OPT_SHAREDLIBEXTENSION:
  118. InfoSharedlibCmd(interp, objv);
  119. break;
  120. case OPT_TCLVERSION:
  121. InfoTclVersionCmd(interp, objv);
  122. break;
  123. case OPT_VARS:
  124. InfoVarsCmd(interp, objv);
  125. break;
  126. }
  127. return TCL.CompletionCode.RETURN;
  128. }
  129. /*
  130. *----------------------------------------------------------------------
  131. *
  132. * InfoArgsCmd --
  133. *
  134. * Called to implement the "info args" command that returns the
  135. * argument list for a procedure. Handles the following syntax:
  136. *
  137. * info args procName
  138. *
  139. * Results:
  140. * Returns if successful, raises TclException otherwise.
  141. *
  142. * Side effects:
  143. * Returns a result in the interpreter's result object.
  144. *
  145. *----------------------------------------------------------------------
  146. */
  147. private static void InfoArgsCmd(Interp interp, TclObject[] objv)
  148. {
  149. string name;
  150. Procedure proc;
  151. TclObject listObj;
  152. if (objv.Length != 3)
  153. {
  154. throw new TclNumArgsException(interp, 2, objv, "procname");
  155. }
  156. name = objv[2].ToString();
  157. proc = Procedure.findProc(interp, name);
  158. if (proc == null)
  159. {
  160. throw new TclException(interp, "\"" + name + "\" isn't a procedure");
  161. }
  162. // Build a return list containing the arguments.
  163. listObj = TclList.newInstance();
  164. for (int i = 0; i < proc.argList.Length; i++)
  165. {
  166. TclObject s = TclString.newInstance(proc.argList[i][0]);
  167. TclList.append(interp, listObj, s);
  168. }
  169. interp.setResult(listObj);
  170. return ;
  171. }
  172. /*
  173. *----------------------------------------------------------------------
  174. *
  175. * InfoBodyCmd --
  176. *
  177. * Called to implement the "info body" command that returns the body
  178. * for a procedure. Handles the following syntax:
  179. *
  180. * info body procName
  181. *
  182. * Results:
  183. * Returns if successful, raises TclException otherwise.
  184. *
  185. * Side effects:
  186. * Returns a result in the interpreter's result object.
  187. *
  188. *----------------------------------------------------------------------
  189. */
  190. private static void InfoBodyCmd(Interp interp, TclObject[] objv)
  191. {
  192. string name;
  193. Procedure proc;
  194. //TclObject body, result;
  195. if (objv.Length != 3)
  196. {
  197. throw new TclNumArgsException(interp, 2, objv, "procname");
  198. }
  199. name = objv[2].ToString();
  200. proc = Procedure.findProc(interp, name);
  201. if (proc == null)
  202. {
  203. throw new TclException(interp, "\"" + name + "\" isn't a procedure");
  204. }
  205. interp.setResult(proc.body.ToString());
  206. return ;
  207. }
  208. /*
  209. *----------------------------------------------------------------------
  210. *
  211. * InfoCmdCountCmd --
  212. *
  213. * Called to implement the "info cmdcount" command that returns the
  214. * number of commands that have been executed. Handles the following
  215. * syntax:
  216. *
  217. * info cmdcount
  218. *
  219. * Results:
  220. * Returns if successful, raises TclException otherwise.
  221. *
  222. * Side effects:
  223. * Returns a result in the interpreter's result object.
  224. *
  225. *----------------------------------------------------------------------
  226. */
  227. private static void InfoCmdCountCmd(Interp interp, TclObject[] objv)
  228. {
  229. if (objv.Length != 2)
  230. {
  231. throw new TclNumArgsException(interp, 2, objv, null);
  232. }
  233. interp.setResult(interp.cmdCount);
  234. return ;
  235. }
  236. /*
  237. *----------------------------------------------------------------------
  238. *
  239. * InfoCommandsCmd --
  240. *
  241. * Called to implement the "info commands" command that returns the
  242. * list of commands in the interpreter that match an optional pattern.
  243. * The pattern, if any, consists of an optional sequence of namespace
  244. * names separated by "::" qualifiers, which is followed by a
  245. * glob-style pattern that restricts which commands are returned.
  246. * Handles the following syntax:
  247. *
  248. * info commands ?pattern?
  249. *
  250. * Results:
  251. * Returns if successful, raises TclException otherwise.
  252. *
  253. * Side effects:
  254. * Returns a result in the interpreter's result object.
  255. *
  256. *----------------------------------------------------------------------
  257. */
  258. private static void InfoCommandsCmd(Interp interp, TclObject[] objv)
  259. {
  260. string cmdName, pattern, simplePattern;
  261. IDictionaryEnumerator search;
  262. NamespaceCmd.Namespace ns;
  263. NamespaceCmd.Namespace globalNs = NamespaceCmd.getGlobalNamespace(interp);
  264. NamespaceCmd.Namespace currNs = NamespaceCmd.getCurrentNamespace(interp);
  265. TclObject list, elemObj;
  266. bool specificNsInPattern = false; // Init. to avoid compiler warning.
  267. WrappedCommand cmd;
  268. // Get the pattern and find the "effective namespace" in which to
  269. // list commands.
  270. if (objv.Length == 2)
  271. {
  272. simplePattern = null;
  273. ns = currNs;
  274. specificNsInPattern = false;
  275. }
  276. else if (objv.Length == 3)
  277. {
  278. // From the pattern, get the effective namespace and the simple
  279. // pattern (no namespace qualifiers or ::'s) at the end. If an
  280. // error was found while parsing the pattern, return it. Otherwise,
  281. // if the namespace wasn't found, just leave ns NULL: we will
  282. // return an empty list since no commands there can be found.
  283. pattern = objv[2].ToString();
  284. // Java does not support passing an address so we pass
  285. // an array of size 1 and then assign arr[0] to the value
  286. NamespaceCmd.Namespace[] nsArr = new NamespaceCmd.Namespace[1];
  287. NamespaceCmd.Namespace[] dummy1Arr = new NamespaceCmd.Namespace[1];
  288. NamespaceCmd.Namespace[] dummy2Arr = new NamespaceCmd.Namespace[1];
  289. string[] simplePatternArr = new string[1];
  290. NamespaceCmd.getNamespaceForQualName(interp, pattern, null, 0, nsArr, dummy1Arr, dummy2Arr, simplePatternArr);
  291. // Get the values out of the arrays!
  292. ns = nsArr[0];
  293. simplePattern = simplePatternArr[0];
  294. if (ns != null)
  295. {
  296. // we successfully found the pattern's ns
  297. specificNsInPattern = (simplePattern.CompareTo(pattern) != 0);
  298. }
  299. }
  300. else
  301. {
  302. throw new TclNumArgsException(interp, 2, objv, "?pattern?");
  303. }
  304. // Scan through the effective namespace's command table and create a
  305. // list with all commands that match the pattern. If a specific
  306. // namespace was requested in the pattern, qualify the command names
  307. // with the namespace name.
  308. list = TclList.newInstance();
  309. if (ns != null)
  310. {
  311. search = ns.cmdTable.GetEnumerator();
  312. while (search.MoveNext())
  313. {
  314. cmdName = ((string) search.Key);
  315. if (((System.Object) simplePattern == null) || Util.stringMatch(cmdName, simplePattern))
  316. {
  317. if (specificNsInPattern)
  318. {
  319. cmd = (WrappedCommand)search.Value;
  320. elemObj = TclString.newInstance(interp.getCommandFullName(cmd));
  321. }
  322. else
  323. {
  324. elemObj = TclString.newInstance(cmdName);
  325. }
  326. TclList.append(interp, list, elemObj);
  327. }
  328. }
  329. // If the effective namespace isn't the global :: namespace, and a
  330. // specific namespace wasn't requested in the pattern, then add in
  331. // all global :: commands that match the simple pattern. Of course,
  332. // we add in only those commands that aren't hidden by a command in
  333. // the effective namespace.
  334. if ((ns != globalNs) && !specificNsInPattern)
  335. {
  336. search = globalNs.cmdTable.GetEnumerator();
  337. while (search.MoveNext())
  338. {
  339. cmdName = ((string)search.Key);
  340. if (((System.Object) simplePattern == null) || Util.stringMatch(cmdName, simplePattern))
  341. {
  342. if (ns.cmdTable[cmdName] == null)
  343. {
  344. TclList.append(interp, list, TclString.newInstance(cmdName));
  345. }
  346. }
  347. }
  348. }
  349. }
  350. interp.setResult(list);
  351. return ;
  352. }
  353. /*
  354. *----------------------------------------------------------------------
  355. *
  356. * InfoCompleteCmd --
  357. *
  358. * Called to implement the "info complete" command that determines
  359. * whether a string is a complete Tcl command. Handles the following
  360. * syntax:
  361. *
  362. * info complete command
  363. *
  364. * Results:
  365. * Returns if successful, raises TclException otherwise.
  366. *
  367. * Side effects:
  368. * Returns a result in the interpreter's result object.
  369. *
  370. *----------------------------------------------------------------------
  371. */
  372. private static void InfoCompleteCmd(Interp interp, TclObject[] objv)
  373. {
  374. if (objv.Length != 3)
  375. {
  376. throw new TclNumArgsException(interp, 2, objv, "command");
  377. }
  378. interp.setResult(tcl.lang.Interp.commandComplete(objv[2].ToString()));
  379. return ;
  380. }
  381. /*
  382. *----------------------------------------------------------------------
  383. *
  384. * InfoDefaultCmd --
  385. *
  386. * Called to implement the "info default" command that returns the
  387. * default value for a procedure argument. Handles the following
  388. * syntax:
  389. *
  390. * info default procName arg varName
  391. *
  392. * Results:
  393. * Returns if successful, raises TclException otherwise.
  394. *
  395. * Side effects:
  396. * Returns a result in the interpreter's result object.
  397. *
  398. *----------------------------------------------------------------------
  399. */
  400. private static void InfoDefaultCmd(Interp interp, TclObject[] objv)
  401. {
  402. string procName, argName, varName;
  403. Procedure proc;
  404. //TclObject valueObj;
  405. if (objv.Length != 5)
  406. {
  407. throw new TclNumArgsException(interp, 2, objv, "procname arg varname");
  408. }
  409. procName = objv[2].ToString();
  410. argName = objv[3].ToString();
  411. proc = Procedure.findProc(interp, procName);
  412. if (proc == null)
  413. {
  414. throw new TclException(interp, "\"" + procName + "\" isn't a procedure");
  415. }
  416. for (int i = 0; i < proc.argList.Length; i++)
  417. {
  418. if (argName.Equals(proc.argList[i][0].ToString()))
  419. {
  420. varName = objv[4].ToString();
  421. try
  422. {
  423. if (proc.argList[i][1] != null)
  424. {
  425. interp.setVar(varName, proc.argList[i][1], 0);
  426. interp.setResult(1);
  427. }
  428. else
  429. {
  430. interp.setVar(varName, "", 0);
  431. interp.setResult(0);
  432. }
  433. }
  434. catch (TclException excp)
  435. {
  436. throw new TclException(interp, "couldn't store default value in variable \"" + varName + "\"");
  437. }
  438. return ;
  439. }
  440. }
  441. throw new TclException(interp, "procedure \"" + procName + "\" doesn't have an argument \"" + argName + "\"");
  442. }
  443. /*
  444. *----------------------------------------------------------------------
  445. *
  446. * InfoExistsCmd --
  447. *
  448. * Called to implement the "info exists" command that determines
  449. * whether a variable exists. Handles the following syntax:
  450. *
  451. * info exists varName
  452. *
  453. * Results:
  454. * Returns if successful, raises TclException otherwise.
  455. *
  456. * Side effects:
  457. * Returns a result in the interpreter's result object.
  458. *
  459. *----------------------------------------------------------------------
  460. */
  461. private static void InfoExistsCmd(Interp interp, TclObject[] objv)
  462. {
  463. string varName;
  464. Var var = null;
  465. if (objv.Length != 3)
  466. {
  467. throw new TclNumArgsException(interp, 2, objv, "varName");
  468. }
  469. varName = objv[2].ToString();
  470. Var[] result = Var.lookupVar(interp, varName, null, 0, "access", false, false);
  471. if (result != null)
  472. {
  473. var = result[0];
  474. }
  475. if ((var != null) && !var.isVarUndefined())
  476. {
  477. interp.setResult(true);
  478. }
  479. else
  480. {
  481. interp.setResult(false);
  482. }
  483. return ;
  484. }
  485. /*
  486. *----------------------------------------------------------------------
  487. *
  488. * InfoGlobalsCmd --
  489. *
  490. * Called to implement the "info globals" command that returns the list
  491. * of global variables matching an optional pattern. Handles the
  492. * following syntax:
  493. *
  494. * info globals ?pattern?*
  495. *
  496. * Results:
  497. * Returns if successful, raises TclException otherwise.
  498. *
  499. * Side effects:
  500. * Returns a result in the interpreter's result object.
  501. *
  502. *----------------------------------------------------------------------
  503. */
  504. private static void InfoGlobalsCmd(Interp interp, TclObject[] objv)
  505. {
  506. string varName, pattern;
  507. NamespaceCmd.Namespace globalNs = NamespaceCmd.getGlobalNamespace(interp);
  508. IDictionaryEnumerator search;
  509. Var var;
  510. TclObject list;
  511. if (objv.Length == 2)
  512. {
  513. pattern = null;
  514. }
  515. else if (objv.Length == 3)
  516. {
  517. pattern = objv[2].ToString();
  518. }
  519. else
  520. {
  521. throw new TclNumArgsException(interp, 2, objv, "?pattern?");
  522. }
  523. // Scan through the global :: namespace's variable table and create a
  524. // list of all global variables that match the pattern.
  525. list = TclList.newInstance();
  526. for (search = globalNs.varTable.GetEnumerator(); search.MoveNext(); )
  527. {
  528. varName = ((string) search.Key);
  529. var = (Var)search.Value;
  530. if (var.isVarUndefined())
  531. {
  532. continue;
  533. }
  534. if (((System.Object) pattern == null) || Util.stringMatch(varName, pattern))
  535. {
  536. TclList.append(interp, list, TclString.newInstance(varName));
  537. }
  538. }
  539. interp.setResult(list);
  540. return ;
  541. }
  542. /*
  543. *----------------------------------------------------------------------
  544. *
  545. * InfoHostnameCmd --
  546. *
  547. * Called to implement the "info hostname" command that returns the
  548. * host name. Handles the following syntax:
  549. *
  550. * info hostname
  551. *
  552. * Results:
  553. * Returns if successful, raises TclException otherwise.
  554. *
  555. * Side effects:
  556. * Returns a result in the interpreter's result object.
  557. *
  558. *----------------------------------------------------------------------
  559. */
  560. private static void InfoHostnameCmd(Interp interp, TclObject[] objv)
  561. {
  562. string name;
  563. if (objv.Length != 2)
  564. {
  565. throw new TclNumArgsException(interp, 2, objv, null);
  566. }
  567. // FIXME : how can we find the hostname
  568. name = null;
  569. if ((System.Object) name != null)
  570. {
  571. interp.setResult(name);
  572. return ;
  573. }
  574. else
  575. {
  576. interp.setResult("unable to determine name of host");
  577. return ;
  578. }
  579. }
  580. /*
  581. *----------------------------------------------------------------------
  582. *
  583. * InfoLevelCmd --
  584. *
  585. * Called to implement the "info level" command that returns
  586. * information about the call stack. Handles the following syntax:
  587. *
  588. * info level ?number?
  589. *
  590. * Results:
  591. * Returns if successful, raises TclException otherwise.
  592. *
  593. * Side effects:
  594. * Returns a result in the interpreter's result object.
  595. *
  596. *----------------------------------------------------------------------
  597. */
  598. private static void InfoLevelCmd(Interp interp, TclObject[] objv)
  599. {
  600. int level;
  601. CallFrame frame;
  602. TclObject list;
  603. if (objv.Length == 2)
  604. {
  605. // just "info level"
  606. if (interp.varFrame == null)
  607. {
  608. interp.setResult(0);
  609. }
  610. else
  611. {
  612. interp.setResult(interp.varFrame.level);
  613. }
  614. return ;
  615. }
  616. else if (objv.Length == 3)
  617. {
  618. level = TclInteger.get(interp, objv[2]);
  619. if (level <= 0)
  620. {
  621. if (interp.varFrame == null)
  622. {
  623. throw new TclException(interp, "bad level \"" + objv[2].ToString() + "\"");
  624. }
  625. level += interp.varFrame.level;
  626. }
  627. for (frame = interp.varFrame; frame != null; frame = frame.callerVar)
  628. {
  629. if (frame.level == level)
  630. {
  631. break;
  632. }
  633. }
  634. if ((frame == null) || frame.objv == null)
  635. {
  636. throw new TclException(interp, "bad level \"" + objv[2].ToString() + "\"");
  637. }
  638. list = TclList.newInstance();
  639. for (int i = 0; i < frame.objv.Length; i++)
  640. {
  641. TclList.append(interp, list, TclString.newInstance(frame.objv[i]));
  642. }
  643. interp.setResult(list);
  644. return ;
  645. }
  646. throw new TclNumArgsException(interp, 2, objv, "?number?");
  647. }
  648. /*
  649. *----------------------------------------------------------------------
  650. *
  651. * InfoLibraryCmd --
  652. *
  653. * Called to implement the "info library" command that returns the
  654. * library directory for the Tcl installation. Handles the following
  655. * syntax:
  656. *
  657. * info library
  658. *
  659. * Results:
  660. * Returns if successful, raises TclException otherwise.
  661. *
  662. * Side effects:
  663. * Returns a result in the interpreter's result object.
  664. *
  665. *----------------------------------------------------------------------
  666. */
  667. private static void InfoLibraryCmd(Interp interp, TclObject[] objv)
  668. {
  669. if (objv.Length != 2)
  670. {
  671. throw new TclNumArgsException(interp, 2, objv, null);
  672. }
  673. try
  674. {
  675. interp.setResult(interp.getVar("tcl_library", TCL.VarFlag.GLOBAL_ONLY));
  676. return ;
  677. }
  678. catch (TclException e)
  679. {
  680. // If the variable has not been defined
  681. throw new TclException(interp, "no library has been specified for Tcl");
  682. }
  683. }
  684. /*
  685. *----------------------------------------------------------------------
  686. *
  687. * InfoLoadedCmd --
  688. *
  689. * Called to implement the "info loaded" command that returns the
  690. * packages that have been loaded into an interpreter. Handles the
  691. * following syntax:
  692. *
  693. * info loaded ?interp?
  694. *
  695. * Results:
  696. * Returns if successful, raises TclException otherwise.
  697. *
  698. * Side effects:
  699. * Returns a result in the interpreter's result object.
  700. *
  701. *----------------------------------------------------------------------
  702. */
  703. private static void InfoLoadedCmd(Interp interp, TclObject[] objv)
  704. {
  705. if (objv.Length != 2 && objv.Length != 3)
  706. {
  707. throw new TclNumArgsException(interp, 2, objv, "?interp?");
  708. }
  709. // FIXME : what should "info loaded" return?
  710. throw new TclException(interp, "info loaded not implemented");
  711. }
  712. /*
  713. *----------------------------------------------------------------------
  714. *
  715. * InfoLocalsCmd --
  716. *
  717. * Called to implement the "info locals" command to return a list of
  718. * local variables that match an optional pattern. Handles the
  719. * following syntax:
  720. *
  721. * info locals ?pattern?
  722. *
  723. * Results:
  724. * Returns if successful, raises TclException otherwise.
  725. *
  726. * Side effects:
  727. * Returns a result in the interpreter's result object.
  728. *
  729. *----------------------------------------------------------------------
  730. */
  731. private static void InfoLocalsCmd(Interp interp, TclObject[] objv)
  732. {
  733. string pattern;
  734. TclObject list;
  735. if (objv.Length == 2)
  736. {
  737. pattern = null;
  738. }
  739. else if (objv.Length == 3)
  740. {
  741. pattern = objv[2].ToString();
  742. }
  743. else
  744. {
  745. throw new TclNumArgsException(interp, 2, objv, "?pattern?");
  746. }
  747. if (interp.varFrame == null || !interp.varFrame.isProcCallFrame)
  748. {
  749. return ;
  750. }
  751. // Return a list containing names of first the compiled locals (i.e. the
  752. // ones stored in the call frame), then the variables in the local hash
  753. // table (if one exists).
  754. list = TclList.newInstance();
  755. AppendLocals(interp, list, pattern, false);
  756. interp.setResult(list);
  757. return ;
  758. }
  759. /*
  760. *----------------------------------------------------------------------
  761. *
  762. * AppendLocals --
  763. *
  764. * Append the local variables for the current frame to the
  765. * specified list object.
  766. *
  767. * Results:
  768. * None.
  769. *
  770. * Side effects:
  771. * None.
  772. *
  773. *----------------------------------------------------------------------
  774. */
  775. private static void AppendLocals(Interp interp, TclObject list, string pattern, bool includeLinks)
  776. {
  777. Var var;
  778. string varName;
  779. Hashtable localVarTable;
  780. IDictionaryEnumerator search;
  781. localVarTable = interp.varFrame.varTable;
  782. // Compiled locals do not exist in Jacl
  783. if (localVarTable != null)
  784. {
  785. for (search = localVarTable.GetEnumerator(); search.MoveNext(); )
  786. {
  787. var = (Var)search.Value;
  788. varName = (string)search.Key;
  789. if (!var.isVarUndefined() && (includeLinks || !var.isVarLink()))
  790. {
  791. if (((System.Object) pattern == null) || Util.stringMatch(varName, pattern))
  792. {
  793. TclList.append(interp, list, TclString.newInstance(varName));
  794. }
  795. }
  796. }
  797. }
  798. }
  799. /*
  800. *----------------------------------------------------------------------
  801. *
  802. * InfoNameOfExecutableCmd --
  803. *
  804. * Called to implement the "info nameofexecutable" command that returns
  805. * the name of the binary file running this application. Handles the
  806. * following syntax:
  807. *
  808. * info nameofexecutable
  809. *
  810. * Results:
  811. * Returns if successful, raises TclException otherwise.
  812. *
  813. * Side effects:
  814. * Returns a result in the interpreter's result object.
  815. *
  816. *----------------------------------------------------------------------
  817. */
  818. private static void InfoNameOfExecutableCmd(Interp interp, TclObject[] objv)
  819. {
  820. if (objv.Length != 2)
  821. {
  822. throw new TclNumArgsException(interp, 2, objv, null);
  823. }
  824. // We depend on a user defined property named "JAVA" since
  825. // the JDK provides no means to learn the name of the executable
  826. // that launched the application.
  827. string nameOfExecutable = "nacl";
  828. if ((System.Object) nameOfExecutable != null)
  829. {
  830. TclObject result = TclList.newInstance();
  831. TclList.append(interp, result, TclString.newInstance(nameOfExecutable));
  832. TclList.append(interp, result, TclString.newInstance("tcl.lang.Shell"));
  833. interp.setResult(result);
  834. }
  835. return ;
  836. }
  837. /*
  838. *----------------------------------------------------------------------
  839. *
  840. * InfoPatchLevelCmd --
  841. *
  842. * Called to implement the "info patchlevel" command that returns the
  843. * default value for an argument to a procedure. Handles the following
  844. * syntax:
  845. *
  846. * info patchlevel
  847. *
  848. * Results:
  849. * Returns if successful, raises TclException otherwise.
  850. *
  851. * Side effects:
  852. * Returns a result in the interpreter's result object.
  853. *
  854. *----------------------------------------------------------------------
  855. */
  856. private static void InfoPatchLevelCmd(Interp interp, TclObject[] objv)
  857. {
  858. if (objv.Length != 2)
  859. {
  860. throw new TclNumArgsException(interp, 2, objv, null);
  861. }
  862. interp.setResult(interp.getVar("tcl_patchLevel", TCL.VarFlag.GLOBAL_ONLY));
  863. return ;
  864. }
  865. /*
  866. *----------------------------------------------------------------------
  867. *
  868. * InfoProcsCmd --
  869. *
  870. * Called to implement the "info procs" command that returns the
  871. * procedures in the current namespace that match an optional pattern.
  872. * Handles the following syntax:
  873. *
  874. * info procs ?pattern?
  875. *
  876. * Results:
  877. * Returns if successful, raises TclException otherwise.
  878. *
  879. * Side effects:
  880. * Returns a result in the interpreter's result object.
  881. *
  882. *----------------------------------------------------------------------
  883. */
  884. private static void InfoProcsCmd(Interp interp, TclObject[] objv)
  885. {
  886. string cmdName, pattern;
  887. NamespaceCmd.Namespace currNs = NamespaceCmd.getCurrentNamespace(interp);
  888. IDictionaryEnumerator search;
  889. WrappedCommand cmd, realCmd;
  890. TclObject list;
  891. if (objv.Length == 2)
  892. {
  893. pattern = null;
  894. }
  895. else if (objv.Length == 3)
  896. {
  897. pattern = objv[2].ToString();
  898. }
  899. else
  900. {
  901. throw new TclNumArgsException(interp, 2, objv, "?pattern?");
  902. }
  903. // Scan through the current namespace's command table and return a list
  904. // of all procs that match the pattern.
  905. list = TclList.newInstance();
  906. for (search = currNs.cmdTable.GetEnumerator(); search.MoveNext(); )
  907. {
  908. cmdName = ((string)search.Key);
  909. cmd = (WrappedCommand)search.Value;
  910. // If the command isn't itself a proc, it still might be an
  911. // imported command that points to a "real" proc in a different
  912. // namespace.
  913. realCmd = NamespaceCmd.getOriginalCommand(cmd);
  914. if (Procedure.isProc(cmd) || ((realCmd != null) && Procedure.isProc(realCmd)))
  915. {
  916. if (((System.Object) pattern == null) || Util.stringMatch(cmdName, pattern))
  917. {
  918. TclList.append(interp, list, TclString.newInstance(cmdName));
  919. }
  920. }
  921. }
  922. interp.setResult(list);
  923. return ;
  924. }
  925. /*
  926. *----------------------------------------------------------------------
  927. *
  928. * InfoScriptCmd --
  929. *
  930. * Called to implement the "info script" command that returns the
  931. * script file that is currently being evaluated. Handles the
  932. * following syntax:
  933. *
  934. * info script
  935. *
  936. * Results:
  937. * Returns if successful, raises TclException otherwise.
  938. *
  939. * Side effects:
  940. * Returns a result in the interpreter's result object.
  941. *
  942. *----------------------------------------------------------------------
  943. */
  944. private static void InfoScriptCmd(Interp interp, TclObject[] objv)
  945. {
  946. if (objv.Length != 2)
  947. {
  948. throw new TclNumArgsException(interp, 2, objv, null);
  949. }
  950. interp.setResult(interp.scriptFile);
  951. return ;
  952. }
  953. /*
  954. *----------------------------------------------------------------------
  955. *
  956. * InfoSharedlibCmd --
  957. *
  958. * Called to implement the "info sharedlibextension" command that
  959. * returns the file extension used for shared libraries. Handles the
  960. * following syntax:
  961. *
  962. * info sharedlibextension
  963. *
  964. * Results:
  965. * Returns if successful, raises TclException otherwise.
  966. *
  967. * Side effects:
  968. * Returns a result in the interpreter's result object.
  969. *
  970. *----------------------------------------------------------------------
  971. */
  972. private static void InfoSharedlibCmd(Interp interp, TclObject[] objv)
  973. {
  974. if (objv.Length != 2)
  975. {
  976. throw new TclNumArgsException(interp, 2, objv, null);
  977. }
  978. interp.setResult(".jar");
  979. return ;
  980. }
  981. /*
  982. *----------------------------------------------------------------------
  983. *
  984. * InfoTclVersionCmd --
  985. *
  986. * Called to implement the "info tclversion" command that returns the
  987. * version number for this Tcl library. Handles the following syntax:
  988. *
  989. * info tclversion
  990. *
  991. * Results:
  992. * Returns if successful, raises TclException otherwise.
  993. *
  994. * Side effects:
  995. * Returns a result in the interpreter's result object.
  996. *
  997. *----------------------------------------------------------------------
  998. */
  999. private static void InfoTclVersionCmd(Interp interp, TclObject[] objv)
  1000. {
  1001. if (objv.Length != 2)
  1002. {
  1003. throw new TclNumArgsException(interp, 2, objv, null);
  1004. }
  1005. interp.setResult(interp.getVar("tcl_version", TCL.VarFlag.GLOBAL_ONLY));
  1006. return ;
  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. private static void InfoVarsCmd(Interp interp, TclObject[] objv)
  1031. {
  1032. string varName, pattern, simplePattern;
  1033. IDictionaryEnumerator search;
  1034. Var var;
  1035. NamespaceCmd.Namespace ns;
  1036. NamespaceCmd.Namespace globalNs = NamespaceCmd.getGlobalNamespace(interp);
  1037. NamespaceCmd.Namespace currNs = NamespaceCmd.getCurrentNamespace(interp);
  1038. TclObject list, elemObj;
  1039. bool specificNsInPattern = false; // Init. to avoid compiler warning.
  1040. // Get the pattern and find the "effective namespace" in which to
  1041. // list variables. We only use this effective namespace if there's
  1042. // no active Tcl procedure frame.
  1043. if (objv.Length == 2)
  1044. {
  1045. simplePattern = null;
  1046. ns = currNs;
  1047. specificNsInPattern = false;
  1048. }
  1049. else if (objv.Length == 3)
  1050. {
  1051. // From the pattern, get the effective namespace and the simple
  1052. // pattern (no namespace qualifiers or ::'s) at the end. If an
  1053. // error was found while parsing the pattern, return it. Otherwise,
  1054. // if the namespace wasn't found, just leave ns = null: we will
  1055. // return an empty list since no variables there can be found.
  1056. pattern = objv[2].ToString();
  1057. // Java does not support passing an address so we pass
  1058. // an array of size 1 and then assign arr[0] to the value
  1059. NamespaceCmd.Namespace[] nsArr = new NamespaceCmd.Namespace[1];
  1060. NamespaceCmd.Namespace[] dummy1Arr = new NamespaceCmd.Namespace[1];
  1061. NamespaceCmd.Namespace[] dummy2Arr = new NamespaceCmd.Namespace[1];
  1062. string[] simplePatternArr = new string[1];
  1063. NamespaceCmd.getNamespaceForQualName(interp, pattern, null, 0, nsArr, dummy1Arr, dummy2Arr, simplePatternArr);
  1064. // Get the values out of the arrays!
  1065. ns = nsArr[0];
  1066. simplePattern = simplePatternArr[0];
  1067. if (ns != null)
  1068. {
  1069. // we successfully found the pattern's ns
  1070. specificNsInPattern = (simplePattern.CompareTo(pattern) != 0);
  1071. }
  1072. }
  1073. else
  1074. {
  1075. throw new TclNumArgsException(interp, 2, objv, "?pattern?");
  1076. }
  1077. // If the namespace specified in the pattern wasn't found, just return.
  1078. if (ns == null)
  1079. {
  1080. return ;
  1081. }
  1082. list = TclList.newInstance();
  1083. if ((interp.varFrame == null) || !interp.varFrame.isProcCallFrame || specificNsInPattern)
  1084. {
  1085. // There is no frame pointer, the frame pointer was pushed only
  1086. // to activate a namespace, or we are in a procedure call frame
  1087. // but a specific namespace was specified. Create a list containing
  1088. // only the variables in the effective namespace's variable table.
  1089. search = ns.varTable.GetEnumerator();
  1090. while (search.MoveNext())
  1091. {
  1092. varName = ((string) search.Key);
  1093. var = (Var)search.Value;
  1094. if (!var.isVarUndefined() || ((var.flags & VarFlags.NAMESPACE_VAR) != 0))
  1095. {
  1096. if (((System.Object) simplePattern == null) || Util.stringMatch(varName, simplePattern))
  1097. {
  1098. if (specificNsInPattern)
  1099. {
  1100. elemObj = TclString.newInstance(Var.getVariableFullName(interp, var));
  1101. }
  1102. else
  1103. {
  1104. elemObj = TclString.newInstance(varName);
  1105. }
  1106. TclList.append(interp, list, elemObj);
  1107. }
  1108. }
  1109. }
  1110. // If the effective namespace isn't the global :: namespace, and a
  1111. // specific namespace wasn't requested in the pattern (i.e., the
  1112. // pattern only specifies variable names), then add in all global ::
  1113. // variables that match the simple pattern. Of course, add in only
  1114. // those variables that aren't hidden by a variable in the effective
  1115. // namespace.
  1116. if ((ns != globalNs) && !specificNsInPattern)
  1117. {
  1118. search = globalNs.varTable.GetEnumerator();
  1119. while (search.MoveNext())
  1120. {
  1121. varName = ((string) search.Key);
  1122. var = (Var)search.Value;
  1123. if (!var.isVarUndefined() || ((var.flags & VarFlags.NAMESPACE_VAR) != 0))
  1124. {
  1125. if (((System.Object) simplePattern == null) || Util.stringMatch(varName, simplePattern))
  1126. {
  1127. // Skip vars defined in current namespace
  1128. if (ns.varTable[varName] == null)
  1129. {
  1130. TclList.append(interp, list, TclString.newInstance(varName));
  1131. }
  1132. }
  1133. }
  1134. }
  1135. }
  1136. }
  1137. else
  1138. {
  1139. AppendLocals(interp, list, simplePattern, true);
  1140. }
  1141. interp.setResult(list);
  1142. return ;
  1143. }
  1144. }
  1145. }