Back to index

glibc  2.9
Classes | Defines | Enumerations | Functions | Variables
obstack.c File Reference
#include "obstack.h"
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include "exitfail.h"
#include "gettext.h"

Go to the source code of this file.

Classes

union  fooround
struct  fooalign

Defines

#define OBSTACK_INTERFACE_VERSION   1
#define COPYING_UNIT   int
#define obstack_exit_failure   exit_failure
#define CALL_CHUNKFUN(h, size)
#define CALL_FREEFUN(h, old_chunk)
#define _(msgid)   gettext (msgid)
#define __attribute__(Spec)   /* empty */

Enumerations

enum  { DEFAULT_ALIGNMENT = offsetof (struct fooalign, u), DEFAULT_ROUNDING = sizeof (union fooround) }

Functions

static void print_and_abort (void)
int _obstack_begin (struct obstack *h, int size, int alignment, void *(*chunkfun)(long), void(*freefun)(void *))
int _obstack_begin_1 (struct obstack *h, int size, int alignment, void *(*chunkfun)(void *, long), void(*freefun)(void *, void *), void *arg)
void _obstack_newchunk (struct obstack *h, int length)
int _obstack_allocated_p (struct obstack *h, void *obj)
void obstack_free (struct obstack *h, void *obj)
int _obstack_memory_used (struct obstack *h)
static void __attribute__ ((noreturn))

Variables

void(* obstack_alloc_failed_handler )(void) = print_and_abort

Class Documentation

union fooround

Definition at line 68 of file obstack.c.

Class Members
long double d
uintmax_t i
void * p
struct fooalign

Definition at line 74 of file obstack.c.

Class Members
char c

Define Documentation

#define _ (   msgid)    gettext (msgid)

Definition at line 410 of file obstack.c.

#define __attribute__ (   Spec)    /* empty */

Definition at line 420 of file obstack.c.

#define CALL_CHUNKFUN (   h,
  size 
)
Value:
(((h) -> use_extra_arg) \
   ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
   : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))

Definition at line 131 of file obstack.c.

#define CALL_FREEFUN (   h,
  old_chunk 
)
Value:
do { \
    if ((h) -> use_extra_arg) \
      (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
    else \
      (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
  } while (0)

Definition at line 136 of file obstack.c.

#define COPYING_UNIT   int

Definition at line 93 of file obstack.c.

#define obstack_exit_failure   exit_failure

Definition at line 112 of file obstack.c.

#define OBSTACK_INTERFACE_VERSION   1

Definition at line 36 of file obstack.c.


Enumeration Type Documentation

anonymous enum
Enumerator:
DEFAULT_ALIGNMENT 
DEFAULT_ROUNDING 

Definition at line 82 of file obstack.c.

  {
    DEFAULT_ALIGNMENT = offsetof (struct fooalign, u),
    DEFAULT_ROUNDING = sizeof (union fooround)
  };

Function Documentation

static void __attribute__ ( (noreturn)  ) [static]

Definition at line 425 of file obstack.c.

{
  /* Don't change any of these strings.  Yes, it would be possible to add
     the newline to the string and use fputs or so.  But this must not
     happen because the "memory exhausted" message appears in other places
     like this and the translation should be reused instead of creating
     a very similar string which requires a separate translation.  */
# ifdef _LIBC
  (void) __fxprintf (NULL, "%s\n", _("memory exhausted"));
# else
  fprintf (stderr, "%s\n", _("memory exhausted"));
# endif
  exit (obstack_exit_failure);
}

Here is the call graph for this function:

int _obstack_allocated_p ( struct obstack h,
void *  obj 
)

Definition at line 332 of file obstack.c.

{
  register struct _obstack_chunk *lp;     /* below addr of any objects in this chunk */
  register struct _obstack_chunk *plp;    /* point to previous chunk if any */

  lp = (h)->chunk;
  /* We use >= rather than > since the object cannot be exactly at
     the beginning of the chunk but might be an empty object exactly
     at the end of an adjacent chunk.  */
  while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
    {
      plp = lp->prev;
      lp = plp;
    }
  return lp != 0;
}
int _obstack_begin ( struct obstack h,
int  size,
int  alignment,
void *(*)(long)  chunkfun,
void(*)(void *)  freefun 
)

Definition at line 154 of file obstack.c.

{
  register struct _obstack_chunk *chunk; /* points to new chunk */

  if (alignment == 0)
    alignment = DEFAULT_ALIGNMENT;
  if (size == 0)
    /* Default size is what GNU malloc can fit in a 4096-byte block.  */
    {
      /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
        Use the values for range checking, because if range checking is off,
        the extra bytes won't be missed terribly, but if range checking is on
        and we used a larger request, a whole extra 4096 bytes would be
        allocated.

        These number are irrelevant to the new GNU malloc.  I suspect it is
        less sensitive to the size of the request.  */
      int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
                  + 4 + DEFAULT_ROUNDING - 1)
                 & ~(DEFAULT_ROUNDING - 1));
      size = 4096 - extra;
    }

  h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
  h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
  h->chunk_size = size;
  h->alignment_mask = alignment - 1;
  h->use_extra_arg = 0;

  chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
  if (!chunk)
    (*obstack_alloc_failed_handler) ();
  h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
                                          alignment - 1);
  h->chunk_limit = chunk->limit
    = (char *) chunk + h->chunk_size;
  chunk->prev = 0;
  /* The initial chunk now contains no empty object.  */
  h->maybe_empty_object = 0;
  h->alloc_failed = 0;
  return 1;
}
int _obstack_begin_1 ( struct obstack h,
int  size,
int  alignment,
void *(*)(void *, long)  chunkfun,
void(*)(void *, void *)  freefun,
void *  arg 
)

Definition at line 201 of file obstack.c.

{
  register struct _obstack_chunk *chunk; /* points to new chunk */

  if (alignment == 0)
    alignment = DEFAULT_ALIGNMENT;
  if (size == 0)
    /* Default size is what GNU malloc can fit in a 4096-byte block.  */
    {
      /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
        Use the values for range checking, because if range checking is off,
        the extra bytes won't be missed terribly, but if range checking is on
        and we used a larger request, a whole extra 4096 bytes would be
        allocated.

        These number are irrelevant to the new GNU malloc.  I suspect it is
        less sensitive to the size of the request.  */
      int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
                  + 4 + DEFAULT_ROUNDING - 1)
                 & ~(DEFAULT_ROUNDING - 1));
      size = 4096 - extra;
    }

  h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
  h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
  h->chunk_size = size;
  h->alignment_mask = alignment - 1;
  h->extra_arg = arg;
  h->use_extra_arg = 1;

  chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
  if (!chunk)
    (*obstack_alloc_failed_handler) ();
  h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
                                          alignment - 1);
  h->chunk_limit = chunk->limit
    = (char *) chunk + h->chunk_size;
  chunk->prev = 0;
  /* The initial chunk now contains no empty object.  */
  h->maybe_empty_object = 0;
  h->alloc_failed = 0;
  return 1;
}
int _obstack_memory_used ( struct obstack h)

Definition at line 391 of file obstack.c.

{
  register struct _obstack_chunk* lp;
  register int nbytes = 0;

  for (lp = h->chunk; lp != 0; lp = lp->prev)
    {
      nbytes += lp->limit - (char *) lp;
    }
  return nbytes;
}
void _obstack_newchunk ( struct obstack h,
int  length 
)

Definition at line 255 of file obstack.c.

{
  register struct _obstack_chunk *old_chunk = h->chunk;
  register struct _obstack_chunk *new_chunk;
  register long      new_size;
  register long obj_size = h->next_free - h->object_base;
  register long i;
  long already;
  char *object_base;

  /* Compute size for new chunk.  */
  new_size = (obj_size + length) + (obj_size >> 3) + h->alignment_mask + 100;
  if (new_size < h->chunk_size)
    new_size = h->chunk_size;

  /* Allocate and initialize the new chunk.  */
  new_chunk = CALL_CHUNKFUN (h, new_size);
  if (!new_chunk)
    (*obstack_alloc_failed_handler) ();
  h->chunk = new_chunk;
  new_chunk->prev = old_chunk;
  new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;

  /* Compute an aligned object_base in the new chunk */
  object_base =
    __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask);

  /* Move the existing object to the new chunk.
     Word at a time is fast and is safe if the object
     is sufficiently aligned.  */
  if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
    {
      for (i = obj_size / sizeof (COPYING_UNIT) - 1;
          i >= 0; i--)
       ((COPYING_UNIT *)object_base)[i]
         = ((COPYING_UNIT *)h->object_base)[i];
      /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
        but that can cross a page boundary on a machine
        which does not do strict alignment for COPYING_UNITS.  */
      already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
    }
  else
    already = 0;
  /* Copy remaining bytes one by one.  */
  for (i = already; i < obj_size; i++)
    object_base[i] = h->object_base[i];

  /* If the object just copied was the only data in OLD_CHUNK,
     free that chunk and remove it from the chain.
     But not if that chunk might contain an empty object.  */
  if (! h->maybe_empty_object
      && (h->object_base
         == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,
                       h->alignment_mask)))
    {
      new_chunk->prev = old_chunk->prev;
      CALL_FREEFUN (h, old_chunk);
    }

  h->object_base = object_base;
  h->next_free = h->object_base + obj_size;
  /* The new chunk certainly contains no empty object yet.  */
  h->maybe_empty_object = 0;
}
void obstack_free ( struct obstack h,
void *  obj 
)

Definition at line 355 of file obstack.c.

{
  register struct _obstack_chunk *lp;     /* below addr of any objects in this chunk */
  register struct _obstack_chunk *plp;    /* point to previous chunk if any */

  lp = h->chunk;
  /* We use >= because there cannot be an object at the beginning of a chunk.
     But there can be an empty object at that address
     at the end of another chunk.  */
  while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
    {
      plp = lp->prev;
      CALL_FREEFUN (h, lp);
      lp = plp;
      /* If we switch chunks, we can't tell whether the new current
        chunk contains an empty object, so assume that it may.  */
      h->maybe_empty_object = 1;
    }
  if (lp)
    {
      h->object_base = h->next_free = (char *) (obj);
      h->chunk_limit = lp->limit;
      h->chunk = lp;
    }
  else if (obj != 0)
    /* obj is not in any of the chunks! */
    abort ();
}

Here is the call graph for this function:

static void print_and_abort ( void  ) [static]

Variable Documentation

Definition at line 104 of file obstack.c.