PageRenderTime 774ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/TCL/src/commands/NamespaceCmd.cs

https://bitbucket.org/eumario/csharp-sqlite
C# | 3674 lines | 1648 code | 560 blank | 1466 comment | 432 complexity | f366282c31d27bc290d1b7945940f83f MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. #undef DEBUG
  2. /*
  3. * NamespaceCmd.java
  4. *
  5. * Copyright (c) 1993-1997 Lucent Technologies.
  6. * Copyright (c) 1997 Sun Microsystems, Inc.
  7. * Copyright (c) 1998-1999 by Scriptics Corporation.
  8. * Copyright (c) 1999 Moses DeJong
  9. *
  10. * Originally implemented by
  11. * Michael J. McLennan
  12. * Bell Labs Innovations for Lucent Technologies
  13. * mmclennan@lucent.com
  14. *
  15. * See the file "license.terms" for information on usage and
  16. * redistribution of this file, and for a DISCLAIMER OF ALL
  17. * WARRANTIES.
  18. *
  19. * Included in SQLite3 port to C# for use in testharness only; 2008 Noah B Hart
  20. *
  21. * RCS @(#) $Id: NamespaceCmd.java,v 1.12 2001/05/05 22:38:13 mdejong Exp $
  22. */
  23. using System;
  24. using System.Collections;
  25. using System.Text;
  26. namespace tcl.lang
  27. {
  28. /// <summary> This class implements the built-in "namespace" command in Tcl.
  29. /// See the user documentation for details on what it does.
  30. /// </summary>
  31. public class NamespaceCmd : InternalRep, Command
  32. {
  33. // Flag passed to getNamespaceForQualName to indicate that it should
  34. // search for a namespace rather than a command or variable inside a
  35. // namespace. Note that this flag's value must not conflict with the values
  36. // of TCL.VarFlag.GLOBAL_ONLY, TCL.VarFlag.NAMESPACE_ONLY, or TCL.VarFlag.CREATE_NS_IF_UNKNOWN.
  37. // Initial size of stack allocated space for tail list - used when resetting
  38. // shadowed command references in the functin: TclResetShadowedCmdRefs.
  39. //private static final int NUM_TRAIL_ELEMS = 5;
  40. // Count of the number of namespaces created. This value is used as a
  41. // unique id for each namespace.
  42. private static long numNsCreated = 0;
  43. private static Object nsMutex;
  44. //
  45. // Flags used to represent the status of a namespace:
  46. //
  47. // NS_DYING - 1 means deleteNamespace has been called to delete the
  48. // namespace but there are still active call frames on the Tcl
  49. // stack that refer to the namespace. When the last call frame
  50. // referring to it has been popped, it's variables and command
  51. // will be destroyed and it will be marked "dead" (NS_DEAD).
  52. // The namespace can no longer be looked up by name.
  53. // NS_DEAD - 1 means deleteNamespace has been called to delete the
  54. // namespace and no call frames still refer to it. Its
  55. // variables and command have already been destroyed. This bit
  56. // allows the namespace resolution code to recognize that the
  57. // namespace is "deleted". When the last namespaceName object
  58. // in any byte code code unit that refers to the namespace has
  59. // been freed (i.e., when the namespace's refCount is 0), the
  60. // namespace's storage will be freed.
  61. internal const int NS_DYING = 0x01;
  62. internal const int NS_DEAD = 0x02;
  63. // Flag passed to getNamespaceForQualName to have it create all namespace
  64. // components of a namespace-qualified name that cannot be found. The new
  65. // namespaces are created within their specified parent. Note that this
  66. // flag's value must not conflict with the values of the flags
  67. // TCL.VarFlag.GLOBAL_ONLY, TCL.VarFlag.NAMESPACE_ONLY, and TCL.VarFlag.FIND_ONLY_NS
  68. // internal const int TCL.VarFlag.CREATE_NS_IF_UNKNOWN = 0x800;
  69. // This value corresponds to the Tcl_Obj.otherValuePtr pointer used
  70. // in the C version of Tcl 8.1. Use it to keep track of a ResolvedNsName.
  71. private ResolvedNsName otherValue = null;
  72. /*
  73. *----------------------------------------------------------------------
  74. *
  75. * Tcl_GetCurrentNamespace -> getCurrentNamespace
  76. *
  77. * Returns a reference to an interpreter's currently active namespace.
  78. *
  79. * Results:
  80. * Returns a reference to the interpreter's current namespace.
  81. *
  82. * Side effects:
  83. * None.
  84. *
  85. *----------------------------------------------------------------------
  86. */
  87. internal static Namespace getCurrentNamespace( Interp interp )
  88. {
  89. if ( interp.varFrame != null )
  90. {
  91. return interp.varFrame.ns;
  92. }
  93. else
  94. {
  95. return interp.globalNs;
  96. }
  97. }
  98. /*
  99. *----------------------------------------------------------------------
  100. *
  101. * Tcl_GetGlobalNamespace -> getGlobalNamespace
  102. *
  103. * Returns a reference to an interpreter's global :: namespace.
  104. *
  105. * Results:
  106. * Returns a reference to the specified interpreter's global namespace.
  107. *
  108. * Side effects:
  109. * None.
  110. *
  111. *----------------------------------------------------------------------
  112. */
  113. internal static Namespace getGlobalNamespace( Interp interp )
  114. {
  115. return interp.globalNs;
  116. }
  117. /*
  118. *----------------------------------------------------------------------
  119. *
  120. * Tcl_PushCallFrame -> pushCallFrame
  121. *
  122. * Pushes a new call frame onto the interpreter's Tcl call stack.
  123. * Called when executing a Tcl procedure or a "namespace eval" or
  124. * "namespace inscope" command.
  125. *
  126. * Results:
  127. * Returns if successful, raises TclException if something goes wrong.
  128. *
  129. * Side effects:
  130. * Modifies the interpreter's Tcl call stack.
  131. *
  132. *----------------------------------------------------------------------
  133. */
  134. internal static void pushCallFrame( Interp interp, CallFrame frame, Namespace namespace_Renamed, bool isProcCallFrame )
  135. // If true, the frame represents a
  136. // called Tcl procedure and may have local
  137. // vars. Vars will ordinarily be looked up
  138. // in the frame. If new variables are
  139. // created, they will be created in the
  140. // frame. If false, the frame is for a
  141. // "namespace eval" or "namespace inscope"
  142. // command and var references are treated
  143. // as references to namespace variables.
  144. {
  145. Namespace ns;
  146. if ( namespace_Renamed == null )
  147. {
  148. ns = getCurrentNamespace( interp );
  149. }
  150. else
  151. {
  152. ns = namespace_Renamed;
  153. if ( ( ns.flags & NS_DEAD ) != 0 )
  154. {
  155. throw new TclRuntimeError( "Trying to push call frame for dead namespace" );
  156. }
  157. }
  158. ns.activationCount++;
  159. frame.ns = ns;
  160. frame.isProcCallFrame = isProcCallFrame;
  161. frame.objv = null;
  162. frame.caller = interp.frame;
  163. frame.callerVar = interp.varFrame;
  164. if ( interp.varFrame != null )
  165. {
  166. frame.level = ( interp.varFrame.level + 1 );
  167. }
  168. else
  169. {
  170. frame.level = 1;
  171. }
  172. // FIXME : does Jacl need a procPtr in the CallFrame class?
  173. //frame.procPtr = null; // no called procedure
  174. frame.varTable = null; // and no local variables
  175. // Compiled locals are not part of Jacl's CallFrame
  176. // Push the new call frame onto the interpreter's stack of procedure
  177. // call frames making it the current frame.
  178. interp.frame = frame;
  179. interp.varFrame = frame;
  180. }
  181. /*
  182. *----------------------------------------------------------------------
  183. *
  184. * Tcl_PopCallFrame -> popCallFrame
  185. *
  186. * Removes a call frame from the Tcl call stack for the interpreter.
  187. * Called to remove a frame previously pushed by Tcl_PushCallFrame.
  188. *
  189. * Results:
  190. * None.
  191. *
  192. * Side effects:
  193. * Modifies the call stack of the interpreter. Resets various fields of
  194. * the popped call frame. If a namespace has been deleted and
  195. * has no more activations on the call stack, the namespace is
  196. * destroyed.
  197. *
  198. *----------------------------------------------------------------------
  199. */
  200. internal static void popCallFrame( Interp interp )
  201. {
  202. CallFrame frame = interp.frame;
  203. int saveErrFlag;
  204. Namespace ns;
  205. // It's important to remove the call frame from the interpreter's stack
  206. // of call frames before deleting local variables, so that traces
  207. // invoked by the variable deletion don't see the partially-deleted
  208. // frame.
  209. interp.frame = frame.caller;
  210. interp.varFrame = frame.callerVar;
  211. // Delete the local variables. As a hack, we save then restore the
  212. // ERR_IN_PROGRESS flag in the interpreter. The problem is that there
  213. // could be unset traces on the variables, which cause scripts to be
  214. // evaluated. This will clear the ERR_IN_PROGRESS flag, losing stack
  215. // trace information if the procedure was exiting with an error. The
  216. // code below preserves the flag. Unfortunately, that isn't really
  217. // enough: we really should preserve the errorInfo variable too
  218. // (otherwise a nested error in the trace script will trash errorInfo).
  219. // What's really needed is a general-purpose mechanism for saving and
  220. // restoring interpreter state.
  221. saveErrFlag = ( interp.flags & Parser.ERR_IN_PROGRESS );
  222. if ( frame.varTable != null )
  223. {
  224. Var.deleteVars( interp, frame.varTable );
  225. frame.varTable = null;
  226. }
  227. interp.flags |= saveErrFlag;
  228. // Decrement the namespace's count of active call frames. If the
  229. // namespace is "dying" and there are no more active call frames,
  230. // call Tcl_DeleteNamespace to destroy it.
  231. ns = frame.ns;
  232. ns.activationCount--;
  233. if ( ( ( ns.flags & NS_DYING ) != 0 ) && ( ns.activationCount == 0 ) )
  234. {
  235. deleteNamespace( ns );
  236. }
  237. frame.ns = null;
  238. }
  239. /*
  240. *----------------------------------------------------------------------
  241. *
  242. * Tcl_CreateNamespace --
  243. *
  244. * Creates a new namespace with the given name. If there is no
  245. * active namespace (i.e., the interpreter is being initialized),
  246. * the global :: namespace is created and returned.
  247. *
  248. * Results:
  249. * Returns a reference to the new namespace if successful. If the
  250. * namespace already exists or if another error occurs, this routine
  251. * returns null, along with an error message in the interpreter's
  252. * result object.
  253. *
  254. * Side effects:
  255. * If the name contains "::" qualifiers and a parent namespace does
  256. * not already exist, it is automatically created.
  257. *
  258. *----------------------------------------------------------------------
  259. */
  260. internal static Namespace createNamespace( Interp interp, string name, DeleteProc deleteProc )
  261. {
  262. Namespace ns, ancestor;
  263. Namespace parent;
  264. Namespace globalNs = getGlobalNamespace( interp );
  265. string simpleName;
  266. StringBuilder buffer1, buffer2;
  267. // If there is no active namespace, the interpreter is being
  268. // initialized.
  269. if ( ( globalNs == null ) && ( interp.varFrame == null ) )
  270. {
  271. // Treat this namespace as the global namespace, and avoid
  272. // looking for a parent.
  273. parent = null;
  274. simpleName = "";
  275. }
  276. else if ( name.Length == 0 )
  277. {
  278. /*
  279. TclObject tobj = interp.getResult();
  280. // FIXME : is there a test case to check this error result?
  281. TclString.append(tobj,
  282. "can't create namespace \"\": only global namespace can have empty name");
  283. */
  284. // FIXME : is there a test case to check this error result?
  285. interp.setResult( "can't create namespace \"\": only global namespace can have empty name" );
  286. return null;
  287. }
  288. else
  289. {
  290. // Find the parent for the new namespace.
  291. // Java does not support passing an address so we pass
  292. // an array of size 1 and then assign arr[0] to the value
  293. Namespace[] parentArr = new Namespace[1];
  294. Namespace[] dummyArr = new Namespace[1];
  295. string[] simpleArr = new string[1];
  296. getNamespaceForQualName( interp, name, null, ( TCL.VarFlag.CREATE_NS_IF_UNKNOWN | TCL.VarFlag.LEAVE_ERR_MSG ), parentArr, dummyArr, dummyArr, simpleArr );
  297. // Get the values out of the arrays!
  298. parent = parentArr[0];
  299. simpleName = simpleArr[0];
  300. // If the unqualified name at the end is empty, there were trailing
  301. // "::"s after the namespace's name which we ignore. The new
  302. // namespace was already (recursively) created and is referenced
  303. // by parent.
  304. if ( simpleName.Length == 0 )
  305. {
  306. return parent;
  307. }
  308. // Check for a bad namespace name and make sure that the name
  309. // does not already exist in the parent namespace.
  310. if ( parent.childTable[simpleName] != null )
  311. {
  312. /*
  313. TclObject tobj = interp.getResult();
  314. // FIXME : is there a test case to check this error result?
  315. TclString.append(tobj,
  316. "can't create namespace \"" + name + "\": already exists");
  317. */
  318. // FIXME : is there a test case to check this error result?
  319. interp.setResult( "can't create namespace \"" + name + "\": already exists" );
  320. return null;
  321. }
  322. }
  323. // Create the new namespace and root it in its parent. Increment the
  324. // count of namespaces created.
  325. ns = new Namespace();
  326. ns.name = simpleName;
  327. ns.fullName = null; // set below
  328. //ns.clientData = clientData;
  329. ns.deleteProc = deleteProc;
  330. ns.parent = parent;
  331. ns.childTable = new Hashtable();
  332. lock ( nsMutex )
  333. {
  334. numNsCreated++;
  335. ns.nsId = numNsCreated;
  336. }
  337. ns.interp = interp;
  338. ns.flags = 0;
  339. ns.activationCount = 0;
  340. // FIXME : there was a problem with the refcount because
  341. // when the namespace was deleted the refocount was 0.
  342. // We avoid this by just using a refcount of 1 for now.
  343. // We can do ignore the refCount because GC will reclaim mem.
  344. //ns.refCount = 0;
  345. ns.refCount = 1;
  346. ns.cmdTable = new Hashtable();
  347. ns.varTable = new Hashtable();
  348. ns.exportArray = null;
  349. ns.numExportPatterns = 0;
  350. ns.maxExportPatterns = 0;
  351. // Jacl does not use these tcl compiler specific members
  352. //ns.cmdRefEpoch = 0;
  353. //ns.resolverEpoch = 0;
  354. ns.resolver = null;
  355. if ( parent != null )
  356. {
  357. SupportClass.PutElement( parent.childTable, simpleName, ns );
  358. }
  359. // Build the fully qualified name for this namespace.
  360. buffer1 = new StringBuilder();
  361. buffer2 = new StringBuilder();
  362. for ( ancestor = ns; ancestor != null; ancestor = ancestor.parent )
  363. {
  364. if ( ancestor != globalNs )
  365. {
  366. buffer1.Append( "::" );
  367. buffer1.Append( ancestor.name );
  368. }
  369. buffer1.Append( buffer2 );
  370. buffer2.Length = 0;
  371. buffer2.Append( buffer1 );
  372. buffer1.Length = 0;
  373. }
  374. name = buffer2.ToString();
  375. ns.fullName = name;
  376. // Return a reference to the new namespace.
  377. return ns;
  378. }
  379. /*
  380. *----------------------------------------------------------------------
  381. *
  382. * Tcl_DeleteNamespace -> deleteNamespace
  383. *
  384. * Deletes a namespace and all of the commands, variables, and other
  385. * namespaces within it.
  386. *
  387. * Results:
  388. * None.
  389. *
  390. * Side effects:
  391. * When a namespace is deleted, it is automatically removed as a
  392. * child of its parent namespace. Also, all its commands, variables
  393. * and child namespaces are deleted.
  394. *
  395. *----------------------------------------------------------------------
  396. */
  397. internal static void deleteNamespace( Namespace namespace_Renamed )
  398. {
  399. Namespace ns = namespace_Renamed;
  400. Interp interp = ns.interp;
  401. Namespace globalNs = getGlobalNamespace( interp );
  402. // If the namespace is on the call frame stack, it is marked as "dying"
  403. // (NS_DYING is OR'd into its flags): the namespace can't be looked up
  404. // by name but its commands and variables are still usable by those
  405. // active call frames. When all active call frames referring to the
  406. // namespace have been popped from the Tcl stack, popCallFrame will
  407. // call this procedure again to delete everything in the namespace.
  408. // If no nsName objects refer to the namespace (i.e., if its refCount
  409. // is zero), its commands and variables are deleted and the storage for
  410. // its namespace structure is freed. Otherwise, if its refCount is
  411. // nonzero, the namespace's commands and variables are deleted but the
  412. // structure isn't freed. Instead, NS_DEAD is OR'd into the structure's
  413. // flags to allow the namespace resolution code to recognize that the
  414. // namespace is "deleted".
  415. if ( ns.activationCount > 0 )
  416. {
  417. ns.flags |= NS_DYING;
  418. if ( ns.parent != null )
  419. {
  420. ns.parent.childTable.Remove( ns.name );
  421. }
  422. ns.parent = null;
  423. }
  424. else
  425. {
  426. // Delete the namespace and everything in it. If this is the global
  427. // namespace, then clear it but don't free its storage unless the
  428. // interpreter is being torn down.
  429. teardownNamespace( ns );
  430. if ( ( ns != globalNs ) || ( ( interp.flags & Parser.DELETED ) != 0 ) )
  431. {
  432. // If this is the global namespace, then it may have residual
  433. // "errorInfo" and "errorCode" variables for errors that
  434. // occurred while it was being torn down. Try to clear the
  435. // variable list one last time.
  436. Var.deleteVars( ns.interp, ns.varTable );
  437. ns.childTable.Clear();
  438. ns.cmdTable.Clear();
  439. // If the reference count is 0, then discard the namespace.
  440. // Otherwise, mark it as "dead" so that it can't be used.
  441. if ( ns.refCount == 0 )
  442. {
  443. free( ns );
  444. }
  445. else
  446. {
  447. ns.flags |= NS_DEAD;
  448. }
  449. }
  450. }
  451. }
  452. /*
  453. *----------------------------------------------------------------------
  454. *
  455. * TclTeardownNamespace -> teardownNamespace
  456. *
  457. * Used internally to dismantle and unlink a namespace when it is
  458. * deleted. Divorces the namespace from its parent, and deletes all
  459. * commands, variables, and child namespaces.
  460. *
  461. * This is kept separate from Tcl_DeleteNamespace so that the global
  462. * namespace can be handled specially. Global variables like
  463. * "errorInfo" and "errorCode" need to remain intact while other
  464. * namespaces and commands are torn down, in case any errors occur.
  465. *
  466. * Results:
  467. * None.
  468. *
  469. * Side effects:
  470. * Removes this namespace from its parent's child namespace hashtable.
  471. * Deletes all commands, variables and namespaces in this namespace.
  472. * If this is the global namespace, the "errorInfo" and "errorCode"
  473. * variables are left alone and deleted later.
  474. *
  475. *----------------------------------------------------------------------
  476. */
  477. internal static void teardownNamespace( Namespace ns )
  478. {
  479. Interp interp = ns.interp;
  480. IEnumerator search;
  481. Namespace globalNs = getGlobalNamespace( interp );
  482. int i;
  483. // Start by destroying the namespace's variable table,
  484. // since variables might trigger traces.
  485. if ( ns == globalNs )
  486. {
  487. // This is the global namespace, so be careful to preserve the
  488. // "errorInfo" and "errorCode" variables. These might be needed
  489. // later on if errors occur while deleting commands. We are careful
  490. // to destroy and recreate the "errorInfo" and "errorCode"
  491. // variables, in case they had any traces on them.
  492. string errorInfoStr, errorCodeStr;
  493. try
  494. {
  495. errorInfoStr = interp.getVar( "errorInfo", TCL.VarFlag.GLOBAL_ONLY ).ToString();
  496. }
  497. catch ( TclException e )
  498. {
  499. errorInfoStr = null;
  500. }
  501. try
  502. {
  503. errorCodeStr = interp.getVar( "errorCode", TCL.VarFlag.GLOBAL_ONLY ).ToString();
  504. }
  505. catch ( TclException e )
  506. {
  507. errorCodeStr = null;
  508. }
  509. Var.deleteVars( interp, ns.varTable );
  510. if ( (System.Object)errorInfoStr != null )
  511. {
  512. try
  513. {
  514. interp.setVar( "errorInfo", errorInfoStr, TCL.VarFlag.GLOBAL_ONLY );
  515. }
  516. catch ( TclException e )
  517. {
  518. // ignore an exception while setting this var
  519. }
  520. }
  521. if ( (System.Object)errorCodeStr != null )
  522. {
  523. try
  524. {
  525. interp.setVar( "errorCode", errorCodeStr, TCL.VarFlag.GLOBAL_ONLY );
  526. }
  527. catch ( TclException e )
  528. {
  529. // ignore an exception while setting this var
  530. }
  531. }
  532. }
  533. else
  534. {
  535. // Variable table should be cleared.
  536. Var.deleteVars( interp, ns.varTable );
  537. }
  538. // Remove the namespace from its parent's child hashtable.
  539. if ( ns.parent != null )
  540. {
  541. ns.parent.childTable.Remove( ns.name );
  542. }
  543. ns.parent = null;
  544. // Delete all the child namespaces.
  545. //
  546. // BE CAREFUL: When each child is deleted, it will divorce
  547. // itself from its parent. You can't traverse a hash table
  548. // properly if its elements are being deleted. We use only
  549. // the Tcl_FirstHashEntry function to be safe.
  550. foreach ( Namespace childNs in new ArrayList( ns.childTable.Values ) )
  551. {
  552. deleteNamespace( childNs );
  553. }
  554. // Delete all commands in this namespace. Be careful when traversing the
  555. // hash table: when each command is deleted, it removes itself from the
  556. // command table.
  557. // FIXME : double check that using an enumeration for a hashtable
  558. // that changes is ok in Java! Also call deleteCommand... correctly!
  559. foreach ( WrappedCommand cmd in new ArrayList( ns.cmdTable.Values ) )
  560. {
  561. interp.deleteCommandFromToken( cmd );
  562. }
  563. ns.cmdTable.Clear();
  564. // Free the namespace's export pattern array.
  565. if ( ns.exportArray != null )
  566. {
  567. ns.exportArray = null;
  568. ns.numExportPatterns = 0;
  569. ns.maxExportPatterns = 0;
  570. }
  571. // Callback invoked when namespace is deleted
  572. if ( ns.deleteProc != null )
  573. {
  574. ns.deleteProc.delete();
  575. }
  576. ns.deleteProc = null;
  577. // Reset the namespace's id field to ensure that this namespace won't
  578. // be interpreted as valid by, e.g., the cache validation code for
  579. // cached command references in Tcl_GetCommandFromObj.
  580. ns.nsId = 0;
  581. }
  582. /*
  583. *----------------------------------------------------------------------
  584. *
  585. * NamespaceFree -> free
  586. *
  587. * Called after a namespace has been deleted, when its
  588. * reference count reaches 0. Frees the data structure
  589. * representing the namespace.
  590. *
  591. * Results:
  592. * None.
  593. *
  594. * Side effects:
  595. * None.
  596. *
  597. *----------------------------------------------------------------------
  598. */
  599. internal static void free( Namespace ns )
  600. {
  601. // Most of the namespace's contents are freed when the namespace is
  602. // deleted by Tcl_DeleteNamespace. All that remains is to free its names
  603. // (for error messages), and the structure itself.
  604. ns.name = null;
  605. ns.fullName = null;
  606. }
  607. /*
  608. *----------------------------------------------------------------------
  609. *
  610. * Tcl_Export -> exportList
  611. *
  612. * Makes all the commands matching a pattern available to later be
  613. * imported from the namespace specified by namespace (or the
  614. * current namespace if namespace is null). The specified pattern is
  615. * appended onto the namespace's export pattern list, which is
  616. * optionally cleared beforehand.
  617. *
  618. * Results:
  619. * Returns if successful, raises TclException if something goes wrong.
  620. *
  621. * Side effects:
  622. * Appends the export pattern onto the namespace's export list.
  623. * Optionally reset the namespace's export pattern list.
  624. *
  625. *----------------------------------------------------------------------
  626. */
  627. internal static void exportList( Interp interp, Namespace namespace_Renamed, string pattern, bool resetListFirst )
  628. {
  629. int INIT_EXPORT_PATTERNS = 5;
  630. Namespace ns, exportNs;
  631. Namespace currNs = getCurrentNamespace( interp );
  632. string simplePattern, patternCpy;
  633. int neededElems, len, i;
  634. // If the specified namespace is null, use the current namespace.
  635. if ( namespace_Renamed == null )
  636. {
  637. ns = currNs;
  638. }
  639. else
  640. {
  641. ns = namespace_Renamed;
  642. }
  643. // If resetListFirst is true (nonzero), clear the namespace's export
  644. // pattern list.
  645. if ( resetListFirst )
  646. {
  647. if ( ns.exportArray != null )
  648. {
  649. for ( i = 0; i < ns.numExportPatterns; i++ )
  650. {
  651. ns.exportArray[i] = null;
  652. }
  653. ns.exportArray = null;
  654. ns.numExportPatterns = 0;
  655. ns.maxExportPatterns = 0;
  656. }
  657. }
  658. // Check that the pattern doesn't have namespace qualifiers.
  659. // Java does not support passing an address so we pass
  660. // an array of size 1 and then assign arr[0] to the value
  661. Namespace[] exportNsArr = new Namespace[1];
  662. Namespace[] dummyArr = new Namespace[1];
  663. string[] simplePatternArr = new string[1];
  664. getNamespaceForQualName( interp, pattern, ns, TCL.VarFlag.LEAVE_ERR_MSG, exportNsArr, dummyArr, dummyArr, simplePatternArr );
  665. // get the values out of the arrays
  666. exportNs = exportNsArr[0];
  667. simplePattern = simplePatternArr[0];
  668. if ( ( exportNs != ns ) || ( pattern.CompareTo( simplePattern ) != 0 ) )
  669. {
  670. throw new TclException( interp, "invalid export pattern \"" + pattern + "\": pattern can't specify a namespace" );
  671. }
  672. // Make sure there is room in the namespace's pattern array for the
  673. // new pattern.
  674. neededElems = ns.numExportPatterns + 1;
  675. if ( ns.exportArray == null )
  676. {
  677. ns.exportArray = new string[INIT_EXPORT_PATTERNS];
  678. ns.numExportPatterns = 0;
  679. ns.maxExportPatterns = INIT_EXPORT_PATTERNS;
  680. }
  681. else if ( neededElems > ns.maxExportPatterns )
  682. {
  683. int numNewElems = 2 * ns.maxExportPatterns;
  684. string[] newArray = new string[numNewElems];
  685. Array.Copy( (System.Array)ns.exportArray, 0, (System.Array)newArray, 0, ns.numExportPatterns );
  686. ns.exportArray = newArray;
  687. ns.maxExportPatterns = numNewElems;
  688. }
  689. // Add the pattern to the namespace's array of export patterns.
  690. ns.exportArray[ns.numExportPatterns] = pattern;
  691. ns.numExportPatterns++;
  692. return;
  693. }
  694. /*
  695. *----------------------------------------------------------------------
  696. *
  697. * Tcl_AppendExportList -> appendExportList
  698. *
  699. * Appends onto the argument object the list of export patterns for the
  700. * specified namespace.
  701. *
  702. * Results:
  703. * The method will return when successful; in this case the object
  704. * referenced by obj has each export pattern appended to it. If an
  705. * error occurs, an exception and the interpreter's result
  706. * holds an error message.
  707. *
  708. * Side effects:
  709. * If necessary, the object referenced by obj is converted into
  710. * a list object.
  711. *
  712. *----------------------------------------------------------------------
  713. */
  714. internal static void appendExportList( Interp interp, Namespace namespace_Renamed, TclObject obj )
  715. {
  716. Namespace ns;
  717. int i;
  718. // If the specified namespace is null, use the current namespace.
  719. if ( namespace_Renamed == null )
  720. {
  721. ns = getCurrentNamespace( interp );
  722. }
  723. else
  724. {
  725. ns = namespace_Renamed;
  726. }
  727. // Append the export pattern list onto objPtr.
  728. for ( i = 0; i < ns.numExportPatterns; i++ )
  729. {
  730. TclList.append( interp, obj, TclString.newInstance( ns.exportArray[i] ) );
  731. }
  732. return;
  733. }
  734. /*
  735. *----------------------------------------------------------------------
  736. *
  737. * Tcl_Import -> importList
  738. *
  739. * Imports all of the commands matching a pattern into the namespace
  740. * specified by namespace (or the current namespace if namespace
  741. * is null). This is done by creating a new command (the "imported
  742. * command") that points to the real command in its original namespace.
  743. *
  744. * If matching commands are on the autoload path but haven't been
  745. * loaded yet, this command forces them to be loaded, then creates
  746. * the links to them.
  747. *
  748. * Results:
  749. * Returns if successful, raises TclException if something goes wrong.
  750. *
  751. * Side effects:
  752. * Creates new commands in the importing namespace. These indirect
  753. * calls back to the real command and are deleted if the real commands
  754. * are deleted.
  755. *
  756. *----------------------------------------------------------------------
  757. */
  758. internal static void importList( Interp interp, Namespace namespace_Renamed, string pattern, bool allowOverwrite )
  759. {
  760. Namespace ns, importNs;
  761. Namespace currNs = getCurrentNamespace( interp );
  762. string simplePattern, cmdName;
  763. IEnumerator search;
  764. WrappedCommand cmd, realCmd;
  765. ImportRef ref_Renamed;
  766. WrappedCommand autoCmd, importedCmd;
  767. ImportedCmdData data;
  768. bool wasExported;
  769. int i, result;
  770. // If the specified namespace is null, use the current namespace.
  771. if ( namespace_Renamed == null )
  772. {
  773. ns = currNs;
  774. }
  775. else
  776. {
  777. ns = namespace_Renamed;
  778. }
  779. // First, invoke the "auto_import" command with the pattern
  780. // being imported. This command is part of the Tcl library.
  781. // It looks for imported commands in autoloaded libraries and
  782. // loads them in. That way, they will be found when we try
  783. // to create links below.
  784. autoCmd = findCommand( interp, "auto_import", null, TCL.VarFlag.GLOBAL_ONLY );
  785. if ( autoCmd != null )
  786. {
  787. TclObject[] objv = new TclObject[2];
  788. objv[0] = TclString.newInstance( "auto_import" );
  789. objv[0].preserve();
  790. objv[1] = TclString.newInstance( pattern );
  791. objv[1].preserve();
  792. cmd = autoCmd;
  793. try
  794. {
  795. // Invoke the command with the arguments
  796. cmd.cmd.cmdProc( interp, objv );
  797. }
  798. finally
  799. {
  800. objv[0].release();
  801. objv[1].release();
  802. }
  803. interp.resetResult();
  804. }
  805. // From the pattern, find the namespace from which we are importing
  806. // and get the simple pattern (no namespace qualifiers or ::'s) at
  807. // the end.
  808. if ( pattern.Length == 0 )
  809. {
  810. throw new TclException( interp, "empty import pattern" );
  811. }
  812. // Java does not support passing an address so we pass
  813. // an array of size 1 and then assign arr[0] to the value
  814. Namespace[] importNsArr = new Namespace[1];
  815. Namespace[] dummyArr = new Namespace[1];
  816. string[] simplePatternArr = new string[1];
  817. getNamespaceForQualName( interp, pattern, ns, TCL.VarFlag.LEAVE_ERR_MSG, importNsArr, dummyArr, dummyArr, simplePatternArr );
  818. importNs = importNsArr[0];
  819. simplePattern = simplePatternArr[0];
  820. if ( importNs == null )
  821. {
  822. throw new TclException( interp, "unknown namespace in import pattern \"" + pattern + "\"" );
  823. }
  824. if ( importNs == ns )
  825. {
  826. if ( (System.Object)pattern == (System.Object)simplePattern )
  827. {
  828. throw new TclException( interp, "no namespace specified in import pattern \"" + pattern + "\"" );
  829. }
  830. else
  831. {
  832. throw new TclException( interp, "import pattern \"" + pattern + "\" tries to import from namespace \"" + importNs.name + "\" into itself" );
  833. }
  834. }
  835. // Scan through the command table in the source namespace and look for
  836. // exported commands that match the string pattern. Create an "imported
  837. // command" in the current namespace for each imported command; these
  838. // commands redirect their invocations to the "real" command.
  839. for ( search = importNs.cmdTable.Keys.GetEnumerator(); search.MoveNext(); )
  840. {
  841. cmdName = ( (string)search.Current );
  842. if ( Util.stringMatch( cmdName, simplePattern ) )
  843. {
  844. // The command cmdName in the source namespace matches the
  845. // pattern. Check whether it was exported. If it wasn't,
  846. // we ignore it.
  847. wasExported = false;
  848. for ( i = 0; i < importNs.numExportPatterns; i++ )
  849. {
  850. if ( Util.stringMatch( cmdName, importNs.exportArray[i] ) )
  851. {
  852. wasExported = true;
  853. break;
  854. }
  855. }
  856. if ( !wasExported )
  857. {
  858. continue;
  859. }
  860. // Unless there is a name clash, create an imported command
  861. // in the current namespace that refers to cmdPtr.
  862. if ( ( ns.cmdTable[cmdName] == null ) || allowOverwrite )
  863. {
  864. // Create the imported command and its client data.
  865. // To create the new command in the current namespace,
  866. // generate a fully qualified name for it.
  867. StringBuilder ds;
  868. ds = new StringBuilder();
  869. ds.Append( ns.fullName );
  870. if ( ns != interp.globalNs )
  871. {
  872. ds.Append( "::" );
  873. }
  874. ds.Append( cmdName );
  875. // Check whether creating the new imported command in the
  876. // current namespace would create a cycle of imported->real
  877. // command references that also would destroy an existing
  878. // "real" command already in the current namespace.
  879. cmd = (WrappedCommand)importNs.cmdTable[cmdName];
  880. if ( cmd.cmd is ImportedCmdData )
  881. {
  882. // This is actually an imported command, find
  883. // the real command it references
  884. realCmd = getOriginalCommand( cmd );
  885. if ( ( realCmd != null ) && ( realCmd.ns == currNs ) && ( currNs.cmdTable[cmdName] != null ) )
  886. {
  887. throw new TclException( interp, "import pattern \"" + pattern + "\" would create a loop containing command \"" + ds.ToString() + "\"" );
  888. }
  889. }
  890. data = new ImportedCmdData();
  891. // Create the imported command inside the interp
  892. interp.createCommand( ds.ToString(), data );
  893. // Lookup in the namespace for the new WrappedCommand
  894. importedCmd = findCommand( interp, ds.ToString(), ns, ( TCL.VarFlag.NAMESPACE_ONLY | TCL.VarFlag.LEAVE_ERR_MSG ) );
  895. data.realCmd = cmd;
  896. data.self = importedCmd;
  897. // Create an ImportRef structure describing this new import
  898. // command and add it to the import ref list in the "real"
  899. // command.
  900. ref_Renamed = new ImportRef();
  901. ref_Renamed.importedCmd = importedCmd;
  902. ref_Renamed.next = cmd.importRef;
  903. cmd.importRef = ref_Renamed;
  904. }
  905. else
  906. {
  907. throw new TclException( interp, "can't import command \"" + cmdName + "\": already exists" );
  908. }
  909. }
  910. }
  911. return;
  912. }
  913. /*
  914. *----------------------------------------------------------------------
  915. *
  916. * Tcl_ForgetImport -> forgetImport
  917. *
  918. * Deletes previously imported commands. Given a pattern that may
  919. * include the name of an exporting namespace, this procedure first
  920. * finds all matching exported commands. It then looks in the namespace
  921. * specified by namespace for any corresponding previously imported
  922. * commands, which it deletes. If namespace is null, commands are
  923. * deleted from the current namespace.
  924. *
  925. * Results:
  926. * Returns if successful, raises TclException if something goes wrong.
  927. *
  928. * Side effects:
  929. * May delete commands.
  930. *
  931. *----------------------------------------------------------------------
  932. */
  933. internal static void forgetImport( Interp interp, Namespace namespace_Renamed, string pattern )
  934. {
  935. Namespace ns, importNs, actualCtx;
  936. string simplePattern, cmdName;
  937. IEnumerator search;
  938. WrappedCommand cmd;
  939. // If the specified namespace is null, use the current namespace.
  940. if ( namespace_Renamed == null )
  941. {
  942. ns = getCurrentNamespace( interp );
  943. }
  944. else
  945. {
  946. ns = namespace_Renamed;
  947. }
  948. // From the pattern, find the namespace from which we are importing
  949. // and get the simple pattern (no namespace qualifiers or ::'s) at
  950. // the end.
  951. // Java does not support passing an address so we pass
  952. // an array of size 1 and then assign arr[0] to the value
  953. Namespace[] importNsArr = new Namespace[1];
  954. Namespace[] dummyArr = new Namespace[1];
  955. Namespace[] actualCtxArr = new Namespace[1];
  956. string[] simplePatternArr = new string[1];
  957. getNamespaceForQualName( interp, pattern, ns, TCL.VarFlag.LEAVE_ERR_MSG, importNsArr, dummyArr, actualCtxArr, simplePatternArr );
  958. // get the values out of the arrays
  959. importNs = importNsArr[0];
  960. actualCtx = actualCtxArr[0];
  961. simplePattern = simplePatternArr[0];
  962. // FIXME : the above call passes TCL.VarFlag.LEAVE_ERR_MSG, but
  963. // it seems like this will be a problem when exception is raised!
  964. if ( importNs == null )
  965. {
  966. throw new TclException( interp, "unknown namespace in namespace forget pattern \"" + pattern + "\"" );
  967. }
  968. // Scan through the command table in the source namespace and look for
  969. // exported commands that match the string pattern. If the current
  970. // namespace has an imported command that refers to one of those real
  971. // commands, delete it.
  972. for ( search = importNs.cmdTable.Keys.GetEnumerator(); search.MoveNext(); )
  973. {
  974. cmdName = ( (string)search.Current );
  975. if ( Util.stringMatch( cmdName, simplePattern ) )
  976. {
  977. cmd = (WrappedCommand)ns.cmdTable[cmdName];
  978. if ( cmd != null )
  979. {
  980. // cmd of same name in current namespace
  981. if ( cmd.cmd is ImportedCmdData )
  982. {
  983. interp.deleteCommandFromToken( cmd );
  984. }
  985. }
  986. }
  987. }
  988. return;
  989. }
  990. /*
  991. *----------------------------------------------------------------------
  992. *
  993. * TclGetOriginalCommand -> getOriginalCommand
  994. *
  995. * An imported command is created in a namespace when a "real" command
  996. * is imported from another namespace. If the specified command is an
  997. * imported command, this procedure returns the original command it
  998. * refers to.
  999. *
  1000. * Results:
  1001. * If the command was imported into a sequence of namespaces a, b,...,n
  1002. * where each successive namespace just imports the command from the
  1003. * previous namespace, this procedure returns the Tcl_Command token in
  1004. * the first namespace, a. Otherwise, if the specified command is not
  1005. * an imported command, the procedure returns null.
  1006. *
  1007. * Side effects:
  1008. * None.
  1009. *
  1010. *----------------------------------------------------------------------
  1011. */
  1012. internal static WrappedCommand getOriginalCommand( WrappedCommand command )
  1013. {
  1014. WrappedCommand cmd = command;
  1015. ImportedCmdData data;
  1016. if ( !( cmd.cmd is ImportedCmdData ) )
  1017. {
  1018. return null;
  1019. }
  1020. while ( cmd.cmd is ImportedCmdData )
  1021. {
  1022. data = (ImportedCmdData)cmd.cmd;
  1023. cmd = data.realCmd;
  1024. }
  1025. return cmd;
  1026. }
  1027. /*
  1028. *----------------------------------------------------------------------
  1029. *
  1030. * InvokeImportedCmd -> invokeImportedCmd
  1031. *
  1032. * Invoked by Tcl whenever the user calls an imported command that
  1033. * was created by Tcl_Import. Finds the "real" command (in another
  1034. * namespace), and passes control to it.
  1035. *
  1036. * Results:
  1037. * Returns if successful, raises TclException if something goes wrong.
  1038. *
  1039. * Side effects:
  1040. * Returns a result in the interpreter's result object. If anything
  1041. * goes wrong, the result object is set to an error message.
  1042. *
  1043. *----------------------------------------------------------------------
  1044. */
  1045. internal static void invokeImportedCmd( Interp interp, ImportedCmdData data, TclObject[] objv )
  1046. {
  1047. WrappedCommand realCmd = data.realCmd;
  1048. realCmd.cmd.cmdProc( interp, objv );
  1049. }
  1050. /*
  1051. *----------------------------------------------------------------------
  1052. *
  1053. * DeleteImportedCmd -> deleteImportedCmd
  1054. *
  1055. * Invoked by Tcl whenever an imported command is deleted. The "real"
  1056. * command keeps a list of all the imported commands that refer to it,
  1057. * so those imported commands can be deleted when the real command is
  1058. * deleted. This procedure removes the imported command reference from
  1059. * the real command's list, and frees up the memory associated with
  1060. * the imported command.
  1061. *
  1062. * Results:
  1063. * None.
  1064. *
  1065. * Side effects:
  1066. * Removes the imported command from the real command's import list.
  1067. *
  1068. *----------------------------------------------------------------------
  1069. */
  1070. internal static void deleteImportedCmd( ImportedCmdData data )
  1071. // The data object for this imported command
  1072. {
  1073. WrappedCommand realCmd = data.realCmd;
  1074. WrappedCommand self = data.self;
  1075. ImportRef ref_Renamed, prev;
  1076. prev = null;
  1077. for ( ref_Renamed = realCmd.importRef; ref_Renamed != null; ref_Renamed = ref_Renamed.next )
  1078. {
  1079. if ( ref_Renamed.importedCmd == self )
  1080. {
  1081. // Remove ref from real command's list of imported commands
  1082. // that refer to it.
  1083. if ( prev == null )
  1084. {
  1085. // ref is first in list
  1086. realCmd.importRef = ref_Renamed.next;
  1087. }
  1088. else
  1089. {
  1090. prev.next = ref_Renamed.next;
  1091. }
  1092. ref_Renamed = null;
  1093. data = null;
  1094. return;
  1095. }
  1096. prev = ref_Renamed;
  1097. }
  1098. throw new TclRuntimeError( "DeleteImportedCmd: did not find cmd in real cmd's list of import references" );
  1099. }
  1100. /*
  1101. *----------------------------------------------------------------------
  1102. *
  1103. * TclGetNamespaceForQualName -> getNamespaceForQualName
  1104. *
  1105. * Given a qualified name specifying a command, variable, or namespace,
  1106. * and a namespace in which to resolve the name, this procedure returns
  1107. * a pointer to the namespace that contains the item. A qualified name
  1108. * consists of the "simple" name of an item qualified by the names of
  1109. * an arbitrary number of containing namespace separated by "::"s. If
  1110. * the qualified name starts with "::", it is interpreted absolutely
  1111. * from the global namespace. Otherwise, it is interpreted relative to
  1112. * the namespace specified by cxtNsPtr if it is non-null. If cxtNsPtr
  1113. * is null, the name is interpreted relative to the current namespace.
  1114. *
  1115. * A relative name like "foo::bar::x" can be found starting in either
  1116. * the current namespace or in the global namespace. So each search
  1117. * usually follows two tracks, and two possible namespaces are
  1118. * returned. If the procedure sets either nsPtrPtr[0] or altNsPtrPtr[0] to
  1119. * null, then that path failed.
  1120. *
  1121. * If "flags" contains TCL.VarFlag.GLOBAL_ONLY, the relative qualified name is
  1122. * sought only in the global :: namespace. The alternate search
  1123. * (also) starting from the global namespace is ignored and
  1124. * altNsPtrPtr[0] is set null.
  1125. *
  1126. * If "flags" contains TCL.VarFlag.NAMESPACE_ONLY, the relative qualified
  1127. * name is sought only in the namespace specified by cxtNsPtr. The
  1128. * alternate search starting from the global namespace is ignored and
  1129. * altNsPtrPtr[0] is set null. If both TCL.VarFlag.GLOBAL_ONLY and
  1130. * TCL.VarFlag.NAMESPACE_ONLY are specified, TCL.VarFlag.GLOBAL_ONLY is ignored and
  1131. * the search starts from the namespace specified by cxtNsPtr.
  1132. *
  1133. * If "flags" contains TCL.VarFlag.CREATE_NS_IF_UNKNOWN, all namespace
  1134. * components of the qualified name that cannot be found are
  1135. * automatically created within their specified parent. This makes sure
  1136. * that functions like Tcl_CreateCommand always succeed. There is no
  1137. * alternate search path, so altNsPtrPtr[0] is set null.
  1138. *
  1139. * If "flags" contains TCL.VarFlag.FIND_ONLY_NS, the qualified name is treated as a
  1140. * reference to a namespace, and the entire qualified name is
  1141. * followed. If the name is relative, the namespace is looked up only
  1142. * in the current namespace. A pointer to the namespace is stored in
  1143. * nsPtrPtr[0] and null is stored in simpleNamePtr[0]. Otherwise, if
  1144. * TCL.VarFlag.FIND_ONLY_NS is not specified, only the leading components are
  1145. * treated as namespace names, and a pointer to the simple name of the
  1146. * final component is stored in simpleNamePtr[0].
  1147. *
  1148. * Results:
  1149. * It sets nsPtrPtr[0] and altNsPtrPtr[0] to point to the two possible
  1150. * namespaces which represent the last (containing) namespace in the
  1151. * qualified name. If the procedure sets either nsPtrPtr[0] or altNsPtrPtr[0]
  1152. * to null, then the search along that path failed. The procedure also
  1153. * stores a pointer to the simple name of the final component in
  1154. * simpleNamePtr[0]. If the qualified name is "::" or was treated as a
  1155. * namespace reference (TCL.VarFlag.FIND_ONLY_NS), the procedure stores a pointer
  1156. * to the namespace in nsPtrPtr[0], null in altNsPtrPtr[0], and sets
  1157. * simpleNamePtr[0] to an empty string.
  1158. *
  1159. * If there is an error, this procedure returns TCL_ERROR. If "flags"
  1160. * contains TCL_LEAVE_ERR_MSG, an error message is returned in the
  1161. * interpreter's result object. Otherwise, the interpreter's result
  1162. * object is left unchanged.
  1163. *
  1164. * actualCxtPtrPtr[0] is set to the actual context namespace. It is
  1165. * set to the input context namespace pointer in cxtNsPtr. If cxtNsPtr
  1166. * is null, it is set to the current namespace context.
  1167. *
  1168. * Side effects:
  1169. * If "flags" contains TCL.VarFlag.CREATE_NS_IF_UNKNOWN, new namespaces may be
  1170. * created.
  1171. *
  1172. *----------------------------------------------------------------------
  1173. */
  1174. internal static void getNamespaceForQualName( Interp interp, string qualName, Namespace cxtNsPtr, TCL.VarFlag flags, Namespace[] nsPtrPtr, Namespace[] altNsPtrPtr, Namespace[] actualCxtPtrPtr, string[] simpleNamePtr )
  1175. {
  1176. // FIXME : remove extra method call checks when we are sure this works!
  1177. if ( true )
  1178. {
  1179. // check invariants
  1180. if ( ( nsPtrPtr == null ) || ( nsPtrPtr.Length != 1 ) )
  1181. {
  1182. throw new System.SystemException( "nsPtrPtr " + nsPtrPtr );
  1183. }
  1184. if ( ( altNsPtrPtr == null ) || ( altNsPtrPtr.Length != 1 ) )
  1185. {
  1186. throw new System.SystemException( "altNsPtrPtr " + altNsPtrPtr );
  1187. }
  1188. if ( ( actualCxtPtrPtr == null ) || ( actualCxtPtrPtr.Length != 1 ) )
  1189. {
  1190. throw new System.SystemException( "actualCxtPtrPtr " + actualCxtPtrPtr );
  1191. }
  1192. if ( ( simpleNamePtr == null ) || ( simpleNamePtr.Length != 1 ) )
  1193. {
  1194. throw new System.SystemException( "simpleNamePtr " + simpleNamePtr );
  1195. }
  1196. }
  1197. Namespace ns = cxtNsPtr;
  1198. Namespace altNs;
  1199. Namespace globalNs = getGlobalNamespace( interp );
  1200. Namespace entryNs;
  1201. string start, end;
  1202. string nsName;
  1203. int len;
  1204. int start_ind, end_ind, name_len;
  1205. // Determine the context namespace ns in which to start the primary
  1206. // search. If TCL.VarFlag.NAMESPACE_ONLY or TCL.VarFlag.FIND_ONLY_NS was specified, search
  1207. // from the current namespace. If the qualName name starts with a "::"
  1208. // or TCL.VarFlag.GLOBAL_ONLY was specified, search from the global
  1209. // namespace. Otherwise, use the given namespace given in cxtNsPtr, or
  1210. // if that is null, use the current namespace context. Note that we
  1211. // always treat two or more adjacent ":"s as a namespace separator.
  1212. if ( ( flags & ( TCL.VarFlag.NAMESPACE_ONLY | TCL.VarFlag.FIND_ONLY_NS ) ) != 0 )
  1213. {
  1214. ns = getCurrentNamespace( interp );
  1215. }
  1216. else if ( ( flags & TCL.VarFlag.GLOBAL_ONLY ) != 0 )
  1217. {
  1218. ns = globalNs;
  1219. }
  1220. else if ( ns == null )
  1221. {
  1222. if ( interp.varFrame != null )
  1223. {
  1224. ns = interp.varFrame.ns;
  1225. }
  1226. else
  1227. {
  1228. ns = interp.globalNs;
  1229. }
  1230. }
  1231. start_ind = 0;
  1232. name_len = qualName.Length;
  1233. if ( ( name_len >= 2 ) && ( qualName[0] == ':' ) && ( qualName[1] == ':' ) )
  1234. {
  1235. start_ind = 2; // skip over the initial ::
  1236. while ( ( start_ind < name_len ) && ( qualName[start_ind] == ':' ) )
  1237. {
  1238. start_ind++; // skip over a subsequent :
  1239. }
  1240. ns = globalNs;
  1241. if ( start_ind >= name_len )
  1242. {
  1243. // qualName is just two or more ":"s
  1244. nsPtrPtr[0] = globalNs;
  1245. altNsPtrPtr[0] = null;
  1246. actualCxtPtrPtr[0] = globalNs;
  1247. simpleNamePtr[0] = ""; // points to empty string
  1248. return;
  1249. }
  1250. }
  1251. actualCxtPtrPtr[0] = ns;
  1252. // Start an alternate search path starting with the global namespace.
  1253. // However, if the starting context is the global namespace, or if the
  1254. // flag is set to search only the namespace cxtNs, ignore the
  1255. // alternate search path.
  1256. altNs = globalNs;
  1257. if ( ( ns == globalNs ) || ( ( flags & ( TCL.VarFlag.NAMESPACE_ONLY | TCL.VarFlag.FIND_ONLY_NS ) ) != 0 ) )
  1258. {
  1259. altNs = null;
  1260. }
  1261. // Loop to resolve each namespace qualifier in qualName.
  1262. end_ind = start_ind;
  1263. while ( start_ind < name_len )
  1264. {
  1265. // Find the next namespace qualifier (i.e., a name ending in "::")
  1266. // or the end of the qualified name (i.e., a name ending in "\0").

Large files files are truncated, but you can click here to view the full file