xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/inferior-iter.h (revision dd75ac5b443e967e26b4d18cc8cd5eb98512bfbf)
1 /* Inferior iterators and ranges for GDB, the GNU debugger.
2 
3    Copyright (C) 2018-2020 Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 #ifndef INFERIOR_ITER_H
21 #define INFERIOR_ITER_H
22 
23 #include "gdbsupport/filtered-iterator.h"
24 #include "gdbsupport/safe-iterator.h"
25 
26 /* A forward iterator that iterates over all inferiors.  */
27 
28 class all_inferiors_iterator
29 {
30 public:
31   typedef all_inferiors_iterator self_type;
32   typedef struct inferior *value_type;
33   typedef struct inferior *&reference;
34   typedef struct inferior **pointer;
35   typedef std::forward_iterator_tag iterator_category;
36   typedef int difference_type;
37 
38   /* Create an iterator pointing at HEAD.  */
39   all_inferiors_iterator (process_stratum_target *proc_target, inferior *head)
40     : m_proc_target (proc_target)
41   {
42     /* Advance M_INF to the first inferior's position.  */
43     for (m_inf = head; m_inf != NULL; m_inf = m_inf->next)
44       if (m_inf_matches ())
45 	return;
46   }
47 
48   /* Create a one-past-end iterator.  */
49   all_inferiors_iterator ()
50     : m_proc_target (nullptr), m_inf (nullptr)
51   {}
52 
53   all_inferiors_iterator &operator++ ()
54   {
55     advance ();
56     return *this;
57   }
58 
59   inferior *operator* () const
60   { return m_inf; }
61 
62   bool operator!= (const all_inferiors_iterator &other) const
63   { return m_inf != other.m_inf; }
64 
65 private:
66   /* Advance to next inferior, skipping filtered inferiors.  */
67   void advance ()
68   {
69     /* The loop below is written in the natural way as-if we'd always
70        start at the beginning of the inferior list.  This
71        fast-forwards the algorithm to the actual current position.  */
72     goto start;
73 
74     while (m_inf != NULL)
75       {
76 	if (m_inf_matches ())
77 	  return;
78       start:
79 	m_inf = m_inf->next;
80       }
81   }
82 
83   bool m_inf_matches ()
84   {
85     return (m_proc_target == nullptr
86 	    || m_proc_target == m_inf->process_target ());
87   }
88 
89   process_stratum_target *m_proc_target;
90   inferior *m_inf;
91 };
92 
93 /* Filter for filtered_iterator.  Filters out exited inferiors.  */
94 
95 struct exited_inferior_filter
96 {
97   bool operator() (inferior *inf)
98   {
99     return inf->pid != 0;
100   }
101 };
102 
103 /* Iterate over all non-exited inferiors.  */
104 
105 using all_non_exited_inferiors_iterator
106   = filtered_iterator<all_inferiors_iterator, exited_inferior_filter>;
107 
108 /* A range adapter that makes it possible to iterate over all
109    inferiors with range-for.  */
110 struct all_inferiors_range
111 {
112   all_inferiors_range (process_stratum_target *proc_target = nullptr)
113     : m_filter_target (proc_target)
114   {}
115 
116   all_inferiors_iterator begin () const
117   { return all_inferiors_iterator (m_filter_target, inferior_list); }
118   all_inferiors_iterator end () const
119   { return all_inferiors_iterator (); }
120 
121 private:
122   process_stratum_target *m_filter_target;
123 };
124 
125 /* Iterate over all inferiors, safely.  */
126 
127 using all_inferiors_safe_iterator
128   = basic_safe_iterator<all_inferiors_iterator>;
129 
130 /* A range adapter that makes it possible to iterate over all
131    inferiors with range-for "safely".  I.e., it is safe to delete the
132    currently-iterated inferior.  */
133 
134 struct all_inferiors_safe_range
135 {
136   explicit all_inferiors_safe_range (process_stratum_target *filter_target)
137     : m_filter_target (filter_target)
138   {}
139 
140   all_inferiors_safe_range ()
141     : m_filter_target (nullptr)
142   {}
143 
144   all_inferiors_safe_iterator begin () const
145   {
146     return (all_inferiors_safe_iterator
147 	    (all_inferiors_iterator (m_filter_target, inferior_list)));
148   }
149 
150   all_inferiors_safe_iterator end () const
151   { return all_inferiors_safe_iterator (); }
152 
153 private:
154   /* The filter.  */
155   process_stratum_target *m_filter_target;
156 };
157 
158 /* A range adapter that makes it possible to iterate over all
159    non-exited inferiors with range-for.  */
160 
161 struct all_non_exited_inferiors_range
162 {
163   explicit all_non_exited_inferiors_range (process_stratum_target *filter_target)
164     : m_filter_target (filter_target)
165   {}
166 
167   all_non_exited_inferiors_range ()
168     : m_filter_target (nullptr)
169   {}
170 
171   all_non_exited_inferiors_iterator begin () const
172   { return all_non_exited_inferiors_iterator (m_filter_target, inferior_list); }
173   all_non_exited_inferiors_iterator end () const
174   { return all_non_exited_inferiors_iterator (); }
175 
176 private:
177   /* The filter.  */
178   process_stratum_target *m_filter_target;
179 };
180 
181 #endif /* !defined (INFERIOR_ITER_H) */
182