Change tui_data_item_window::content to be a unique_xmalloc_ptr
[external/binutils.git] / gdb / continuations.c
1 /* Continuations for GDB, the GNU debugger.
2
3    Copyright (C) 1986-2019 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 #include "defs.h"
21 #include "gdbthread.h"
22 #include "inferior.h"
23 #include "continuations.h"
24
25 struct continuation
26 {
27   struct continuation *next;
28   continuation_ftype *function;
29   continuation_free_arg_ftype *free_arg;
30   void *arg;
31 };
32
33 /* Add a new continuation to the continuation chain.  Args are
34    FUNCTION to run the continuation up with, and ARG to pass to
35    it.  */
36
37 static void
38 make_continuation (struct continuation **pmy_chain,
39                    continuation_ftype *function,
40                    void *arg,  void (*free_arg) (void *))
41 {
42   struct continuation *newobj = XNEW (struct continuation);
43
44   newobj->next = *pmy_chain;
45   newobj->function = function;
46   newobj->free_arg = free_arg;
47   newobj->arg = arg;
48   *pmy_chain = newobj;
49 }
50
51 static void
52 do_my_continuations_1 (struct continuation **pmy_chain, int err)
53 {
54   struct continuation *ptr;
55
56   while ((ptr = *pmy_chain) != NULL)
57     {
58       *pmy_chain = ptr->next;   /* Do this first in case of recursion.  */
59       (*ptr->function) (ptr->arg, err);
60       if (ptr->free_arg)
61         (*ptr->free_arg) (ptr->arg);
62       xfree (ptr);
63     }
64 }
65
66 static void
67 do_my_continuations (struct continuation **list, int err)
68 {
69   struct continuation *continuations;
70
71   if (*list == NULL)
72     return;
73
74   /* Copy the list header into another pointer, and set the global
75      list header to null, so that the global list can change as a side
76      effect of invoking the continuations and the processing of the
77      preexisting continuations will not be affected.  */
78
79   continuations = *list;
80   *list = NULL;
81
82   /* Work now on the list we have set aside.  */
83   do_my_continuations_1 (&continuations, err);
84 }
85
86 static void
87 discard_my_continuations_1 (struct continuation **pmy_chain)
88 {
89   struct continuation *ptr;
90
91   while ((ptr = *pmy_chain) != NULL)
92     {
93       *pmy_chain = ptr->next;
94       if (ptr->free_arg)
95         (*ptr->free_arg) (ptr->arg);
96       xfree (ptr);
97     }
98 }
99
100 static void
101 discard_my_continuations (struct continuation **list)
102 {
103   discard_my_continuations_1 (list);
104   *list = NULL;
105 }
106
107 /* Add a continuation to the continuation list of INFERIOR.  The new
108    continuation will be added at the front.  */
109
110 void
111 add_inferior_continuation (continuation_ftype *hook, void *args,
112                            continuation_free_arg_ftype *free_arg)
113 {
114   struct inferior *inf = current_inferior ();
115
116   make_continuation (&inf->continuations, hook, args, free_arg);
117 }
118
119 /* Do all continuations of the current inferior.  */
120
121 void
122 do_all_inferior_continuations (int err)
123 {
124   struct inferior *inf = current_inferior ();
125   do_my_continuations (&inf->continuations, err);
126 }
127
128 /* Get rid of all the inferior-wide continuations of INF.  */
129
130 void
131 discard_all_inferior_continuations (struct inferior *inf)
132 {
133   discard_my_continuations (&inf->continuations);
134 }