xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/target-connection.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
17d62b00eSchristos /* List of target connections for GDB.
27d62b00eSchristos 
3*6881a400Schristos    Copyright (C) 2017-2023 Free Software Foundation, Inc.
47d62b00eSchristos 
57d62b00eSchristos    This file is part of GDB.
67d62b00eSchristos 
77d62b00eSchristos    This program is free software; you can redistribute it and/or modify
87d62b00eSchristos    it under the terms of the GNU General Public License as published by
97d62b00eSchristos    the Free Software Foundation; either version 3 of the License, or
107d62b00eSchristos    (at your option) any later version.
117d62b00eSchristos 
127d62b00eSchristos    This program is distributed in the hope that it will be useful,
137d62b00eSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
147d62b00eSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
157d62b00eSchristos    GNU General Public License for more details.
167d62b00eSchristos 
177d62b00eSchristos    You should have received a copy of the GNU General Public License
187d62b00eSchristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
197d62b00eSchristos 
207d62b00eSchristos #include "defs.h"
217d62b00eSchristos #include "target-connection.h"
227d62b00eSchristos 
237d62b00eSchristos #include <map>
247d62b00eSchristos 
257d62b00eSchristos #include "inferior.h"
267d62b00eSchristos #include "target.h"
27*6881a400Schristos #include "observable.h"
287d62b00eSchristos 
297d62b00eSchristos /* A map between connection number and representative process_stratum
307d62b00eSchristos    target.  */
317d62b00eSchristos static std::map<int, process_stratum_target *> process_targets;
327d62b00eSchristos 
337d62b00eSchristos /* The highest connection number ever given to a target.  */
347d62b00eSchristos static int highest_target_connection_num;
357d62b00eSchristos 
367d62b00eSchristos /* See target-connection.h.  */
377d62b00eSchristos 
387d62b00eSchristos void
397d62b00eSchristos connection_list_add (process_stratum_target *t)
407d62b00eSchristos {
417d62b00eSchristos   if (t->connection_number == 0)
427d62b00eSchristos     {
437d62b00eSchristos       t->connection_number = ++highest_target_connection_num;
447d62b00eSchristos       process_targets[t->connection_number] = t;
457d62b00eSchristos     }
467d62b00eSchristos }
477d62b00eSchristos 
487d62b00eSchristos /* See target-connection.h.  */
497d62b00eSchristos 
507d62b00eSchristos void
517d62b00eSchristos connection_list_remove (process_stratum_target *t)
527d62b00eSchristos {
53*6881a400Schristos   /* Notify about the connection being removed before we reset the
54*6881a400Schristos      connection number to zero.  */
55*6881a400Schristos   gdb::observers::connection_removed.notify (t);
567d62b00eSchristos   process_targets.erase (t->connection_number);
577d62b00eSchristos   t->connection_number = 0;
587d62b00eSchristos }
597d62b00eSchristos 
607d62b00eSchristos /* See target-connection.h.  */
617d62b00eSchristos 
627d62b00eSchristos std::string
637d62b00eSchristos make_target_connection_string (process_stratum_target *t)
647d62b00eSchristos {
657d62b00eSchristos   if (t->connection_string () != NULL)
667d62b00eSchristos     return string_printf ("%s %s", t->shortname (),
677d62b00eSchristos 			  t->connection_string ());
687d62b00eSchristos   else
697d62b00eSchristos     return t->shortname ();
707d62b00eSchristos }
717d62b00eSchristos 
727d62b00eSchristos /* Prints the list of target connections and their details on UIOUT.
737d62b00eSchristos 
747d62b00eSchristos    If REQUESTED_CONNECTIONS is not NULL, it's a list of GDB ids of the
757d62b00eSchristos    target connections that should be printed.  Otherwise, all target
767d62b00eSchristos    connections are printed.  */
777d62b00eSchristos 
787d62b00eSchristos static void
797d62b00eSchristos print_connection (struct ui_out *uiout, const char *requested_connections)
807d62b00eSchristos {
817d62b00eSchristos   int count = 0;
827d62b00eSchristos   size_t what_len = 0;
837d62b00eSchristos 
847d62b00eSchristos   /* Compute number of lines we will print.  */
857d62b00eSchristos   for (const auto &it : process_targets)
867d62b00eSchristos     {
877d62b00eSchristos       if (!number_is_in_list (requested_connections, it.first))
887d62b00eSchristos 	continue;
897d62b00eSchristos 
907d62b00eSchristos       ++count;
917d62b00eSchristos 
927d62b00eSchristos       process_stratum_target *t = it.second;
937d62b00eSchristos 
94*6881a400Schristos       size_t l = make_target_connection_string (t).length ();
957d62b00eSchristos       if (l > what_len)
967d62b00eSchristos 	what_len = l;
977d62b00eSchristos     }
987d62b00eSchristos 
997d62b00eSchristos   if (count == 0)
1007d62b00eSchristos     {
1017d62b00eSchristos       uiout->message (_("No connections.\n"));
1027d62b00eSchristos       return;
1037d62b00eSchristos     }
1047d62b00eSchristos 
1057d62b00eSchristos   ui_out_emit_table table_emitter (uiout, 4, process_targets.size (),
1067d62b00eSchristos 				   "connections");
1077d62b00eSchristos 
1087d62b00eSchristos   uiout->table_header (1, ui_left, "current", "");
1097d62b00eSchristos   uiout->table_header (4, ui_left, "number", "Num");
1107d62b00eSchristos   /* The text in the "what" column may include spaces.  Add one extra
1117d62b00eSchristos      space to visually separate the What and Description columns a
1127d62b00eSchristos      little better.  Compare:
1137d62b00eSchristos       "* 1    remote :9999 Remote serial target in gdb-specific protocol"
1147d62b00eSchristos       "* 1    remote :9999  Remote serial target in gdb-specific protocol"
1157d62b00eSchristos   */
1167d62b00eSchristos   uiout->table_header (what_len + 1, ui_left, "what", "What");
1177d62b00eSchristos   uiout->table_header (17, ui_left, "description", "Description");
1187d62b00eSchristos 
1197d62b00eSchristos   uiout->table_body ();
1207d62b00eSchristos 
1217d62b00eSchristos   for (const auto &it : process_targets)
1227d62b00eSchristos     {
1237d62b00eSchristos       process_stratum_target *t = it.second;
1247d62b00eSchristos 
1257d62b00eSchristos       if (!number_is_in_list (requested_connections, t->connection_number))
1267d62b00eSchristos 	continue;
1277d62b00eSchristos 
1287d62b00eSchristos       ui_out_emit_tuple tuple_emitter (uiout, NULL);
1297d62b00eSchristos 
1307d62b00eSchristos       if (current_inferior ()->process_target () == t)
1317d62b00eSchristos 	uiout->field_string ("current", "*");
1327d62b00eSchristos       else
1337d62b00eSchristos 	uiout->field_skip ("current");
1347d62b00eSchristos 
1357d62b00eSchristos       uiout->field_signed ("number", t->connection_number);
1367d62b00eSchristos 
137*6881a400Schristos       uiout->field_string ("what", make_target_connection_string (t));
1387d62b00eSchristos 
1397d62b00eSchristos       uiout->field_string ("description", t->longname ());
1407d62b00eSchristos 
1417d62b00eSchristos       uiout->text ("\n");
1427d62b00eSchristos     }
1437d62b00eSchristos }
1447d62b00eSchristos 
1457d62b00eSchristos /* The "info connections" command.  */
1467d62b00eSchristos 
1477d62b00eSchristos static void
1487d62b00eSchristos info_connections_command (const char *args, int from_tty)
1497d62b00eSchristos {
1507d62b00eSchristos   print_connection (current_uiout, args);
1517d62b00eSchristos }
1527d62b00eSchristos 
1537d62b00eSchristos void _initialize_target_connection ();
1547d62b00eSchristos 
1557d62b00eSchristos void
1567d62b00eSchristos _initialize_target_connection ()
1577d62b00eSchristos {
1587d62b00eSchristos   add_info ("connections", info_connections_command,
1597d62b00eSchristos 	    _("\
1607d62b00eSchristos Target connections in use.\n\
1617d62b00eSchristos Shows the list of target connections currently in use."));
1627d62b00eSchristos }
163