/////////////////////////////////////////////////////////////////////// public string ToString( string pattern, bool noCase, bool qualified ) { if (qualified) { StringList list = new StringList(); foreach (Type type in this) { if (type != null) { list.Add(FormatOps.QualifiedName(type)); } } return(GenericOps <string> .ListToString( list, Index.Invalid, Index.Invalid, ToStringFlags.None, Characters.Space.ToString(), pattern, noCase)); } else { return(GenericOps <Type> .ListToString( this, Index.Invalid, Index.Invalid, ToStringFlags.None, Characters.Space.ToString(), pattern, noCase)); } }
/////////////////////////////////////////////////////////////////////// #region Public Static Methods public static object StaticFireDynamicInvokeCallback( object firstArgument, object[] args ) { ICallback callback; lock (syncRoot) { if ((firstArgument == null) || (callbacks == null) || !callbacks.TryGetValue(firstArgument, out callback)) { throw new ScriptException(String.Format( "{0} for object {1} with hash code {2} not found", typeof(ICallback), FormatOps.WrapOrNull( firstArgument), RuntimeHelpers.GetHashCode( firstArgument))); } } // // NOTE: The "callback" variable could be null at this point. // return CommandCallback.StaticFireDynamicInvokeCallback( callback, args); }
/////////////////////////////////////////////////////////////////////// public StringPairList ToList() { StringPairList list = new StringPairList(); list.Add("findFlags", findFlags.ToString()); list.Add("loadFlags", loadFlags.ToString()); list.Add("findData", StringOps.GetStringsFromObject(findData)); list.Add("fileName", fileName); list.Add("priority", priority.ToString()); list.Add("sequence", sequence.ToString()); list.Add("operatingSystem", operatingSystemId.ToString()); list.Add("version", (version != null) ? version.ToString() : null); list.Add("patchLevel", (patchLevel != null) ? patchLevel.ToString() : null); list.Add("releaseLevel", releaseLevel.ToString()); list.Add("magic", FormatOps.Hexadecimal(magic, true)); list.Add("threaded", threaded.ToString()); list.Add("debug", debug.ToString()); list.Add("defaultThreaded", DefaultThreaded.ToString()); list.Add("matchDebug", MatchDebug.ToString()); return(list); }
/////////////////////////////////////////////////////////////////////// public override string GetString( Interpreter interpreter, string name, CultureInfo cultureInfo, ref Result error ) { if (!enableGetString) { return(base.GetString( interpreter, name, cultureInfo, ref error)); } if (name != null) { return(String.Format( "interpreter: {0}, name: {1}, cultureInfo: {2}", FormatOps.InterpreterNoThrow(interpreter), FormatOps.WrapOrNull(name), FormatOps.WrapOrNull(cultureInfo))); } else { error = "invalid string name"; return(null); } }
/////////////////////////////////////////////////////////////////////// #region ToString Methods public ReturnCode ToList( string pattern, bool noCase, bool fullName, bool qualified, ref StringList list, ref Result error ) { StringList inputList = new StringList(); foreach (Type type in this) { if (type != null) { inputList.Add(FormatOps.QualifiedAndOrFullName( type, fullName, qualified, false)); } } if (list == null) { list = new StringList(); } return(GenericOps <string> .FilterList( inputList, list, Index.Invalid, Index.Invalid, ToStringFlags.None, pattern, noCase, ref error)); }
/////////////////////////////////////////////////////////////////////// #region IPackage Members public override ReturnCode Select( PackagePreference preference, ref Version version, ref Result error ) { if (preference == PackagePreference.Default) { string name = this.Name; VersionStringDictionary ifNeeded = this.IfNeeded; if (ifNeeded != null) { // // NOTE: *HACK* For now, always select the latest version // from the list of candidate versions. // Version latest = null; foreach (Version candidate in ifNeeded.Keys) { if (PackageOps.VersionCompare(candidate, latest) > 0) { latest = candidate; } } // // NOTE: Were we able to find the latest (i.e. any) // version? // if (latest != null) { version = latest; return(ReturnCode.Ok); } else { error = String.Format( "can't find package \"{0}\"", FormatOps.PackageName(name, null)); } } else { error = String.Format( "package \"{0}\" ifneeded scripts not available", name); } } else { error = String.Format( "unsupported package preference \"{0}\"", preference); } return(ReturnCode.Error); }
/////////////////////////////////////////////////////////////////////// #region IPlugin Members public override ReturnCode About( Interpreter interpreter, ref Result result ) { result = FormatOps.PluginAbout(this, false); return(ReturnCode.Ok); }
/////////////////////////////////////////////////////////////////////// public virtual string ToString( string format, int limit, bool strict ) { return(FormatOps.Ellipsis( String.Format(format, this.X, this.Y), limit, strict)); }
/////////////////////////////////////////////////////////////////////////////////////////////// #region Public Methods #if CACHE_STATISTICS public bool HaveCacheCounts() { if (this.Count > 0) { return(true); } return(FormatOps.HaveCacheCounts(cacheCounts)); }
/////////////////////////////////////////////////////////////////////// private ICommand CreateCommand( IClientData clientData ) { return(new _Commands.Nop(new CommandData( FormatOps.PluginCommand(this.Assembly, this.Name, typeof(_Commands.Nop), null), null, null, clientData, typeof(_Commands.Nop).FullName, CommandFlags.None, this, 0))); }
/////////////////////////////////////////////////////////////////////////////////////////////// public string CacheToString() { return(StringList.MakeList( "count", this.Count, #if CACHE_DICTIONARY "maximumCount", this.MaximumCount, "maximumAccessCount", this.MaximumAccessCount, #endif FormatOps.CacheCounts(cacheCounts))); }
/////////////////////////////////////////////////////////////////////// public void AddRange( IEnumerable <ExecuteCallback> collection ) { foreach (ExecuteCallback item in collection) { if (item != null) { this.Add(FormatOps.DelegateName(item), item); } } }
/////////////////////////////////////////////////////////////////////// public static StringDictionary FromString( string value, bool addOnly, ref Result error ) { StringList list = StringList.FromString(value, ref error); if (list == null) { return(null); } int count = list.Count; if ((count % 2) != 0) { error = String.Format( "list of name/value pairs must have an even number of " + "elements, has {0}", count); return(null); } StringDictionary dictionary = new StringDictionary(); for (int index = 0; index < count; index += 2) { string key = list[index]; if (key == null) { error = String.Format( "key at index {0} cannot be null", index); return(null); } if (addOnly && dictionary.ContainsKey(key)) { error = String.Format( "key {0} at index {1} already exists", FormatOps.WrapOrNull(key), index); return(null); } dictionary[key] = list[index + 1]; } return(dictionary); }
/////////////////////////////////////////////////////////////////////// public static OptionDictionary FromString( Interpreter interpreter, string text, AppDomain appDomain, bool allowInteger, bool strict, bool verbose, bool noCase, CultureInfo cultureInfo, ref Result error ) { StringList list = null; if (Parser.SplitList( interpreter, text, 0, Length.Invalid, true, ref list, ref error) == ReturnCode.Ok) { OptionDictionary options = new OptionDictionary(); foreach (string element in list) { IOption option = Option.FromString( interpreter, element, appDomain, allowInteger, strict, verbose, noCase, cultureInfo, ref error); if (option == null) { return(null); } if (options.Has(option)) { error = String.Format( "duplicate option name {0}", FormatOps.WrapOrNull(option.Name)); return(null); } options.Add(option); } return(options); } return(null); }
/////////////////////////////////////////////////////////////////////// public static StringList GetRangeAsStringList( IList list, int firstIndex, int lastIndex, bool dequote ) { StringList range = null; if (list != null) { range = new StringList(); if (firstIndex == Index.Invalid) { firstIndex = 0; } if (lastIndex == Index.Invalid) { lastIndex = list.Count - 1; } for (int index = firstIndex; index <= lastIndex; index++) { object item = list[index]; if (item == null) { range.Add((string)null); continue; } string @string = item.ToString(); if (dequote) { @string = FormatOps.StripOuter( @string, Characters.QuotationMark); } range.Add(@string); } } return(range); }
/////////////////////////////////////////////////////////////////////// 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); }
/////////////////////////////////////////////////////////////////////// #region Private Constructors private Event( object syncRoot, /* in: OPTIONAL */ Delegate @delegate, /* in: OPTIONAL */ EventType type, /* in */ EventFlags flags, /* in */ EventPriority priority, /* in */ Interpreter interpreter, /* in: OPTIONAL */ string name, /* in: OPTIONAL */ DateTime dateTime, /* in */ EventCallback callback, /* in: OPTIONAL */ IClientData clientData /* in: OPTIONAL */ ) { this.syncRoot = syncRoot; this.@delegate = @delegate; this.type = type; this.flags = flags; this.priority = priority; this.interpreter = interpreter; this.name = name; this.dateTime = dateTime; this.callback = callback; this.clientData = clientData; // // NOTE: Setup inter-thread communication event. // doneEventName = FormatOps.EventName(interpreter, typeof(Event).Name, name, GlobalState.NextEventId( interpreter)); doneEvent = ThreadOps.CreateEvent(doneEventName); // // NOTE: Setup the initial result state. // ResetResultData(); // // NOTE: Keep track of how many event objects are created // within this AppDomain. // Interlocked.Increment(ref createCount); }
/////////////////////////////////////////////////////////////////////// private bool WaitOnEventHandle( int milliseconds, ref Result error ) { EventWaitHandle doneEvent = null; try { doneEvent = ThreadOps.OpenEvent(doneEventName); if (doneEvent != null) { if (ThreadOps.WaitEvent( doneEvent, milliseconds)) { return(true); } else { error = String.Format( "timed wait of {0} milliseconds for event {1} failed", milliseconds, FormatOps.WrapOrNull(doneEventName)); } } else { error = String.Format( "cannot open event {0} in order to wait", FormatOps.WrapOrNull(doneEventName)); } } finally { /* NO RESULT */ ThreadOps.CloseEvent(ref doneEvent); } return(false); }
/////////////////////////////////////////////////////////////////////// #region Internal Methods internal string ToTraceString() { IStringList list = new StringPairList(); list.Add("debug", debug.ToString()); list.Add("args", FormatOps.WrapArgumentsOrNull(true, true, args)); list.Add("code", code.ToString()); list.Add("breakpointType", breakpointType.ToString()); list.Add("breakpointName", FormatOps.WrapOrNull(breakpointName)); list.Add("token", (token != null).ToString()); list.Add("traceInfo", (traceInfo != null).ToString()); list.Add("engineFlags", FormatOps.WrapOrNull(engineFlags)); list.Add("substitutionFlags", FormatOps.WrapOrNull(substitutionFlags)); list.Add("eventFlags", FormatOps.WrapOrNull(eventFlags)); list.Add("expressionFlags", FormatOps.WrapOrNull(expressionFlags)); list.Add("headerFlags", FormatOps.WrapOrNull(headerFlags)); list.Add("clientData", FormatOps.WrapOrNull(clientData)); list.Add("arguments", FormatOps.WrapOrNull(true, true, arguments)); list.Add("exit", exit.ToString()); return(list.ToString()); }
/////////////////////////////////////////////////////////////////////// private bool SetEventHandle( ref Result error ) { EventWaitHandle doneEvent = null; try { doneEvent = ThreadOps.OpenEvent(doneEventName); if (doneEvent != null) { if (ThreadOps.SetEvent(doneEvent)) { return(true); } else { error = String.Format( "set for event {0} failed", FormatOps.WrapOrNull(doneEventName)); } } else { error = String.Format( "cannot open event {0} in order to set", FormatOps.WrapOrNull(doneEventName)); } } finally { /* NO RESULT */ ThreadOps.CloseEvent(ref doneEvent); } return(false); }
/////////////////////////////////////////////////////////////////////// internal string ToTraceString() { IStringList list = new StringPairList(); list.Add("ArgumentCallback", FormatOps.WrapOrNull( FormatOps.DelegateName(argumentCallback))); list.Add("EvaluateScriptCallback", FormatOps.WrapOrNull( FormatOps.DelegateName(evaluateScriptCallback))); list.Add("EvaluateFileCallback", FormatOps.WrapOrNull( FormatOps.DelegateName(evaluateFileCallback))); list.Add("EvaluateEncodedFileCallback", FormatOps.WrapOrNull( FormatOps.DelegateName(evaluateEncodedFileCallback))); list.Add("InteractiveLoopCallback", FormatOps.WrapOrNull( FormatOps.DelegateName(interactiveLoopCallback))); list.Add("Initialized", initialized.ToString()); list.Add("HadArgumentCallback", hadArgumentCallback.ToString()); list.Add("HadEvaluateScriptCallback", hadEvaluateScriptCallback.ToString()); list.Add("HadEvaluateFileCallback", hadEvaluateFileCallback.ToString()); list.Add("HadEvaluateEncodedFileCallback", hadEvaluateEncodedFileCallback.ToString()); list.Add("HadInteractiveLoopCallback", hadInteractiveLoopCallback.ToString()); return(list.ToString()); }
/////////////////////////////////////////////////////////////////////////////////////////////// #region IExecuteArgument Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Argument value, ref Result error ) { ReturnCode code = ReturnCode.Ok; if (interpreter != null) { if (arguments != null) { try { string name = null; Variant operand1 = null; Variant operand2 = null; code = Value.GetOperandsFromArguments(interpreter, this, arguments, ValueFlags.AnyVariant, interpreter.CultureInfo, ref name, ref operand1, ref operand2, ref error); if (code == ReturnCode.Ok) { code = Value.FixupVariants( this, operand1, operand2, null, null, false, false, ref error); if (code == ReturnCode.Ok) { if (operand1.IsDouble()) { value = ((double)operand1.Value >= (double)operand2.Value); } else if (operand1.IsDecimal()) { value = ((decimal)operand1.Value >= (decimal)operand2.Value); } else if (operand1.IsWideInteger()) { value = ((long)operand1.Value >= (long)operand2.Value); } else if (operand1.IsInteger()) { value = ((int)operand1.Value >= (int)operand2.Value); } else if (operand1.IsBoolean()) { value = (ConversionOps.ToInt((bool)operand1.Value) >= ConversionOps.ToInt((bool)operand2.Value)); } else { error = String.Format( "unsupported operand type for operator {0}", FormatOps.OperatorName(name, this.Lexeme)); code = ReturnCode.Error; } } else { // // NOTE: Fine, try to treat the operands as strings. // code = Value.FixupStringVariants( this, operand1, operand2, ref error); if (code == ReturnCode.Ok) { if (operand1.IsString()) { value = (String.Compare( (string)operand1.Value, (string)operand2.Value, StringOps.UserStringComparisonType) >= 0); } else { error = String.Format( "unsupported operand type for operator {0}", FormatOps.OperatorName(name, this.Lexeme)); code = ReturnCode.Error; } } } } } catch (Exception e) { Engine.SetExceptionErrorCode(interpreter, e); error = String.Format( "caught math exception: {0}", e); code = ReturnCode.Error; } } else { error = "invalid argument list"; code = ReturnCode.Error; } } else { error = "invalid interpreter"; code = ReturnCode.Error; } return(code); }
/////////////////////////////////////////////////////////////////////// public ReturnCode VerifyModule( ref Result error ) { if (String.IsNullOrEmpty(fileName)) { error = "invalid Tcl native module file name"; return(ReturnCode.Error); } if (!NativeOps.IsValidHandle(module)) { error = "invalid Tcl native module handle"; return(ReturnCode.Error); } // // HACK: We cannot actually verify the native module handle on any // non-Windows operating system. // if (!PlatformOps.IsWindowsOperatingSystem()) { return(ReturnCode.Ok); } try { IntPtr newModule = NativeOps.GetModuleHandle(fileName); if (newModule == IntPtr.Zero) { error = String.Format( "bad Tcl native module handle {0}, file name {1} is " + "no longer loaded", module, FormatOps.WrapOrNull( fileName)); TraceOps.DebugTrace(String.Format( "VerifyModule: {0}", FormatOps.WrapOrNull(error)), typeof(TclModule).Name, TracePriority.NativeError); return(ReturnCode.Error); } if (newModule != module) { // // NOTE: This situation should really never happen. If it // does, that indicates that the native Tcl module // was unloaded and then reloaded out from under the // native Tcl integration subsystem. // error = String.Format( "bad Tcl native module handle {0}, got {1} for file " + "name {2}", module, newModule, FormatOps.WrapOrNull( fileName)); TraceOps.DebugTrace(String.Format( "VerifyModule: {0}", FormatOps.WrapOrNull(error)), typeof(TclModule).Name, TracePriority.NativeError); return(ReturnCode.Error); } return(ReturnCode.Ok); } catch (Exception e) { error = e; } return(ReturnCode.Error); }
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) { OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.NoCase | OptionFlags.MustHaveBooleanValue, Index.Invalid, Index.Invalid, "-statistics", null), new Option(null, OptionFlags.NoCase | OptionFlags.MustHaveBooleanValue, Index.Invalid, Index.Invalid, "-breakOk", null), new Option(null, OptionFlags.NoCase | OptionFlags.MustHaveBooleanValue, Index.Invalid, Index.Invalid, "-errorOk", null), new Option(null, OptionFlags.NoCase | OptionFlags.MustHaveBooleanValue, Index.Invalid, Index.Invalid, "-noCancel", null), new Option(null, OptionFlags.NoCase | OptionFlags.MustHaveBooleanValue, Index.Invalid, Index.Invalid, "-noHalt", null), new Option(null, OptionFlags.NoCase | OptionFlags.MustHaveBooleanValue, Index.Invalid, Index.Invalid, "-noEvent", null), new Option(null, OptionFlags.NoCase | OptionFlags.MustHaveBooleanValue, Index.Invalid, Index.Invalid, "-noExit", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null) }); int argumentIndex = Index.Invalid; if (arguments.Count > 3) { code = interpreter.GetOptions(options, arguments, 0, 3, Index.Invalid, true, ref argumentIndex, ref result); } else { code = ReturnCode.Ok; } if (code == ReturnCode.Ok) { if (argumentIndex == Index.Invalid) { long requestedIterations = 1; /* DEFAULT: One iteration. */ if (arguments.Count >= 3) { if (Value.GetWideInteger2( (IGetValue)arguments[2], ValueFlags.AnyWideInteger, interpreter.CultureInfo, ref requestedIterations, ref result) != ReturnCode.Ok) { return(ReturnCode.Error); } } Variant value = null; bool statistics = false; if (options.IsPresent("-statistics", ref value)) { statistics = (bool)value.Value; } bool breakOk = false; if (options.IsPresent("-breakOk", ref value)) { breakOk = (bool)value.Value; } bool errorOk = false; if (options.IsPresent("-errorOk", ref value)) { errorOk = (bool)value.Value; } bool noCancel = false; if (options.IsPresent("-noCancel", ref value)) { noCancel = (bool)value.Value; } bool noHalt = false; if (options.IsPresent("-noHalt", ref value)) { noHalt = (bool)value.Value; } bool noExit = false; if (options.IsPresent("-noExit", ref value)) { noExit = (bool)value.Value; } bool noEvent = false; if (options.IsPresent("-noEvent", ref value)) { noEvent = (bool)value.Value; } // // NOTE: These variables are used to keep track of // the minimum and maximum performance counts // for a given iteration (i.e. only when the // statistics option is enabled). // long?minimumIterationCount = null; long?maximumIterationCount = null; // // NOTE: Always start with the number of iterations // requested by the caller. Also, record the // overall starting performance count now. // long actualIterations = 0; long remainingIterations = requestedIterations; long startCount = PerformanceOps.GetCount(); // // NOTE: If the requested number of iterations is // exactly negative one, we will keep going // forever (i.e. until canceled). // try { while (true) { if (remainingIterations == 0) { break; } long iterationStartCount = statistics ? PerformanceOps.GetCount() : 0; code = interpreter.EvaluateScript(arguments[1], ref result); if (statistics) { long iterationStopCount = PerformanceOps.GetCount(); long iterationCount = iterationStopCount - iterationStartCount; if ((minimumIterationCount == null) || (iterationCount < minimumIterationCount)) { minimumIterationCount = iterationCount; } if ((maximumIterationCount == null) || (iterationCount > maximumIterationCount)) { maximumIterationCount = iterationCount; } } actualIterations++; if (code == ReturnCode.Continue) { continue; } if (code != ReturnCode.Ok) { break; } if (remainingIterations == Count.Invalid) { continue; } if (--remainingIterations <= 0) { break; } } } finally { if (noCancel) { /* IGNORED */ Engine.ResetCancel(interpreter, CancelFlags.Time); } if (noHalt) { /* IGNORED */ Engine.ResetHalt(interpreter, CancelFlags.Time); } if (noEvent) { /* IGNORED */ interpreter.ClearEvents(); } // // NOTE: If requested, prevent the interactive loop from // actually exiting and reset the exit code to be // "success". // if (noExit && interpreter.Exit) { interpreter.ExitCode = ResultOps.SuccessExitCode(); interpreter.Exit = false; } } // // NOTE: Make sure the return code indicates "success". // if ((code == ReturnCode.Ok) || (code == ReturnCode.Break) || (errorOk && (code == ReturnCode.Error))) { // // NOTE: Record the overall ending performance count // now. // long stopCount = PerformanceOps.GetCount(); // // NOTE: Calculate the average number of microseconds // per iteration based on the starting and ending // performance counts and the effective number of // iterations. // long resultIterations = PerformanceOps.GetIterations( requestedIterations, actualIterations, code, breakOk); double averageMicroseconds = (resultIterations != 0) ? PerformanceOps.GetMicroseconds(startCount, stopCount, resultIterations) : 0; if (statistics) { result = FormatOps.PerformanceWithStatistics( requestedIterations, actualIterations, resultIterations, code, (code == ReturnCode.Error) ? result : null, startCount, stopCount, averageMicroseconds, PerformanceOps.GetMicroseconds( (minimumIterationCount != null) ? (long)minimumIterationCount : 0, 1), PerformanceOps.GetMicroseconds( (maximumIterationCount != null) ? (long)maximumIterationCount : 0, 1)); } else { result = FormatOps.Performance(averageMicroseconds); } // // NOTE: If the "errorOk" option was used, make sure an // "Error" return code gets translated to "Ok". // if (errorOk && (code == ReturnCode.Error)) { Engine.ResetCancel(interpreter, CancelFlags.Time); code = ReturnCode.Ok; } } } else { result = "wrong # args: should be \"time script ?count? ?options?\""; code = ReturnCode.Error; } } } else { result = "wrong # args: should be \"time script ?count? ?options?\""; 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 IExecuteArgument Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Argument value, ref Result error ) { ReturnCode code = ReturnCode.Ok; if (interpreter != null) { if (arguments != null) { try { string name = null; Variant operand1 = null; Variant operand2 = null; code = Value.GetOperandsFromArguments(interpreter, this, arguments, ValueFlags.AnyVariant, interpreter.CultureInfo, ref name, ref operand1, ref operand2, ref error); if (code == ReturnCode.Ok) { code = Value.FixupVariants( this, operand1, operand2, null, null, false, false, ref error); if (code == ReturnCode.Ok) { if (operand1.IsWideInteger()) { value = ((long)operand1.Value ^ (long)operand2.Value); } else if (operand1.IsInteger()) { value = ((int)operand1.Value ^ (int)operand2.Value); } else if (operand1.IsBoolean()) { value = ((bool)operand1.Value ^ (bool)operand2.Value); } else { error = String.Format( "unsupported operand type for operator {0}", FormatOps.OperatorName(name, this.Lexeme)); code = ReturnCode.Error; } } } } catch (Exception e) { Engine.SetExceptionErrorCode(interpreter, e); error = String.Format( "caught math exception: {0}", e); code = ReturnCode.Error; } } else { error = "invalid argument list"; code = ReturnCode.Error; } } else { error = "invalid interpreter"; code = ReturnCode.Error; } return(code); }
public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Argument value, ref Result error ) { ReturnCode code = ReturnCode.Ok; if (interpreter != null) { if (arguments != null) { try { string name = null; Variant operand1 = null; Variant operand2 = null; code = Value.GetOperandsFromArguments(interpreter, this, arguments, ValueFlags.AnyVariant, interpreter.CultureInfo, ref name, ref operand1, ref operand2, ref error); if (code == ReturnCode.Ok) { // // NOTE: Fine, try to treat the operands as strings. // code = Value.FixupStringVariants( this, operand1, operand2, ref error); if (code == ReturnCode.Ok) { if (operand1.IsString()) { string str1 = (string)operand1.Value; string str2 = (string)operand2.Value; value = (str1.StartsWith(str2)); } else { error = String.Format( "unsupported operand type for operator {0}", FormatOps.OperatorName(name, this.Lexeme)); code = ReturnCode.Error; } } } } catch (Exception e) { Engine.SetExceptionErrorCode(interpreter, e); error = String.Format( "caught math exception: {0}", e); code = ReturnCode.Error; } } else { error = "invalid argument list"; code = ReturnCode.Error; } } else { error = "invalid interpreter"; code = ReturnCode.Error; } return(code); }
/////////////////////////////////////////////////////////////////////////////////////////////// #region IExecuteArgument Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Argument value, ref Result error ) { ReturnCode code = ReturnCode.Ok; if (interpreter != null) { if (arguments != null) { try { string name = null; Variant operand1 = null; Variant operand2 = null; code = Value.GetOperandsFromArguments(interpreter, this, arguments, ValueFlags.AnyVariant, interpreter.CultureInfo, ref name, ref operand1, ref operand2, ref error); if (code == ReturnCode.Ok) { if (operand1 != null) { if (operand1.ConvertTo(typeof(bool))) { if (operand1.IsBoolean()) { value = LogicOps.Not((bool)operand1.Value); } else { error = String.Format( "unsupported operand type for operator {0}", FormatOps.OperatorName(name, this.Lexeme)); code = ReturnCode.Error; } } else { error = String.Format( "failed to convert operand to type \"{0}\"", typeof(bool)); code = ReturnCode.Error; } } else { error = String.Format( "operand for operator {0} is invalid", FormatOps.OperatorName(name, this.Lexeme)); code = ReturnCode.Error; } } } catch (Exception e) { Engine.SetExceptionErrorCode(interpreter, e); error = String.Format( "caught math exception: {0}", e); code = ReturnCode.Error; } } else { error = "invalid argument list"; code = ReturnCode.Error; } } else { error = "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 = ReturnCode.Ok; if (interpreter != null) { if (arguments != null) { if (arguments.Count >= 2) { // // NOTE: lambdaExpr must be a two element list {args body} or a three element // list {args body namespace}. // StringList lambdaExpr = null; code = Parser.SplitList( interpreter, arguments[1], 0, Length.Invalid, true, ref lambdaExpr, ref result); if (code == ReturnCode.Ok) { if ((lambdaExpr.Count == 2) || (lambdaExpr.Count == 3)) { byte[] hashValue = arguments[1].GetHashValue(ref result); if (hashValue != null) { INamespace @namespace = null; if (lambdaExpr.Count == 3) { @namespace = NamespaceOps.Lookup( interpreter, lambdaExpr[2], true, false, ref result); if (@namespace == null) { code = ReturnCode.Error; } } if (code == ReturnCode.Ok) { // // NOTE: Parse the arguments into a list and make sure there are enough // supplied to satisfy the request. // StringList list = null; code = Parser.SplitList( interpreter, lambdaExpr[0], 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) { // // NOTE: We *MUST* have the formal arguments in an actual ArgumentList // container now. The variadic and optional argument semantics // depend on it. // ArgumentList formalArguments = new ArgumentList( list2, ArgumentFlags.NameOnly); // // NOTE: Compare lambda argument count with the total outer argument // count minus the "apply" and "lambdaExpr" arguments. // bool hasArgs = formalArguments.IsVariadic(true); int totalArgs = hasArgs ? formalArguments.Count - 1 : formalArguments.Count; int optionalArgs = formalArguments.GetOptionalCount(); if ((((arguments.Count - 2) >= (totalArgs - optionalArgs)) && ((arguments.Count - 2) <= totalArgs)) || (hasArgs && ((arguments.Count - 2) >= (totalArgs - optionalArgs)))) { string name = NextName(interpreter, @namespace); ICallFrame frame = null; try { frame = interpreter.NewProcedureCallFrame( name, CallFrameFlags.Procedure | CallFrameFlags.Lambda, new ClientData(hashValue), this, arguments); VariableDictionary variables = frame.Variables; frame.ProcedureArguments = new ArgumentList(arguments[0]); for (int argumentIndex = 0; argumentIndex < formalArguments.Count; argumentIndex++) { string varName = formalArguments[argumentIndex].Name; if (!variables.ContainsKey(varName)) { ArgumentFlags flags = ArgumentFlags.None; object varValue; if (hasArgs && (argumentIndex == (formalArguments.Count - 1))) { // // NOTE: This argument is part of an argument list. // flags |= ArgumentFlags.ArgumentList; // // NOTE: Build the list for the final formal argument value, // which consists of all the remaining argument values. // ArgumentList argsArguments = new ArgumentList(); for (int argsArgumentIndex = argumentIndex + 2; argsArgumentIndex < arguments.Count; argsArgumentIndex++) { // // NOTE: Sync up the argument name and flags for use when // debugging (below). // Argument argsArgument = Argument.GetOrCreate( interpreter, arguments[argsArgumentIndex].Flags | flags, String.Format("{0}{1}{2}", varName, Characters.Space, argsArguments.Count), arguments[argsArgumentIndex], interpreter.HasNoCacheArgument()); argsArguments.Add(argsArgument); } varValue = argsArguments; } else { if ((argumentIndex + 2) < arguments.Count) { // // NOTE: Sync up the argument name for use when // debugging (below) and use the value // supplied by the caller. // varValue = Argument.GetOrCreate(interpreter, arguments[argumentIndex + 2].Flags | flags, varName, arguments[argumentIndex + 2], interpreter.HasNoCacheArgument()); } else { // // NOTE: We cannot sync up the argument name here // because we are out-of-bounds on that list // and it cannot be extended (i.e. it would // break [info level]); therefore, we punt // on that for now. Use the default value // for this argument, if any; otherwise, use // an empty string. // object @default = formalArguments[argumentIndex].Default; varValue = (@default != null) ? @default : Argument.NoValue; } } code = interpreter.SetVariableValue2(VariableFlags.Argument, frame, varName, varValue, ref result); if (code != ReturnCode.Ok) { break; } // // BUGFIX: Now, also keep track of this argument in the procedure // arguments list. Primarily because we do not want to // have to redo this logic later (i.e. for [scope]). // frame.ProcedureArguments.Add(Argument.GetOrCreate( interpreter, flags, varName, varValue, interpreter.HasNoCacheArgument())); } } // // NOTE: Make sure we succeeded in creating the call frame. // if (code == ReturnCode.Ok) { ICallFrame savedFrame = null; interpreter.PushProcedureCallFrame(frame, true, ref savedFrame); try { #if DEBUGGER && DEBUGGER_EXECUTE if (DebuggerOps.CanHitBreakpoints(interpreter, EngineFlags.None, BreakpointType.BeforeLambdaBody)) { code = interpreter.CheckBreakpoints( code, BreakpointType.BeforeLambdaBody, this.Name, null, null, this, null, clientData, arguments, ref result); } #endif if (code == ReturnCode.Ok) { interpreter.ReturnCode = ReturnCode.Ok; code = interpreter.EvaluateScript(lambdaExpr[1], arguments[1], ref result); #if DEBUGGER && DEBUGGER_EXECUTE if (DebuggerOps.CanHitBreakpoints(interpreter, EngineFlags.None, BreakpointType.AfterLambdaBody)) { code = interpreter.CheckBreakpoints( code, BreakpointType.AfterLambdaBody, this.Name, null, null, this, null, clientData, arguments, ref result); } #endif // // BUGFIX: If an opaque object handle is being returned, add // a reference to it now. // if ((code == ReturnCode.Ok) || (code == ReturnCode.Return)) { code = interpreter.AddObjectReference( code, result, ObjectReferenceType.Return, ref result); } if (code == ReturnCode.Return) { code = Engine.UpdateReturnInformation(interpreter); } else if (code == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, result, String.Format("{0} (lambda term \"{1}\" line {2})", Environment.NewLine, FormatOps.Ellipsis(arguments[1]), Interpreter.GetErrorLine(interpreter))); } } } finally { /* IGNORED */ interpreter.PopProcedureCallFrame(frame, ref savedFrame); } } } finally { if (frame != null) { IDisposable disposable = frame as IDisposable; if (disposable != null) { disposable.Dispose(); disposable = null; } frame = null; } } } else { result = String.Format( "wrong # args: should be \"apply lambdaExpr {0}\"", formalArguments.ToRawString(ToStringFlags.Decorated, Characters.Space.ToString())); code = ReturnCode.Error; } } } } } else { code = ReturnCode.Error; } } else { result = String.Format( "can't interpret \"{0}\" as a lambda expression", arguments[1]); code = ReturnCode.Error; } } } else { result = "wrong # args: should be \"apply lambdaExpr ?arg1 arg2 ...?\""; 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) { OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.None, 1, Index.Invalid, "-exact", null), new Option(null, OptionFlags.None, 3, Index.Invalid, "-integer", null), new Option(null, OptionFlags.None, 3, Index.Invalid, "-substring", null), new Option(null, OptionFlags.None, 1, Index.Invalid, "-glob", null), new Option(null, OptionFlags.None, 1, Index.Invalid, "-regexp", null), new Option(null, OptionFlags.None, 2, Index.Invalid, "-subst", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-nocase", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null) }); int argumentIndex = Index.Invalid; if (arguments.Count > 1) { code = interpreter.GetOptions(options, arguments, 0, 1, Index.Invalid, false, ref argumentIndex, ref result); } else { code = ReturnCode.Ok; } if (code == ReturnCode.Ok) { if ((argumentIndex != Index.Invalid) && ((argumentIndex + 1) < arguments.Count)) { MatchMode mode = StringOps.DefaultSwitchMatchMode; if (options.IsPresent("-integer")) { mode = MatchMode.Integer; } else if (options.IsPresent("-regexp")) { mode = MatchMode.RegExp; } else if (options.IsPresent("-glob")) { mode = MatchMode.Glob; } else if (options.IsPresent("-substring")) { mode = MatchMode.SubString; } else if (options.IsPresent("-exact")) { mode = MatchMode.Exact; } if (options.IsPresent("-subst")) { mode |= MatchMode.Substitute; } bool noCase = false; if (options.IsPresent("-nocase")) { noCase = true; } bool splitList = false; StringList list = null; IScriptLocation location = null; // // NOTE: Is there only one argument following the string to match? // if ((argumentIndex + 2) == arguments.Count) { code = Parser.SplitList( interpreter, arguments[argumentIndex + 1], 0, Length.Invalid, true, ref list); if (code == ReturnCode.Ok) { if (list.Count > 0) { location = arguments[argumentIndex + 1]; splitList = true; } else { result = "wrong # args: should be \"switch ?switches? string {pattern body ... ?default body?}\""; code = ReturnCode.Error; } } } else { // // TODO: Make sure this is always accurate. // code = ScriptOps.GetLocation( interpreter, arguments, argumentIndex + 1, ref location, ref result); if (code == ReturnCode.Ok) { list = ArgumentList.GetRangeAsStringList(arguments, argumentIndex + 1); } } // // NOTE: Ok, now we should have a list of patterns and bodies // if everything went Ok above. // if (code == ReturnCode.Ok) { // // NOTE: Complain if there is an odd number of words in the // list of patterns and bodies. // if ((list.Count % 2) == 0) { // // NOTE: Complain if the last body is a continuation. // if (String.Compare(list[list.Count - 1], Characters.MinusSign.ToString(), StringOps.SystemStringComparisonType) != 0) { // // NOTE: Get the text to match against. // string input = arguments[argumentIndex]; // // NOTE: We need to return an empty string if we do not // match anything. // result = String.Empty; // // NOTE: Search the patterns for a match. // for (int index = 0; index < list.Count; index += 2) { Result pattern = list[index]; bool match = false; if ((index == (list.Count - 2)) && (String.Compare(pattern, Switch.Default, StringOps.SystemStringComparisonType) == 0)) { // // NOTE: Default pattern at end always matches. // match = true; } else { if ((mode & MatchMode.Substitute) == MatchMode.Substitute) { code = interpreter.SubstituteString(pattern, ref pattern); } if (code != ReturnCode.Ok) { result = pattern; break; } code = StringOps.Match( interpreter, mode, input, pattern, noCase, ref match, ref result); if (code != ReturnCode.Ok) { break; } } if (!match) { continue; } // // NOTE: We've got a match. Find a body to execute, skipping // bodies that are "-". // for (int index2 = index + 1; ; index2 += 2) { if (index2 >= list.Count) { result = "fall-out when searching for body to match pattern"; code = ReturnCode.Error; goto switch_done; } if (String.Compare(list[index2], Characters.MinusSign.ToString(), StringOps.SystemStringComparisonType) != 0) { code = interpreter.EvaluateScript(list[index2], location, ref result); if (code == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, result, String.Format("{0} (\"{1}\" arm line {2})", Environment.NewLine, FormatOps.Ellipsis(pattern), Interpreter.GetErrorLine(interpreter))); } goto switch_done; } } } switch_done: ; } else { result = String.Format( "no body specified for pattern \"{0}\"", list[list.Count - 2]); code = ReturnCode.Error; } } else { result = "extra switch pattern with no body"; code = ReturnCode.Error; if (splitList) { /* * Check if this can be due to a badly placed comment * in the switch block. * * The following is an heuristic to detect the infamous * "comment in switch" error: just check if a pattern * begins with '#'. */ for (int index = 0; index < list.Count; index++) { if (!String.IsNullOrEmpty(list[index]) && (list[index][0] == Characters.NumberSign)) { result += ", this may be due to a comment incorrectly placed " + "outside of a switch body - see the \"switch\" documentation"; break; } } } } } } else { if ((argumentIndex != Index.Invalid) && Option.LooksLikeOption(arguments[argumentIndex])) { result = OptionDictionary.BadOption(options, arguments[argumentIndex]); } else { result = "wrong # args: should be \"switch ?switches? string pattern body ... ?default body?\""; } code = ReturnCode.Error; } } } else { result = "invalid argument list"; code = ReturnCode.Error; } } else { result = "invalid interpreter"; code = ReturnCode.Error; } return(code); }