Beispiel #1
0
		/*
		*----------------------------------------------------------------------
		*
		* DeleteImportedCmd -> deleteImportedCmd
		*
		*	Invoked by Tcl whenever an imported command is deleted. The "real"
		*	command keeps a list of all the imported commands that refer to it,
		*	so those imported commands can be deleted when the real command is
		*	deleted. This procedure removes the imported command reference from
		*	the real command's list, and frees up the memory associated with
		*	the imported command.
		*
		* Results:
		*	None.
		*
		* Side effects:
		*	Removes the imported command from the real command's import list.
		*
		*----------------------------------------------------------------------
		*/
		
		internal static void  deleteImportedCmd(ImportedCmdData data)
		// The data object for this imported command
		{
			WrappedCommand realCmd = data.realCmd;
			WrappedCommand self = data.self;
			ImportRef ref_Renamed, prev;
			
			prev = null;
			for (ref_Renamed = realCmd.importRef; ref_Renamed != null; ref_Renamed = ref_Renamed.next)
			{
				if (ref_Renamed.importedCmd == self)
				{
					// Remove ref from real command's list of imported commands
					// that refer to it.
					
					if (prev == null)
					{
						// ref is first in list
						realCmd.importRef = ref_Renamed.next;
					}
					else
					{
						prev.next = ref_Renamed.next;
					}
					ref_Renamed = null;
					data = null;
					return ;
				}
				prev = ref_Renamed;
			}
			
			throw new TclRuntimeError("DeleteImportedCmd: did not find cmd in real cmd's list of import references");
		}
Beispiel #2
0
		/*
		*----------------------------------------------------------------------
		*
		* Tcl_Import -> importList
		*
		*	Imports all of the commands matching a pattern into the namespace
		*	specified by namespace (or the current namespace if namespace
		*	is null). This is done by creating a new command (the "imported
		*	command") that points to the real command in its original namespace.
		*
		*      If matching commands are on the autoload path but haven't been
		*	loaded yet, this command forces them to be loaded, then creates
		*	the links to them.
		*
		* Results:
		*  Returns if successful, raises TclException if something goes wrong.
		*
		* Side effects:
		*	Creates new commands in the importing namespace. These indirect
		*	calls back to the real command and are deleted if the real commands
		*	are deleted.
		*
		*----------------------------------------------------------------------
		*/
		
		internal static void  importList(Interp interp, Namespace namespace_Renamed, string pattern, bool allowOverwrite)
		{
			Namespace ns, importNs;
			Namespace currNs = getCurrentNamespace(interp);
			string simplePattern, cmdName;
			IEnumerator search;
			WrappedCommand cmd, realCmd;
			ImportRef ref_Renamed;
			WrappedCommand autoCmd, importedCmd;
			ImportedCmdData data;
			bool wasExported;
			int i, result;
			
			// If the specified namespace is null, use the current namespace.
			
			if (namespace_Renamed == null)
			{
				ns = currNs;
			}
			else
			{
				ns = namespace_Renamed;
			}
			
			// First, invoke the "auto_import" command with the pattern
			// being imported.  This command is part of the Tcl library.
			// It looks for imported commands in autoloaded libraries and
			// loads them in.  That way, they will be found when we try
			// to create links below.
			
			autoCmd = findCommand(interp, "auto_import", null, TCL.VarFlag.GLOBAL_ONLY);
			
			if (autoCmd != null)
			{
				TclObject[] objv = new TclObject[2];
				
				objv[0] = TclString.newInstance("auto_import");
				objv[0].preserve();
				objv[1] = TclString.newInstance(pattern);
				objv[1].preserve();
				
				cmd = autoCmd;
				try
				{
					// Invoke the command with the arguments
					cmd.cmd.cmdProc(interp, objv);
				}
				finally
				{
					objv[0].release();
					objv[1].release();
				}
				
				interp.resetResult();
			}
			
			// From the pattern, find the namespace from which we are importing
			// and get the simple pattern (no namespace qualifiers or ::'s) at
			// the end.
			
			if (pattern.Length == 0)
			{
				throw new TclException(interp, "empty import pattern");
			}
			
			// Java does not support passing an address so we pass
			// an array of size 1 and then assign arr[0] to the value
			Namespace[] importNsArr = new Namespace[1];
			Namespace[] dummyArr = new Namespace[1];
			string[] simplePatternArr = new string[1];
			
			getNamespaceForQualName(interp, pattern, ns, TCL.VarFlag.LEAVE_ERR_MSG, importNsArr, dummyArr, dummyArr, simplePatternArr);
			
			importNs = importNsArr[0];
			simplePattern = simplePatternArr[0];
			
			if (importNs == null)
			{
				throw new TclException(interp, "unknown namespace in import pattern \"" + pattern + "\"");
			}
			if (importNs == ns)
			{
				if ((System.Object) pattern == (System.Object) simplePattern)
				{
					throw new TclException(interp, "no namespace specified in import pattern \"" + pattern + "\"");
				}
				else
				{
					throw new TclException(interp, "import pattern \"" + pattern + "\" tries to import from namespace \"" + importNs.name + "\" into itself");
				}
			}
			
			// Scan through the command table in the source namespace and look for
			// exported commands that match the string pattern. Create an "imported
			// command" in the current namespace for each imported command; these
			// commands redirect their invocations to the "real" command.
			
			
			for (search = importNs.cmdTable.Keys.GetEnumerator(); search.MoveNext(); )
			{
				
				cmdName = ((string) search.Current);
				if (Util.stringMatch(cmdName, simplePattern))
				{
					// The command cmdName in the source namespace matches the
					// pattern. Check whether it was exported. If it wasn't,
					// we ignore it.
					
					wasExported = false;
					for (i = 0; i < importNs.numExportPatterns; i++)
					{
						if (Util.stringMatch(cmdName, importNs.exportArray[i]))
						{
							wasExported = true;
							break;
						}
					}
					if (!wasExported)
					{
						continue;
					}
					
					// Unless there is a name clash, create an imported command
					// in the current namespace that refers to cmdPtr.
					
					if ((ns.cmdTable[cmdName] == null) || allowOverwrite)
					{
						// Create the imported command and its client data.
						// To create the new command in the current namespace, 
						// generate a fully qualified name for it.
						
						System.Text.StringBuilder ds;
						
						ds = new System.Text.StringBuilder();
						ds.Append(ns.fullName);
						if (ns != interp.globalNs)
						{
							ds.Append("::");
						}
						ds.Append(cmdName);
						
						// Check whether creating the new imported command in the
						// current namespace would create a cycle of imported->real
						// command references that also would destroy an existing
						// "real" command already in the current namespace.
						
						cmd = (WrappedCommand) importNs.cmdTable[cmdName];
						
						if (cmd.cmd is ImportedCmdData)
						{
							// This is actually an imported command, find
							// the real command it references
							realCmd = getOriginalCommand(cmd);
							if ((realCmd != null) && (realCmd.ns == currNs) && (currNs.cmdTable[cmdName] != null))
							{
								throw new TclException(interp, "import pattern \"" + pattern + "\" would create a loop containing command \"" + ds.ToString() + "\"");
							}
						}
						
						data = new ImportedCmdData();
						
						// Create the imported command inside the interp
						interp.createCommand(ds.ToString(), data);
						
						// Lookup in the namespace for the new WrappedCommand
						importedCmd = findCommand(interp, ds.ToString(), ns, (TCL.VarFlag.NAMESPACE_ONLY | TCL.VarFlag.LEAVE_ERR_MSG));
						
						data.realCmd = cmd;
						data.self = importedCmd;
						
						// Create an ImportRef structure describing this new import
						// command and add it to the import ref list in the "real"
						// command.
						
						ref_Renamed = new ImportRef();
						ref_Renamed.importedCmd = importedCmd;
						ref_Renamed.next = cmd.importRef;
						cmd.importRef = ref_Renamed;
					}
					else
					{
						throw new TclException(interp, "can't import command \"" + cmdName + "\": already exists");
					}
				}
			}
			return ;
		}
Beispiel #3
0
		/*
		*----------------------------------------------------------------------
		*
		* InvokeImportedCmd -> invokeImportedCmd
		*
		*	Invoked by Tcl whenever the user calls an imported command that
		*	was created by Tcl_Import. Finds the "real" command (in another
		*	namespace), and passes control to it.
		*
		* Results:
		*	Returns if successful, raises TclException if something goes wrong.
		*
		* Side effects:
		*	Returns a result in the interpreter's result object. If anything
		*	goes wrong, the result object is set to an error message.
		*
		*----------------------------------------------------------------------
		*/
		
		internal static void  invokeImportedCmd(Interp interp, ImportedCmdData data, TclObject[] objv)
		{
			WrappedCommand realCmd = data.realCmd;
			realCmd.cmd.cmdProc(interp, objv);
		}