1 /* 2 tre-stack.c - Simple stack implementation 3 4 This software is released under a BSD-style license. 5 See the file LICENSE for details and copyright. 6 7 */ 8 9 #ifdef HAVE_CONFIG_H 10 #include <config.h> 11 #endif /* HAVE_CONFIG_H */ 12 #include <stdlib.h> 13 #include <assert.h> 14 15 #include "tre-internal.h" 16 #include "tre-stack.h" 17 #include "xmalloc.h" 18 19 union tre_stack_item { 20 void *voidptr_value; 21 int int_value; 22 }; 23 24 struct tre_stack_rec { 25 int size; 26 int max_size; 27 int increment; 28 int ptr; 29 union tre_stack_item *stack; 30 }; 31 32 33 tre_stack_t * 34 tre_stack_new(int size, int max_size, int increment) 35 { 36 tre_stack_t *s; 37 38 s = xmalloc(sizeof(*s)); 39 if (s != NULL) 40 { 41 s->stack = xmalloc(sizeof(*s->stack) * size); 42 if (s->stack == NULL) 43 { 44 xfree(s); 45 return NULL; 46 } 47 s->size = size; 48 s->max_size = max_size; 49 s->increment = increment; 50 s->ptr = 0; 51 } 52 return s; 53 } 54 55 void 56 tre_stack_destroy(tre_stack_t *s) 57 { 58 xfree(s->stack); 59 xfree(s); 60 } 61 62 int 63 tre_stack_num_objects(tre_stack_t *s) 64 { 65 return s->ptr; 66 } 67 68 static reg_errcode_t 69 tre_stack_push(tre_stack_t *s, union tre_stack_item value) 70 { 71 if (s->ptr < s->size) 72 { 73 s->stack[s->ptr] = value; 74 s->ptr++; 75 } 76 else 77 { 78 if (s->size >= s->max_size) 79 { 80 DPRINT(("tre_stack_push: stack full\n")); 81 return REG_ESPACE; 82 } 83 else 84 { 85 union tre_stack_item *new_buffer; 86 int new_size; 87 DPRINT(("tre_stack_push: trying to realloc more space\n")); 88 new_size = s->size + s->increment; 89 if (new_size > s->max_size) 90 new_size = s->max_size; 91 new_buffer = xrealloc(s->stack, sizeof(*new_buffer) * new_size); 92 if (new_buffer == NULL) 93 { 94 DPRINT(("tre_stack_push: realloc failed.\n")); 95 return REG_ESPACE; 96 } 97 DPRINT(("tre_stack_push: realloc succeeded.\n")); 98 assert(new_size > s->size); 99 s->size = new_size; 100 s->stack = new_buffer; 101 tre_stack_push(s, value); 102 } 103 } 104 return REG_OK; 105 } 106 107 #define define_pushf(typetag, type) \ 108 declare_pushf(typetag, type) { \ 109 union tre_stack_item item; \ 110 item.typetag ## _value = value; \ 111 return tre_stack_push(s, item); \ 112 } 113 114 define_pushf(int, int) 115 define_pushf(voidptr, void *) 116 117 #define define_popf(typetag, type) \ 118 declare_popf(typetag, type) { \ 119 return s->stack[--s->ptr].typetag ## _value; \ 120 } 121 122 define_popf(int, int) 123 define_popf(voidptr, void *) 124 125 /* EOF */ 126