1*ef5ccd6cSJohn Marino /* General queue data structure for GDB, the GNU debugger. 2*ef5ccd6cSJohn Marino 3*ef5ccd6cSJohn Marino Copyright (C) 2012-2013 Free Software Foundation, Inc. 4*ef5ccd6cSJohn Marino 5*ef5ccd6cSJohn Marino This file is part of GDB. 6*ef5ccd6cSJohn Marino 7*ef5ccd6cSJohn Marino This program is free software; you can redistribute it and/or modify 8*ef5ccd6cSJohn Marino it under the terms of the GNU General Public License as published by 9*ef5ccd6cSJohn Marino the Free Software Foundation; either version 3 of the License, or 10*ef5ccd6cSJohn Marino (at your option) any later version. 11*ef5ccd6cSJohn Marino 12*ef5ccd6cSJohn Marino This program is distributed in the hope that it will be useful, 13*ef5ccd6cSJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of 14*ef5ccd6cSJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*ef5ccd6cSJohn Marino GNU General Public License for more details. 16*ef5ccd6cSJohn Marino 17*ef5ccd6cSJohn Marino You should have received a copy of the GNU General Public License 18*ef5ccd6cSJohn Marino along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19*ef5ccd6cSJohn Marino 20*ef5ccd6cSJohn Marino #ifndef QUEUE_H 21*ef5ccd6cSJohn Marino #define QUEUE_H 22*ef5ccd6cSJohn Marino 23*ef5ccd6cSJohn Marino #include "libiberty.h" /* xmalloc */ 24*ef5ccd6cSJohn Marino #include "gdb_assert.h" 25*ef5ccd6cSJohn Marino 26*ef5ccd6cSJohn Marino /* These macros implement functions and structs for a general queue. 27*ef5ccd6cSJohn Marino Macro 'DEFINE_QUEUE_P(TYPEDEF)' is to define the new queue type for 28*ef5ccd6cSJohn Marino TYPEDEF', and macro 'DECLARE_QUEUE_P' is to declare external queue 29*ef5ccd6cSJohn Marino APIs. The character P indicates TYPEDEF is a pointer (P). The 30*ef5ccd6cSJohn Marino counterpart on object (O) and integer (I) are not implemented. 31*ef5ccd6cSJohn Marino 32*ef5ccd6cSJohn Marino An example of their use would be, 33*ef5ccd6cSJohn Marino 34*ef5ccd6cSJohn Marino typedef struct foo 35*ef5ccd6cSJohn Marino {} *foo_p; 36*ef5ccd6cSJohn Marino 37*ef5ccd6cSJohn Marino DEFINE_QUEUE_P (foo_p); 38*ef5ccd6cSJohn Marino // A pointer to a queue of foo pointers. FOO_XFREE is a destructor 39*ef5ccd6cSJohn Marino // function for foo instances in queue. 40*ef5ccd6cSJohn Marino QUEUE(foo_p) *foo_queue = QUEUE_alloc (foo_p, foo_xfree); 41*ef5ccd6cSJohn Marino 42*ef5ccd6cSJohn Marino foo_p foo_var_p; 43*ef5ccd6cSJohn Marino // Enqueue and Dequeue 44*ef5ccd6cSJohn Marino QUEUE_enque (foo_p, foo_queue, foo_var_p); 45*ef5ccd6cSJohn Marino foo_var_p = QUEUE_deque (foo_p, foo_queue); 46*ef5ccd6cSJohn Marino 47*ef5ccd6cSJohn Marino static int visit_foo (QUEUE (foo_p) *q, QUEUE_ITER (foo_p) *iter, 48*ef5ccd6cSJohn Marino foo_p f, void *data) 49*ef5ccd6cSJohn Marino { 50*ef5ccd6cSJohn Marino return 1; 51*ef5ccd6cSJohn Marino } 52*ef5ccd6cSJohn Marino // Iterate over queue. 53*ef5ccd6cSJohn Marino QUEUE_iterate (foo_p, foo_queue, visit_foo, ¶m); 54*ef5ccd6cSJohn Marino 55*ef5ccd6cSJohn Marino QUEUE_free (foo_p, foo_queue); // Free queue. */ 56*ef5ccd6cSJohn Marino 57*ef5ccd6cSJohn Marino /* Typical enqueue operation. Put V into queue Q. */ 58*ef5ccd6cSJohn Marino #define QUEUE_enque(TYPE, Q, V) queue_ ## TYPE ## _enque ((Q), (V)) 59*ef5ccd6cSJohn Marino 60*ef5ccd6cSJohn Marino /* Typical dequeue operation. Return head element of queue Q and 61*ef5ccd6cSJohn Marino remove it. Q must not be empty. */ 62*ef5ccd6cSJohn Marino #define QUEUE_deque(TYPE, Q) queue_ ## TYPE ## _deque (Q) 63*ef5ccd6cSJohn Marino 64*ef5ccd6cSJohn Marino /* Return the head element, but don't remove it from the queue. 65*ef5ccd6cSJohn Marino Q must not be empty. */ 66*ef5ccd6cSJohn Marino #define QUEUE_peek(TYPE, Q) queue_ ## TYPE ## _peek (Q) 67*ef5ccd6cSJohn Marino 68*ef5ccd6cSJohn Marino /* Return true if queue Q is empty. */ 69*ef5ccd6cSJohn Marino #define QUEUE_is_empty(TYPE, Q) queue_ ## TYPE ## _is_empty (Q) 70*ef5ccd6cSJohn Marino 71*ef5ccd6cSJohn Marino /* Allocate memory for queue. FREE_FUNC is a function to release the 72*ef5ccd6cSJohn Marino data put in each queue element. */ 73*ef5ccd6cSJohn Marino #define QUEUE_alloc(TYPE, FREE_FUNC) queue_ ## TYPE ## _alloc (FREE_FUNC) 74*ef5ccd6cSJohn Marino 75*ef5ccd6cSJohn Marino /* Length of queue Q. */ 76*ef5ccd6cSJohn Marino #define QUEUE_length(TYPE, Q) queue_ ## TYPE ## _length (Q) 77*ef5ccd6cSJohn Marino 78*ef5ccd6cSJohn Marino /* Free queue Q. Q's free_func is called once for each element. */ 79*ef5ccd6cSJohn Marino #define QUEUE_free(TYPE, Q) queue_ ## TYPE ## _free (Q) 80*ef5ccd6cSJohn Marino 81*ef5ccd6cSJohn Marino /* Iterate over elements in the queue Q and call function OPERATE on 82*ef5ccd6cSJohn Marino each element. It is allowed to remove element by OPERATE. OPERATE 83*ef5ccd6cSJohn Marino returns false to terminate the iteration and true to continue the 84*ef5ccd6cSJohn Marino iteration. Return false if iteration is terminated by function 85*ef5ccd6cSJohn Marino OPERATE, otherwise return true. */ 86*ef5ccd6cSJohn Marino #define QUEUE_iterate(TYPE, Q, OPERATE, PARAM) \ 87*ef5ccd6cSJohn Marino queue_ ## TYPE ## _iterate ((Q), (OPERATE), (PARAM)) 88*ef5ccd6cSJohn Marino 89*ef5ccd6cSJohn Marino /* Remove the element per the state of iterator ITER from queue Q. 90*ef5ccd6cSJohn Marino Leave the caller to release the data in the queue element. */ 91*ef5ccd6cSJohn Marino #define QUEUE_remove_elem(TYPE, Q, ITER) \ 92*ef5ccd6cSJohn Marino queue_ ## TYPE ## _remove_elem ((Q), (ITER)) 93*ef5ccd6cSJohn Marino 94*ef5ccd6cSJohn Marino /* Define a new queue implementation. */ 95*ef5ccd6cSJohn Marino 96*ef5ccd6cSJohn Marino #define QUEUE(TYPE) struct queue_ ## TYPE 97*ef5ccd6cSJohn Marino #define QUEUE_ELEM(TYPE) struct queue_elem_ ## TYPE 98*ef5ccd6cSJohn Marino #define QUEUE_ITER(TYPE) struct queue_iter_ ## TYPE 99*ef5ccd6cSJohn Marino #define QUEUE_ITER_FUNC(TYPE) queue_ ## TYPE ## _operate_func 100*ef5ccd6cSJohn Marino 101*ef5ccd6cSJohn Marino #define DEFINE_QUEUE_P(TYPE) \ 102*ef5ccd6cSJohn Marino QUEUE_ELEM (TYPE) \ 103*ef5ccd6cSJohn Marino { \ 104*ef5ccd6cSJohn Marino QUEUE_ELEM (TYPE) *next; \ 105*ef5ccd6cSJohn Marino \ 106*ef5ccd6cSJohn Marino TYPE data; \ 107*ef5ccd6cSJohn Marino }; \ 108*ef5ccd6cSJohn Marino \ 109*ef5ccd6cSJohn Marino /* Queue iterator. */ \ 110*ef5ccd6cSJohn Marino QUEUE_ITER (TYPE) \ 111*ef5ccd6cSJohn Marino { \ 112*ef5ccd6cSJohn Marino /* The current element during traverse. */ \ 113*ef5ccd6cSJohn Marino QUEUE_ELEM (TYPE) *p; \ 114*ef5ccd6cSJohn Marino /* The previous element of P. */ \ 115*ef5ccd6cSJohn Marino QUEUE_ELEM (TYPE) *prev; \ 116*ef5ccd6cSJohn Marino }; \ 117*ef5ccd6cSJohn Marino \ 118*ef5ccd6cSJohn Marino QUEUE(TYPE) \ 119*ef5ccd6cSJohn Marino { \ 120*ef5ccd6cSJohn Marino /* The head and tail of the queue. */ \ 121*ef5ccd6cSJohn Marino QUEUE_ELEM (TYPE) *head; \ 122*ef5ccd6cSJohn Marino QUEUE_ELEM (TYPE) *tail; \ 123*ef5ccd6cSJohn Marino /* Function to release the data put in each \ 124*ef5ccd6cSJohn Marino queue element. */ \ 125*ef5ccd6cSJohn Marino void (*free_func) (TYPE); \ 126*ef5ccd6cSJohn Marino }; \ 127*ef5ccd6cSJohn Marino \ 128*ef5ccd6cSJohn Marino void \ 129*ef5ccd6cSJohn Marino queue_ ## TYPE ## _enque (QUEUE (TYPE) *q, TYPE v) \ 130*ef5ccd6cSJohn Marino { \ 131*ef5ccd6cSJohn Marino QUEUE_ELEM (TYPE) *p \ 132*ef5ccd6cSJohn Marino = xmalloc (sizeof (QUEUE_ELEM (TYPE))); \ 133*ef5ccd6cSJohn Marino \ 134*ef5ccd6cSJohn Marino gdb_assert (q != NULL); \ 135*ef5ccd6cSJohn Marino p->data = v; \ 136*ef5ccd6cSJohn Marino p->next = NULL; \ 137*ef5ccd6cSJohn Marino if (q->tail == NULL) \ 138*ef5ccd6cSJohn Marino { \ 139*ef5ccd6cSJohn Marino q->tail = p; \ 140*ef5ccd6cSJohn Marino q->head = p; \ 141*ef5ccd6cSJohn Marino } \ 142*ef5ccd6cSJohn Marino else \ 143*ef5ccd6cSJohn Marino { \ 144*ef5ccd6cSJohn Marino q->tail->next = p; \ 145*ef5ccd6cSJohn Marino q->tail = p; \ 146*ef5ccd6cSJohn Marino } \ 147*ef5ccd6cSJohn Marino } \ 148*ef5ccd6cSJohn Marino \ 149*ef5ccd6cSJohn Marino TYPE \ 150*ef5ccd6cSJohn Marino queue_ ## TYPE ## _deque (QUEUE (TYPE) *q) \ 151*ef5ccd6cSJohn Marino { \ 152*ef5ccd6cSJohn Marino QUEUE_ELEM (TYPE) *p; \ 153*ef5ccd6cSJohn Marino TYPE v; \ 154*ef5ccd6cSJohn Marino \ 155*ef5ccd6cSJohn Marino gdb_assert (q != NULL); \ 156*ef5ccd6cSJohn Marino p = q->head; \ 157*ef5ccd6cSJohn Marino gdb_assert (p != NULL); \ 158*ef5ccd6cSJohn Marino \ 159*ef5ccd6cSJohn Marino if (q->head == q->tail) \ 160*ef5ccd6cSJohn Marino { \ 161*ef5ccd6cSJohn Marino q->head = NULL; \ 162*ef5ccd6cSJohn Marino q->tail = NULL; \ 163*ef5ccd6cSJohn Marino } \ 164*ef5ccd6cSJohn Marino else \ 165*ef5ccd6cSJohn Marino q->head = q->head->next; \ 166*ef5ccd6cSJohn Marino \ 167*ef5ccd6cSJohn Marino v = p->data; \ 168*ef5ccd6cSJohn Marino \ 169*ef5ccd6cSJohn Marino xfree (p); \ 170*ef5ccd6cSJohn Marino return v; \ 171*ef5ccd6cSJohn Marino } \ 172*ef5ccd6cSJohn Marino \ 173*ef5ccd6cSJohn Marino TYPE \ 174*ef5ccd6cSJohn Marino queue_ ## TYPE ## _peek (QUEUE (TYPE) *q) \ 175*ef5ccd6cSJohn Marino { \ 176*ef5ccd6cSJohn Marino gdb_assert (q != NULL); \ 177*ef5ccd6cSJohn Marino gdb_assert (q->head != NULL); \ 178*ef5ccd6cSJohn Marino return q->head->data; \ 179*ef5ccd6cSJohn Marino } \ 180*ef5ccd6cSJohn Marino \ 181*ef5ccd6cSJohn Marino int \ 182*ef5ccd6cSJohn Marino queue_ ## TYPE ## _is_empty (QUEUE (TYPE) *q) \ 183*ef5ccd6cSJohn Marino { \ 184*ef5ccd6cSJohn Marino gdb_assert (q != NULL); \ 185*ef5ccd6cSJohn Marino return q->head == NULL; \ 186*ef5ccd6cSJohn Marino } \ 187*ef5ccd6cSJohn Marino \ 188*ef5ccd6cSJohn Marino void \ 189*ef5ccd6cSJohn Marino queue_ ## TYPE ## _remove_elem (QUEUE (TYPE) *q, \ 190*ef5ccd6cSJohn Marino QUEUE_ITER (TYPE) *iter) \ 191*ef5ccd6cSJohn Marino { \ 192*ef5ccd6cSJohn Marino gdb_assert (q != NULL); \ 193*ef5ccd6cSJohn Marino gdb_assert (iter != NULL && iter->p != NULL); \ 194*ef5ccd6cSJohn Marino \ 195*ef5ccd6cSJohn Marino if (iter->p == q->head || iter->p == q->tail) \ 196*ef5ccd6cSJohn Marino { \ 197*ef5ccd6cSJohn Marino if (iter->p == q->head) \ 198*ef5ccd6cSJohn Marino q->head = iter->p->next; \ 199*ef5ccd6cSJohn Marino if (iter->p == q->tail) \ 200*ef5ccd6cSJohn Marino q->tail = iter->prev; \ 201*ef5ccd6cSJohn Marino } \ 202*ef5ccd6cSJohn Marino else \ 203*ef5ccd6cSJohn Marino iter->prev->next = iter->p->next; \ 204*ef5ccd6cSJohn Marino \ 205*ef5ccd6cSJohn Marino xfree (iter->p); \ 206*ef5ccd6cSJohn Marino /* Indicate that ITER->p has been deleted from QUEUE q. */ \ 207*ef5ccd6cSJohn Marino iter->p = NULL; \ 208*ef5ccd6cSJohn Marino } \ 209*ef5ccd6cSJohn Marino \ 210*ef5ccd6cSJohn Marino int \ 211*ef5ccd6cSJohn Marino queue_ ## TYPE ## _iterate (QUEUE (TYPE) *q, \ 212*ef5ccd6cSJohn Marino QUEUE_ITER_FUNC (TYPE) operate, \ 213*ef5ccd6cSJohn Marino void *data) \ 214*ef5ccd6cSJohn Marino { \ 215*ef5ccd6cSJohn Marino QUEUE_ELEM (TYPE) *next = NULL; \ 216*ef5ccd6cSJohn Marino QUEUE_ITER (TYPE) iter = { NULL, NULL }; \ 217*ef5ccd6cSJohn Marino \ 218*ef5ccd6cSJohn Marino gdb_assert (q != NULL); \ 219*ef5ccd6cSJohn Marino \ 220*ef5ccd6cSJohn Marino for (iter.p = q->head; iter.p != NULL; iter.p = next) \ 221*ef5ccd6cSJohn Marino { \ 222*ef5ccd6cSJohn Marino next = iter.p->next; \ 223*ef5ccd6cSJohn Marino if (!operate (q, &iter, iter.p->data, data)) \ 224*ef5ccd6cSJohn Marino return 0; \ 225*ef5ccd6cSJohn Marino /* ITER.P was not deleted by function OPERATE. */ \ 226*ef5ccd6cSJohn Marino if (iter.p != NULL) \ 227*ef5ccd6cSJohn Marino iter.prev = iter.p; \ 228*ef5ccd6cSJohn Marino } \ 229*ef5ccd6cSJohn Marino return 1; \ 230*ef5ccd6cSJohn Marino } \ 231*ef5ccd6cSJohn Marino \ 232*ef5ccd6cSJohn Marino QUEUE (TYPE) * \ 233*ef5ccd6cSJohn Marino queue_ ## TYPE ## _alloc (void (*free_func) (TYPE)) \ 234*ef5ccd6cSJohn Marino { \ 235*ef5ccd6cSJohn Marino QUEUE (TYPE) *q; \ 236*ef5ccd6cSJohn Marino \ 237*ef5ccd6cSJohn Marino q = (QUEUE (TYPE) *) xmalloc (sizeof (QUEUE (TYPE))); \ 238*ef5ccd6cSJohn Marino q->head = NULL; \ 239*ef5ccd6cSJohn Marino q->tail = NULL; \ 240*ef5ccd6cSJohn Marino q->free_func = free_func; \ 241*ef5ccd6cSJohn Marino return q; \ 242*ef5ccd6cSJohn Marino } \ 243*ef5ccd6cSJohn Marino \ 244*ef5ccd6cSJohn Marino int \ 245*ef5ccd6cSJohn Marino queue_ ## TYPE ## _length (QUEUE (TYPE) *q) \ 246*ef5ccd6cSJohn Marino { \ 247*ef5ccd6cSJohn Marino QUEUE_ELEM (TYPE) *p; \ 248*ef5ccd6cSJohn Marino int len = 0; \ 249*ef5ccd6cSJohn Marino \ 250*ef5ccd6cSJohn Marino gdb_assert (q != NULL); \ 251*ef5ccd6cSJohn Marino \ 252*ef5ccd6cSJohn Marino for (p = q->head; p != NULL; p = p->next) \ 253*ef5ccd6cSJohn Marino len++; \ 254*ef5ccd6cSJohn Marino \ 255*ef5ccd6cSJohn Marino return len; \ 256*ef5ccd6cSJohn Marino } \ 257*ef5ccd6cSJohn Marino \ 258*ef5ccd6cSJohn Marino void \ 259*ef5ccd6cSJohn Marino queue_ ## TYPE ## _free (QUEUE (TYPE) *q) \ 260*ef5ccd6cSJohn Marino { \ 261*ef5ccd6cSJohn Marino QUEUE_ELEM (TYPE) *p, *next; \ 262*ef5ccd6cSJohn Marino \ 263*ef5ccd6cSJohn Marino gdb_assert (q != NULL); \ 264*ef5ccd6cSJohn Marino \ 265*ef5ccd6cSJohn Marino for (p = q->head; p != NULL; p = next) \ 266*ef5ccd6cSJohn Marino { \ 267*ef5ccd6cSJohn Marino next = p->next; \ 268*ef5ccd6cSJohn Marino if (q->free_func) \ 269*ef5ccd6cSJohn Marino q->free_func (p->data); \ 270*ef5ccd6cSJohn Marino xfree (p); \ 271*ef5ccd6cSJohn Marino } \ 272*ef5ccd6cSJohn Marino xfree (q); \ 273*ef5ccd6cSJohn Marino } \ 274*ef5ccd6cSJohn Marino 275*ef5ccd6cSJohn Marino /* External declarations for queue functions. */ 276*ef5ccd6cSJohn Marino #define DECLARE_QUEUE_P(TYPE) \ 277*ef5ccd6cSJohn Marino QUEUE (TYPE); \ 278*ef5ccd6cSJohn Marino QUEUE_ELEM (TYPE); \ 279*ef5ccd6cSJohn Marino QUEUE_ITER (TYPE); \ 280*ef5ccd6cSJohn Marino extern void \ 281*ef5ccd6cSJohn Marino queue_ ## TYPE ## _enque (QUEUE (TYPE) *q, TYPE v); \ 282*ef5ccd6cSJohn Marino extern TYPE \ 283*ef5ccd6cSJohn Marino queue_ ## TYPE ## _deque (QUEUE (TYPE) *q); \ 284*ef5ccd6cSJohn Marino extern int queue_ ## TYPE ## _is_empty (QUEUE (TYPE) *q); \ 285*ef5ccd6cSJohn Marino extern QUEUE (TYPE) * \ 286*ef5ccd6cSJohn Marino queue_ ## TYPE ## _alloc (void (*free_func) (TYPE)); \ 287*ef5ccd6cSJohn Marino extern int queue_ ## TYPE ## _length (QUEUE (TYPE) *q); \ 288*ef5ccd6cSJohn Marino extern TYPE \ 289*ef5ccd6cSJohn Marino queue_ ## TYPE ## _peek (QUEUE (TYPE) *q); \ 290*ef5ccd6cSJohn Marino extern void queue_ ## TYPE ## _free (QUEUE (TYPE) *q); \ 291*ef5ccd6cSJohn Marino typedef int QUEUE_ITER_FUNC(TYPE) (QUEUE (TYPE) *, \ 292*ef5ccd6cSJohn Marino QUEUE_ITER (TYPE) *, \ 293*ef5ccd6cSJohn Marino TYPE, \ 294*ef5ccd6cSJohn Marino void *); \ 295*ef5ccd6cSJohn Marino extern int \ 296*ef5ccd6cSJohn Marino queue_ ## TYPE ## _iterate (QUEUE (TYPE) *q, \ 297*ef5ccd6cSJohn Marino QUEUE_ITER_FUNC (TYPE) operate, \ 298*ef5ccd6cSJohn Marino void *); \ 299*ef5ccd6cSJohn Marino extern void \ 300*ef5ccd6cSJohn Marino queue_ ## TYPE ## _remove_elem (QUEUE (TYPE) *q, \ 301*ef5ccd6cSJohn Marino QUEUE_ITER (TYPE) *iter); \ 302*ef5ccd6cSJohn Marino 303*ef5ccd6cSJohn Marino #endif /* QUEUE_H */ 304