/////////////////////////////////////////////////////////////////////// private string GetOriginName( string aliasName ) { if (aliasName == null) { return(null); } Result result = null; if (NamespaceOps.Origin(interpreter, this, NamespaceOps.MakeAbsoluteName(aliasName), ref result) == ReturnCode.Ok) { return(ScriptOps.MakeCommandName(result)); } return(null); }
/////////////////////////////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { ReturnCode code = ReturnCode.Ok; if (interpreter != null) { if (arguments != null) { if (arguments.Count == 4) { string name = arguments[1]; StringList list = null; code = Parser.SplitList( interpreter, arguments[2], 0, Length.Invalid, true, ref list, ref result); if (code == ReturnCode.Ok) { StringPairList list2 = new StringPairList(); for (int argumentIndex = 0; argumentIndex < list.Count; argumentIndex++) { StringList list3 = null; code = Parser.SplitList( interpreter, list[argumentIndex], 0, Length.Invalid, true, ref list3, ref result); if (code != ReturnCode.Ok) { break; } if (list3.Count > 2) { result = String.Format( "too many fields in argument specifier \"{0}\"", list[argumentIndex]); code = ReturnCode.Error; break; } else if ((list3.Count == 0) || String.IsNullOrEmpty(list3[0])) { result = "argument with no name"; code = ReturnCode.Error; break; } else if (!Parser.IsSimpleScalarVariableName(list3[0], String.Format(Interpreter.ArgumentNotSimpleError, list3[0]), String.Format(Interpreter.ArgumentNotScalarError, list3[0]), ref result)) { code = ReturnCode.Error; break; } string argName = list3[0]; string argDefault = (list3.Count >= 2) ? list3[1] : null; list2.Add(new StringPair(argName, argDefault)); } if (code == ReturnCode.Ok) { lock (interpreter.SyncRoot) /* TRANSACTIONAL */ { ProcedureFlags procedureFlags = interpreter.ProcedureFlags; IProcedure procedure = RuntimeOps.NewCoreProcedure( interpreter, interpreter.AreNamespacesEnabled() ? NamespaceOps.MakeQualifiedName(interpreter, name) : ScriptOps.MakeCommandName(name), null, null, procedureFlags, new ArgumentList(list2, ArgumentFlags.NameOnly), arguments[3], ScriptLocation.Create(arguments[3]), clientData); code = interpreter.AddOrUpdateProcedureWithReplace( procedure, clientData, ref result); if (code == ReturnCode.Ok) { result = String.Empty; } } } } if (code == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, result, String.Format("{0} (creating proc \"{1}\")", Environment.NewLine, name)); } } else { result = "wrong # args: should be \"proc name args body\""; code = ReturnCode.Error; } } else { result = "invalid argument list"; code = ReturnCode.Error; } } else { result = "invalid interpreter"; code = ReturnCode.Error; } return(code); }
/////////////////////////////////////////////////////////////////////// public StringList GetImportNames( string pattern, bool keys, bool tailOnly ) { CheckDisposed(); StringList list = new StringList(); if (imports == null) { return(list); } if (pattern != null) { pattern = ScriptOps.MakeCommandName(pattern); } foreach (KeyValuePair <string, object> pair in imports) { IAlias alias = pair.Value as IAlias; if (alias == null) { continue; } if (keys) { string importName = pair.Key; string importNameTailOnly = NamespaceOps.TailOnly( importName); if ((pattern == null) || StringOps.Match( interpreter, MatchMode.Glob, importNameTailOnly, pattern, false)) { list.Add(tailOnly ? importNameTailOnly : importName); } } else { string aliasName = NamespaceOps.GetAliasName(alias); string aliasNameTailOnly = NamespaceOps.TailOnly( aliasName); if ((pattern == null) || StringOps.Match( interpreter, MatchMode.Glob, aliasNameTailOnly, pattern, false)) { list.Add(tailOnly ? aliasNameTailOnly : aliasName); } } } return(list); }
/////////////////////////////////////////////////////////////////////// public ReturnCode RemoveImports( string qualifiedPattern, bool strict, ref Result error ) { CheckDisposed(); if (imports == null) { error = String.Format( "imports not available in namespace \"{0}\"", GetDisplayName()); return(ReturnCode.Error); } INamespace patternNamespace = null; if ((qualifiedPattern != null) && (interpreter != null)) { patternNamespace = NamespaceOps.LookupParent( interpreter, qualifiedPattern, false, true, false, ref error); if (patternNamespace == null) { return(ReturnCode.Error); } } int count = 0; ObjectDictionary localImports = new ObjectDictionary( (IDictionary <string, object>)imports); foreach (KeyValuePair <string, object> pair in localImports) { IAlias alias = pair.Value as IAlias; string aliasName = NamespaceOps.GetAliasName(alias); string originName = GetOriginName(aliasName); if ((qualifiedPattern == null) || StringOps.Match(interpreter, MatchMode.Glob, aliasName, ScriptOps.MakeCommandName(qualifiedPattern), false) || ((originName != null) && StringOps.Match(interpreter, MatchMode.Glob, originName, ScriptOps.MakeCommandName(qualifiedPattern), false))) { INamespace originNamespace = null; if (originName != null) { originNamespace = NamespaceOps.LookupParent( interpreter, originName, false, true, false, ref error); if (originNamespace == null) { return(ReturnCode.Error); } } if ((patternNamespace == null) || ((alias != null) && (NamespaceOps.IsSame( alias.TargetNamespace, patternNamespace) || NamespaceOps.IsSame( originNamespace, patternNamespace)))) { if ((alias != null) && (interpreter != null)) { string nameToken = alias.NameToken; if ((nameToken != null) && interpreter.RemoveAliasAndCommand( alias.NameToken, null, false, ref error) != ReturnCode.Ok) { return(ReturnCode.Error); } } count += imports.Remove(pair.Key) ? 1 : 0; } } } if (strict && (count == 0)) { error = String.Format( "no imports matched pattern \"{0}\" in namespace \"{1}\"", qualifiedPattern, GetDisplayName()); return(ReturnCode.Error); } return(ReturnCode.Ok); }
/////////////////////////////////////////////////////////////////////// public ReturnCode RenameImport( string oldQualifiedName, string newQualifiedName, bool strict, ref Result error ) { CheckDisposed(); if (imports == null) { error = String.Format( "imports not available in namespace \"{0}\"", GetDisplayName()); return(ReturnCode.Error); } INamespace oldNamespace = NamespaceOps.LookupParent( interpreter, oldQualifiedName, false, true, false, ref error); if (oldNamespace == null) { return(ReturnCode.Error); } INamespace newNamespace = NamespaceOps.LookupParent( interpreter, newQualifiedName, false, true, false, ref error); if (newNamespace == null) { return(ReturnCode.Error); } int count = 0; ObjectDictionary localImports = new ObjectDictionary( (IDictionary <string, object>)imports); foreach (KeyValuePair <string, object> pair in localImports) { IAlias alias = pair.Value as IAlias; if (alias == null) { continue; } string aliasName = NamespaceOps.GetAliasName(alias); if (NamespaceOps.IsSame( alias.TargetNamespace, oldNamespace) && StringOps.Match(interpreter, MatchMode.Glob, aliasName, ScriptOps.MakeCommandName(oldQualifiedName), false)) { alias.TargetNamespace = newNamespace; NamespaceOps.SetAliasName(alias, newQualifiedName); return(ReturnCode.Ok); } else if (strict) { error = String.Format( "import \"{0}\" is not an alias in namespace \"{1}\"", oldQualifiedName, GetDisplayName()); return(ReturnCode.Error); } } if (strict && (count == 0)) { error = String.Format( "no imports matched name \"{0}\" in namespace \"{1}\"", oldQualifiedName, GetDisplayName()); return(ReturnCode.Error); } return(ReturnCode.Ok); }
/////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { ReturnCode code; // // NOTE: *WARNING* We do NOT actually support namespaces. This // command exists for the sole purpose of improving source // code compatibility with simple stand alone scripts that // may simply wrap themselves in a "namespace eval" block, // etc. Any other (more involved) use may not work at all // or may cause undesired and/or unpredictable results. // if (interpreter != null) { if (arguments != null) { if (arguments.Count >= 2) { string subCommand = arguments[1]; bool tried = false; code = ScriptOps.TryExecuteSubCommandFromEnsemble( interpreter, this, clientData, arguments, true, false, ref subCommand, ref tried, ref result); if ((code == ReturnCode.Ok) && !tried) { switch (subCommand) { case "children": { if ((arguments.Count >= 2) && (arguments.Count <= 4)) { string name = null; if (arguments.Count >= 3) { name = arguments[2]; } if ((arguments.Count < 3) || NamespaceOps.IsGlobalName(name)) { result = String.Empty; code = ReturnCode.Ok; } else { if (NamespaceOps.IsAbsoluteName(name)) { result = String.Format("namespace \"{0}\" not found", name); } else { result = String.Format("namespace \"{0}\" not found in \"{1}\"", name, TclVars.GlobalNamespace); } code = ReturnCode.Error; } } else { result = "wrong # args: should be \"namespace children ?name? ?pattern?\""; code = ReturnCode.Error; } break; } case "code": { if (arguments.Count == 3) { // // NOTE: We are always in the global namespace, fake it. // result = new StringList( TclVars.GlobalNamespace + this.Name, "inscope", TclVars.GlobalNamespace, arguments[2]); code = ReturnCode.Ok; } else { result = "wrong # args: should be \"namespace code script\""; code = ReturnCode.Error; } break; } case "current": { if (arguments.Count == 2) { result = TclVars.GlobalNamespace; code = ReturnCode.Ok; } else { result = "wrong # args: should be \"namespace current\""; code = ReturnCode.Error; } break; } case "delete": { if (arguments.Count >= 2) { code = ReturnCode.Ok; for (int index = 2; index < arguments.Count; index++) { if (!NamespaceOps.IsGlobalName(arguments[index])) { // // NOTE: We only know about the global namespace; an attempt // to delete any other namespace is an error. // result = String.Format( "unknown namespace \"{0}\" in namespace delete command", arguments[index]); code = ReturnCode.Error; break; } } if (code == ReturnCode.Ok) { for (int index = 2; index < arguments.Count; /* index++ */) { // // NOTE: Delete the one-and-only namespace (global) now (actually, // as soon as the evaluation stack unwinds). // code = interpreter.DeleteNamespace( VariableFlags.None, arguments[index], false, ref result); // // NOTE: Since we only know about the global namespace there // is no point in attempting to delete it multiple times. // break; } } if (code == ReturnCode.Ok) { result = String.Empty; } } else { result = "wrong # args: should be \"namespace delete ?name name ...?\""; code = ReturnCode.Error; } break; } case "enable": { if ((arguments.Count >= 2) && (arguments.Count <= 4)) { if (arguments.Count >= 3) { bool enabled = false; code = Value.GetBoolean2( arguments[2], ValueFlags.AnyBoolean, interpreter.CultureInfo, ref enabled, ref result); bool force = false; if ((code == ReturnCode.Ok) && (arguments.Count >= 4)) { code = Value.GetBoolean2( arguments[3], ValueFlags.AnyBoolean, interpreter.CultureInfo, ref force, ref result); } if (code == ReturnCode.Ok) { code = NamespaceOps.Enable( interpreter, enabled, force, ref result); } } if (code == ReturnCode.Ok) { result = interpreter.AreNamespacesEnabled(); } } else { result = "wrong # args: should be \"namespace enable ?enabled? ?force?\""; code = ReturnCode.Error; } break; } case "eval": { if (arguments.Count >= 4) { string name = StringList.MakeList("namespace eval", arguments[2]); ICallFrame frame = interpreter.NewTrackingCallFrame(name, CallFrameFlags.Namespace | CallFrameFlags.Evaluate); interpreter.PushAutomaticCallFrame(frame); if (arguments.Count == 4) { code = interpreter.EvaluateScript(arguments[3], ref result); } else { code = interpreter.EvaluateScript(arguments, 3, ref result); } if (code == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, result, String.Format("{0} (in namespace eval \"{1}\" script line {2})", Environment.NewLine, arguments[2], Interpreter.GetErrorLine(interpreter))); } // // NOTE: Pop the original call frame that we pushed above and // any intervening scope call frames that may be leftover // (i.e. they were not explicitly closed). // /* IGNORED */ interpreter.PopScopeCallFramesAndOneMore(); } else { result = "wrong # args: should be \"namespace eval name arg ?arg ...?\""; code = ReturnCode.Error; } break; } case "exists": { if (arguments.Count == 3) { if (NamespaceOps.IsGlobalName(arguments[2])) { result = true; } else { result = false; } code = ReturnCode.Ok; } else { result = "wrong # args: should be \"namespace exists name\""; code = ReturnCode.Error; } break; } case "export": { if (arguments.Count >= 2) { OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-clear", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null) }); int argumentIndex = Index.Invalid; if (arguments.Count > 2) { code = interpreter.GetOptions(options, arguments, 0, 2, Index.Invalid, false, ref argumentIndex, ref result); } else { code = ReturnCode.Ok; } // // NOTE: We do not support importing or exporting of namespace commands // because we do not really support namespaces; therefore, we do // nothing. // if (code == ReturnCode.Ok) { result = String.Empty; } } else { result = "wrong # args: should be \"namespace export ?-clear? ?pattern pattern ...?\""; code = ReturnCode.Error; } break; } case "forget": { if (arguments.Count >= 2) { // // NOTE: We do not support importing or exporting of namespace commands // because we do not really support namespaces; therefore, we do // nothing. // result = String.Empty; code = ReturnCode.Ok; } else { result = "wrong # args: should be \"namespace forget ?pattern pattern ...?\""; code = ReturnCode.Error; } break; } case "import": { if (arguments.Count >= 2) { OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-force", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null) }); int argumentIndex = Index.Invalid; if (arguments.Count > 2) { code = interpreter.GetOptions(options, arguments, 0, 2, Index.Invalid, false, ref argumentIndex, ref result); } else { code = ReturnCode.Ok; } // // NOTE: We do not support importing or exporting of namespace commands // because we do not really support namespaces; therefore, we do // nothing. // if (code == ReturnCode.Ok) { result = String.Empty; } } else { result = "wrong # args: should be \"namespace import ?-force? ?pattern pattern ...?\""; code = ReturnCode.Error; } break; } case "info": { if (arguments.Count == 3) { code = NamespaceOps.InfoSubCommand( interpreter, arguments[2], ref result); } else { result = "wrong # args: should be \"namespace info name\""; code = ReturnCode.Error; } break; } case "inscope": { if (arguments.Count >= 4) { if (NamespaceOps.IsGlobalName(arguments[2])) { if (arguments.Count > 4) { IScriptLocation location = null; #if DEBUGGER && BREAKPOINTS code = ScriptOps.GetLocation( interpreter, arguments, 3, ref location, ref result); if (code == ReturnCode.Ok) #endif { string name = StringList.MakeList("namespace inscope", arguments[2]); ICallFrame frame = interpreter.NewTrackingCallFrame(name, CallFrameFlags.Namespace | CallFrameFlags.InScope); interpreter.PushAutomaticCallFrame(frame); StringList list = new StringList(arguments, 4); code = interpreter.EvaluateScript( ListOps.Concat(arguments[3], list.ToString()), location, ref result); if (code == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, result, String.Format("{0} (in namespace inscope \"{1}\" script line {2})", Environment.NewLine, arguments[2], Interpreter.GetErrorLine(interpreter))); } // // NOTE: Pop the original call frame that we pushed above and // any intervening scope call frames that may be leftover // (i.e. they were not explicitly closed). // /* IGNORED */ interpreter.PopScopeCallFramesAndOneMore(); } } else { string name = StringList.MakeList("namespace inscope", arguments[2]); ICallFrame frame = interpreter.NewTrackingCallFrame(name, CallFrameFlags.Namespace | CallFrameFlags.InScope); interpreter.PushAutomaticCallFrame(frame); code = interpreter.EvaluateScript(arguments[3], ref result); if (code == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, result, String.Format("{0} (in namespace inscope \"{1}\" script line {2})", Environment.NewLine, arguments[2], Interpreter.GetErrorLine(interpreter))); } // // NOTE: Pop the original call frame that we pushed above and // any intervening scope call frames that may be leftover // (i.e. they were not explicitly closed). // /* IGNORED */ interpreter.PopScopeCallFramesAndOneMore(); } } else { result = String.Format( "unknown namespace \"{0}\" in inscope namespace command", arguments[2]); code = ReturnCode.Error; } } else { result = "wrong # args: should be \"namespace inscope name arg ?arg...?\""; code = ReturnCode.Error; } break; } case "mappings": { if (arguments.Count == 2) { lock (interpreter.SyncRoot) /* TRANSACTIONAL */ { StringDictionary namespaceMappings = interpreter.NamespaceMappings; if (namespaceMappings != null) { result = namespaceMappings.KeysAndValuesToString(null, false); code = ReturnCode.Ok; } else { result = "namespace mappings not available"; code = ReturnCode.Error; } } } else { result = "wrong # args: should be \"namespace mappings\""; code = ReturnCode.Error; } break; } case "name": { if (arguments.Count == 3) { // // NOTE: We are always in the global namespace, fake it. // string name = arguments[2]; if (!NamespaceOps.IsQualifiedName(name)) { result = NamespaceOps.MakeAbsoluteName(name); code = ReturnCode.Ok; } else { result = "only non-qualified names are allowed"; code = ReturnCode.Error; } } else { result = "wrong # args: should be \"namespace name name\""; code = ReturnCode.Error; } break; } case "origin": { if (arguments.Count == 3) { string executeName = arguments[2]; IExecute execute = null; code = interpreter.GetIExecuteViaResolvers( interpreter.GetResolveEngineFlags(true), executeName, null, LookupFlags.Default, ref execute, ref result); if (code == ReturnCode.Ok) { result = TclVars.GlobalNamespace + executeName; } } else { result = "wrong # args: should be \"namespace origin name\""; code = ReturnCode.Error; } break; } case "parent": { if ((arguments.Count == 2) || (arguments.Count == 3)) { // // NOTE: Either they did not specify a namespace argument (use current // namespace, which is always global and always exists) or they // specified a namespace which should be the global one; otherwise, // an error is reported because we do not really support namespaces. // if ((arguments.Count == 2) || NamespaceOps.IsGlobalName(arguments[2])) { result = String.Empty; code = ReturnCode.Ok; } else { // // NOTE: See if they prefixed the argument with "::" to figure out // the appropriate error message (Tcl emulation). // if (NamespaceOps.IsAbsoluteName(arguments[2])) { result = String.Format("namespace \"{0}\" not found", arguments[2]); } else { result = String.Format("namespace \"{0}\" not found in \"{1}\"", arguments[2], TclVars.GlobalNamespace); } code = ReturnCode.Error; } } else { result = "wrong # args: should be \"namespace parent ?name?\""; code = ReturnCode.Error; } break; } case "qualifiers": { if (arguments.Count == 3) { string qualifiers = null; string tail = null; code = NamespaceOps.SplitName( arguments[2], ref qualifiers, ref tail, ref result); if (code == ReturnCode.Ok) { result = qualifiers; } } else { result = "wrong # args: should be \"namespace qualifiers string\""; code = ReturnCode.Error; } break; } case "rename": { if (arguments.Count == 4) { result = "not implemented"; code = ReturnCode.Error; } else { result = "wrong # args: should be \"namespace rename oldName newName\""; code = ReturnCode.Error; } break; } case "tail": { if (arguments.Count == 3) { string qualifiers = null; string tail = null; code = NamespaceOps.SplitName( arguments[2], ref qualifiers, ref tail, ref result); if (code == ReturnCode.Ok) { result = tail; } } else { result = "wrong # args: should be \"namespace tail string\""; code = ReturnCode.Error; } break; } case "unknown": { // // NOTE: The string is currently used as the name of the command // or procedure to execute when an unknown command is // encountered by the engine. // if ((arguments.Count == 2) || (arguments.Count == 3)) { if (arguments.Count == 3) { string unknown = StringOps.NullIfEmpty(arguments[2]); if (String.IsNullOrEmpty(unknown)) { interpreter.NamespaceUnknown = interpreter.GlobalUnknown; } else { interpreter.NamespaceUnknown = unknown; } result = unknown; } else { result = interpreter.NamespaceUnknown; } code = ReturnCode.Ok; } else { result = "wrong # args: should be \"namespace unknown ?script?\""; code = ReturnCode.Error; } break; } case "which": { // // TODO: *FIXME* Only the global namespace is supported here. // if (arguments.Count >= 2) { OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-command", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-variable", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null) }); int argumentIndex = Index.Invalid; if (arguments.Count > 2) { code = interpreter.GetOptions(options, arguments, 0, 2, Index.Invalid, OptionBehaviorFlags.LastIsNonOption, false, ref argumentIndex, ref result); } else { code = ReturnCode.Ok; } if (code == ReturnCode.Ok) { if ((argumentIndex != Index.Invalid) && ((argumentIndex + 1) == arguments.Count)) { string name = arguments[argumentIndex]; bool isCommand = false; if (options.IsPresent("-command")) { isCommand = true; } bool isVariable = false; if (options.IsPresent("-variable")) { isVariable = true; } if (!isCommand || !isVariable) { if (!isCommand && !isVariable) { isCommand = true; } if (isCommand) { IExecute execute = null; code = interpreter.GetIExecuteViaResolvers( interpreter.GetResolveEngineFlags(true), name, null, LookupFlags.Default, ref execute, ref result); if (code == ReturnCode.Ok) { result = TclVars.GlobalNamespace + ScriptOps.MakeCommandName(name); } else { result = String.Empty; code = ReturnCode.Ok; } } else { VariableFlags flags = VariableFlags.NamespaceWhichMask; IVariable variable = null; code = interpreter.GetVariableViaResolversWithSplit( name, ref flags, ref variable, ref result); if (code == ReturnCode.Ok) { result = TclVars.GlobalNamespace + ScriptOps.MakeVariableName(name); } else { result = String.Empty; code = ReturnCode.Ok; } } } else { result = "wrong # args: should be \"namespace which ?-command? ?-variable? name\""; /* COMPAT: Tcl */ code = ReturnCode.Error; } } else { if ((argumentIndex != Index.Invalid) && Option.LooksLikeOption(arguments[argumentIndex])) { result = OptionDictionary.BadOption(options, arguments[argumentIndex]); } else { result = "wrong # args: should be \"namespace which ?-command? ?-variable? name\""; } code = ReturnCode.Error; } } } else { result = "wrong # args: should be \"namespace which ?-command? ?-variable? name\""; code = ReturnCode.Error; } break; } default: { result = ScriptOps.BadSubCommand( interpreter, null, null, subCommand, this, null, null); code = ReturnCode.Error; break; } } } } else { result = "wrong # args: should be \"namespace subcommand ?arg ...?\""; code = ReturnCode.Error; } } else { result = "invalid argument list"; code = ReturnCode.Error; } } else { result = "invalid interpreter"; code = ReturnCode.Error; } return(code); }