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 *)