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 19union tre_stack_item { 20 void *voidptr_value; 21 int int_value; 22}; 23 24struct 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 33tre_stack_t * 34tre_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 55void 56tre_stack_destroy(tre_stack_t *s) 57{ 58 xfree(s->stack); 59 xfree(s); 60} 61 62int 63tre_stack_num_objects(tre_stack_t *s) 64{ 65 return s->ptr; 66} 67 68static reg_errcode_t 69tre_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 114define_pushf(int, int) 115define_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 122define_popf(int, int) 123define_popf(voidptr, void *) 124 125/* EOF */ 126