1 /* 2 * Copyright (c) 2001-2009 Ville Laurikari <vl@iki.fi> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 tre-stack.c - Simple stack implementation 31 */ 32 33 #include <stdlib.h> 34 #include <assert.h> 35 36 #include "tre-internal.h" 37 #include "tre-stack.h" 38 39 union tre_stack_item { 40 void *voidptr_value; 41 int int_value; 42 }; 43 44 struct tre_stack_rec { 45 int size; 46 int max_size; 47 int increment; 48 int ptr; 49 union tre_stack_item *stack; 50 }; 51 52 tre_stack_t * 53 tre_stack_new(int size, int max_size, int increment) 54 { 55 tre_stack_t *s; 56 57 s = malloc(sizeof(*s)); 58 if (s != NULL) 59 { 60 s->stack = malloc(sizeof(*s->stack) * size); 61 if (s->stack == NULL) 62 { 63 free(s); 64 return NULL; 65 } 66 s->size = size; 67 s->max_size = max_size; 68 s->increment = increment; 69 s->ptr = 0; 70 } 71 return s; 72 } 73 74 void 75 tre_stack_destroy(tre_stack_t *s) 76 { 77 free(s->stack); 78 free(s); 79 } 80 81 int 82 tre_stack_num_objects(tre_stack_t *s) 83 { 84 return s->ptr; 85 } 86 87 static reg_errcode_t 88 tre_stack_push(tre_stack_t *s, union tre_stack_item value) 89 { 90 if (s->ptr < s->size) 91 { 92 s->stack[s->ptr] = value; 93 s->ptr++; 94 } 95 else 96 { 97 if (s->size >= s->max_size) 98 { 99 DPRINT(("tre_stack_push: stack full\n")); 100 return REG_ESPACE; 101 } 102 else 103 { 104 union tre_stack_item *new_buffer; 105 int new_size; 106 DPRINT(("tre_stack_push: trying to realloc more space\n")); 107 new_size = s->size + s->increment; 108 if (new_size > s->max_size) 109 new_size = s->max_size; 110 new_buffer = realloc(s->stack, sizeof(*new_buffer) * new_size); 111 if (new_buffer == NULL) 112 { 113 DPRINT(("tre_stack_push: realloc failed.\n")); 114 return REG_ESPACE; 115 } 116 DPRINT(("tre_stack_push: realloc succeeded.\n")); 117 assert(new_size > s->size); 118 s->size = new_size; 119 s->stack = new_buffer; 120 tre_stack_push(s, value); 121 } 122 } 123 return REG_OK; 124 } 125 126 #define define_pushf(typetag, type) \ 127 declare_pushf(typetag, type) { \ 128 union tre_stack_item item; \ 129 item.typetag ## _value = value; \ 130 return tre_stack_push(s, item); \ 131 } 132 133 define_pushf(int, int) 134 define_pushf(voidptr, void *) 135 136 #define define_popf(typetag, type) \ 137 declare_popf(typetag, type) { \ 138 return s->stack[--s->ptr].typetag ## _value; \ 139 } 140 141 define_popf(int, int) 142 define_popf(voidptr, void *)