1/* User Interface Events.
2
3   Copyright (C) 1999, 2001, 2002, 2004, 2005, 2007
4   Free Software Foundation, Inc.
5
6   Contributed by Cygnus Solutions.
7
8   This file is part of GDB.
9
10   This program is free software; you can redistribute it and/or modify
11   it under the terms of the GNU General Public License as published by
12   the Free Software Foundation; either version 3 of the License, or
13   (at your option) any later version.
14
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19
20   You should have received a copy of the GNU General Public License
21   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
23/* Work in progress */
24
25/* This file was created with the aid of ``gdb-events.sh''.
26
27   The bourn shell script ``gdb-events.sh'' creates the files
28   ``new-gdb-events.c'' and ``new-gdb-events.h and then compares
29   them against the existing ``gdb-events.[hc]''.  Any differences
30   found being reported.
31
32   If editing this file, please also run gdb-events.sh and merge any
33   changes into that script. Conversely, when making sweeping changes
34   to this file, modifying gdb-events.sh and using its output may
35   prove easier.  */
36
37
38#include "defs.h"
39#include "gdb-events.h"
40#include "gdbcmd.h"
41
42static struct gdb_events null_event_hooks;
43static struct gdb_events queue_event_hooks;
44static struct gdb_events *current_event_hooks = &null_event_hooks;
45
46int gdb_events_debug;
47static void
48show_gdb_events_debug (struct ui_file *file, int from_tty,
49		       struct cmd_list_element *c, const char *value)
50{
51  fprintf_filtered (file, _("Event debugging is %s.\n"), value);
52}
53
54
55void
56breakpoint_create_event (int b)
57{
58  if (gdb_events_debug)
59    fprintf_unfiltered (gdb_stdlog, "breakpoint_create_event\n");
60  if (!current_event_hooks->breakpoint_create)
61    return;
62  current_event_hooks->breakpoint_create (b);
63}
64
65void
66breakpoint_delete_event (int b)
67{
68  if (gdb_events_debug)
69    fprintf_unfiltered (gdb_stdlog, "breakpoint_delete_event\n");
70  if (!current_event_hooks->breakpoint_delete)
71    return;
72  current_event_hooks->breakpoint_delete (b);
73}
74
75void
76breakpoint_modify_event (int b)
77{
78  if (gdb_events_debug)
79    fprintf_unfiltered (gdb_stdlog, "breakpoint_modify_event\n");
80  if (!current_event_hooks->breakpoint_modify)
81    return;
82  current_event_hooks->breakpoint_modify (b);
83}
84
85void
86tracepoint_create_event (int number)
87{
88  if (gdb_events_debug)
89    fprintf_unfiltered (gdb_stdlog, "tracepoint_create_event\n");
90  if (!current_event_hooks->tracepoint_create)
91    return;
92  current_event_hooks->tracepoint_create (number);
93}
94
95void
96tracepoint_delete_event (int number)
97{
98  if (gdb_events_debug)
99    fprintf_unfiltered (gdb_stdlog, "tracepoint_delete_event\n");
100  if (!current_event_hooks->tracepoint_delete)
101    return;
102  current_event_hooks->tracepoint_delete (number);
103}
104
105void
106tracepoint_modify_event (int number)
107{
108  if (gdb_events_debug)
109    fprintf_unfiltered (gdb_stdlog, "tracepoint_modify_event\n");
110  if (!current_event_hooks->tracepoint_modify)
111    return;
112  current_event_hooks->tracepoint_modify (number);
113}
114
115void
116architecture_changed_event (void)
117{
118  if (gdb_events_debug)
119    fprintf_unfiltered (gdb_stdlog, "architecture_changed_event\n");
120  if (!current_event_hooks->architecture_changed)
121    return;
122  current_event_hooks->architecture_changed ();
123}
124
125struct gdb_events *
126deprecated_set_gdb_event_hooks (struct gdb_events *vector)
127{
128  struct gdb_events *old_events = current_event_hooks;
129  if (vector == NULL)
130    current_event_hooks = &queue_event_hooks;
131  else
132    current_event_hooks = vector;
133  return old_events;
134}
135
136void
137clear_gdb_event_hooks (void)
138{
139  deprecated_set_gdb_event_hooks (&null_event_hooks);
140}
141
142enum gdb_event
143{
144  breakpoint_create,
145  breakpoint_delete,
146  breakpoint_modify,
147  tracepoint_create,
148  tracepoint_delete,
149  tracepoint_modify,
150  architecture_changed,
151  nr_gdb_events
152};
153
154struct breakpoint_create
155  {
156    int b;
157  };
158
159struct breakpoint_delete
160  {
161    int b;
162  };
163
164struct breakpoint_modify
165  {
166    int b;
167  };
168
169struct tracepoint_create
170  {
171    int number;
172  };
173
174struct tracepoint_delete
175  {
176    int number;
177  };
178
179struct tracepoint_modify
180  {
181    int number;
182  };
183
184struct event
185  {
186    enum gdb_event type;
187    struct event *next;
188    union
189      {
190	struct breakpoint_create breakpoint_create;
191	struct breakpoint_delete breakpoint_delete;
192	struct breakpoint_modify breakpoint_modify;
193	struct tracepoint_create tracepoint_create;
194	struct tracepoint_delete tracepoint_delete;
195	struct tracepoint_modify tracepoint_modify;
196      }
197    data;
198  };
199struct event *pending_events;
200struct event *delivering_events;
201
202static void
203append (struct event *new_event)
204{
205  struct event **event = &pending_events;
206  while ((*event) != NULL)
207    event = &((*event)->next);
208  (*event) = new_event;
209  (*event)->next = NULL;
210}
211
212static void
213queue_breakpoint_create (int b)
214{
215  struct event *event = XMALLOC (struct event);
216  event->type = breakpoint_create;
217  event->data.breakpoint_create.b = b;
218  append (event);
219}
220
221static void
222queue_breakpoint_delete (int b)
223{
224  struct event *event = XMALLOC (struct event);
225  event->type = breakpoint_delete;
226  event->data.breakpoint_delete.b = b;
227  append (event);
228}
229
230static void
231queue_breakpoint_modify (int b)
232{
233  struct event *event = XMALLOC (struct event);
234  event->type = breakpoint_modify;
235  event->data.breakpoint_modify.b = b;
236  append (event);
237}
238
239static void
240queue_tracepoint_create (int number)
241{
242  struct event *event = XMALLOC (struct event);
243  event->type = tracepoint_create;
244  event->data.tracepoint_create.number = number;
245  append (event);
246}
247
248static void
249queue_tracepoint_delete (int number)
250{
251  struct event *event = XMALLOC (struct event);
252  event->type = tracepoint_delete;
253  event->data.tracepoint_delete.number = number;
254  append (event);
255}
256
257static void
258queue_tracepoint_modify (int number)
259{
260  struct event *event = XMALLOC (struct event);
261  event->type = tracepoint_modify;
262  event->data.tracepoint_modify.number = number;
263  append (event);
264}
265
266static void
267queue_architecture_changed (void)
268{
269  struct event *event = XMALLOC (struct event);
270  event->type = architecture_changed;
271  append (event);
272}
273
274void
275gdb_events_deliver (struct gdb_events *vector)
276{
277  /* Just zap any events left around from last time. */
278  while (delivering_events != NULL)
279    {
280      struct event *event = delivering_events;
281      delivering_events = event->next;
282      xfree (event);
283    }
284  /* Process any pending events.  Because one of the deliveries could
285     bail out we move everything off of the pending queue onto an
286     in-progress queue where it can, later, be cleaned up if
287     necessary. */
288  delivering_events = pending_events;
289  pending_events = NULL;
290  while (delivering_events != NULL)
291    {
292      struct event *event = delivering_events;
293      switch (event->type)
294	{
295	case breakpoint_create:
296	  vector->breakpoint_create
297	    (event->data.breakpoint_create.b);
298	  break;
299	case breakpoint_delete:
300	  vector->breakpoint_delete
301	    (event->data.breakpoint_delete.b);
302	  break;
303	case breakpoint_modify:
304	  vector->breakpoint_modify
305	    (event->data.breakpoint_modify.b);
306	  break;
307	case tracepoint_create:
308	  vector->tracepoint_create
309	    (event->data.tracepoint_create.number);
310	  break;
311	case tracepoint_delete:
312	  vector->tracepoint_delete
313	    (event->data.tracepoint_delete.number);
314	  break;
315	case tracepoint_modify:
316	  vector->tracepoint_modify
317	    (event->data.tracepoint_modify.number);
318	  break;
319	case architecture_changed:
320	  vector->architecture_changed ();
321	  break;
322	}
323      delivering_events = event->next;
324      xfree (event);
325    }
326}
327
328void _initialize_gdb_events (void);
329void
330_initialize_gdb_events (void)
331{
332  struct cmd_list_element *c;
333  queue_event_hooks.breakpoint_create = queue_breakpoint_create;
334  queue_event_hooks.breakpoint_delete = queue_breakpoint_delete;
335  queue_event_hooks.breakpoint_modify = queue_breakpoint_modify;
336  queue_event_hooks.tracepoint_create = queue_tracepoint_create;
337  queue_event_hooks.tracepoint_delete = queue_tracepoint_delete;
338  queue_event_hooks.tracepoint_modify = queue_tracepoint_modify;
339  queue_event_hooks.architecture_changed = queue_architecture_changed;
340
341  add_setshow_zinteger_cmd ("event", class_maintenance,
342			    &gdb_events_debug, _("\
343Set event debugging."), _("\
344Show event debugging."), _("\
345When non-zero, event/notify debugging is enabled."),
346			    NULL,
347			    show_gdb_events_debug,
348			    &setdebuglist, &showdebuglist);
349}
350