1 /*
2   tre-stack.c - Simple stack implementation
3 
4   Copyright (c) 2001-2006 Ville Laurikari <vl@iki.fi>
5 
6   This library is free software; you can redistribute it and/or
7   modify it under the terms of the GNU Lesser General Public
8   License as published by the Free Software Foundation; either
9   version 2.1 of the License, or (at your option) any later version.
10 
11   This library is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   Lesser General Public License for more details.
15 
16   You should have received a copy of the GNU Lesser General Public
17   License along with this library; if not, write to the Free Software
18   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19 
20 */
21 
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif /* HAVE_CONFIG_H */
25 #include <stdlib.h>
26 #include <assert.h>
27 
28 #include "tre-internal.h"
29 #include "tre-stack.h"
30 #include "xmalloc.h"
31 
32 union tre_stack_item {
33   void *voidptr_value;
34   int int_value;
35 };
36 
37 struct tre_stack_rec {
38   int size;
39   int max_size;
40   int increment;
41   int ptr;
42   union tre_stack_item *stack;
43 };
44 
45 
46 tre_stack_t *
tre_stack_new(int size,int max_size,int increment)47 tre_stack_new(int size, int max_size, int increment)
48 {
49   tre_stack_t *s;
50 
51   s = xmalloc(sizeof(*s));
52   if (s != NULL)
53     {
54       s->stack = xmalloc(sizeof(*s->stack) * size);
55       if (s->stack == NULL)
56 	{
57 	  xfree(s);
58 	  return NULL;
59 	}
60       s->size = size;
61       s->max_size = max_size;
62       s->increment = increment;
63       s->ptr = 0;
64     }
65   return s;
66 }
67 
68 void
tre_stack_destroy(tre_stack_t * s)69 tre_stack_destroy(tre_stack_t *s)
70 {
71   xfree(s->stack);
72   xfree(s);
73 }
74 
75 int
tre_stack_num_objects(tre_stack_t * s)76 tre_stack_num_objects(tre_stack_t *s)
77 {
78   return s->ptr;
79 }
80 
81 static reg_errcode_t
tre_stack_push(tre_stack_t * s,union tre_stack_item value)82 tre_stack_push(tre_stack_t *s, union tre_stack_item value)
83 {
84   if (s->ptr < s->size)
85     {
86       s->stack[s->ptr] = value;
87       s->ptr++;
88     }
89   else
90     {
91       if (s->size >= s->max_size)
92 	{
93 	  DPRINT(("tre_stack_push: stack full\n"));
94 	  return REG_ESPACE;
95 	}
96       else
97 	{
98 	  union tre_stack_item *new_buffer;
99 	  int new_size;
100 	  DPRINT(("tre_stack_push: trying to realloc more space\n"));
101 	  new_size = s->size + s->increment;
102 	  if (new_size > s->max_size)
103 	    new_size = s->max_size;
104 	  new_buffer = xrealloc(s->stack, sizeof(*new_buffer) * new_size);
105 	  if (new_buffer == NULL)
106 	    {
107 	      DPRINT(("tre_stack_push: realloc failed.\n"));
108 	      return REG_ESPACE;
109 	    }
110 	  DPRINT(("tre_stack_push: realloc succeeded.\n"));
111 	  assert(new_size > s->size);
112 	  s->size = new_size;
113 	  s->stack = new_buffer;
114 	  tre_stack_push(s, value);
115 	}
116     }
117   return REG_OK;
118 }
119 
120 #define define_pushf(typetag, type)  \
121   declare_pushf(typetag, type) {     \
122     union tre_stack_item item;	     \
123     item.typetag ## _value = value;  \
124     return tre_stack_push(s, item);  \
125 }
126 
127 define_pushf(int, int)
128 define_pushf(voidptr, void *)
129 
130 #define define_popf(typetag, type)		    \
131   declare_popf(typetag, type) {			    \
132     return s->stack[--s->ptr].typetag ## _value;    \
133   }
134 
135 define_popf(int, int)
136 define_popf(voidptr, void *)
137 
138 /* EOF */
139