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