/////////////////////////////////////////////////////////////////////// private static bool IsSuccess( ReturnCode code, /* in */ bool okOrReturnOnly, /* in */ bool allowExceptions /* in */ ) { if (okOrReturnOnly) { return(ResultOps.IsOkOrReturn(code)); } return(ResultOps.IsSuccess(code, allowExceptions)); }
/////////////////////////////////////////////////////////////////////// #region Public Methods public ReturnCode Process( ref StringBuilder output, /* in, out */ ref ResultList errors /* in, out */ ) /* ENTRY-POINT, THREAD-SAFE, RE-ENTRANT */ { CheckDisposed(); if (interpreter == null) { if (errors == null) { errors = new ResultList(); } errors.Add("invalid interpreter"); return(ReturnCode.Error); } if (text == null) { if (errors == null) { errors = new ResultList(); } errors.Add("invalid block text"); return(ReturnCode.Error); } int localLiteralCount = 0; int localBlockCount = 0; int localEvaluateCount = 0; int localSubstituteCount = 0; int localVariableCount = 0; int localFailCount = 0; int localErrorCount = 0; int length = text.Length; int index = 0; while (index < length) { int remaining = length - index; int openIndex = text.IndexOf(OpenBlock, index, remaining, StringOps.SystemStringComparisonType); int closeIndex = text.IndexOf(CloseBlock, index, remaining, StringOps.SystemStringComparisonType); if (openIndex != Index.Invalid) { int literalLength = openIndex - index; if (literalLength > 0) { if (output == null) { output = NewStringBuilder(remaining); } output.Append(text, index, literalLength); localLiteralCount++; } int savedOpenIndex = openIndex; openIndex += OpenLength; closeIndex = text.IndexOf( CloseBlock, openIndex, length - openIndex, StringOps.SystemStringComparisonType); if (closeIndex != Index.Invalid) { // // NOTE: We found another block to process. // localBlockCount++; // // NOTE: Evaluate the block we just found and insert // the resulting text. If a script error is // raised, either stop (in strict mode) -OR- // record it and continue (in non-strict mode). // int blockLength = closeIndex - openIndex; // // NOTE: If the block is "empty" (i.e. it contains no // characters whatsoever, not even whitespace, // then skip extracting the script and evaluate // an empty string. We evaluate an empty string // just in case the script engine needs to // perform some "background" tasks at this point, // such as the processing of asynchronous events. // bool isSubstitute; bool isVariable; string blockText; if (blockLength > 0) { // // HACK: Sneak a peek at the first character of the // block. // char firstCharacter = text[openIndex]; // // HACK: If it is the Tcl comment character (i.e. // '#'), we need to skip that character when // extracting the block to actually operate // on. // isSubstitute = IsSubstituteChar(firstCharacter); int blockIndex = openIndex; if (isSubstitute) { isVariable = false; blockIndex += 1; blockLength -= 1; } else { isVariable = IsVariableChar(firstCharacter); if (isVariable) { blockIndex += 1; blockLength -= 1; } } blockText = (blockLength > 0) ? text.Substring(blockIndex, blockLength) : String.Empty; } else { isSubstitute = false; isVariable = false; blockText = String.Empty; } ReturnCode localCode; Result localResult = null; int localErrorLine = 0; // // HACK: If the *VERY* first character of the block is // the comment character ("#") or the equal sign // ("="), then do not evaluate the block; rather, // just perform any textual substitutions inside // it -OR- replace it with the variable value. // if (isSubstitute) { // // NOTE: We found another substitution to perform. // localSubstituteCount++; localCode = interpreter.SubstituteString(blockText, ref localResult); } else if (isVariable) { // // NOTE: We found another variable to replace. // localVariableCount++; Result localValue = null; Result localError = null; localCode = interpreter.GetVariableValue( VariableFlags.None, blockText, ref localValue, ref localError); if (localCode == ReturnCode.Ok) { localResult = localValue; } else { localResult = localError; } } else { // // NOTE: We found another evaluation to perform. // localEvaluateCount++; localCode = interpreter.EvaluateScript(blockText, ref localResult, ref localErrorLine); } // // NOTE: Was the block was processed successfully? // if (IsSuccess( localCode, okOrReturnOnly, allowExceptions)) { if (output == null) { output = NewStringBuilder(remaining); } if ((localResult != null) && (localResult.Length > 0)) { string formatted = trimSpace ? (string)localResult.Trim(WhiteSpaceChars) : (string)localResult; output.Append(formatted); } } else { string formatted = ResultOps.Format( localCode, localResult, localErrorLine); if (errors == null) { errors = new ResultList(); } errors.Add(String.Format( "block from absolute index {0} to absolute " + "index {1} had {2} error: {3}", savedOpenIndex, closeIndex, isSubstitute ? "substitution" : "evaluation", formatted)); if (emitErrors) { if (output == null) { output = NewStringBuilder(remaining); } output.AppendFormat( "{0}{0}BLOCK ERROR: {1}{0}{0}", Environment.NewLine, formatted); } localErrorCount++; if (stopOnError) { break; } } // // NOTE: The very next thing to process is just after // the closing block tag. // index = closeIndex + CloseLength; } else { // // NOTE: The open tag has no matching close tag. // if (errors == null) { errors = new ResultList(); } Result localError = String.Format( "found opening tag \"{0}\" at absolute index " + "{1} and expected closing tag \"{2}\", which " + "was not found", OpenBlock, savedOpenIndex, CloseBlock); errors.Add(localError); if (emitFailures) { if (output == null) { output = NewStringBuilder(remaining); } output.AppendFormat( "{0}{0}PARSE ERROR: {1}{0}{0}", Environment.NewLine, localError); } localFailCount++; if (stopOnFailure) { break; } // // NOTE: The very next thing to process is just // after the opening block tag. // index = openIndex + OpenLength; } } else if (closeIndex != Index.Invalid) { // // NOTE: The close tag has no matching open tag. // if (errors == null) { errors = new ResultList(); } Result localError = String.Format( "found closing tag \"{0}\" at absolute index " + "{1} and expected opening tag \"{2}\", which " + "was not found", CloseBlock, closeIndex, OpenBlock); errors.Add(localError); if (emitFailures) { if (output == null) { output = NewStringBuilder(remaining); } output.AppendFormat( "{0}{0}PARSE ERROR: {1}{0}{0}", Environment.NewLine, localError); } localFailCount++; if (stopOnFailure) { break; } // // NOTE: The very next thing to process is just // after the closing block tag. // index = closeIndex + CloseLength; } else { if (output == null) { output = NewStringBuilder(remaining); } output.Append(text, index, remaining); localLiteralCount++; index += remaining; } } literalCount += localLiteralCount; blockCount += localBlockCount; evaluateCount += localEvaluateCount; substituteCount += localSubstituteCount; variableCount += localVariableCount; failCount += localFailCount; errorCount += localErrorCount; return((localFailCount == 0) && (localErrorCount == 0) ? ReturnCode.Ok : ReturnCode.Error); }
public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { ReturnCode code; if (interpreter != null) { if (arguments != null) { if (arguments.Count >= 1) { OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.Unsafe, Index.Invalid, Index.Invalid, "-force", null), new Option(null, OptionFlags.Unsafe, Index.Invalid, Index.Invalid, "-fail", null), new Option(null, OptionFlags.MustHaveValue, Index.Invalid, Index.Invalid, "-message", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-current", 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)) { bool force = false; if (options.IsPresent("-force")) { force = true; } bool fail = false; if (options.IsPresent("-fail")) { fail = true; } Variant value = null; string message = null; if (options.IsPresent("-message", ref value)) { message = value.ToString(); } // // NOTE: The default exit code is "success" (i.e. zero). // ExitCode exitCode = ResultOps.SuccessExitCode(); if (options.IsPresent("-current")) { exitCode = interpreter.ExitCode; } // // NOTE: Was an exit code specified in the command? // if (argumentIndex != Index.Invalid) { object enumValue = EnumOps.TryParseEnum( typeof(ExitCode), arguments[argumentIndex], true, true, ref result); if (enumValue is ExitCode) { exitCode = (ExitCode)enumValue; } else { result = ScriptOps.BadValue( null, "exit code", arguments[argumentIndex], Enum.GetNames(typeof(ExitCode)), null, ", or an integer"); code = ReturnCode.Error; } } // // NOTE: Make sure we succeeded at coverting the exit code to an integer. // if (code == ReturnCode.Ok) { // // NOTE: Make sure the interpreter host, if any, agrees to exit (i.e. it may deny the // request if the application is doing something that should not be interrupted). // code = interpreter.CanExit(exitCode, force, fail, message, ref result); if (code == ReturnCode.Ok) { // // NOTE: Exit the application (either by marking the current interpreter as "exited" // or physically exiting the containing process). // TraceOps.DebugTrace(String.Format( "Execute: {0}, interpreter = {1}, message = {2}", force && fail ? "forcibly failing" : force ? "forcibly exiting" : "exiting", FormatOps.InterpreterNoThrow(interpreter), FormatOps.WrapOrNull(message)), typeof(Exit).Name, TracePriority.Command); if (force) { #if !MONO if (fail && !CommonOps.Runtime.IsMono()) { try { // // NOTE: Using this method to exit a script is NOT recommended unless // you are trying to prevent damaging another part of the system. // // MONO: This method is not supported by the Mono runtime. // Environment.FailFast(message); /* NOT REACHED */ result = "failed to exit process"; code = ReturnCode.Error; } catch (Exception e) { result = e; code = ReturnCode.Error; } } else #endif { // // BUGFIX: Try to dispose our containing interpreter now. We must do // this to prevent it from being disposed on a random GC thread. // try { interpreter.Dispose(); interpreter = null; } catch (Exception e) { result = e; code = ReturnCode.Error; } // // NOTE: If we could not dispose the interpreter properly, complain; // however, keep exiting anyway. // if (code != ReturnCode.Ok) { DebugOps.Complain(interpreter, code, result); } try { // // NOTE: Using this method to exit a script is NOT recommended unless // you are running a standalone script in the Eagle Shell (i.e. // you are not hosted within another application). // Environment.Exit((int)exitCode); /* NOT REACHED */ result = "failed to exit process"; code = ReturnCode.Error; } catch (Exception e) { result = e; code = ReturnCode.Error; } } } else { interpreter.ExitCode = exitCode; interpreter.Exit = true; result = String.Empty; code = ReturnCode.Ok; } } } } else { if ((argumentIndex != Index.Invalid) && Option.LooksLikeOption(arguments[argumentIndex])) { result = OptionDictionary.BadOption(options, arguments[argumentIndex]); } else { result = "wrong # args: should be \"exit ?options? ?returnCode?\""; } code = ReturnCode.Error; } } } else { result = "wrong # args: should be \"exit ?options? ?returnCode?\""; 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) { 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) { OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-debug", null), // simple switch new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-commandline", null), // simple switch new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-dequote", null), // simple switch new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-quoteall", null), // simple switch new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-unicode", null), // simple switch new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-ignorestderr", null), // simple switch new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-killonerror", null), // simple switch new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-keepnewline", null), // simple switch new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-noexitcode", null), // simple switch new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-nocapture", null), // simple switch new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-shell", null), // simple switch new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-nocarriagereturns", null), // simple switch new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-trimall", null), // simple switch new Option(typeof(ExitCode), OptionFlags.MustHaveEnumValue, Index.Invalid, Index.Invalid, "-success", null), // success exit code new Option(null, OptionFlags.MustHaveValue, Index.Invalid, Index.Invalid, "-domainname", null), new Option(null, OptionFlags.MustHaveValue, Index.Invalid, Index.Invalid, "-username", null), new Option(null, OptionFlags.MustHaveSecureStringValue, Index.Invalid, Index.Invalid, "-password", null), new Option(null, OptionFlags.MustHaveListValue, Index.Invalid, Index.Invalid, "-preprocessarguments", null), // command new Option(null, OptionFlags.MustHaveValue, Index.Invalid, Index.Invalid, "-directory", null), // directory name new Option(null, OptionFlags.MustHaveValue, Index.Invalid, Index.Invalid, "-processid", null), // varName for processId new Option(null, OptionFlags.MustHaveValue, Index.Invalid, Index.Invalid, "-exitcode", null), // varName for exitCode new Option(null, OptionFlags.MustHaveValue, Index.Invalid, Index.Invalid, "-stdin", null), // varName for StdIn input new Option(null, OptionFlags.MustHaveValue, Index.Invalid, Index.Invalid, "-stdout", null), // varName for StdOut output new Option(null, OptionFlags.MustHaveValue, Index.Invalid, Index.Invalid, "-stderr", null), // varName for StdErr output new Option(typeof(EventFlags), OptionFlags.MustHaveEnumValue, Index.Invalid, Index.Invalid, "-eventflags", new Variant(interpreter.EngineEventFlags)), 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, true, ref argumentIndex, ref result); if (code == ReturnCode.Ok) { if (argumentIndex != Index.Invalid) { bool debug = false; if (options.IsPresent("-debug")) { debug = true; } bool commandLine = false; if (options.IsPresent("-commandline")) { commandLine = true; } bool dequote = false; if (options.IsPresent("-dequote")) { dequote = true; } bool quoteAll = false; if (options.IsPresent("-quoteall")) { quoteAll = true; } bool captureExitCode = true; if (options.IsPresent("-noexitcode")) { captureExitCode = false; } bool captureInput = true; bool captureOutput = true; if (options.IsPresent("-nocapture")) { captureInput = false; captureOutput = false; } bool useUnicode = false; if (options.IsPresent("-unicode")) { useUnicode = true; } bool ignoreStdErr = false; if (options.IsPresent("-ignorestderr")) { ignoreStdErr = true; } bool killOnError = false; if (options.IsPresent("-killonerror")) { killOnError = true; } bool keepNewLine = false; if (options.IsPresent("-keepnewline")) { keepNewLine = true; } bool carriageReturns = true; if (options.IsPresent("-nocarriagereturns")) { carriageReturns = false; } bool trimAll = false; if (options.IsPresent("-trimall")) { trimAll = true; } bool useShellExecute = false; if (options.IsPresent("-shell")) { useShellExecute = true; } Variant value = null; ExitCode?successExitCode = null; if (options.IsPresent("-success", ref value)) { successExitCode = (ExitCode)value.Value; } string domainName = null; if (options.IsPresent("-domainname", ref value)) { domainName = value.ToString(); } string userName = null; if (options.IsPresent("-username", ref value)) { userName = value.ToString(); } SecureString password = null; if (options.IsPresent("-password", ref value)) { password = (SecureString)value.Value; } string directory = null; if (options.IsPresent("-directory", ref value)) { directory = value.ToString(); } string processIdVarName = null; if (options.IsPresent("-processid", ref value)) { processIdVarName = value.ToString(); } string exitCodeVarName = null; if (options.IsPresent("-exitcode", ref value)) { exitCodeVarName = value.ToString(); } string stdInVarName = null; if (options.IsPresent("-stdin", ref value)) { stdInVarName = value.ToString(); } string stdOutVarName = null; if (options.IsPresent("-stdout", ref value)) { stdOutVarName = value.ToString(); } string stdErrVarName = null; if (options.IsPresent("-stderr", ref value)) { stdErrVarName = value.ToString(); } EventFlags eventFlags = interpreter.EngineEventFlags; if (options.IsPresent("-eventflags", ref value)) { eventFlags = (EventFlags)value.Value; } StringList list = null; if (options.IsPresent("-preprocessarguments", ref value)) { list = (StringList)value.Value; } int argumentStopIndex = arguments.Count - 1; bool background = false; if (arguments[arguments.Count - 1] == Characters.Ampersand.ToString()) { argumentStopIndex--; background = true; } string execFileName = arguments[argumentIndex]; if (!PathOps.IsRemoteUri(execFileName)) { execFileName = PathOps.GetNativePath(execFileName); } string execArguments = null; if ((argumentIndex + 1) < arguments.Count) { if (commandLine) { execArguments = RuntimeOps.BuildCommandLine( ArgumentList.GetRangeAsStringList(arguments, argumentIndex + 1, argumentStopIndex, dequote), quoteAll); } else { execArguments = ListOps.Concat(arguments, argumentIndex + 1, argumentStopIndex); } } Result input = null; if ((code == ReturnCode.Ok) && !useShellExecute && captureInput && (stdInVarName != null)) { code = interpreter.GetVariableValue(VariableFlags.None, stdInVarName, ref input, ref result); } if (debug) { TraceOps.DebugTrace(String.Format( "Execute: interpreter = {0}, domainName = {1}, userName = {2}, " + "password = {3}, execFileName = {4}, execArguments = {5}, " + "directory = {6}, input = {7}, eventFlags = {8}, debug = {9}, " + "commandLine = {10}, dequote = {11}, quoteAll = {12}, " + "useShellExecute = {13}, captureExitCode = {14}, " + "captureInput = {15}, captureOutput = {16}, useUnicode = {17}, " + "ignoreStdErr = {18}, killOnError = {19}, keepNewLine = {20}, " + "carriageReturns = {21}, trimAll = {22}, background = {23}, " + "successExitCode = {24}, processIdVarName = {25}, exitCodeVarName = {26}, " + "stdInVarName = {27}, stdOutVarName = {28}, stdErrVarName = {29}", FormatOps.InterpreterNoThrow(interpreter), FormatOps.WrapOrNull(domainName), FormatOps.WrapOrNull(userName), FormatOps.WrapOrNull(password), FormatOps.WrapOrNull(execFileName), FormatOps.WrapOrNull(execArguments), FormatOps.WrapOrNull(directory), FormatOps.WrapOrNull(input), FormatOps.WrapOrNull(eventFlags), debug, commandLine, dequote, quoteAll, useShellExecute, captureExitCode, captureInput, captureOutput, useUnicode, ignoreStdErr, killOnError, keepNewLine, carriageReturns, trimAll, background, FormatOps.WrapOrNull(successExitCode), FormatOps.WrapOrNull(processIdVarName), FormatOps.WrapOrNull(exitCodeVarName), FormatOps.WrapOrNull(stdInVarName), FormatOps.WrapOrNull(stdOutVarName), FormatOps.WrapOrNull(stdErrVarName)), typeof(Exec).Name, TracePriority.Command); } int processId = 0; ExitCode exitCode = ResultOps.SuccessExitCode(); Result error = null; if (code == ReturnCode.Ok) { if (list != null) { list.Add(execFileName); list.Add(directory); list.Add(execArguments); code = interpreter.EvaluateScript(list.ToString(), ref result); if (code == ReturnCode.Return) { execArguments = result; code = ReturnCode.Ok; } else if (code == ReturnCode.Continue) { code = ReturnCode.Ok; goto done; } } if (code == ReturnCode.Ok) { code = ProcessOps.ExecuteProcess( interpreter, domainName, userName, password, execFileName, execArguments, directory, input, eventFlags, useShellExecute, captureExitCode, captureOutput, useUnicode, ignoreStdErr, killOnError, keepNewLine, background, !background, ref processId, ref exitCode, ref result, ref error); } } done: if (debug) { TraceOps.DebugTrace(String.Format( "Execute: interpreter = {0}, domainName = {1}, userName = {2}, " + "password = {3}, execFileName = {4}, execArguments = {5}, " + "directory = {6}, input = {7}, eventFlags = {8}, debug = {9}, " + "commandLine = {10}, dequote = {11}, quoteAll = {12}, " + "useShellExecute = {13}, captureExitCode = {14}, " + "captureInput = {15}, captureOutput = {16}, useUnicode = {17}, " + "ignoreStdErr = {18}, killOnError = {19}, keepNewLine = {20}, " + "carriageReturns = {21}, trimAll = {22}, background = {23}, " + "successExitCode = {24}, processIdVarName = {25}, exitCodeVarName = {26}, " + "stdInVarName = {27}, stdOutVarName = {28}, stdErrVarName = {29}, " + "processId = {30}, exitCode = {31}, result = {32}, error = {33}", FormatOps.InterpreterNoThrow(interpreter), FormatOps.WrapOrNull(domainName), FormatOps.WrapOrNull(userName), FormatOps.WrapOrNull(password), FormatOps.WrapOrNull(execFileName), FormatOps.WrapOrNull(execArguments), FormatOps.WrapOrNull(directory), FormatOps.WrapOrNull(input), FormatOps.WrapOrNull(eventFlags), debug, commandLine, dequote, quoteAll, useShellExecute, captureExitCode, captureInput, captureOutput, useUnicode, ignoreStdErr, killOnError, keepNewLine, carriageReturns, trimAll, background, FormatOps.WrapOrNull(successExitCode), FormatOps.WrapOrNull(processIdVarName), FormatOps.WrapOrNull(exitCodeVarName), FormatOps.WrapOrNull(stdInVarName), FormatOps.WrapOrNull(stdOutVarName), FormatOps.WrapOrNull(stdErrVarName), processId, exitCode, FormatOps.WrapOrNull(true, true, result), FormatOps.WrapOrNull(true, true, error)), typeof(Exec).Name, TracePriority.Command); } // // NOTE: Even upon failure, always set the variable to contain // process Id, if applicable. // if (processIdVarName != null) { /* IGNORED */ interpreter.SetVariableValue( /* EXEMPT */ VariableFlags.NoReady, processIdVarName, processId.ToString(), null); } if (code == ReturnCode.Ok) { // // NOTE: Remove all carriage returns from output (leaving // only line feeds as line separators)? // if (!carriageReturns) { if (!String.IsNullOrEmpty(result)) { result = result.Replace( Characters.CarriageReturnString, String.Empty); } if (!String.IsNullOrEmpty(error)) { error = error.Replace( Characters.CarriageReturnString, String.Empty); } } // // NOTE: Remove all surrounding whitespace from the output? // if (trimAll) { if (!String.IsNullOrEmpty(result)) { result = result.Trim(); } if (!String.IsNullOrEmpty(error)) { error = error.Trim(); } } // // NOTE: Now, "result" contains any StdOut output and "error" // contains any StdErr output. // if ((code == ReturnCode.Ok) && !background && captureExitCode && (exitCodeVarName != null)) { code = interpreter.SetVariableValue(VariableFlags.None, exitCodeVarName, exitCode.ToString(), null, ref error); } if ((code == ReturnCode.Ok) && !useShellExecute && !background && captureOutput && (stdOutVarName != null)) { code = interpreter.SetVariableValue(VariableFlags.None, stdOutVarName, result, null, ref error); } if ((code == ReturnCode.Ok) && !useShellExecute && !background && captureOutput && (stdErrVarName != null)) { code = interpreter.SetVariableValue(VariableFlags.None, stdErrVarName, error, null, ref error); } // // NOTE: If they specified a "success" exit code, make sure // that is the same as the exit code we actually got // from the process. // if ((code == ReturnCode.Ok) && !background && captureExitCode && (successExitCode != null) && (exitCode != successExitCode)) { /* IGNORED */ interpreter.SetVariableValue( /* EXEMPT */ Engine.ErrorCodeVariableFlags, TclVars.ErrorCode, StringList.MakeList( "CHILDSTATUS", processId, exitCode), null); Engine.SetErrorCodeSet(interpreter, true); error = "child process exited abnormally"; code = ReturnCode.Error; } if (code != ReturnCode.Ok) { // // NOTE: Transfer error to command result. // result = error; } } else { // // NOTE: Transfer error to command result. // result = error; } } else { result = "wrong # args: should be \"exec ?options? arg ?arg ...?\""; code = ReturnCode.Error; } } } else { result = "wrong # args: should be \"exec ?options? arg ?arg ...?\""; code = ReturnCode.Error; } } else { result = "invalid argument list"; code = ReturnCode.Error; } } else { result = "invalid interpreter"; code = ReturnCode.Error; } return(code); }