// We have separate argument parsing for guest mode.
        //
        // There are a few reasons:
        //    * The arguments for the standalone EXE and the arguments for guest mode
        //      don't necessarily match (we don't need -File for guest mode, we want to
        //      let people just type a command instead of having to type "-Command" first,
        //      -ReadFromStdin doesn't make sense, etc.)
        //    * The "normal mode" argument parsing happens on a code path that is only run
        //      once in guest mode, the first time !dbgshell is run. Of course it would be
        //      possible to change that, but I'm trying to minimize the amount of churn
        //      caused by introducing guest mode.
        private static string _ParseGuestModeArgs(string line,
                                                  bool firstTime,
                                                  out bool noProfile,
                                                  out bool inBreakpointCommand)
        {
            line = line.Trim();

            bool noExit    = false;
            bool isEncoded = false;

            noProfile           = false;
            inBreakpointCommand = false;

            StringBuilder sbCmd = new StringBuilder(line.Length * 2);

            sbCmd.AppendLine("try {");

            // I think we shouldn't need "-File", because both execution operators seem to
            // work fine:
            //
            //    !dbgshell & D:\blah\foo.ps1
            //    !dbgshell . D:\blah\foo.ps1
            //

            int idx = 0;

            while (idx < line.Length)
            {
                // Eat space.
                while ((idx < line.Length) &&
                       ((line[idx] == ' ') || (line[idx] == '\t')))
                {
                    idx++;
                }

                if (idx >= line.Length)
                {
                    break;
                }

                if ((line[idx] == '/') || (line[idx] == '-'))
                {
                    idx++;

                    int idxSpace = line.IndexOfAny(sm_delims, idx);

                    if (idxSpace < 0)
                    {
                        idxSpace = line.Length;
                    }

                    string opt = line.Substring(idx, (idxSpace - idx));

                    if (0 == opt.Length)
                    {
                        // Just a "- "?
                        idx++;
                        continue;
                    }

                    if ("NoExit".StartsWith(opt, StringComparison.OrdinalIgnoreCase))
                    {
                        noExit = true;
                    }
                    else if ("NoProfile".StartsWith(opt, StringComparison.OrdinalIgnoreCase))
                    {
                        noProfile = true;
                    }
                    else if ("EncodedCommand".StartsWith(opt, StringComparison.OrdinalIgnoreCase))
                    {
                        isEncoded = true;
                        idx       = idx + opt.Length;
                        break;
                    }
                    else if ("Bp".StartsWith(opt, StringComparison.OrdinalIgnoreCase))
                    {
                        inBreakpointCommand = true;

                        // When we hit a breakpoint, we could be on a different thread.
                        sbCmd.AppendLine("[MS.Dbg.DbgProvider]::SetLocationByDebuggerContext()");
                    }
                    else
                    {
                        sbCmd.AppendLine(Util.Sprintf("Write-Error 'Unexpected option: ''-{0}''.'", opt));
                    }

                    idx = idx + opt.Length;
                } // end if( it's an option )
                else
                {
                    // Done with options.
                    break;
                }
            } // end while( idx < line.Length )


            if (noProfile && !firstTime)
            {
                sbCmd.AppendLine("Write-Warning '-NoProfile only works when used with the first invocation of !dbgshell.'");
                sbCmd.AppendLine("Write-Warning 'You can unload and reload DbgShellExt, and then run \"!dbgshell -NoProfile\".'");
            }

            if (isEncoded)
            {
                string encoded = line.Substring(idx).Trim();
                if (0 == encoded.Length)
                {
                    sbCmd.AppendLine("Write-Warning \"Encoded command was empty.\"");
                }
                else
                {
                    sbCmd.AppendLine(DbgProvider.DecodeString(encoded));
                }
            }
            else
            {
                if (idx < line.Length)
                {
                    sbCmd.AppendLine(line.Substring(idx));
                }
                else
                {
                    // No command implies we want the shell to stick around so we can use it
                    // interactively.
                    noExit = true;
                }
            }

            bool reentering = DbgProvider.EntryDepth > 1;

            if (!noExit && !reentering)
            {
                sbCmd.AppendLine("exit");
            }
            else if (noExit && reentering)
            {
                sbCmd.AppendLine("Write-Warning 'N.B. There is already a running pipeline--you are now in a nested prompt.'");
                sbCmd.AppendLine("$Host.EnterNestedPrompt()");
            }

            sbCmd.AppendLine("} finally { }");
            return(sbCmd.ToString());
        } // end _ParseGuestModeArgs()
        private bool ParseCommand(string[] args, ref int i, bool noexitSeen, bool isEncoded)
        {
            if (commandLineCommand != null)
            {
                // we've already set the command, so squawk

                //ui.WriteErrorLine(CommandLineParameterParserStrings.CommandAlreadySpecified);
                ui.WriteErrorLine("Hey wait; there's already a command!");
                showHelp     = true;
                abortStartup = true;
                exitCode     = ExitCodeBadCommandLineParameter;
                return(false);
            }

            ++i;
            if (i >= args.Length)
            {
                //ui.WriteErrorLine(CommandLineParameterParserStrings.MissingCommandParameter);
                ui.WriteErrorLine("Missing command.");
                showHelp     = true;
                abortStartup = true;
                exitCode     = ExitCodeBadCommandLineParameter;
                return(false);
            }

            if (isEncoded)
            {
                try
                {
                    //commandLineCommand = StringToBase64Converter.Base64ToString(args[i]);
                    //commandLineCommand = Encoding.Unicode.GetString( Convert.FromBase64String( args[ i ] ) );
                    commandLineCommand = DbgProvider.DecodeString(args[i]);
                }
                // decoding failed
                catch
                {
                    //ui.WriteErrorLine(CommandLineParameterParserStrings.BadCommandValue);
                    ui.WriteErrorLine("Bad command value.");
                    showHelp     = true;
                    abortStartup = true;
                    exitCode     = ExitCodeBadCommandLineParameter;
                    return(false);
                }
            }
            else if (args[i] == "-")
            {
                // the arg to -command is -, which is secret code for "read the commands from stdin with no prompts"

                readFromStdin = true;
                noPrompt      = true;

                ++i;
                if (i != args.Length)
                {
                    // there are more parameters to -command than -, which is an error.

                    //ui.WriteErrorLine(CommandLineParameterParserStrings.TooManyParametersToCommand);
                    ui.WriteErrorLine("Too many parameters for command.");
                    showHelp     = true;
                    abortStartup = true;
                    exitCode     = ExitCodeBadCommandLineParameter;
                    return(false);
                }

                if (!parent.IsStandardInputRedirected)
                {
                    //ui.WriteErrorLine(CommandLineParameterParserStrings.StdinNotRedirected);
                    ui.WriteErrorLine("StdIn not redirected.");
                    showHelp     = true;
                    abortStartup = true;
                    exitCode     = ExitCodeBadCommandLineParameter;
                    return(false);
                }
            }
            else
            {
                // Collect the remaining parameters and combine them into a single command to be run.

                StringBuilder cmdLineCmdSB = new StringBuilder();

                while (i < args.Length)
                {
                    cmdLineCmdSB.Append(args[i] + " ");
                    ++i;
                }
                if (cmdLineCmdSB.Length > 0)
                {
                    // remove the last blank
                    cmdLineCmdSB.Remove(cmdLineCmdSB.Length - 1, 1);
                }
                commandLineCommand = cmdLineCmdSB.ToString();
            }

            if (!noexitSeen)
            {
                // don't reset this if they've already specified -noexit

                noExit = false;
            }

            showBanner = false;

            return(true);
        }