@@ -1129,11 +1129,51 @@ class CommandObjectThreadUntil : public CommandObjectParsed {
11291129
11301130// CommandObjectThreadSelect
11311131
1132+ #define LLDB_OPTIONS_thread_select
1133+ #include " CommandOptions.inc"
1134+
11321135class CommandObjectThreadSelect : public CommandObjectParsed {
11331136public:
1137+ class OptionGroupThreadSelect : public OptionGroup {
1138+ public:
1139+ OptionGroupThreadSelect () { OptionParsingStarting (nullptr ); }
1140+
1141+ ~OptionGroupThreadSelect () override = default ;
1142+
1143+ void OptionParsingStarting (ExecutionContext *execution_context) override {
1144+ m_thread_id = LLDB_INVALID_THREAD_ID;
1145+ }
1146+
1147+ Status SetOptionValue (uint32_t option_idx, llvm::StringRef option_arg,
1148+ ExecutionContext *execution_context) override {
1149+ const int short_option = g_thread_select_options[option_idx].short_option ;
1150+ switch (short_option) {
1151+ case ' t' : {
1152+ if (option_arg.getAsInteger (0 , m_thread_id)) {
1153+ m_thread_id = LLDB_INVALID_THREAD_ID;
1154+ return Status (" Invalid thread ID: '%s'." , option_arg.str ().c_str ());
1155+ }
1156+ break ;
1157+ }
1158+
1159+ default :
1160+ llvm_unreachable (" Unimplemented option" );
1161+ }
1162+
1163+ return {};
1164+ }
1165+
1166+ llvm::ArrayRef<OptionDefinition> GetDefinitions () override {
1167+ return llvm::ArrayRef (g_thread_select_options);
1168+ }
1169+
1170+ lldb::tid_t m_thread_id;
1171+ };
1172+
11341173 CommandObjectThreadSelect (CommandInterpreter &interpreter)
11351174 : CommandObjectParsed(interpreter, " thread select" ,
1136- " Change the currently selected thread." , nullptr ,
1175+ " Change the currently selected thread." ,
1176+ " thread select <thread-index> (or -t <thread-id>)" ,
11371177 eCommandRequiresProcess | eCommandTryTargetAPILock |
11381178 eCommandProcessMustBeLaunched |
11391179 eCommandProcessMustBePaused) {
@@ -1143,13 +1183,17 @@ class CommandObjectThreadSelect : public CommandObjectParsed {
11431183 // Define the first (and only) variant of this arg.
11441184 thread_idx_arg.arg_type = eArgTypeThreadIndex;
11451185 thread_idx_arg.arg_repetition = eArgRepeatPlain;
1186+ thread_idx_arg.arg_opt_set_association = LLDB_OPT_SET_1;
11461187
11471188 // There is only one variant this argument could be; put it into the
11481189 // argument entry.
11491190 arg.push_back (thread_idx_arg);
11501191
11511192 // Push the data for the first argument into the m_arguments vector.
11521193 m_arguments.push_back (arg);
1194+
1195+ m_option_group.Append (&m_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1196+ m_option_group.Finalize ();
11531197 }
11541198
11551199 ~CommandObjectThreadSelect () override = default ;
@@ -1165,37 +1209,59 @@ class CommandObjectThreadSelect : public CommandObjectParsed {
11651209 nullptr );
11661210 }
11671211
1212+ Options *GetOptions () override { return &m_option_group; }
1213+
11681214protected:
11691215 void DoExecute (Args &command, CommandReturnObject &result) override {
11701216 Process *process = m_exe_ctx.GetProcessPtr ();
11711217 if (process == nullptr ) {
11721218 result.AppendError (" no process" );
11731219 return ;
1174- } else if (command.GetArgumentCount () != 1 ) {
1220+ } else if (m_options.m_thread_id == LLDB_INVALID_THREAD_ID &&
1221+ command.GetArgumentCount () != 1 ) {
11751222 result.AppendErrorWithFormat (
1176- " '%s' takes exactly one thread index argument:\n Usage: %s\n " ,
1223+ " '%s' takes exactly one thread index argument, or a thread ID "
1224+ " option:\n Usage: %s\n " ,
11771225 m_cmd_name.c_str (), m_cmd_syntax.c_str ());
11781226 return ;
1179- }
1180-
1181- uint32_t index_id;
1182- if (!llvm::to_integer (command.GetArgumentAtIndex (0 ), index_id)) {
1183- result.AppendErrorWithFormat (" Invalid thread index '%s'" ,
1184- command.GetArgumentAtIndex (0 ));
1227+ } else if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID &&
1228+ command.GetArgumentCount () != 0 ) {
1229+ result.AppendErrorWithFormat (" '%s' cannot take both a thread ID option "
1230+ " and a thread index argument:\n Usage: %s\n " ,
1231+ m_cmd_name.c_str (), m_cmd_syntax.c_str ());
11851232 return ;
11861233 }
11871234
1188- Thread *new_thread =
1189- process->GetThreadList ().FindThreadByIndexID (index_id).get ();
1190- if (new_thread == nullptr ) {
1191- result.AppendErrorWithFormat (" invalid thread #%s.\n " ,
1192- command.GetArgumentAtIndex (0 ));
1193- return ;
1235+ Thread *new_thread = nullptr ;
1236+ if (command.GetArgumentCount () == 1 ) {
1237+ uint32_t index_id;
1238+ if (!llvm::to_integer (command.GetArgumentAtIndex (0 ), index_id)) {
1239+ result.AppendErrorWithFormat (" Invalid thread index '%s'" ,
1240+ command.GetArgumentAtIndex (0 ));
1241+ return ;
1242+ }
1243+ new_thread = process->GetThreadList ().FindThreadByIndexID (index_id).get ();
1244+ if (new_thread == nullptr ) {
1245+ result.AppendErrorWithFormat (" Invalid thread index #%s.\n " ,
1246+ command.GetArgumentAtIndex (0 ));
1247+ return ;
1248+ }
1249+ } else {
1250+ new_thread =
1251+ process->GetThreadList ().FindThreadByID (m_options.m_thread_id ).get ();
1252+ if (new_thread == nullptr ) {
1253+ result.AppendErrorWithFormat (" Invalid thread ID %" PRIu64 " .\n " ,
1254+ m_options.m_thread_id );
1255+ return ;
1256+ }
11941257 }
11951258
11961259 process->GetThreadList ().SetSelectedThreadByID (new_thread->GetID (), true );
11971260 result.SetStatus (eReturnStatusSuccessFinishNoResult);
11981261 }
1262+
1263+ OptionGroupThreadSelect m_options;
1264+ OptionGroupOptions m_option_group;
11991265};
12001266
12011267// CommandObjectThreadList
0 commit comments