Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
John McEleney
/
mailutils
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
Commit
c45b72f4
...
c45b72f49c185c7077cc9c29fc1a66e38d7c41f3
authored
2001-09-14 12:06:50 +0000
by
Sergey Poznyakoff
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
GNU obstack functions
1 parent
684c0a89
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1015 additions
and
0 deletions
lib/obstack.c
lib/obstack.h
lib/obstack.c
0 → 100644
View file @
c45b72f
/* obstack.c - subroutines used implicitly by object stack macros
Copyright (C) 1988, 89, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "obstack.h"
/* NOTE BEFORE MODIFYING THIS FILE: This version number must be
incremented whenever callers compiled using an old obstack.h can no
longer properly call the functions in this obstack.c. */
#define OBSTACK_INTERFACE_VERSION 1
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself, and the installed library
supports the same library interface we do. This code is part of the GNU
C Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object
files, it is simpler to just do this in the source for each such file. */
#include <stdio.h>
/* Random thing to get __GNU_LIBRARY__. */
#if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
#include <gnu-versions.h>
#if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
#define ELIDE_CODE
#endif
#endif
#ifndef ELIDE_CODE
#if defined (__STDC__) && __STDC__
#define POINTER void *
#else
#define POINTER char *
#endif
/* Determine default alignment. */
struct
fooalign
{
char
x
;
double
d
;};
#define DEFAULT_ALIGNMENT \
((PTR_INT_TYPE) ((char *)&((struct fooalign *) 0)->d - (char *)0))
/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
But in fact it might be less smart and round addresses to as much as
DEFAULT_ROUNDING. So we prepare for it to do that. */
union
fooround
{
long
x
;
double
d
;};
#define DEFAULT_ROUNDING (sizeof (union fooround))
/* When we copy a long block of data, this is the unit to do it with.
On some machines, copying successive ints does not work;
in such a case, redefine COPYING_UNIT to `long' (if that works)
or `char' as a last resort. */
#ifndef COPYING_UNIT
#define COPYING_UNIT int
#endif
/* The non-GNU-C macros copy the obstack into this global variable
to avoid multiple evaluation. */
struct
obstack
*
_obstack
;
/* Define a macro that either calls functions with the traditional malloc/free
calling interface, or calls functions with the mmalloc/mfree interface
(that adds an extra first argument), based on the state of use_extra_arg.
For free, do not use ?:, since some compilers, like the MIPS compilers,
do not allow (expr) ? void : void. */
#define CALL_CHUNKFUN(h, size) \
(((h) -> use_extra_arg) \
? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
: (*(h)->chunkfun) ((size)))
#define CALL_FREEFUN(h, old_chunk) \
do { \
if ((h) -> use_extra_arg) \
(*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
else \
(*(h)->freefun) ((old_chunk)); \
} while (0)
/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
Objects start on multiples of ALIGNMENT (0 means use default).
CHUNKFUN is the function to use to allocate chunks,
and FREEFUN the function to free them.
Return nonzero if successful, zero if out of memory.
To recover from an out of memory error,
free up some memory, then call this again. */
int
_obstack_begin
(
h
,
size
,
alignment
,
chunkfun
,
freefun
)
struct
obstack
*
h
;
int
size
;
int
alignment
;
POINTER
(
*
chunkfun
)
();
void
(
*
freefun
)
();
{
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
*
(
*
)())
chunkfun
;
h
->
freefun
=
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
)
{
h
->
alloc_failed
=
1
;
return
0
;
}
h
->
alloc_failed
=
0
;
h
->
next_free
=
h
->
object_base
=
chunk
->
contents
;
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
;
return
1
;
}
int
_obstack_begin_1
(
h
,
size
,
alignment
,
chunkfun
,
freefun
,
arg
)
struct
obstack
*
h
;
int
size
;
int
alignment
;
POINTER
(
*
chunkfun
)
();
void
(
*
freefun
)
();
POINTER
arg
;
{
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
*
(
*
)())
chunkfun
;
h
->
freefun
=
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
)
{
h
->
alloc_failed
=
1
;
return
0
;
}
h
->
alloc_failed
=
0
;
h
->
next_free
=
h
->
object_base
=
chunk
->
contents
;
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
;
return
1
;
}
/* Allocate a new current chunk for the obstack *H
on the assumption that LENGTH bytes need to be added
to the current object, or a new object of length LENGTH allocated.
Copies any partial object from the end of the old chunk
to the beginning of the new one. */
void
_obstack_newchunk
(
h
,
length
)
struct
obstack
*
h
;
int
length
;
{
register
struct
_obstack_chunk
*
old_chunk
=
h
->
chunk
;
register
struct
_obstack_chunk
*
new_chunk
;
register
long
new_size
;
register
int
obj_size
=
h
->
next_free
-
h
->
object_base
;
register
int
i
;
int
already
;
/* Compute size for new chunk. */
new_size
=
(
obj_size
+
length
)
+
(
obj_size
>>
3
)
+
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
)
{
h
->
alloc_failed
=
1
;
return
;
}
h
->
alloc_failed
=
0
;
h
->
chunk
=
new_chunk
;
new_chunk
->
prev
=
old_chunk
;
new_chunk
->
limit
=
h
->
chunk_limit
=
(
char
*
)
new_chunk
+
new_size
;
/* 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
*
)
new_chunk
->
contents
)[
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
++
)
new_chunk
->
contents
[
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
->
object_base
==
old_chunk
->
contents
&&
!
h
->
maybe_empty_object
)
{
new_chunk
->
prev
=
old_chunk
->
prev
;
CALL_FREEFUN
(
h
,
old_chunk
);
}
h
->
object_base
=
new_chunk
->
contents
;
h
->
next_free
=
h
->
object_base
+
obj_size
;
/* The new chunk certainly contains no empty object yet. */
h
->
maybe_empty_object
=
0
;
}
/* Return nonzero if object OBJ has been allocated from obstack H.
This is here for debugging.
If you use it in a program, you are probably losing. */
#if defined (__STDC__) && __STDC__
/* Suppress -Wmissing-prototypes warning. We don't want to declare this in
obstack.h because it is just for debugging. */
int
_obstack_allocated_p
(
struct
obstack
*
h
,
POINTER
obj
);
#endif
int
_obstack_allocated_p
(
h
,
obj
)
struct
obstack
*
h
;
POINTER
obj
;
{
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
&&
((
POINTER
)
lp
>=
obj
||
(
POINTER
)(
lp
)
->
limit
<
obj
))
{
plp
=
lp
->
prev
;
lp
=
plp
;
}
return
lp
!=
0
;
}
/* Free objects in obstack H, including OBJ and everything allocate
more recently than OBJ. If OBJ is zero, free everything in H. */
#undef obstack_free
/* This function has two names with identical definitions.
This is the first one, called from non-ANSI code. */
void
_obstack_free
(
h
,
obj
)
struct
obstack
*
h
;
POINTER
obj
;
{
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
&&
((
POINTER
)
lp
>=
obj
||
(
POINTER
)(
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
();
}
/* This function is used from ANSI code. */
void
obstack_free
(
h
,
obj
)
struct
obstack
*
h
;
POINTER
obj
;
{
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
&&
((
POINTER
)
lp
>=
obj
||
(
POINTER
)(
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
();
}
#if 0
/* These are now turned off because the applications do not use it
and it uses bcopy via obstack_grow, which causes trouble on sysV. */
/* Now define the functional versions of the obstack macros.
Define them to simply use the corresponding macros to do the job. */
#if defined (__STDC__) && __STDC__
/* These function definitions do not work with non-ANSI preprocessors;
they won't pass through the macro names in parentheses. */
/* The function names appear in parentheses in order to prevent
the macro-definitions of the names from being expanded there. */
POINTER (obstack_base) (obstack)
struct obstack *obstack;
{
return obstack_base (obstack);
}
POINTER (obstack_next_free) (obstack)
struct obstack *obstack;
{
return obstack_next_free (obstack);
}
int (obstack_object_size) (obstack)
struct obstack *obstack;
{
return obstack_object_size (obstack);
}
int (obstack_room) (obstack)
struct obstack *obstack;
{
return obstack_room (obstack);
}
void (obstack_grow) (obstack, pointer, length)
struct obstack *obstack;
POINTER pointer;
int length;
{
obstack_grow (obstack, pointer, length);
}
void (obstack_grow0) (obstack, pointer, length)
struct obstack *obstack;
POINTER pointer;
int length;
{
obstack_grow0 (obstack, pointer, length);
}
void (obstack_1grow) (obstack, character)
struct obstack *obstack;
int character;
{
obstack_1grow (obstack, character);
}
void (obstack_blank) (obstack, length)
struct obstack *obstack;
int length;
{
obstack_blank (obstack, length);
}
void (obstack_1grow_fast) (obstack, character)
struct obstack *obstack;
int character;
{
obstack_1grow_fast (obstack, character);
}
void (obstack_blank_fast) (obstack, length)
struct obstack *obstack;
int length;
{
obstack_blank_fast (obstack, length);
}
POINTER (obstack_finish) (obstack)
struct obstack *obstack;
{
return obstack_finish (obstack);
}
POINTER (obstack_alloc) (obstack, length)
struct obstack *obstack;
int length;
{
return obstack_alloc (obstack, length);
}
POINTER (obstack_copy) (obstack, pointer, length)
struct obstack *obstack;
POINTER pointer;
int length;
{
return obstack_copy (obstack, pointer, length);
}
POINTER (obstack_copy0) (obstack, pointer, length)
struct obstack *obstack;
POINTER pointer;
int length;
{
return obstack_copy0 (obstack, pointer, length);
}
#endif /* __STDC__ */
#endif /* 0 */
#endif
/* !ELIDE_CODE */
lib/obstack.h
0 → 100644
View file @
c45b72f
/* obstack.h - object stack macros
Copyright (C) 1988, 89, 90, 91, 92, 93, 94, 95, 96 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Summary:
All the apparent functions defined here are macros. The idea
is that you would use these pre-tested macros to solve a
very specific set of problems, and they would run fast.
Caution: no side-effects in arguments please!! They may be
evaluated MANY times!!
These macros operate a stack of objects. Each object starts life
small, and may grow to maturity. (Consider building a word syllable
by syllable.) An object can move while it is growing. Once it has
been "finished" it never changes address again. So the "top of the
stack" is typically an immature growing object, while the rest of the
stack is of mature, fixed size and fixed address objects.
These routines grab large chunks of memory, using a function you
supply, called `obstack_chunk_alloc'. On occasion, they free chunks,
by calling `obstack_chunk_free'. You must define them and declare
them before using any obstack macros.
Each independent stack is represented by a `struct obstack'.
Each of the obstack macros expects a pointer to such a structure
as the first argument.
One motivation for this package is the problem of growing char strings
in symbol tables. Unless you are "fascist pig with a read-only mind"
--Gosper's immortal quote from HAKMEM item 154, out of context--you
would not like to put any arbitrary upper limit on the length of your
symbols.
In practice this often means you will build many short symbols and a
few long symbols. At the time you are reading a symbol you don't know
how long it is. One traditional method is to read a symbol into a
buffer, realloc()ating the buffer every time you try to read a symbol
that is longer than the buffer. This is beaut, but you still will
want to copy the symbol from the buffer to a more permanent
symbol-table entry say about half the time.
With obstacks, you can work differently. Use one obstack for all symbol
names. As you read a symbol, grow the name in the obstack gradually.
When the name is complete, finalize it. Then, if the symbol exists already,
free the newly read name.
The way we do this is to take a large chunk, allocating memory from
low addresses. When you want to build a symbol in the chunk you just
add chars above the current "high water mark" in the chunk. When you
have finished adding chars, because you got to the end of the symbol,
you know how long the chars are, and you can create a new object.
Mostly the chars will not burst over the highest address of the chunk,
because you would typically expect a chunk to be (say) 100 times as
long as an average object.
In case that isn't clear, when we have enough chars to make up
the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
so we just point to it where it lies. No moving of chars is
needed and this is the second win: potentially long strings need
never be explicitly shuffled. Once an object is formed, it does not
change its address during its lifetime.
When the chars burst over a chunk boundary, we allocate a larger
chunk, and then copy the partly formed object from the end of the old
chunk to the beginning of the new larger chunk. We then carry on
accreting characters to the end of the object as we normally would.
A special macro is provided to add a single char at a time to a
growing object. This allows the use of register variables, which
break the ordinary 'growth' macro.
Summary:
We allocate large chunks.
We carve out one object at a time from the current chunk.
Once carved, an object never moves.
We are free to append data of any size to the currently
growing object.
Exactly one object is growing in an obstack at any one time.
You can run one obstack per control block.
You may have as many control blocks as you dare.
Because of the way we do it, you can `unwind' an obstack
back to a previous state. (You may remove objects much
as you would with a stack.)
*/
/* Don't do the contents of this file more than once. */
#ifndef __OBSTACK_H__
#define __OBSTACK_H__
/* We use subtraction of (char *)0 instead of casting to int
because on word-addressable machines a simple cast to int
may ignore the byte-within-word field of the pointer. */
#ifndef __PTR_TO_INT
#define __PTR_TO_INT(P) ((P) - (char *)0)
#endif
#ifndef __INT_TO_PTR
#define __INT_TO_PTR(P) ((P) + (char *)0)
#endif
/* We need the type of the resulting object. In ANSI C it is ptrdiff_t
but in traditional C it is usually long. If we are in ANSI C and
don't already have ptrdiff_t get it. */
#if defined (__STDC__) && ! defined (offsetof)
#if defined (__GNUC__) && defined (IN_GCC)
/* On Next machine, the system's stddef.h screws up if included
after we have defined just ptrdiff_t, so include all of stddef.h.
Otherwise, define just ptrdiff_t, which is all we need. */
#ifndef __NeXT__
#define __need_ptrdiff_t
#endif
#endif
#include <stddef.h>
#endif
#ifdef __STDC__
#define PTR_INT_TYPE ptrdiff_t
#else
#define PTR_INT_TYPE long
#endif
struct
_obstack_chunk
/* Lives at front of each chunk. */
{
char
*
limit
;
/* 1 past end of this chunk */
struct
_obstack_chunk
*
prev
;
/* address of prior chunk or NULL */
char
contents
[
4
];
/* objects begin here */
};
struct
obstack
/* control current object in current chunk */
{
long
chunk_size
;
/* preferred size to allocate chunks in */
struct
_obstack_chunk
*
chunk
;
/* address of current struct obstack_chunk */
char
*
object_base
;
/* address of object we are building */
char
*
next_free
;
/* where to add next char to current object */
char
*
chunk_limit
;
/* address of char after current chunk */
PTR_INT_TYPE
temp
;
/* Temporary for some macros. */
int
alignment_mask
;
/* Mask of alignment for each object. */
struct
_obstack_chunk
*
(
*
chunkfun
)
();
/* User's fcn to allocate a chunk. */
void
(
*
freefun
)
();
/* User's function to free a chunk. */
char
*
extra_arg
;
/* first arg for chunk alloc/dealloc funcs */
unsigned
use_extra_arg
:
1
;
/* chunk alloc/dealloc funcs take extra arg */
unsigned
maybe_empty_object
:
1
;
/* There is a possibility that the current
chunk contains a zero-length object. This
prevents freeing the chunk if we allocate
a bigger chunk to replace it. */
unsigned
alloc_failed
:
1
;
/* chunk alloc func returned 0 */
};
/* Declare the external functions we use; they are in obstack.c. */
#ifdef __STDC__
extern
void
_obstack_newchunk
(
struct
obstack
*
,
int
);
extern
void
_obstack_free
(
struct
obstack
*
,
void
*
);
extern
int
_obstack_begin
(
struct
obstack
*
,
int
,
int
,
void
*
(
*
)
(),
void
(
*
)
());
extern
int
_obstack_begin_1
(
struct
obstack
*
,
int
,
int
,
void
*
(
*
)
(),
void
(
*
)
(),
void
*
);
extern
int
_obstack_memory_used
(
struct
obstack
*
);
#else
extern
void
_obstack_newchunk
();
extern
void
_obstack_free
();
extern
int
_obstack_begin
();
extern
int
_obstack_begin_1
();
extern
int
_obstack_memory_used
();
#endif
#ifdef __STDC__
/* Do the function-declarations after the structs
but before defining the macros. */
void
obstack_init
(
struct
obstack
*
obstack
);
void
*
obstack_alloc
(
struct
obstack
*
obstack
,
int
size
);
void
*
obstack_copy
(
struct
obstack
*
obstack
,
void
*
address
,
int
size
);
void
*
obstack_copy0
(
struct
obstack
*
obstack
,
void
*
address
,
int
size
);
void
obstack_free
(
struct
obstack
*
obstack
,
void
*
block
);
void
obstack_blank
(
struct
obstack
*
obstack
,
int
size
);
void
obstack_grow
(
struct
obstack
*
obstack
,
void
*
data
,
int
size
);
void
obstack_grow0
(
struct
obstack
*
obstack
,
void
*
data
,
int
size
);
void
obstack_1grow
(
struct
obstack
*
obstack
,
int
data_char
);
void
obstack_ptr_grow
(
struct
obstack
*
obstack
,
void
*
data
);
void
obstack_int_grow
(
struct
obstack
*
obstack
,
int
data
);
void
*
obstack_finish
(
struct
obstack
*
obstack
);
int
obstack_object_size
(
struct
obstack
*
obstack
);
int
obstack_room
(
struct
obstack
*
obstack
);
void
obstack_1grow_fast
(
struct
obstack
*
obstack
,
int
data_char
);
void
obstack_ptr_grow_fast
(
struct
obstack
*
obstack
,
void
*
data
);
void
obstack_int_grow_fast
(
struct
obstack
*
obstack
,
int
data
);
void
obstack_blank_fast
(
struct
obstack
*
obstack
,
int
size
);
void
*
obstack_base
(
struct
obstack
*
obstack
);
void
*
obstack_next_free
(
struct
obstack
*
obstack
);
int
obstack_alignment_mask
(
struct
obstack
*
obstack
);
int
obstack_chunk_size
(
struct
obstack
*
obstack
);
int
obstack_memory_used
(
struct
obstack
*
obstack
);
#endif
/* __STDC__ */
/* Non-ANSI C cannot really support alternative functions for these macros,
so we do not declare them. */
/* Pointer to beginning of object being allocated or to be allocated next.
Note that this might not be the final address of the object
because a new chunk might be needed to hold the final size. */
#define obstack_base(h) ((h)->alloc_failed ? 0 : (h)->object_base)
/* Size for allocating ordinary chunks. */
#define obstack_chunk_size(h) ((h)->chunk_size)
/* Pointer to next byte not yet allocated in current chunk. */
#define obstack_next_free(h) ((h)->alloc_failed ? 0 : (h)->next_free)
/* Mask specifying low bits that should be clear in address of an object. */
#define obstack_alignment_mask(h) ((h)->alignment_mask)
#define obstack_init(h) \
_obstack_begin ((h), 0, 0, \
(void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free)
#define obstack_begin(h, size) \
_obstack_begin ((h), (size), 0, \
(void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free)
#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
_obstack_begin ((h), (size), (alignment), \
(void *(*) ()) (chunkfun), (void (*) ()) (freefun))
#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
_obstack_begin_1 ((h), (size), (alignment), \
(void *(*) ()) (chunkfun), (void (*) ()) (freefun), (arg))
#define obstack_chunkfun(h, newchunkfun) \
((h) -> chunkfun = (struct _obstack_chunk *(*)()) (newchunkfun))
#define obstack_freefun(h, newfreefun) \
((h) -> freefun = (void (*)()) (newfreefun))
#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
#define obstack_blank_fast(h,n) ((h)->next_free += (n))
#define obstack_memory_used(h) _obstack_memory_used (h)
#if defined (__GNUC__) && defined (__STDC__)
#if __GNUC__ < 2
#define __extension__
#endif
/* For GNU C, if not -traditional,
we can define these macros to compute all args only once
without using a global variable.
Also, we can avoid using the `temp' slot, to make faster code. */
#define obstack_object_size(OBSTACK) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
__o->alloc_failed ? 0 : \
(unsigned) (__o->next_free - __o->object_base); })
#define obstack_room(OBSTACK) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
(unsigned) (__o->chunk_limit - __o->next_free); })
#define obstack_grow(OBSTACK,where,length) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
int __len = (length); \
if (__o->next_free + __len > __o->chunk_limit) \
_obstack_newchunk (__o, __len); \
if (!__o->alloc_failed) \
{ \
bcopy (where, __o->next_free, __len); \
__o->next_free += __len; \
} \
(void) 0; })
#define obstack_grow0(OBSTACK,where,length) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
int __len = (length); \
if (__o->next_free + __len + 1 > __o->chunk_limit) \
_obstack_newchunk (__o, __len + 1); \
if (!__o->alloc_failed) \
{ \
bcopy (where, __o->next_free, __len); \
__o->next_free += __len; \
*(__o->next_free)++ = 0; \
} \
(void) 0; })
#define obstack_1grow(OBSTACK,datum) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
if (__o->next_free + 1 > __o->chunk_limit) \
_obstack_newchunk (__o, 1); \
if (!__o->alloc_failed) \
*(__o->next_free)++ = (datum); \
(void) 0; })
/* These assume that the obstack alignment is good enough for pointers or ints,
and that the data added so far to the current object
shares that much alignment. */
#define obstack_ptr_grow(OBSTACK,datum) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
if (__o->next_free + sizeof (void *) > __o->chunk_limit) \
_obstack_newchunk (__o, sizeof (void *)); \
if (!__o->alloc_failed) \
*((void **)__o->next_free)++ = ((void *)datum); \
(void) 0; })
#define obstack_int_grow(OBSTACK,datum) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
if (__o->next_free + sizeof (int) > __o->chunk_limit) \
_obstack_newchunk (__o, sizeof (int)); \
if (!__o->alloc_failed) \
*((int *)__o->next_free)++ = ((int)datum); \
(void) 0; })
#define obstack_ptr_grow_fast(h,aptr) (*((void **)(h)->next_free)++ = (void *)aptr)
#define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint)
#define obstack_blank(OBSTACK,length) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
int __len = (length); \
if (__o->chunk_limit - __o->next_free < __len) \
_obstack_newchunk (__o, __len); \
if (!__o->alloc_failed) \
__o->next_free += __len; \
(void) 0; })
#define obstack_alloc(OBSTACK,length) \
__extension__ \
({ struct obstack *__h = (OBSTACK); \
obstack_blank (__h, (length)); \
obstack_finish (__h); })
#define obstack_copy(OBSTACK,where,length) \
__extension__ \
({ struct obstack *__h = (OBSTACK); \
obstack_grow (__h, (where), (length)); \
obstack_finish (__h); })
#define obstack_copy0(OBSTACK,where,length) \
__extension__ \
({ struct obstack *__h = (OBSTACK); \
obstack_grow0 (__h, (where), (length)); \
obstack_finish (__h); })
/* The local variable is named __o1 to avoid a name conflict
when obstack_blank is called. */
#define obstack_finish(OBSTACK) \
__extension__ \
({ struct obstack *__o1 = (OBSTACK); \
void *value; \
if (__o1->alloc_failed) \
value = 0; \
else \
{ \
value = (void *) __o1->object_base; \
if (__o1->next_free == value) \
__o1->maybe_empty_object = 1; \
__o1->next_free \
= __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\
& ~ (__o1->alignment_mask)); \
if (__o1->next_free - (char *)__o1->chunk \
> __o1->chunk_limit - (char *)__o1->chunk) \
__o1->next_free = __o1->chunk_limit; \
__o1->object_base = __o1->next_free; \
} \
value; })
#define obstack_free(OBSTACK, OBJ) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
void *__obj = (OBJ); \
if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
__o->next_free = __o->object_base = __obj; \
else (obstack_free) (__o, __obj); })
#else
/* not __GNUC__ or not __STDC__ */
#define obstack_object_size(h) \
(unsigned) ((h)->alloc_failed ? 0 : (h)->next_free - (h)->object_base)
#define obstack_room(h) \
(unsigned) ((h)->chunk_limit - (h)->next_free)
/* Note that the call to _obstack_newchunk is enclosed in (..., 0)
so that we can avoid having void expressions
in the arms of the conditional expression.
Casting the third operand to void was tried before,
but some compilers won't accept it. */
#define obstack_grow(h,where,length) \
( (h)->temp = (length), \
(((h)->next_free + (h)->temp > (h)->chunk_limit) \
? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
((h)->alloc_failed ? 0 : \
(bcopy (where, (h)->next_free, (h)->temp), \
(h)->next_free += (h)->temp)))
#define obstack_grow0(h,where,length) \
( (h)->temp = (length), \
(((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \
? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \
((h)->alloc_failed ? 0 : \
(bcopy (where, (h)->next_free, (h)->temp), \
(h)->next_free += (h)->temp, \
*((h)->next_free)++ = 0)))
#define obstack_1grow(h,datum) \
( (((h)->next_free + 1 > (h)->chunk_limit) \
? (_obstack_newchunk ((h), 1), 0) : 0), \
((h)->alloc_failed ? 0 : \
(*((h)->next_free)++ = (datum))))
#define obstack_ptr_grow(h,datum) \
( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
((h)->alloc_failed ? 0 : \
(*((char **)(((h)->next_free+=sizeof(char *))-sizeof(char *))) = ((char *)datum))))
#define obstack_int_grow(h,datum) \
( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \
? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
((h)->alloc_failed ? 0 : \
(*((int *)(((h)->next_free+=sizeof(int))-sizeof(int))) = ((int)datum))))
#define obstack_ptr_grow_fast(h,aptr) (*((char **)(h)->next_free)++ = (char *)aptr)
#define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint)
#define obstack_blank(h,length) \
( (h)->temp = (length), \
(((h)->chunk_limit - (h)->next_free < (h)->temp) \
? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
((h)->alloc_failed ? 0 : \
((h)->next_free += (h)->temp)))
#define obstack_alloc(h,length) \
(obstack_blank ((h), (length)), obstack_finish ((h)))
#define obstack_copy(h,where,length) \
(obstack_grow ((h), (where), (length)), obstack_finish ((h)))
#define obstack_copy0(h,where,length) \
(obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
#define obstack_finish(h) \
( (h)->alloc_failed ? 0 : \
(((h)->next_free == (h)->object_base \
? (((h)->maybe_empty_object = 1), 0) \
: 0), \
(h)->temp = __PTR_TO_INT ((h)->object_base), \
(h)->next_free \
= __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \
& ~ ((h)->alignment_mask)), \
(((h)->next_free - (char *)(h)->chunk \
> (h)->chunk_limit - (char *)(h)->chunk) \
? ((h)->next_free = (h)->chunk_limit) : 0), \
(h)->object_base = (h)->next_free, \
__INT_TO_PTR ((h)->temp)))
#ifdef __STDC__
#define obstack_free(h,obj) \
( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
(((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
? (int) ((h)->next_free = (h)->object_base \
= (h)->temp + (char *) (h)->chunk) \
: (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0)))
#else
#define obstack_free(h,obj) \
( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
(((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
? (int) ((h)->next_free = (h)->object_base \
= (h)->temp + (char *) (h)->chunk) \
: (_obstack_free ((h), (h)->temp + (char *) (h)->chunk), 0)))
#endif
#endif
/* not __GNUC__ or not __STDC__ */
#endif
/* not __OBSTACK_H__ */
Please
register
or
sign in
to post a comment