PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/TCL/src/commands/InfoCmd.cs

https://bitbucket.org/eumario/csharp-sqlite
C# | 1309 lines | 656 code | 164 blank | 489 comment | 169 complexity | aa19eb71b0b39e253f51573cfe772417 MD5 | raw file
  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. *
  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. }