/////////////////////////////////////////////////////////////////////// #region Private Methods private bool HasFlags( ScriptBlockFlags hasFlags, /* in */ bool all /* in */ ) { return(FlagOps.HasFlags(scriptBlockFlags, hasFlags, all)); }
/////////////////////////////////////////////////////////////////////// internal ArgumentList( /* NOTE: For [apply] and [proc] use only. */ StringPairList list, ArgumentFlags flags ) : this() { if (list != null) { int count = list.Count; for (int index = 0; index < count; index++) { IPair <string> element = list[index]; // // HACK: Skip over any null entries, thus ignoring // them. // if (element == null) { continue; } // // NOTE: Does this argument list accept a variable // numbers of arguments (COMPAT: Tcl)? If so, // add a flag to the final argument to mark it // as an "argument list". // ArgumentFlags nameFlags = ArgumentFlags.None; if ((index == (count - 1)) && String.Compare( element.X, TclVars.Arguments, StringOps.SystemStringComparisonType) == 0) { nameFlags |= ArgumentFlags.ArgumentList; } ArgumentFlags valueFlags = (element.Y != null) ? ArgumentFlags.HasDefault : ArgumentFlags.None; Argument argument; if (FlagOps.HasFlags(flags, ArgumentFlags.NameOnly, true)) { argument = Argument.InternalCreate( flags | nameFlags | valueFlags, element.X, Argument.NoValue, element.Y); } else { argument = Argument.InternalCreate( flags | nameFlags | valueFlags, Argument.NoName, element.X, element.Y); } this.Add(argument); } } }
/////////////////////////////////////////////////////////////////////// public bool HasFlags( VariableFlags hasFlags, bool all ) { return(FlagOps.HasFlags(flags, hasFlags, all)); }
public bool HasFlags( ResultFlags hasFlags, bool all ) { return(FlagOps.HasFlags(flags, hasFlags, all)); }
/////////////////////////////////////////////////////////////////////// public bool HasFlags( OptionFlags flags, bool all ) { return(FlagOps.HasFlags(this.flags, flags, all)); }
/////////////////////////////////////////////////////////////////////// public ReturnCode ToList( AliasFlags hasFlags, AliasFlags notHasFlags, bool hasAll, bool notHasAll, string pattern, bool noCase, ref StringList list, ref Result error ) { StringList inputList; // // NOTE: If no flags were supplied, we do not bother filtering on // them. // if ((hasFlags == AliasFlags.None) && (notHasFlags == AliasFlags.None)) { inputList = new StringList(this.Keys); } else { inputList = new StringList(); foreach (KeyValuePair <string, _Wrappers.Alias> pair in this) { IAlias alias = pair.Value as IAlias; if (alias == null) { continue; } if (((hasFlags == AliasFlags.None) || FlagOps.HasFlags( alias.AliasFlags, hasFlags, hasAll)) && ((notHasFlags == AliasFlags.None) || !FlagOps.HasFlags( alias.AliasFlags, notHasFlags, notHasAll))) { inputList.Add(pair.Key); } } } if (list == null) { list = new StringList(); } return(GenericOps <string> .FilterList( inputList, list, Index.Invalid, Index.Invalid, ToStringFlags.None, pattern, noCase, ref error)); }
/////////////////////////////////////////////////////////////////////// private ArgumentList GetArgumentsForExecute( ArgumentList arguments ) { SubCommandFlags subCommandFlags = this.Flags; if (FlagOps.HasFlags(subCommandFlags, SubCommandFlags.UseExecuteArguments, true)) { return(arguments); } return(null); }
/////////////////////////////////////////////////////////////////////// public string ToString( DetailFlags detailFlags ) { CheckDisposed(); if (FlagOps.HasFlags( detailFlags, DetailFlags.ICallFrameNameOnly, true)) { return((name != null) ? name : String.Empty); } else { return(ToList(detailFlags).ToString()); } }
/////////////////////////////////////////////////////////////////////// internal static bool MaybeDispose( IEvent @event /* in */ ) { if (@event != null) { EventFlags flags = EntityOps.GetFlagsNoThrow(@event); if (FlagOps.HasFlags( flags, EventFlags.FireAndForget, true)) { return(Dispose(@event)); } } return(false); }
/////////////////////////////////////////////////////////////////////// public bool MaybeAddOrReplace( FindFlags flags, /* in */ string key, /* in */ TclBuild value, /* in */ ref Result error /* out */ ) { if (key == null) { error = String.Format( "can't add Tcl build file {0}: invalid key", FormatOps.TclBuildFileName(value)); return(false); } if (FlagOps.HasFlags(flags, FindFlags.TrustedOnly, true) && ((value == null) || !RuntimeOps.IsFileTrusted(value.FileName, IntPtr.Zero))) { error = String.Format( "can't add Tcl build file {0}: not trusted", FormatOps.TclBuildFileName(value)); return(false); } if (!this.ContainsKey(key)) { this.Add(key, value); return(true); } if (FlagOps.HasFlags( flags, FindFlags.OverwriteBuilds, true)) { this[key] = value; return(true); } error = String.Format( "can't add Tcl build file {0}: already present", FormatOps.TclBuildFileName(value)); return(false); }
/////////////////////////////////////////////////////////////////////// public int GetOptionalCount() { // // NOTE: Return the total number of arguments in the list // that are optional. In order for an argument to // be considered optional, it must meet the following // criteria: // // 1. It must have a default value that is not null. // // 2. No non-optional arguments may occur after it // in the argument list (COMPAT: Tcl). // int result = 0; // // NOTE: Grab the count as we need to use it several times in // this method. // int count = this.Count; // // NOTE: Count all the arguments starting from the end of the // list going backward that have a default value. // int index = IsVariadic(false) ? count - 2 : count - 1; for (; index >= 0; index--) { Argument argument = this[index]; if ((argument != null) && FlagOps.HasFlags( argument.Flags, ArgumentFlags.HasDefault, true)) { result++; } else { break; } } return(result); }
/////////////////////////////////////////////////////////////////////// public virtual ReturnCode AddOrUpdateSubCommand( string name, ISubCommand subCommand, IClientData clientData, SubCommandFlags flags, ref Result error ) { if (name == null) { error = "invalid sub-command name"; return(ReturnCode.Error); } EnsembleDictionary subCommands = this.SubCommands; if (subCommands == null) { error = "sub-commands not available"; return(ReturnCode.Error); } if ((subCommand == null) && FlagOps.HasFlags(flags, SubCommandFlags.Core, true)) { subCommand = GetCoreSubCommand(); } subCommands[name] = subCommand; if (subCommand != null) { EnsembleDictionary subSubCommands = subCommand.SubCommands; if (subSubCommands != null) { subSubCommands[name] = subCommand; } } return(ReturnCode.Ok); }
/////////////////////////////////////////////////////////////////////// public override ReturnCode Initialize( Interpreter interpreter, IClientData clientData, ref Result result ) { if (interpreter != null) { NotifyType notifyTypes = GetTypes(interpreter); if (!FlagOps.HasFlags( interpreter.NotifyTypes, notifyTypes, true)) { // // NOTE: Add the notify types that we need to the // interpreter. // interpreter.GlobalNotifyTypes |= notifyTypes; savedNotifyTypes = notifyTypes; } /////////////////////////////////////////////////////////////// NotifyFlags notifyFlags = GetFlags(interpreter); if (!FlagOps.HasFlags( interpreter.NotifyFlags, notifyFlags, true)) { // // NOTE: Add the notify flags that we need to the // interpreter. // interpreter.GlobalNotifyFlags |= notifyFlags; savedNotifyFlags = notifyFlags; } } /////////////////////////////////////////////////////////////////// return(base.Initialize(interpreter, clientData, ref result)); }
/////////////////////////////////////////////////////////////////////// internal ArgumentList( IEnumerable <string> collection, ArgumentFlags flags ) : this() { foreach (string item in collection) { Argument argument; if (FlagOps.HasFlags(flags, ArgumentFlags.NameOnly, true)) { argument = Argument.InternalCreate(flags, item); } else { argument = Argument.InternalCreate( flags, Argument.NoName, item); } this.Add(argument); } }
/////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { if (interpreter == null) { result = "invalid interpreter"; return(ReturnCode.Error); } if (arguments == null) { result = "invalid argument list"; return(ReturnCode.Error); } if (arguments.Count < 2) { result = "wrong # args: should be \"variable ?name value...? name ?value?\""; return(ReturnCode.Error); } ICallFrame localFrame = null; if (interpreter.GetVariableFrameViaResolvers( LookupFlags.Default, ref localFrame, ref result) != ReturnCode.Ok) { return(ReturnCode.Error); } if (localFrame == null) { result = "local call frame is invalid"; return(ReturnCode.Error); } if (!localFrame.IsVariable) { result = "local call frame does not support variables"; return(ReturnCode.Error); } bool useNamespaces = interpreter.AreNamespacesEnabled(); INamespace currentNamespace = null; if (useNamespaces && interpreter.GetCurrentNamespaceViaResolvers( null, LookupFlags.Default, ref currentNamespace, ref result) != ReturnCode.Ok) { return(ReturnCode.Error); } ICallFrame otherFrame = null; if ((currentNamespace != null) && !interpreter.IsGlobalNamespace(currentNamespace)) { otherFrame = currentNamespace.VariableFrame; } else { otherFrame = interpreter.CurrentGlobalFrame; } for (int argumentIndex = 1; argumentIndex < arguments.Count; argumentIndex += 2) { string varName = arguments[argumentIndex]; lock (interpreter.SyncRoot) /* TRANSACTIONAL */ { VariableFlags flags = VariableFlags.NoElement; if (!useNamespaces) { flags |= VariableFlags.GlobalOnly; } IVariable otherVariable = null; Result error = null; if (interpreter.GetVariableViaResolversWithSplit( varName, ref flags, ref otherVariable, ref error) != ReturnCode.Ok) { if (FlagOps.HasFlags( flags, VariableFlags.NotFound, true)) { error = null; if (interpreter.AddVariable2( VariableFlags.Undefined | flags, varName, null, true, ref otherVariable, ref error) != ReturnCode.Ok) { result = error; return(ReturnCode.Error); } } else { // // NOTE: We did not search for the variable, let // the caller know why. // result = error; return(ReturnCode.Error); } } // // NOTE: Create the variable link between the local frame // (i.e. a procedure, etc) and the other frame (i.e. // namespace or global). // if (CallFrameOps.IsLocal(localFrame)) { error = null; if (ScriptOps.LinkVariable( interpreter, localFrame, varName, otherFrame, varName, ref error) != ReturnCode.Ok) { result = error; return(ReturnCode.Error); } } // // NOTE: If they provided a value, set it now. // // BUGFIX: This must be done after setting up the link // and not before; otherwise, the LinkVariable // method will detect a defined variable with // the same name in the local call frame and // refuse to overwrite it (by design). // if ((argumentIndex + 1) < arguments.Count) { error = null; if (interpreter.SetVariableValue2( VariableFlags.None, otherFrame, varName, null, arguments[argumentIndex + 1].Value, null, ref otherVariable, ref error) != ReturnCode.Ok) { result = error; return(ReturnCode.Error); } } } } result = String.Empty; return(ReturnCode.Ok); }
/////////////////////////////////////////////////////////////////////////////////////////////// #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 >= 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 "forget": { if (arguments.Count >= 2) { code = interpreter.PkgForget( new StringList(arguments, 2), ref result); } else { result = "wrong # args: should be \"package forget ?package package ...?\""; code = ReturnCode.Error; } break; } case "ifneeded": { if ((arguments.Count == 4) || (arguments.Count == 5)) { Version version = null; code = Value.GetVersion( arguments[3], interpreter.CultureInfo, ref version, ref result); if (code == ReturnCode.Ok) { string text = null; if (arguments.Count == 5) { text = arguments[4]; } code = interpreter.PkgIfNeeded( arguments[2], version, text, interpreter.PackageFlags, ref result); } } else { result = "wrong # args: should be \"package ifneeded package version ?script?\""; code = ReturnCode.Error; } break; } case "indexes": { if ((arguments.Count == 2) || (arguments.Count == 3)) { string pattern = null; if (arguments.Count == 3) { pattern = arguments[2]; } code = interpreter.PkgIndexes( pattern, false, ref result); } else { result = "wrong # args: should be \"package indexes ?pattern?\""; code = ReturnCode.Error; } break; } case "info": { if (arguments.Count == 3) { IPackage package = null; code = interpreter.GetPackage( arguments[2], LookupFlags.Default, ref package, ref result); if (code == ReturnCode.Ok) { bool scrub = interpreter.IsSafe(); PackageFlags flags = package.Flags; Guid id = AttributeOps.GetObjectId(package); result = StringList.MakeList( "kind", package.Kind, "id", package.Id.Equals(Guid.Empty) ? id : package.Id, "name", package.Name, "description", package.Description, "indexFileName", scrub ? PathOps.ScrubPath( GlobalState.GetBasePath(), package.IndexFileName) : package.IndexFileName, "provideFileName", scrub ? PathOps.ScrubPath( GlobalState.GetBasePath(), package.ProvideFileName) : package.ProvideFileName, "flags", flags, "loaded", (package.Loaded != null) ? package.Loaded : null, "ifNeeded", (!scrub && (package.IfNeeded != null)) ? package.IfNeeded.KeysAndValuesToString(null, false) : null); } } else { result = "wrong # args: should be \"package info name\""; code = ReturnCode.Error; } break; } case "loaded": { if ((arguments.Count == 2) || (arguments.Count == 3)) { string pattern = null; if (arguments.Count == 3) { pattern = arguments[2]; } code = interpreter.PkgLoaded( pattern, false, false, ref result); } else { result = "wrong # args: should be \"package loaded ?pattern?\""; code = ReturnCode.Error; } break; } case "names": { if ((arguments.Count == 2) || (arguments.Count == 3)) { string pattern = null; if (arguments.Count == 3) { pattern = arguments[2]; } code = interpreter.PkgNames( pattern, false, ref result); } else { result = "wrong # args: should be \"package names ?pattern?\""; code = ReturnCode.Error; } break; } case "present": { if (arguments.Count >= 3) { OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-exact", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null) }); int argumentIndex = Index.Invalid; code = interpreter.GetOptions(options, arguments, 0, 2, Index.Invalid, false, ref argumentIndex, ref result); if (code == ReturnCode.Ok) { if ((argumentIndex != Index.Invalid) && ((argumentIndex + 2) >= arguments.Count)) { bool exact = false; if (options.IsPresent("-exact")) { exact = true; } Version version = null; if ((argumentIndex + 1) < arguments.Count) { code = Value.GetVersion( arguments[argumentIndex + 1], interpreter.CultureInfo, ref version, ref result); } if (code == ReturnCode.Ok) { code = interpreter.PresentPackage( arguments[argumentIndex], version, exact, ref result); } } else { if ((argumentIndex != Index.Invalid) && Option.LooksLikeOption(arguments[argumentIndex])) { result = OptionDictionary.BadOption(options, arguments[argumentIndex]); } else { result = "wrong # args: should be \"package present ?-exact? package ?version?\""; } code = ReturnCode.Error; } } } else { result = "wrong # args: should be \"package present ?-exact? package ?version?\""; code = ReturnCode.Error; } break; } case "provide": { if ((arguments.Count == 3) || (arguments.Count == 4)) { PackageFlags flags = interpreter.PackageFlags; if (!FlagOps.HasFlags(flags, PackageFlags.NoProvide, true)) { Version version = null; if (arguments.Count == 4) { code = Value.GetVersion(arguments[3], interpreter.CultureInfo, ref version, ref result); } if (code == ReturnCode.Ok) { code = interpreter.PkgProvide(arguments[2], version, flags, ref result); } } else { // // HACK: Do nothing, provide no package, and return nothing. // result = String.Empty; code = ReturnCode.Ok; } } else { result = "wrong # args: should be \"package provide package ?version?\""; code = ReturnCode.Error; } break; } case "relativefilename": { if ((arguments.Count == 3) || (arguments.Count == 4)) { PathComparisonType pathComparisonType = PathComparisonType.Default; if (arguments.Count == 4) { object enumValue = EnumOps.TryParseFlagsEnum( interpreter, typeof(PathComparisonType), pathComparisonType.ToString(), arguments[3], interpreter.CultureInfo, true, true, true, ref result); if (enumValue is EventFlags) { pathComparisonType = (PathComparisonType)enumValue; } else { code = ReturnCode.Error; } } if (code == ReturnCode.Ok) { string fileName = null; code = PackageOps.GetRelativeFileName( interpreter, arguments[2], pathComparisonType, ref fileName, ref result); if (code == ReturnCode.Ok) { result = fileName; } } } else { result = "wrong # args: should be \"package relativefilename fileName ?type?\""; code = ReturnCode.Error; } break; } case "require": { if (arguments.Count >= 3) { OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-exact", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null) }); int argumentIndex = Index.Invalid; code = interpreter.GetOptions(options, arguments, 0, 2, Index.Invalid, false, ref argumentIndex, ref result); if (code == ReturnCode.Ok) { if ((argumentIndex != Index.Invalid) && ((argumentIndex + 2) >= arguments.Count)) { bool exact = false; if (options.IsPresent("-exact")) { exact = true; } Version version = null; if ((argumentIndex + 1) < arguments.Count) { code = Value.GetVersion( arguments[argumentIndex + 1], interpreter.CultureInfo, ref version, ref result); } if (code == ReturnCode.Ok) { code = interpreter.RequirePackage( arguments[argumentIndex], version, exact, ref result); } // // NOTE: This is a new feature. If the initial attempt to // require a package fails, call the package fallback // delegate for the interpreter and then try requiring // the package again. // if ((code != ReturnCode.Ok) && !ScriptOps.HasFlags( interpreter, InterpreterFlags.NoPackageFallback, true)) { PackageCallback packageFallback = interpreter.PackageFallback; if (packageFallback != null) { code = packageFallback( interpreter, arguments[argumentIndex], version, null, interpreter.PackageFlags, exact, ref result); if (code == ReturnCode.Ok) { code = interpreter.RequirePackage( arguments[argumentIndex], version, exact, ref result); } } } // // BUGFIX: This is really a new feature. In the event of a failure // here, we now fallback to the "unknown package handler", // just like Tcl does. // if ((code != ReturnCode.Ok) && !ScriptOps.HasFlags( interpreter, InterpreterFlags.NoPackageUnknown, true)) { string text = interpreter.PackageUnknown + Characters.Space + Parser.Quote(arguments[argumentIndex]); if (version != null) { text += Characters.Space + Parser.Quote(version.ToString()); } code = interpreter.EvaluateScript(text, ref result); /* EXEMPT */ if (code == ReturnCode.Ok) { code = interpreter.RequirePackage( arguments[argumentIndex], version, exact, ref result); } } } else { if ((argumentIndex != Index.Invalid) && Option.LooksLikeOption(arguments[argumentIndex])) { result = OptionDictionary.BadOption(options, arguments[argumentIndex]); } else { result = "wrong # args: should be \"package require ?-exact? package ?version?\""; } code = ReturnCode.Error; } } } else { result = "wrong # args: should be \"package require ?-exact? package ?version?\""; code = ReturnCode.Error; } break; } case "reset": { if (arguments.Count == 2) { code = interpreter.ResetPkgIndexes(ref result); if (code == ReturnCode.Ok) { result = String.Empty; } } else { result = "wrong # args: should be \"package reset\""; code = ReturnCode.Error; } break; } case "scan": { if (arguments.Count >= 2) { OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-interpreter", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-preferfilesystem", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-preferhost", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-host", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-normal", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-nonormal", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-recursive", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-resolve", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-refresh", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-autopath", 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, true, ref argumentIndex, ref result); } else { code = ReturnCode.Ok; } if (code == ReturnCode.Ok) { lock (interpreter.SyncRoot) /* TRANSACTIONAL */ { PackageIndexFlags flags; if (options.IsPresent("-interpreter")) { flags = interpreter.PackageIndexFlags; } else { flags = PackageIndexFlags.Default; } if (options.IsPresent("-preferfilesystem")) { flags |= PackageIndexFlags.PreferFileSystem; } if (options.IsPresent("-preferhost")) { flags |= PackageIndexFlags.PreferHost; } if (options.IsPresent("-host")) { flags |= PackageIndexFlags.Host; } if (options.IsPresent("-normal")) { flags |= PackageIndexFlags.Normal; } if (options.IsPresent("-nonormal")) { flags |= PackageIndexFlags.NoNormal; } if (options.IsPresent("-recursive")) { flags |= PackageIndexFlags.Recursive; } if (options.IsPresent("-refresh")) { flags |= PackageIndexFlags.Refresh; } if (options.IsPresent("-resolve")) { flags |= PackageIndexFlags.Resolve; } bool autoPath = false; if (options.IsPresent("-autopath")) { autoPath = true; } StringList paths; if (argumentIndex != Index.Invalid) { // // NOTE: Refresh the specified path list. // paths = new StringList(arguments, argumentIndex); } else { // // NOTE: Refresh the default path list. // paths = GlobalState.GetAutoPathList(interpreter, autoPath); // // NOTE: Did they request the auto-path be rebuilt? // if (autoPath) { // // NOTE: Since the actual auto-path may have changed, // update the variable now. We disable traces // here because we manually rescan, if necessary, // below. // code = interpreter.SetLibraryVariableValue( VariableFlags.SkipTrace, TclVars.AutoPath, (paths != null) ? paths.ToString() : null, ref result); } } if (code == ReturnCode.Ok) { PackageIndexDictionary packageIndexes = interpreter.CopyPackageIndexes(); if (code == ReturnCode.Ok) { code = PackageOps.FindAll( interpreter, paths, flags, ref packageIndexes, ref result); } if (code == ReturnCode.Ok) { interpreter.PackageIndexes = packageIndexes; result = String.Empty; } } } } } else { result = "wrong # args: should be \"package scan ?options? ?dir dir ...?\""; code = ReturnCode.Error; } break; } case "unknown": { if ((arguments.Count == 2) || (arguments.Count == 3)) { if (arguments.Count == 3) { interpreter.PackageUnknown = arguments[2]; result = String.Empty; } else { result = interpreter.PackageUnknown; } code = ReturnCode.Ok; } else { result = "wrong # args: should be \"package unknown ?command?\""; code = ReturnCode.Error; } break; } case "vcompare": { if (arguments.Count == 4) { Version version1 = null; code = Value.GetVersion( arguments[2], interpreter.CultureInfo, ref version1, ref result); Version version2 = null; if (code == ReturnCode.Ok) { code = Value.GetVersion( arguments[3], interpreter.CultureInfo, ref version2, ref result); } if (code == ReturnCode.Ok) { result = PackageOps.VersionCompare(version1, version2); } } else { result = "wrong # args: should be \"package vcompare version1 version2\""; code = ReturnCode.Error; } break; } case "versions": { if (arguments.Count == 3) { code = interpreter.PkgVersions( arguments[2], ref result); } else { result = "wrong # args: should be \"package versions package\""; code = ReturnCode.Error; } break; } case "vloaded": { if ((arguments.Count == 2) || (arguments.Count == 3)) { string pattern = null; if (arguments.Count == 3) { pattern = arguments[2]; } code = interpreter.PkgLoaded( pattern, false, true, ref result); } else { result = "wrong # args: should be \"package vloaded ?pattern?\""; code = ReturnCode.Error; } break; } case "vsatisfies": { if (arguments.Count == 4) { PackageFlags flags = interpreter.PackageFlags; if (!FlagOps.HasFlags(flags, PackageFlags.AlwaysSatisfy, true)) { Version version1 = null; code = Value.GetVersion(arguments[2], interpreter.CultureInfo, ref version1, ref result); Version version2 = null; if (code == ReturnCode.Ok) { code = Value.GetVersion( arguments[3], interpreter.CultureInfo, ref version2, ref result); } if (code == ReturnCode.Ok) { result = PackageOps.VersionSatisfies( version1, version2, false); } } else { // // HACK: Always fake that this was a satisfied package request. // result = true; code = ReturnCode.Ok; } } else { result = "wrong # args: should be \"package vsatisfies version1 version2\""; code = ReturnCode.Error; } break; } case "withdraw": { if ((arguments.Count == 3) || (arguments.Count == 4)) { Version version = null; if (arguments.Count == 4) { code = Value.GetVersion( arguments[3], interpreter.CultureInfo, ref version, ref result); } if (code == ReturnCode.Ok) { code = interpreter.WithdrawPackage( arguments[2], version, ref result); } } else { result = "wrong # args: should be \"package withdraw package ?version?\""; 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 \"package arg ?arg ...?\""; code = ReturnCode.Error; } } else { result = "invalid argument list"; code = ReturnCode.Error; } } else { result = "invalid interpreter"; code = ReturnCode.Error; } return(code); }
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 >= 2) { string fileName = arguments[1]; if (interpreter.HasChannels(ref result)) { MapOpenAccess access = MapOpenAccess.Default; int permissions = 0; // NOTE: This is ONLY parsed, NOT used for opening the file. string type = null; if (arguments.Count >= 3) { Result enumString = arguments[2]; if (!String.IsNullOrEmpty(enumString)) { // // HACK: Translate illegal mode char "+" to what our Enum uses. // This strategy will backfire later if we ever decide to // allow parsing of the access mode as "flags" (via GetOptions). // enumString = enumString.Replace(Characters.PlusSign.ToString(), "Plus"); } code = StringOps.StringToEnumList(interpreter, enumString, ref enumString); if (code == ReturnCode.Ok) { object enumValue = EnumOps.TryParseEnum( typeof(MapOpenAccess), enumString, true, true); if (enumValue is MapOpenAccess) { access = (MapOpenAccess)enumValue; } else { enumString = ScriptOps.BadValue( "invalid", "access mode", arguments[2], Enum.GetNames(typeof(MapOpenAccess)), null, null); code = ReturnCode.Error; } } if (code != ReturnCode.Ok) { // // NOTE: Transfer local result from above and add to the error info. // result = enumString; Engine.AddErrorInformation(interpreter, result, String.Format("{0} while processing open access modes \"{1}\"", Environment.NewLine, FormatOps.Ellipsis(arguments[2]))); } } if ((code == ReturnCode.Ok) && (arguments.Count >= 4)) { code = Value.GetInteger2( (IGetValue)arguments[3], ValueFlags.AnyInteger, interpreter.CultureInfo, ref permissions, ref result); } if (code == ReturnCode.Ok) { if (arguments.Count >= 5) { type = arguments[4]; } OptionDictionary options = new OptionDictionary( new IOption[] { #if CONSOLE new Option(null, OptionFlags.None, 1, Index.Invalid, "-stdin", null), new Option(null, OptionFlags.None, 1, Index.Invalid, "-stdout", null), new Option(null, OptionFlags.None, 1, Index.Invalid, "-stderr", null), #else new Option(null, OptionFlags.Unsupported, 1, Index.Invalid, "-stdin", null), new Option(null, OptionFlags.Unsupported, 1, Index.Invalid, "-stdout", null), new Option(null, OptionFlags.Unsupported, 1, Index.Invalid, "-stderr", null), #endif new Option(null, OptionFlags.MustHaveValue, Index.Invalid, Index.Invalid, "-channelid", null), new Option(null, OptionFlags.MustHaveIntegerValue, Index.Invalid, Index.Invalid, "-buffersize", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-autoflush", null), new Option(typeof(HostStreamFlags), OptionFlags.MustHaveEnumValue, Index.Invalid, Index.Invalid, "-streamflags", new Variant(HostStreamFlags.Default)), new Option(typeof(FileOptions), OptionFlags.MustHaveEnumValue, Index.Invalid, Index.Invalid, "-options", new Variant(FileOptions.None)), new Option(typeof(FileShare), OptionFlags.MustHaveEnumValue, Index.Invalid, Index.Invalid, "-share", new Variant(FileShare.Read)) }); int argumentIndex = Index.Invalid; if (arguments.Count > 5) { code = interpreter.GetOptions(options, arguments, 0, 5, Index.Invalid, true, ref argumentIndex, ref result); } else { code = ReturnCode.Ok; } if (code == ReturnCode.Ok) { if (argumentIndex == Index.Invalid) { Variant value = null; string channelId = null; if (options.IsPresent("-channelid", ref value)) { channelId = value.ToString(); } if ((channelId == null) || (interpreter.DoesChannelExist(channelId) != ReturnCode.Ok)) { #if CONSOLE if (options.IsPresent("-stdin")) { // // NOTE: Enforce the proper access for the standard input // channel. // if (access == MapOpenAccess.RdOnly) { try { IStreamHost streamHost = interpreter.Host; // // NOTE: *WARNING* This option causes the "fileName", // "access", "permissions", and "type" arguments // to be ignored. // lock (interpreter.SyncRoot) /* TRANSACTIONAL */ { if (streamHost.In == null) { int?bufferSize = null; if (options.IsPresent("-buffersize", ref value)) { bufferSize = (int)value.Value; } streamHost.In = (bufferSize != null) ? Console.OpenStandardInput((int)bufferSize) : Console.OpenStandardInput(); } } code = interpreter.ModifyStandardChannels( streamHost, channelId, ChannelType.Input | ChannelType.ErrorOnExist, ref result); if (code == ReturnCode.Ok) { result = (channelId != null) ? channelId : StandardChannel.Input; } } catch (Exception e) { Engine.SetExceptionErrorCode(interpreter, e); result = e; code = ReturnCode.Error; } } else { result = String.Format( "illegal access mode \"{0}\", standard input " + "can only be opened using access mode \"{1}\"", access, MapOpenAccess.RdOnly); code = ReturnCode.Error; } } else if (options.IsPresent("-stdout")) { // // NOTE: Enforce the proper access for the standard output // channel. // if (access == MapOpenAccess.WrOnly) { try { IStreamHost streamHost = interpreter.Host; // // NOTE: *WARNING* This option causes the "fileName", // "access", "permissions", and "type" arguments // to be ignored. // lock (interpreter.SyncRoot) /* TRANSACTIONAL */ { if (streamHost.Out == null) { int?bufferSize = null; if (options.IsPresent("-buffersize", ref value)) { bufferSize = (int)value.Value; } streamHost.Out = (bufferSize != null) ? Console.OpenStandardOutput((int)bufferSize) : Console.OpenStandardOutput(); } } code = interpreter.ModifyStandardChannels( streamHost, channelId, ChannelType.Output | ChannelType.ErrorOnExist, ref result); if (code == ReturnCode.Ok) { result = (channelId != null) ? channelId : StandardChannel.Output; } } catch (Exception e) { Engine.SetExceptionErrorCode(interpreter, e); result = e; code = ReturnCode.Error; } } else { result = String.Format( "illegal access mode \"{0}\", standard output " + "can only be opened using access mode \"{1}\"", access, MapOpenAccess.WrOnly); code = ReturnCode.Error; } } else if (options.IsPresent("-stderr")) { // // NOTE: Enforce the proper access for the standard error // channel. // if (access == MapOpenAccess.WrOnly) { try { IStreamHost streamHost = interpreter.Host; // // NOTE: *WARNING* This option causes the "fileName", // "access", "permissions", and "type" arguments // to be ignored. // lock (interpreter.SyncRoot) /* TRANSACTIONAL */ { if (streamHost.Error == null) { int?bufferSize = null; if (options.IsPresent("-buffersize", ref value)) { bufferSize = (int)value.Value; } streamHost.Error = (bufferSize != null) ? Console.OpenStandardError((int)bufferSize) : Console.OpenStandardError(); } } code = interpreter.ModifyStandardChannels( streamHost, channelId, ChannelType.Error | ChannelType.ErrorOnExist, ref result); if (code == ReturnCode.Ok) { result = (channelId != null) ? channelId : StandardChannel.Error; } } catch (Exception e) { Engine.SetExceptionErrorCode(interpreter, e); result = e; code = ReturnCode.Error; } } else { result = String.Format( "illegal access mode \"{0}\", standard error " + "can only be opened using access mode \"{1}\"", access, MapOpenAccess.WrOnly); code = ReturnCode.Error; } } else #endif { Stream stream = null; bool autoFlush = false; switch (type) { case null: /* FALL-THROUGH */ case /* String.Empty */ "": /* FALL-THROUGH */ case "file": { try { HostStreamFlags hostStreamFlags = HostStreamFlags.OpenCommand; FileAccess fileAccess = FileOps.FileAccessFromAccess(access); FileMode fileMode = FileOps.FileModeFromAccess(access); FileShare fileShare = FileShare.Read; if (options.IsPresent("-streamflags", ref value)) { hostStreamFlags = (HostStreamFlags)value.Value; } if (options.IsPresent("-share", ref value)) { fileShare = (FileShare)value.Value; } int bufferSize = Channel.DefaultBufferSize; if (options.IsPresent("-buffersize", ref value)) { bufferSize = (int)value.Value; } FileOptions fileOptions = FileOptions.None; if (options.IsPresent("-options", ref value)) { fileOptions = (FileOptions)value.Value; } if (options.IsPresent("-autoflush")) { autoFlush = true; } bool seekToEof = false; // // HACK: Check for special case where they want to Append // and Read/ReadWrite. // if (((fileAccess == FileAccess.Read) || (fileAccess == FileAccess.ReadWrite)) && (FlagOps.HasFlags(access, MapOpenAccess.SeekToEof, true) || FlagOps.HasFlags(access, MapOpenAccess.Append, true))) { seekToEof = true; } code = interpreter.GetStream( fileName, fileMode, fileAccess, fileShare, bufferSize, fileOptions, Channel.StrictGetStream, ref hostStreamFlags, ref stream, ref result); if (code == ReturnCode.Ok) { if ((stream != null) && seekToEof) { stream.Seek(0, SeekOrigin.End); } } } catch (Exception e) { Engine.SetExceptionErrorCode(interpreter, e); result = e; code = ReturnCode.Error; } break; } default: { result = String.Format( "unsupported channel type \"{0}\"", type); code = ReturnCode.Error; break; } } // // NOTE: Did we manage to open the file successfully? // if (code == ReturnCode.Ok) { StreamFlags flags = StreamFlags.PreventClose; if (channelId == null) { channelId = FormatOps.Id("file", null, interpreter.NextId()); } code = interpreter.AddFileOrSocketChannel( channelId, stream, options, flags, FlagOps.HasFlags(access, MapOpenAccess.Append, true), autoFlush, null, ref result); if (code == ReturnCode.Ok) { result = channelId; } } } } else { result = String.Format( "can't add \"{0}\": channel already exists", channelId); code = ReturnCode.Error; } } else { result = "wrong # args: should be \"open fileName ?access? ?permissions? ?type? ?options?\""; code = ReturnCode.Error; } } } } else { code = ReturnCode.Error; } } else { result = "wrong # args: should be \"open fileName ?access? ?permissions? ?type? ?options?\""; code = ReturnCode.Error; } } else { result = "invalid argument list"; code = ReturnCode.Error; } } else { result = "invalid interpreter"; code = ReturnCode.Error; } return(code); }
/////////////////////////////////////////////////////////////////////// #region INotify Members public override ReturnCode Notify( Interpreter interpreter, IScriptEventArgs eventArgs, IClientData clientData, ArgumentList arguments, ref Result result ) { if (eventArgs == null) { return(ReturnCode.Ok); } if (!FlagOps.HasFlags( eventArgs.NotifyTypes, NotifyType.CallFrame, false)) { return(ReturnCode.Ok); } NotifyFlags notifyFlags = eventArgs.NotifyFlags; if (!FlagOps.HasFlags(notifyFlags, NotifyFlags.Popped | NotifyFlags.Deleted, false)) { return(ReturnCode.Ok); } IClientData eventClientData = eventArgs.ClientData; if (eventClientData == null) { return(ReturnCode.Ok); } ICallFrame newFrame = eventClientData.Data as ICallFrame; if (newFrame == null) { return(ReturnCode.Ok); } // // NOTE: Make sure the variables in this frame actually BELONG // to this frame. Also, we do not handle the global call // frame. // if (!FlagOps.HasFlags(notifyFlags, NotifyFlags.Force, true) && !CallFrameOps.IsNonGlobalVariable(newFrame)) { return(ReturnCode.Ok); } // // NOTE: If this is a [scope] created call frame, we do NOT want // to change any reference counts unless the call frame is // being deleted, not simply popped. // if (!FlagOps.HasFlags(notifyFlags, NotifyFlags.Deleted, true) && CallFrameOps.IsScope(newFrame)) { return(ReturnCode.Ok); } // // NOTE: Grab the variables for this call frame. If there are // none, we are done. // VariableDictionary variables = newFrame.Variables; if (variables == null) { return(ReturnCode.Ok); } // // NOTE: Process each variable in the call frame to adjust all // all the reference counts. After this point, we need // the interpreter context for the event. // Interpreter eventInterpreter = eventArgs.Interpreter; if (eventInterpreter == null) { return(ReturnCode.Ok); } foreach (KeyValuePair <string, IVariable> pair in variables) { // // NOTE: Grab the variable and make sure the variable it is // valid. // IVariable variable = pair.Value; if (variable == null) { continue; } // // NOTE: For unset operations, ObjectTraceCallback uses only // the "traceInfo.Variable" and "traceInfo.oldValue" // members of the ITraceInfo object instance. If the // number of trace and/or watch levels exceeds one, // force creation of a new TraceInfo object here; // otherwise, we may interfere with the setting of an // unrelated variable value. // ITraceInfo traceInfo = ScriptOps.NewTraceInfo( interpreter, null, BreakpointType.BeforeVariableUnset, newFrame, variable, pair.Key, null, VariableFlags.None, variable.Value, null, null, null, null, interpreter.NeedNewTraceInfo(VariableFlags.None), false, !EntityOps.IsNoPostProcess(variable), ReturnCode.Ok); // // HACK: Manually invoke the Interpreter.ObjectTraceCallback // static (trace callback) method, in order to handle // contained object reference(s), if any. After this // method returns, the entire call frame will be going // away, along with any object references contained // within it. // ReturnCode code = Interpreter.ObjectTraceCallback( traceInfo.BreakpointType, eventInterpreter, traceInfo, ref result); if (code != ReturnCode.Ok) { return(code); } } return(ReturnCode.Ok); }
/////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { if (targetInterpreter == null) { result = "invalid interpreter"; return(ReturnCode.Error); } ReturnCode code; string targetName = null; ArgumentList targetArguments = null; code = targetInterpreter.GetAliasArguments( this, arguments, ref targetName, ref targetArguments, ref result); if (code == ReturnCode.Ok) { // // NOTE: Grab the target of the alias (this will be null if we // are late-bound). // IExecute target = null; bool useUnknown = false; code = targetInterpreter.GetAliasTarget(this, targetName, targetArguments, LookupFlags.Default, true, ref target, ref useUnknown, ref result); // // NOTE: Do we have a valid target now (we may have already had // one or we may have just succeeded in looking it up)? // if (code == ReturnCode.Ok) { // // NOTE: Create and push a new call frame to track the // activation of this alias. // string name = StringList.MakeList("alias", this.Name); AliasFlags aliasFlags = this.AliasFlags; ICallFrame frame = interpreter.NewTrackingCallFrame(name, CallFrameFlags.Alias); interpreter.PushAutomaticCallFrame(frame); /////////////////////////////////////////////////////////// bool targetUsable; if (useUnknown) { targetInterpreter.EnterUnknownLevel(); } try { if (FlagOps.HasFlags( aliasFlags, AliasFlags.Evaluate, true)) { code = targetInterpreter.EvaluateScript( targetArguments, 0, ref result); } else { // // NOTE: Save the current engine flags and then // enable the external execution flags. // EngineFlags savedEngineFlags = targetInterpreter.BeginExternalExecution(); code = targetInterpreter.Execute( targetName, target, clientData, targetArguments, ref result); // // NOTE: Restore the saved engine flags, masking // off the external execution flags as // necessary. // /* IGNORED */ targetInterpreter.EndAndCleanupExternalExecution( savedEngineFlags); } } finally { targetUsable = Engine.IsUsable(targetInterpreter); if (useUnknown && targetUsable) { targetInterpreter.ExitUnknownLevel(); } } /////////////////////////////////////////////////////////// // // 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(); } } return(code); }
/////////////////////////////////////////////////////////////////////// #region INotify Members public override ReturnCode Notify( Interpreter interpreter, IScriptEventArgs eventArgs, IClientData clientData, ArgumentList arguments, ref Result result ) { // // NOTE: If we are disabled -OR- there are no event arguments -OR- // this event does not match the kind we are interested in // then just return "success" now. // if (disabled || (eventArgs == null) || !FlagOps.HasFlags( eventArgs.NotifyTypes, NotifyType.Engine, false) || !FlagOps.HasFlags( eventArgs.NotifyFlags, NotifyFlags.Executed, false)) { return(ReturnCode.Ok); } // // NOTE: In "direct" mode, skip [almost] all the tracing ceremony // and just call into Trace.WriteLine(). Otherwise, use the // TraceOps class and all its special handling. Either way, // figure out the String.Format() arguments ahead of time, // based on our current "normalize" and "ellipsis" settings. // try { string arg0 = FormatOps.WrapTraceOrNull( normalizeArguments, ellipsisArguments, quoteArguments, displayArguments, eventArgs.Arguments); string arg1 = FormatOps.WrapTraceOrNull( normalizeResult, ellipsisResult, quoteResult, displayResult, eventArgs.Result); if (direct) { // // NOTE: This is just an extremely thin wrapper around // the Trace.WriteLine method. // DebugOps.TraceWriteLine(String.Format( directFormat, arg0, arg1), directCategory); } else { // // NOTE: Use the tracing subsystem. // TraceOps.DebugTrace(String.Format( normalFormat, arg0, arg1), normalCategory, TracePriority.EngineDebug); } return(ReturnCode.Ok); } catch (Exception e) { TraceOps.DebugTrace( e, typeof(Trace).Name, TracePriority.EngineError); result = e; return(ReturnCode.Error); } }
private Version loading; // which version are we actively loading? /////////////////////////////////////////////////////////////////////// public override ReturnCode Load( Interpreter interpreter, Version version, ref Result result ) { if (interpreter != null) { if (version != null) { string name = this.Name; VersionStringDictionary ifNeeded = this.IfNeeded; if (ifNeeded != null) { string text; if (ifNeeded.TryGetValue(version, out text)) { if (!FlagOps.HasFlags(Flags, PackageFlags.Loading, true)) { Flags |= PackageFlags.Loading; loading = version; try { return(interpreter.EvaluateGlobalScript( text, ref result)); } catch (Exception e) { result = String.Format( "caught exception while evaluating ifneeded script: {0}", e); } finally { loading = null; Flags &= ~PackageFlags.Loading; } } else { result = String.Format( "circular package dependency: " + "attempt to provide \"{0}\" requires \"{1}\"", FormatOps.PackageName(name, version), FormatOps.PackageName(name, loading)); } } else { result = String.Format( "can't find package \"{0}\"", FormatOps.PackageName(name, version)); } } else { result = String.Format( "package \"{0}\" ifneeded scripts not available", name); } } else { result = "invalid package version"; } } else { result = "invalid interpreter"; } return(ReturnCode.Error); }
/////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { if (interpreter == null) { result = "invalid interpreter"; return(ReturnCode.Error); } if (arguments == null) { result = "invalid argument list"; return(ReturnCode.Error); } if (arguments.Count < 2) { result = "wrong # args: should be \"global varName ?varName ...?\""; return(ReturnCode.Error); } ICallFrame localFrame = null; if (interpreter.GetVariableFrameViaResolvers( LookupFlags.Default, ref localFrame, ref result) == ReturnCode.Ok) { if ((localFrame != null) && !interpreter.IsGlobalCallFrame(localFrame)) { bool useNamespaces = interpreter.AreNamespacesEnabled(); for (int argumentIndex = 1; argumentIndex < arguments.Count; argumentIndex++) { string varName = arguments[argumentIndex]; ICallFrame otherFrame = interpreter.CurrentGlobalFrame; if (useNamespaces) { string qualifiers = null; string tail = null; NamespaceFlags namespaceFlags = NamespaceFlags.None; if (NamespaceOps.SplitName( varName, ref qualifiers, ref tail, ref namespaceFlags, ref result) == ReturnCode.Ok) { // // NOTE: For linking between call frames, use // the simple variable name only. // varName = tail; } else { return(ReturnCode.Error); } if (FlagOps.HasFlags(namespaceFlags, NamespaceFlags.Qualified, true)) { INamespace @namespace = NamespaceOps.Lookup( interpreter, qualifiers, false, false, ref result); if (@namespace != null) { otherFrame = @namespace.VariableFrame; } else { return(ReturnCode.Error); } } } if (ScriptOps.LinkVariable( interpreter, localFrame, varName, otherFrame, varName, ref result) != ReturnCode.Ok) { return(ReturnCode.Error); } } result = String.Empty; } else { // already in global scope... this is a NOP. result = String.Empty; } return(ReturnCode.Ok); } else { return(ReturnCode.Error); } }
/////////////////////////////////////////////////////////////////////// /// <summary> /// Initialize the plugin and add any contained commands. /// /// WARNING: PLEASE DO NOT CHANGE THIS METHOD BECAUSE DERIVED PLUGINS /// DEPEND ON ITS EXACT SEMANTICS. /// </summary> /// /// <param name="interpreter"> /// The interpreter context we are executing in. /// </param> /// /// <param name="clientData"> /// The extra data supplied when this plugin was initially created, /// if any. /// </param> /// /// <param name="result"> /// Upon success, this may contain an informational message. /// Upon failure, this must contain an appropriate error message. /// </param> /// /// <returns> /// ReturnCode.Ok on success, ReturnCode.Error on failure. /// </returns> public virtual ReturnCode Initialize( Interpreter interpreter, IClientData clientData, ref Result result ) { ReturnCode code; if (FlagOps.HasFlags( this.Flags, PluginFlags.NoInitialize, true)) { if (!FlagOps.HasFlags( this.Flags, PluginFlags.NoInitializeFlag, true)) { initialized = true; } if (!FlagOps.HasFlags( this.Flags, PluginFlags.NoResult, true)) { result = String.Empty; } code = ReturnCode.Ok; } else { // // NOTE: We require a valid interpreter context. // if (interpreter != null) { code = ReturnCode.Ok; if ((code == ReturnCode.Ok) && !FlagOps.HasFlags( this.Flags, PluginFlags.NoCommands, true)) { // // NOTE: Call the interpreter helper method that // takes care of loading all valid commands // (i.e. classes that implement ICommand, // directly or indirectly) in this plugin. // code = interpreter.AddCommands( this, clientData, CommandFlags.None, ref result); if (code == ReturnCode.Ok) { code = interpreter.MoveExposedAndHiddenCommands( this.Flags, ref result); } } if ((code == ReturnCode.Ok) && !FlagOps.HasFlags( this.Flags, PluginFlags.NoPolicies, true)) { // // NOTE: Call the interpreter helper method that // takes care of loading all valid policies // (i.e. methods that are flagged as a "policy" // and are of the appropriate delegate type(s)) // in this plugin. // code = interpreter.AddPolicies( this, clientData, ref result); } Version version = null; if ((code == ReturnCode.Ok) && !FlagOps.HasFlags( this.Flags, PluginFlags.NoProvide, true)) { // // NOTE: Grab the plugin version now, if // necessary, since we know that we // need it. // if (version == null) { version = this.Version; } // // NOTE: Formally "provide" (i.e. announce) this // package to the interpreter so that scripts // can easily detect it. // code = interpreter.PkgProvide( this.GetType().FullName, version, GetPackageFlags(), ref result); } // // NOTE: If the above steps succeeded, mark the // plugin as initialized and return an // appropriate result. // if (code == ReturnCode.Ok) { if (!FlagOps.HasFlags( this.Flags, PluginFlags.NoInitializeFlag, true)) { initialized = true; } // // NOTE: Returning the loaded plugin name // and version is HIGHLY RECOMMENDED // here. // if (!FlagOps.HasFlags( this.Flags, PluginFlags.NoResult, true)) { // // NOTE: Grab the plugin version now, if // necessary, since we know that // we need it. // if (version == null) { version = this.Version; } result = StringList.MakeList( this.Name, version); } } } else { result = "invalid interpreter"; code = ReturnCode.Error; } } return(code); }
/////////////////////////////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { ReturnCode code; if (interpreter != null) { if (arguments != null) { if (arguments.Count >= 2) { // // NOTE: Grab the variable and event wait flags from the // interpreter and use them as the defaults for the // associated options. // EventWaitFlags eventWaitFlags = interpreter.EventWaitFlags; VariableFlags variableFlags = interpreter.EventVariableFlags; OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.MustHaveObjectValue | OptionFlags.Unsafe, Index.Invalid, Index.Invalid, "-handle", null), new Option(typeof(EventWaitFlags), OptionFlags.MustHaveEnumValue | OptionFlags.Unsafe, Index.Invalid, Index.Invalid, "-eventwaitflags", new Variant(eventWaitFlags)), new Option(typeof(VariableFlags), OptionFlags.MustHaveEnumValue | OptionFlags.Unsafe, Index.Invalid, Index.Invalid, "-variableflags", new Variant(variableFlags)), new Option(null, OptionFlags.MustHaveIntegerValue | OptionFlags.Unsafe, Index.Invalid, Index.Invalid, "-limit", null), new Option(null, OptionFlags.Unsafe, Index.Invalid, Index.Invalid, "-force", null), new Option(null, OptionFlags.Unsafe, Index.Invalid, Index.Invalid, "-nocomplain", null), new Option(null, OptionFlags.Unsafe, Index.Invalid, Index.Invalid, "-leaveresult", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null) }); int argumentIndex = Index.Invalid; code = interpreter.GetOptions( options, arguments, 0, 1, Index.Invalid, false, ref argumentIndex, ref result); if (code == ReturnCode.Ok) { if ((argumentIndex != Index.Invalid) && ((argumentIndex + 1) == arguments.Count)) { Variant value = null; EventWaitHandle @event = null; if (options.IsPresent("-handle", ref value)) { IObject @object = (IObject)value.Value; if ((@object.Value == null) || (@object.Value is EventWaitHandle)) { @event = (EventWaitHandle)@object.Value; } else { result = "option value has invalid EventWaitHandle"; code = ReturnCode.Error; } } if (code == ReturnCode.Ok) { int limit = 0; if (options.IsPresent("-limit", ref value)) { limit = (int)value.Value; } if (options.IsPresent("-eventwaitflags", ref value)) { eventWaitFlags = (EventWaitFlags)value.Value; } if (options.IsPresent("-variableflags", ref value)) { variableFlags = (VariableFlags)value.Value; } bool force = false; if (options.IsPresent("-force")) { force = true; } bool noComplain = false; if (options.IsPresent("-nocomplain")) { noComplain = true; } bool leaveResult = false; if (options.IsPresent("-leaveresult")) { leaveResult = true; } // // NOTE: Typically, we do not want to enter a wait state if // there are no events queued because there would be // no possible way to ever (gracefully) exit the wait; // however, there are exceptions to this. // if (force || interpreter.ShouldWaitVariable()) { // // HACK: The call to ThreadOps.IsStaThread here is made // under the assumption that no user-interface // thread can exist without also being an STA // thread. This may eventually prove to be false; // however, currently WinForms, WPF, et al require // this (i.e. an STA thread). // if (!FlagOps.HasFlags( eventWaitFlags, EventWaitFlags.UserInterface, true) && ThreadOps.IsStaThread()) { eventWaitFlags |= EventWaitFlags.UserInterface; } code = interpreter.WaitVariable(eventWaitFlags, variableFlags, arguments[argumentIndex], limit, @event, ref result); if ((code != ReturnCode.Ok) && noComplain) { code = ReturnCode.Ok; } if ((code == ReturnCode.Ok) && !leaveResult) { Engine.ResetResult(interpreter, ref result); } } else { result = String.Format( "can't wait for variable \"{0}\": would wait forever", arguments[1]); code = ReturnCode.Error; } } } else { if ((argumentIndex != Index.Invalid) && Option.LooksLikeOption(arguments[argumentIndex])) { result = OptionDictionary.BadOption( options, arguments[argumentIndex]); } else { result = "wrong # args: should be \"vwait ?options? varName\""; } code = ReturnCode.Error; } } } else { result = "wrong # args: should be \"vwait ?options? varName\""; code = ReturnCode.Error; } } else { result = "invalid argument list"; code = ReturnCode.Error; } } else { result = "invalid interpreter"; code = ReturnCode.Error; } return(code); }
/////////////////////////////////////////////////////////////////////// public static IOption FromString( Interpreter interpreter, string text, AppDomain appDomain, ValueFlags valueFlags, CultureInfo cultureInfo, ref Result error ) { StringList list = null; if (Parser.SplitList( interpreter, text, 0, Length.Invalid, true, ref list, ref error) != ReturnCode.Ok) { return(null); } if (list.Count < MinimumElementCount) { error = String.Format( "cannot create option, only {0} of {1} " + "required elements were specified", list.Count, MinimumElementCount); return(null); } bool allowInteger; bool strict; bool verbose; bool noCase; _Public.Value.ExtractTypeValueFlags( valueFlags, out allowInteger, out strict, out verbose, out noCase); object enumValue = EnumOps.TryParseFlagsEnum( interpreter, typeof(OptionFlags), null, list[0], cultureInfo, allowInteger, strict, noCase, ref error); if (!(enumValue is OptionFlags)) { return(null); } OptionFlags optionFlags = (OptionFlags)enumValue; string name = list[1]; if (name == null) { error = "invalid option name"; return(null); } int nextIndex = MinimumElementCount; Type type = null; if (FlagOps.HasFlags( optionFlags, OptionFlags.MustBeEnumMask, false)) { if (nextIndex >= list.Count) { error = String.Format( "option with {0} or {1} flags must have type name", FormatOps.WrapOrNull(OptionFlags.MustBeEnum), FormatOps.WrapOrNull(OptionFlags.MustBeEnumList)); return(null); } ResultList errors = null; if (_Public.Value.GetType( interpreter, list[nextIndex], null, appDomain, _Public.Value.GetTypeValueFlags(optionFlags), cultureInfo, ref type, ref errors) != ReturnCode.Ok) { error = errors; return(null); } nextIndex++; } Variant value = null; if (ScriptOps.GetOptionValue( interpreter, list, type, optionFlags, false, allowInteger, strict, noCase, cultureInfo, ref value, ref nextIndex, ref error) != ReturnCode.Ok) { return(null); } int groupIndex = _Constants.Index.Invalid; if (nextIndex < list.Count) { if (_Public.Value.GetInteger2( list[nextIndex], ValueFlags.AnyInteger, cultureInfo, ref groupIndex, ref error) != ReturnCode.Ok) { return(null); } nextIndex++; } return(new Option( type, optionFlags, groupIndex, _Constants.Index.Invalid, name, value)); }
/// <summary> /// This is the constructor used by the core library to create an /// instance of the plugin, passing the necessary data to be used /// for initializing the plugin. /// </summary> /// /// <param name="pluginData"> /// An instance of the plugin data component used to hold the data /// necessary to fully initialize the plugin instance. This /// parameter may be null. Derived plugins are free to override /// this constructor; however, they are very strongly encouraged to /// call this constructor (i.e. the base class constructor) in that /// case. /// </param> public Default( IPluginData pluginData ) { kind = IdentifierKind.Plugin; // // VIRTUAL: Id of the deepest derived class. // id = AttributeOps.GetObjectId(this); // // VIRTUAL: Group of the deepest derived class. // group = AttributeOps.GetObjectGroup(this); // // NOTE: Is the supplied plugin data valid? // if (pluginData != null) { EntityOps.MaybeSetGroup( this, pluginData.Group); name = pluginData.Name; description = pluginData.Description; flags = pluginData.Flags; clientData = pluginData.ClientData; version = pluginData.Version; uri = pluginData.Uri; appDomain = pluginData.AppDomain; assembly = pluginData.Assembly; assemblyName = pluginData.AssemblyName; fileName = pluginData.FileName; typeName = pluginData.TypeName; } // // NOTE: Are we going to use their command list or create an // entirely new list? // if ((pluginData != null) && (pluginData.Commands != null)) { commands = pluginData.Commands; } else { commands = new CommandDataList(); } // // NOTE: Are we going to use their policy list or create an // entirely new list? // if ((pluginData != null) && (pluginData.Policies != null)) { policies = pluginData.Policies; } else { policies = new PolicyDataList(); } // // NOTE: Are we going to use their command tokens or create an // entirely new list? // if ((pluginData != null) && (pluginData.CommandTokens != null)) { commandTokens = pluginData.CommandTokens; } else { commandTokens = new LongList(); } // // NOTE: Are we going to use their command tokens or create an // entirely new list? // if ((pluginData != null) && (pluginData.FunctionTokens != null)) { functionTokens = pluginData.FunctionTokens; } else { functionTokens = new LongList(); } // // NOTE: Are we going to use their policy tokens or create an // entirely new list? // if ((pluginData != null) && (pluginData.PolicyTokens != null)) { policyTokens = pluginData.PolicyTokens; } else { policyTokens = new LongList(); } // // NOTE: Are we going to use their trace tokens or create an // entirely new list? // if ((pluginData != null) && (pluginData.TraceTokens != null)) { traceTokens = pluginData.TraceTokens; } else { traceTokens = new LongList(); } // // NOTE: Are we going to use the resource manager they specified or // create a new one based on the plugin name and assembly? // if ((pluginData != null) && (pluginData.ResourceManager != null)) { resourceManager = pluginData.ResourceManager; } else { // // NOTE: If the assembly is null we are probably loaded into an // isolated application domain. Therefore, in that case, // and only in that case, since we are executing in the // target application domain, load the assembly based on // the assembly name and then use that to create the // resource manager. However, do not simply set the // assembly field of this plugin to any non-null value // because we do not want to cause issues with the // interpreter plugin manager later. Also, skip attempts // to create a resource manager if the NoResources flag // has been set on the plugin. // if (!FlagOps.HasFlags(flags, PluginFlags.NoResources, true)) { if (assembly != null) { resourceManager = RuntimeOps.NewResourceManager( assembly); } else if (assemblyName != null) { resourceManager = RuntimeOps.NewResourceManager( assemblyName); } } } // // NOTE: Are we going to use the auxiliary data they specified or // create a new one? // if ((pluginData != null) && (pluginData.AuxiliaryData != null)) { auxiliaryData = pluginData.AuxiliaryData; } else { if (!FlagOps.HasFlags( flags, PluginFlags.NoAuxiliaryData, true)) { auxiliaryData = new ObjectDictionary(); } } // // NOTE: Also store the plugin token (which may be zero at this // point). // if (pluginData != null) { token = pluginData.Token; } }
/////////////////////////////////////////////////////////////////////// public ReturnCode ToList( OperatorFlags hasFlags, OperatorFlags notHasFlags, bool hasAll, bool notHasAll, string pattern, bool noCase, ref StringList list, ref Result error ) { StringList inputList; // // NOTE: If no flags were supplied, we do not bother filtering on // them. // if ((hasFlags == OperatorFlags.None) && (notHasFlags == OperatorFlags.None)) { inputList = new StringList(); foreach (KeyValuePair <string, _Wrappers.Operator> pair in this) { _Wrappers.Operator @operator = pair.Value; if (@operator != null) { inputList.Add(StringList.MakeList( @operator.Lexeme.ToString(), @operator.Operands.ToString(), @operator.Flags.ToString(), pair.Key)); } } } else { inputList = new StringList(); foreach (KeyValuePair <string, _Wrappers.Operator> pair in this) { _Wrappers.Operator @operator = pair.Value; if (@operator != null) { if (((hasFlags == OperatorFlags.None) || FlagOps.HasFlags(@operator.Flags, hasFlags, hasAll)) && ((notHasFlags == OperatorFlags.None) || !FlagOps.HasFlags(@operator.Flags, notHasFlags, notHasAll))) { inputList.Add(StringList.MakeList( @operator.Lexeme.ToString(), @operator.Operands.ToString(), @operator.Flags.ToString(), pair.Key)); } } } } if (list == null) { list = new StringList(); } return(GenericOps <string> .FilterList( inputList, list, Index.Invalid, Index.Invalid, ToStringFlags.None, pattern, noCase, ref error)); }
/////////////////////////////////////////////////////////////////////// /// <summary> /// Terminate the plugin and remove any contained commands. /// /// WARNING: PLEASE DO NOT CHANGE THIS METHOD BECAUSE DERIVED PLUGINS /// DEPEND ON ITS EXACT SEMANTICS. /// </summary> /// /// <param name="interpreter"> /// The interpreter context we are executing in. /// </param> /// /// <param name="clientData"> /// The extra data supplied when this plugin was initially created, /// if any. /// </param> /// /// <param name="result"> /// Upon success, this may contain an informational message. /// Upon failure, this must contain an appropriate error message. /// </param> /// /// <returns> /// ReturnCode.Ok on success, ReturnCode.Error on failure. /// </returns> public virtual ReturnCode Terminate( Interpreter interpreter, IClientData clientData, ref Result result ) { ReturnCode code; if (FlagOps.HasFlags( this.Flags, PluginFlags.NoTerminate, true)) { if (!FlagOps.HasFlags( this.Flags, PluginFlags.NoInitializeFlag, true)) { initialized = false; } if (!FlagOps.HasFlags( this.Flags, PluginFlags.NoResult, true)) { result = null; } code = ReturnCode.Ok; } else { // // NOTE: We require a valid interpreter context. // if (interpreter != null) { code = ReturnCode.Ok; if ((code == ReturnCode.Ok) && !FlagOps.HasFlags( this.Flags, PluginFlags.NoTraces, true)) { // // NOTE: Call the interpreter helper method that // takes care of unloading all previously // loaded traces (i.e. methods that are // flagged as a "trace" and are of the // appropriate delegate type(s)) from this // plugin. // code = interpreter.RemoveTraces( this, clientData, ref result); } if ((code == ReturnCode.Ok) && !FlagOps.HasFlags( this.Flags, PluginFlags.NoPolicies, true)) { // // NOTE: Call the interpreter helper method that // takes care of unloading all previously // loaded policies (i.e. methods that are // flagged as a "policy" and are of the // appropriate delegate type(s)) from this // plugin. // code = interpreter.RemovePolicies( this, clientData, ref result); } if ((code == ReturnCode.Ok) && !FlagOps.HasFlags( this.Flags, PluginFlags.NoFunctions, true)) { // // NOTE: Call the interpreter helper method that // takes care of unloading all previously // loaded functions (i.e. classes that // implement IFunction, directly or // indirectly) from this plugin. // code = interpreter.RemoveFunctions( this, clientData, FunctionFlags.None, ref result); } if ((code == ReturnCode.Ok) && !FlagOps.HasFlags( this.Flags, PluginFlags.NoCommands, true)) { // // NOTE: Call the interpreter helper method that // takes care of unloading all previously // loaded commands (i.e. classes that // implement ICommand, directly or // indirectly) from this plugin. // code = interpreter.RemoveCommands( this, clientData, CommandFlags.None, ref result); } Version version = null; if ((code == ReturnCode.Ok) && !FlagOps.HasFlags( this.Flags, PluginFlags.NoProvide, true)) { // // NOTE: Grab the plugin version now, if // necessary, since we know that we // need it. // if (version == null) { version = this.Version; } // // NOTE: Formally "withdraw" (i.e. unannounce) // this package from the interpreter so // that scripts can no longer detect it. // code = interpreter.WithdrawPackage( this.GetType().FullName, version, ref result); } // // NOTE: If the above steps succeeded, mark the // plugin as not initialized and return an // appropriate result. // if (code == ReturnCode.Ok) { if (!FlagOps.HasFlags( this.Flags, PluginFlags.NoInitializeFlag, true)) { initialized = false; } // // NOTE: Returning the unloaded plugin name // and version is HIGHLY RECOMMENDED // here. // if (!FlagOps.HasFlags( this.Flags, PluginFlags.NoResult, true)) { // // NOTE: Grab the plugin version now, if // necessary, since we know that // we need it. // if (version == null) { version = this.Version; } result = StringList.MakeList( this.Name, version); } } } else { result = "invalid interpreter"; code = ReturnCode.Error; } } return(code); }
/////////////////////////////////////////////////////////////////////// #region Private Methods private void Initialize() { noHandle = FlagOps.HasFlags( marshalFlags, MarshalFlags.NoHandle, true); }
/////////////////////////////////////////////////////////////////////// public string ToString( OptionFlags flags ) { string result; if (FlagOps.HasFlags(flags, OptionFlags.MustHaveValue, true)) { if (FlagOps.HasFlags( flags, OptionFlags.MustBeExecute, true)) { result = "execute"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBePlugin, true)) { result = "plugin"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeEncoding, true)) { result = "encoding"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeSecureString, true)) { result = "secure string"; } #if NATIVE && TCL else if (FlagOps.HasFlags( flags, OptionFlags.MustBeTclInterpreter, true)) { result = "tcl interpreter"; } #endif else if (FlagOps.HasFlags( flags, OptionFlags.MustBeRelativeNamespace, true)) { result = "relative namespace"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeAbsoluteNamespace, true)) { result = "absolute namespace"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeOption, true)) { result = "option"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeAlias, true)) { result = "alias"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeReturnCodeList, true)) { result = "return code list"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeAbsoluteUri, true)) { result = "absolute uri"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeVersion, true)) { result = "version"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeTypeList, true)) { result = "type list"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeType, true)) { result = "type"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeInterpreter, true)) { result = "interpreter"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeObject, true)) { result = "object"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeValue, true)) { result = "numeric"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeMatchMode, true)) { result = "match mode"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeDictionary, true)) { result = "dictionary"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeList, true)) { result = "list"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeTimeSpan, true)) { result = "time-span"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeDateTime, true)) { result = "date-time"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeGuid, true)) { result = "guid"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeEnum, true)) { result = (type != null) ? String.Format("{0} enumeration", FormatOps.TypeNameOrFullName(type)) : "enumeration"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeEnumList, true)) { result = (type != null) ? String.Format("{0} enumeration list", FormatOps.TypeNameOrFullName(type)) : "enumeration list"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeReturnCode, true)) { result = "return code"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeLevel, true)) { result = "level"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeIndex, true)) { result = "index"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeUnsignedWideInteger, true)) { result = "unsigned wide integer"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeWideInteger, true)) { result = "wide integer"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeUnsignedInteger, true)) { result = "unsigned integer"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeInteger, true)) { result = "integer"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeUnsignedNarrowInteger, true)) { result = "unsigned narrow integer"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeNarrowInteger, true)) { result = "narrow integer"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeByte, true)) { result = "byte"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeSignedByte, true)) { result = "signed byte"; } else if (FlagOps.HasFlags( flags, OptionFlags.MustBeBoolean, true)) { result = "boolean"; } else { result = "string"; } } else if (FlagOps.HasFlags(flags, OptionFlags.EndOfOptions, true)) { result = "end of options"; } else if (FlagOps.HasFlags(flags, OptionFlags.ListOfOptions, true)) { result = "list of options"; } else { result = "nothing"; } return(result); }