]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMgr.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / tools / lldb-mi / MIDriverMgr.cpp
1 //===-- MIDriverMgr.cpp -----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // Third Party Headers:
11 #include "lldb/API/SBError.h"
12
13 // In-house headers:
14 #include "MICmnLog.h"
15 #include "MICmnLogMediumFile.h"
16 #include "MICmnResources.h"
17 #include "MICmnStreamStdout.h"
18 #include "MIDriver.h"
19 #include "MIDriverMgr.h"
20 #include "MIUtilSingletonHelper.h"
21
22 //++
23 //------------------------------------------------------------------------------------
24 // Details: CMIDriverMgr constructor.
25 // Type:    Method.
26 // Args:    None.
27 // Return:  None.
28 // Throws:  None.
29 //--
30 CMIDriverMgr::CMIDriverMgr() : m_pDriverCurrent(nullptr), m_bInMi2Mode(false) {}
31
32 //++
33 //------------------------------------------------------------------------------------
34 // Details: CMIDriverMgr destructor.
35 // Type:    Overridden.
36 // Args:    None.
37 // Return:  None.
38 // Throws:  None.
39 //--
40 CMIDriverMgr::~CMIDriverMgr() { Shutdown(); }
41
42 //++
43 //------------------------------------------------------------------------------------
44 // Details: Initialize *this manager.
45 // Type:    Method.
46 // Args:    None.
47 // Return:  MIstatus::success - Functional succeeded.
48 //          MIstatus::failure - Functional failed.
49 // Throws:  None.
50 //--
51 bool CMIDriverMgr::Initialize() {
52   m_clientUsageRefCnt++;
53
54   ClrErrorDescription();
55
56   if (m_bInitialized)
57     return MIstatus::success;
58
59   bool bOk = MIstatus::success;
60   CMIUtilString errMsg;
61
62   // Note initialisation order is important here as some resources depend on
63   // previous
64   MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg);
65   MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg);
66
67   m_bInitialized = bOk;
68
69   if (!bOk) {
70     CMIUtilString strInitError(CMIUtilString::Format(
71         MIRSRC(IDS_MI_INIT_ERR_DRIVERMGR), errMsg.c_str()));
72     SetErrorDescription(strInitError);
73     return MIstatus::failure;
74   }
75
76   return bOk;
77 }
78
79 //++
80 //------------------------------------------------------------------------------------
81 // Details: Unbind detach or release resources used by this server in general
82 // common
83 //          functionality shared between versions of any server interfaces
84 //          implemented.
85 // Type:    Method.
86 // Args:    vbAppExitOk - (R) True = No problems, false = App exiting with
87 // problems (investigate!).
88 // Return:  MIstatus::success - Functional succeeded.
89 //          MIstatus::failure - Functional failed.
90 // Throws:  None.
91 //--
92 bool CMIDriverMgr::Shutdown() {
93   // Do not want a ref counter because this function needs to be called how ever
94   // this
95   // application stops running
96   // if( --m_clientUsageRefCnt > 0 )
97   //  return MIstatus::success;
98
99   ClrErrorDescription();
100
101   if (!m_bInitialized)
102     return MIstatus::success;
103
104   m_bInitialized = false;
105
106   bool bOk = MIstatus::success;
107   CMIUtilString errMsg;
108
109   // Tidy up
110   UnregisterDriverAll();
111
112   // Note shutdown order is important here
113   MI::ModuleShutdown<CMICmnResources>(IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg);
114   MI::ModuleShutdown<CMICmnLog>(IDS_MI_SHTDWN_ERR_LOG, bOk, errMsg);
115
116   if (!bOk) {
117     SetErrorDescriptionn(MIRSRC(IDS_MI_SHTDWN_ERR_DRIVERMGR), errMsg.c_str());
118   }
119
120   return bOk;
121 }
122 //++
123 //------------------------------------------------------------------------------------
124 // Details: Unregister all the Driver registered with *this manager. The manager
125 // also
126 //          deletes
127 // Type:    Method.
128 // Args:    None.
129 // Return:  MIstatus::success - Functional succeeded.
130 //          MIstatus::failure - Functional failed.
131 // Throws:  None.
132 //--
133 bool CMIDriverMgr::UnregisterDriverAll() {
134   MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
135   while (it != m_mapDriverIdToDriver.end()) {
136     IDriver *pDriver = (*it).second;
137     pDriver->DoShutdown();
138
139     // Next
140     ++it;
141   }
142
143   m_mapDriverIdToDriver.clear();
144   m_pDriverCurrent = NULL;
145
146   return MIstatus::success;
147 }
148
149 //++
150 //------------------------------------------------------------------------------------
151 // Details: Register a driver with *this Driver Manager. Call
152 // SetUseThisDriverToDoWork()
153 //          inform the manager which driver is the one to the work. The manager
154 //          calls
155 //          the driver's init function which must be successful in order to
156 //          complete the
157 //          registration.
158 // Type:    Method.
159 // Args:    vrDriver    - (R) The driver to register.
160 //          vrDriverID  - (R) The driver's ID to lookup by.
161 // Return:  MIstatus::success - Functional succeeded.
162 //          MIstatus::failure - Functional failed.
163 // Throws:  None.
164 //--
165 bool CMIDriverMgr::RegisterDriver(const IDriver &vrDriver,
166                                   const CMIUtilString &vrDriverID) {
167   if (HaveDriverAlready(vrDriver))
168     return MIstatus::success;
169
170   IDriver *pDriver = const_cast<IDriver *>(&vrDriver);
171   if (!pDriver->SetId(vrDriverID))
172     return MIstatus::failure;
173   if (!pDriver->DoInitialize()) {
174     SetErrorDescriptionn(MIRSRC(IDS_DRIVERMGR_DRIVER_ERR_INIT),
175                          pDriver->GetName().c_str(), vrDriverID.c_str(),
176                          pDriver->GetError().c_str());
177     return MIstatus::failure;
178   }
179
180   MapPairDriverIdToDriver_t pr(vrDriverID, pDriver);
181   m_mapDriverIdToDriver.insert(pr);
182
183   return MIstatus::success;
184 }
185
186 //++
187 //------------------------------------------------------------------------------------
188 // Details: Query the Driver Manager to see if *this manager has the driver
189 // already
190 //          registered.
191 // Type:    Method.
192 // Args:    vrDriver    - (R) The driver to query.
193 // Return:  True - registered.
194 //          False - not registered.
195 // Throws:  None.
196 //--
197 bool CMIDriverMgr::HaveDriverAlready(const IDriver &vrDriver) const {
198   MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
199   while (it != m_mapDriverIdToDriver.end()) {
200     const IDriver *pDrvr = (*it).second;
201     if (pDrvr == &vrDriver)
202       return true;
203
204     // Next
205     ++it;
206   }
207
208   return false;
209 }
210
211 //++
212 //------------------------------------------------------------------------------------
213 // Details: Unregister a driver from the Driver Manager. Call the
214 // SetUseThisDriverToDoWork()
215 //          function to define another driver to do work if the one being
216 //          unregistered did
217 //          the work previously.
218 // Type:    Method.
219 // Args:    vrDriver    - (R) The driver to unregister.
220 // Return:  MIstatus::success - Functional succeeded.
221 //          MIstatus::failure - Functional failed.
222 // Throws:  None.
223 //--
224 bool CMIDriverMgr::UnregisterDriver(const IDriver &vrDriver) {
225   const IDriver *pDrvr = nullptr;
226   MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
227   while (it != m_mapDriverIdToDriver.end()) {
228     pDrvr = (*it).second;
229     if (pDrvr == &vrDriver)
230       break;
231
232     // Next
233     ++it;
234   }
235   m_mapDriverIdToDriver.erase(it);
236
237   if (m_pDriverCurrent == pDrvr)
238     m_pDriverCurrent = nullptr;
239
240   return MIstatus::success;
241 }
242
243 //++
244 //------------------------------------------------------------------------------------
245 // Details: Specify the driver to do work. The Driver Manager drives this
246 // driver. Any
247 //          previous driver doing work is not called anymore (so be sure the
248 //          previous
249 //          driver is in a tidy state before stopping it working).
250 // Type:    Method.
251 // Args:    vrADriver   - (R) A lldb::SBBroadcaster/IDriver derived object.
252 // Return:  MIstatus::success - Functional succeeded.
253 //          MIstatus::failure - Functional failed.
254 // Throws:  None.
255 //--
256 bool CMIDriverMgr::SetUseThisDriverToDoWork(const IDriver &vrADriver) {
257   m_pDriverCurrent = const_cast<IDriver *>(&vrADriver);
258
259   const CMIUtilString msg(
260       CMIUtilString::Format(MIRSRC(IDS_DRIVER_SAY_DRIVER_USING),
261                             m_pDriverCurrent->GetName().c_str()));
262   m_pLog->Write(msg, CMICmnLog::eLogVerbosity_Log);
263
264   m_bInMi2Mode = m_pDriverCurrent->GetDriverIsGDBMICompatibleDriver();
265
266   return MIstatus::success;
267 }
268
269 //++
270 //------------------------------------------------------------------------------------
271 // Details: Ask *this manager which driver is currently doing the work.
272 // Type:    Method.
273 // Args:    None.
274 // Return:  IDriver * - Pointer to a driver, NULL if there is no current working
275 // driver.
276 // Throws:  None.
277 //--
278 CMIDriverMgr::IDriver *CMIDriverMgr::GetUseThisDriverToDoWork() const {
279   return m_pDriverCurrent;
280 }
281
282 //++
283 //------------------------------------------------------------------------------------
284 // Details: Call this function puts *this driver to work.
285 // Type:    Method.
286 // Args:    None.
287 // Return:  MIstatus::success - Functional succeeded.
288 //          MIstatus::failure - Functional failed.
289 // Throws:  None.
290 //--
291 bool CMIDriverMgr::DriverMainLoop() {
292   if (m_pDriverCurrent != nullptr) {
293     if (!m_pDriverCurrent->DoMainLoop()) {
294       const CMIUtilString errMsg(
295           CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_MAINLOOP),
296                                 m_pDriverCurrent->GetError().c_str()));
297       CMICmnStreamStdout::Instance().Write(errMsg, true);
298       return MIstatus::failure;
299     }
300   } else {
301     const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET));
302     CMICmnStreamStdout::Instance().Write(errMsg, true);
303     return MIstatus::failure;
304   }
305
306   return MIstatus::success;
307 }
308
309 //++
310 //------------------------------------------------------------------------------------
311 // Details: Get the current driver to validate executable command line
312 // arguments.
313 // Type:    Method.
314 // Args:    argc        - (R)   An integer that contains the count of arguments
315 // that follow in
316 //                              argv. The argc parameter is always greater than
317 //                              or equal to 1.
318 //          argv        - (R)   An array of null-terminated strings representing
319 //          command-line
320 //                              arguments entered by the user of the program. By
321 //                              convention,
322 //                              argv[0] is the command with which the program is
323 //                              invoked.
324 //          vpStdOut    - (R)   Point to a standard output stream.
325 //          vwbExiting  - (W)   True = *this want to exit, false = continue to
326 //          work.
327 // Return:  MIstatus::success - Functional succeeded.
328 //          MIstatus::failure - Functional failed.
329 // Throws:  None.
330 //--
331 bool CMIDriverMgr::DriverParseArgs(const int argc, const char *argv[],
332                                    FILE *vpStdOut, bool &vwbExiting) {
333   if (m_pDriverCurrent == nullptr) {
334     const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET));
335     CMICmnStreamStdout::Instance().Write(errMsg, true);
336     return MIstatus::failure;
337   }
338
339   const lldb::SBError error(
340       m_pDriverCurrent->DoParseArgs(argc, argv, vpStdOut, vwbExiting));
341   bool bOk = !error.Fail();
342   if (!bOk) {
343     CMIUtilString errMsg;
344     const char *pErrorCstr = error.GetCString();
345     if (pErrorCstr != nullptr)
346       errMsg = CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_PARSE_ARGS),
347                                      m_pDriverCurrent->GetName().c_str(),
348                                      pErrorCstr);
349     else
350       errMsg = CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN),
351                                      m_pDriverCurrent->GetName().c_str());
352
353     bOk = CMICmnStreamStdout::Instance().Write(errMsg, true);
354   }
355
356   return bOk;
357 }
358
359 //++
360 //------------------------------------------------------------------------------------
361 // Details: Retrieve the current driver's last error condition.
362 // Type:    Method.
363 // Args:    None.
364 // Return:  CMIUtilString - Text description.
365 // Throws:  None.
366 //--
367 CMIUtilString CMIDriverMgr::DriverGetError() const {
368   if (m_pDriverCurrent != nullptr)
369     return m_pDriverCurrent->GetError();
370   else {
371     const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET));
372     CMICmnStreamStdout::Instance().Write(errMsg, true);
373   }
374
375   return CMIUtilString();
376 }
377
378 //++
379 //------------------------------------------------------------------------------------
380 // Details: Retrieve the current driver's name.
381 // Type:    Method.
382 // Args:    None.
383 // Return:  CMIUtilString - Driver name.
384 //                          Empty string = no current working driver specified.
385 // Throws:  None.
386 //--
387 CMIUtilString CMIDriverMgr::DriverGetName() const {
388   if (m_pDriverCurrent != nullptr)
389     return m_pDriverCurrent->GetName();
390   else {
391     const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET));
392     CMICmnStreamStdout::Instance().Write(errMsg, true);
393   }
394
395   return CMIUtilString();
396 }
397
398 //++
399 //------------------------------------------------------------------------------------
400 // Details: Retrieve the current driver's debugger object.
401 // Type:    Method.
402 // Args:    None.
403 // Return:  lldb::SBDebugger * - Ptr to driver's debugger object.
404 //                             - NULL = no current working driver specified.
405 // Throws:  None.
406 //--
407 lldb::SBDebugger *CMIDriverMgr::DriverGetTheDebugger() {
408   lldb::SBDebugger *pDebugger = nullptr;
409   if (m_pDriverCurrent != nullptr)
410     pDebugger = &m_pDriverCurrent->GetTheDebugger();
411   else {
412     const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET));
413     CMICmnStreamStdout::Instance().Write(errMsg, true);
414   }
415
416   return pDebugger;
417 }
418
419 //++
420 //------------------------------------------------------------------------------------
421 // Details: Check the arguments given on the command line. The main purpose of
422 // this
423 //          function is to check for the presence of the --interpreter option.
424 //          Having
425 //          this option present tells *this manager to set the CMIDriver to do
426 //          work. If
427 //          not use the LLDB driver. The following are options that are only
428 //          handled by
429 //          the CMIDriverMgr are:
430 //              --help or -h
431 //              --interpreter
432 //              --version
433 //              --versionLong
434 //              --log
435 //              --executable
436 //              --log-dir
437 //          The above arguments are not handled by any driver object except for
438 //          --executable.
439 //          The options --interpreter and --executable in code act very similar.
440 //          The
441 //          --executable is necessary to differentiate whither the MI Driver is
442 //          being using
443 //          by a client i.e. Eclipse or from the command line. Eclipse issues
444 //          the option
445 //          --interpreter and also passes additional arguments which can be
446 //          interpreted as an
447 //          executable if called from the command line. Using --executable tells
448 //          the MI
449 //          Driver is being called the command line and that the executable
450 //          argument is indeed
451 //          a specified executable an so actions commands to set up the
452 //          executable for a
453 //          debug session. Using --interpreter on the command line does not
454 //          action additional
455 //          commands to initialise a debug session and so be able to launch the
456 //          process. The directory
457 //          where the log file is created is specified using --log-dir.
458 // Type:    Method.
459 // Args:    argc        - (R)   An integer that contains the count of arguments
460 // that follow in
461 //                              argv. The argc parameter is always greater than
462 //                              or equal to 1.
463 //          argv        - (R)   An array of null-terminated strings representing
464 //          command-line
465 //                              arguments entered by the user of the program. By
466 //                              convention,
467 //                              argv[0] is the command with which the program is
468 //                              invoked.
469 //          vwbExiting  - (W)   True = *this want to exit, Reasons: help,
470 //          invalid arg(s),
471 //                              version information only.
472 //                              False = Continue to work, start debugger i.e.
473 //                              Command
474 //                              interpreter.
475 // Return:  lldb::SBError - LLDB current error status.
476 // Throws:  None.
477 //--
478 bool CMIDriverMgr::ParseArgs(const int argc, const char *argv[],
479                              bool &vwbExiting) {
480   bool bOk = MIstatus::success;
481
482   vwbExiting = false;
483
484   // Print MI application path to the Log file
485   const CMIUtilString appPath(
486       CMIUtilString::Format(MIRSRC(IDS_MI_APP_FILEPATHNAME), argv[0]));
487   bOk = m_pLog->Write(appPath, CMICmnLog::eLogVerbosity_Log);
488
489   // Print application arguments to the Log file
490   const bool bHaveArgs(argc >= 2);
491   CMIUtilString strArgs(MIRSRC(IDS_MI_APP_ARGS));
492   if (!bHaveArgs) {
493     strArgs += MIRSRC(IDS_WORD_NONE);
494     bOk = bOk && m_pLog->Write(strArgs, CMICmnLog::eLogVerbosity_Log);
495   } else {
496     for (MIint i = 1; i < argc; i++) {
497       strArgs += CMIUtilString::Format("%d:'%s' ", i, argv[i]);
498     }
499     bOk = bOk && m_pLog->Write(strArgs, CMICmnLog::eLogVerbosity_Log);
500   }
501
502   // Look for the command line options
503   bool bHaveArgInterpret = false;
504   bool bHaveArgVersion = false;
505   bool bHaveArgVersionLong = false;
506   bool bHaveArgLog = false;
507   bool bHaveArgLogDir = false;
508   bool bHaveArgHelp = false;
509   CMIUtilString strLogDir;
510
511   bHaveArgInterpret = true;
512   if (bHaveArgs) {
513     // CODETAG_MIDRIVE_CMD_LINE_ARG_HANDLING
514     for (MIint i = 1; i < argc; i++) {
515       // *** Add args to help in GetHelpOnCmdLineArgOptions() ***
516       const CMIUtilString strArg(argv[i]);
517
518       // Argument "--executable" is also check for in CMIDriver::ParseArgs()
519       if (("--interpreter" == strArg) || // Given by the client such as Eclipse
520           ("--executable" == strArg))    // Used to specify that there
521                                          // is executable argument also
522                                          // on the command line
523       {                                  // See fn description.
524         bHaveArgInterpret = true;
525       }
526       if ("--version" == strArg) {
527         bHaveArgVersion = true;
528       }
529       if ("--versionLong" == strArg) {
530         bHaveArgVersionLong = true;
531       }
532       if ("--log" == strArg) {
533         bHaveArgLog = true;
534       }
535       if (0 == strArg.compare(0, 10, "--log-dir=")) {
536         strLogDir = strArg.substr(10, CMIUtilString::npos);
537         bHaveArgLogDir = true;
538       }
539       if (("--help" == strArg) || ("-h" == strArg)) {
540         bHaveArgHelp = true;
541       }
542     }
543   }
544
545   if (bHaveArgLog) {
546     CMICmnLog::Instance().SetEnabled(true);
547   }
548
549   if (bHaveArgLogDir) {
550     bOk = bOk && CMICmnLogMediumFile::Instance().SetDirectory(strLogDir);
551   }
552
553   // Todo: Remove this output when MI is finished. It is temporary to persuade
554   // Eclipse plugin to work.
555   //       Eclipse reads this literally and will not work unless it gets this
556   //       exact version text.
557   // Handle --version option (ignore the --interpreter option if present)
558   if (bHaveArgVersion) {
559     vwbExiting = true;
560     bOk = bOk &&
561           CMICmnStreamStdout::Instance().WriteMIResponse(
562               MIRSRC(IDE_MI_VERSION_GDB));
563     return bOk;
564   }
565
566   // Todo: Make this the --version when the above --version version is removed
567   // Handle --versionlong option (ignore the --interpreter option if present)
568   if (bHaveArgVersionLong) {
569     vwbExiting = true;
570     bOk =
571         bOk && CMICmnStreamStdout::Instance().WriteMIResponse(GetAppVersion());
572     return bOk;
573   }
574
575   // Both '--help' and '--interpreter' means give help for MI only. Without
576   // '--interpreter' help the LLDB driver is working and so help is for that.
577   if (bHaveArgHelp && bHaveArgInterpret) {
578     vwbExiting = true;
579     bOk = bOk &&
580           CMICmnStreamStdout::Instance().WriteMIResponse(
581               GetHelpOnCmdLineArgOptions());
582     return bOk;
583   }
584
585   // This makes the assumption that there is at least one MI compatible
586   // driver registered and one LLDB driver registered and the CMIDriver
587   // is the first one found.
588   // ToDo: Implement a better solution that handle any order, any number
589   // of drivers. Or this 'feature' may be removed if deemed not required.
590   IDriver *pLldbDriver = GetFirstNonMIDriver();
591   IDriver *pMi2Driver = GetFirstMIDriver();
592   if (bHaveArgInterpret && (pMi2Driver != nullptr))
593     bOk = bOk && SetUseThisDriverToDoWork(*pMi2Driver);
594   else if (pLldbDriver != nullptr)
595     bOk = bOk && SetUseThisDriverToDoWork(*pLldbDriver);
596   else {
597     if (bOk) {
598       vwbExiting = true;
599       const CMIUtilString msg(MIRSRC(IDS_DRIVER_ERR_NON_REGISTERED));
600       bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse(msg);
601     }
602   }
603
604   return bOk;
605 }
606
607 //++
608 //------------------------------------------------------------------------------------
609 // Details: Return formatted application version and name information.
610 // Type:    Method.
611 // Args:    None.
612 // Return:  CMIUtilString - Text data.
613 // Throws:  None.
614 //--
615 CMIUtilString CMIDriverMgr::GetAppVersion() const {
616   const CMIUtilString strProj(MIRSRC(IDS_PROJNAME));
617   const CMIUtilString strVsn(CMIDriver::Instance().GetVersionDescription());
618   const CMIUtilString strGdb(MIRSRC(IDE_MI_VERSION_GDB));
619   const CMIUtilString strVrsnInfo(CMIUtilString::Format(
620       "%s\n%s\n%s", strProj.c_str(), strVsn.c_str(), strGdb.c_str()));
621
622   return strVrsnInfo;
623 }
624
625 //++
626 //------------------------------------------------------------------------------------
627 // Details: Return formatted help information on all the MI command line
628 // options.
629 // Type:    Method.
630 // Args:    None.
631 // Return:  CMIUtilString - Text data.
632 // Throws:  None.
633 //--
634 CMIUtilString CMIDriverMgr::GetHelpOnCmdLineArgOptions() const {
635   const CMIUtilString pHelp[] = {
636       MIRSRC(IDE_MI_APP_DESCRIPTION), MIRSRC(IDE_MI_APP_INFORMATION),
637       MIRSRC(IDE_MI_APP_ARG_USAGE), MIRSRC(IDE_MI_APP_ARG_HELP),
638       MIRSRC(IDE_MI_APP_ARG_VERSION), MIRSRC(IDE_MI_APP_ARG_VERSION_LONG),
639       MIRSRC(IDE_MI_APP_ARG_INTERPRETER), MIRSRC(IDE_MI_APP_ARG_SOURCE),
640       MIRSRC(IDE_MI_APP_ARG_EXECUTEABLE),
641       MIRSRC(IDE_MI_APP_ARG_SYNCHRONOUS),
642       CMIUtilString::Format(
643           MIRSRC(IDE_MI_APP_ARG_APP_LOG),
644           CMICmnLogMediumFile::Instance().GetFileName().c_str()),
645       MIRSRC(IDE_MI_APP_ARG_APP_LOG_DIR), MIRSRC(IDE_MI_APP_ARG_EXECUTABLE),
646       MIRSRC(IDS_CMD_QUIT_HELP), MIRSRC(IDE_MI_APP_ARG_EXAMPLE)};
647   const MIuint nHelpItems = sizeof pHelp / sizeof pHelp[0];
648   CMIUtilString strHelp;
649   for (MIuint i = 0; i < nHelpItems; i++) {
650     strHelp += pHelp[i];
651     strHelp += "\n\n";
652   }
653
654   return strHelp;
655 }
656
657 //++
658 //------------------------------------------------------------------------------------
659 // Details: Search the registered drivers and return the first driver which says
660 // it is
661 //          GDB/MI compatible i.e. the CMIDriver class.
662 // Type:    Method.
663 // Args:    None.
664 // Return:  IDriver * - Ptr to driver, NULL = no driver found.
665 // Throws:  None.
666 //--
667 CMIDriverMgr::IDriver *CMIDriverMgr::GetFirstMIDriver() const {
668   IDriver *pDriver = nullptr;
669   MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
670   while (it != m_mapDriverIdToDriver.end()) {
671     const CMIUtilString &rDrvId = (*it).first;
672     MIunused(rDrvId);
673     IDriver *pDvr = (*it).second;
674     if (pDvr->GetDriverIsGDBMICompatibleDriver()) {
675       pDriver = pDvr;
676       break;
677     }
678
679     // Next
680     ++it;
681   }
682
683   return pDriver;
684 }
685
686 //++
687 //------------------------------------------------------------------------------------
688 // Details: Search the registered drivers and return the first driver which says
689 // it is
690 //          not GDB/MI compatible i.e. the LLDB Driver class.
691 // Type:    Method.
692 // Args:    None.
693 // Return:  IDriver * - Ptr to driver, NULL = no driver found.
694 // Throws:  None.
695 //--
696 CMIDriverMgr::IDriver *CMIDriverMgr::GetFirstNonMIDriver() const {
697   IDriver *pDriver = nullptr;
698   MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
699   while (it != m_mapDriverIdToDriver.end()) {
700     const CMIUtilString &rDrvId = (*it).first;
701     MIunused(rDrvId);
702     IDriver *pDvr = (*it).second;
703     if (!pDvr->GetDriverIsGDBMICompatibleDriver()) {
704       pDriver = pDvr;
705       break;
706     }
707
708     // Next
709     ++it;
710   }
711
712   return pDriver;
713 }
714
715 //++
716 //------------------------------------------------------------------------------------
717 // Details: Search the registered drivers and return driver with the specified
718 // ID.
719 // Type:    Method.
720 // Args:    vrDriverId  - (R) ID of a driver.
721 // Return:  IDriver * - Ptr to driver, NULL = no driver found.
722 // Throws:  None.
723 //--
724 CMIDriverMgr::IDriver *
725 CMIDriverMgr::GetDriver(const CMIUtilString &vrDriverId) const {
726   MapDriverIdToDriver_t::const_iterator it =
727       m_mapDriverIdToDriver.find(vrDriverId);
728   if (it == m_mapDriverIdToDriver.end())
729     return nullptr;
730
731   IDriver *pDriver = (*it).second;
732
733   return pDriver;
734 }
735
736 //++
737 //------------------------------------------------------------------------------------
738 // Details: Gets called when lldb-mi gets a signal. Passed signal to current
739 // driver.
740 //
741 // Type:    Method.
742 // Args:    signal that was delivered
743 // Return:  None.
744 // Throws:  None.
745 //--
746 void CMIDriverMgr::DeliverSignal(int signal) {
747   if (m_pDriverCurrent != nullptr)
748     m_pDriverCurrent->DeliverSignal(signal);
749 }