* [PATCH 3/5] 64-bit obstack support, part 1
[not found] <cover.1414461460.git.amodra@gmail.com>
@ 2014-10-29 3:32 ` Alan Modra
2014-10-30 19:52 ` Roland McGrath
2014-10-29 3:32 ` [PATCH 1/5] obstack tidy " Alan Modra
` (4 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Alan Modra @ 2014-10-29 3:32 UTC (permalink / raw)
To: libc-alpha, bug-gnulib
a) Correct calls to alloc function, to use a size_t arg. "long" is
just wrong on targets like x86_64-mingw64 where "long" is 32 bits
and "size_t" 64 bits.
b) Consolidate _obstack_begin and _obstack_begin1 code.
* lib/obstack.h (struct obstack <chunkfun>): Correct prototype to
use "size_t" rather than "long".
(_obstack_begin, _obstack_begin1): Likewise.
(obstack_init, obstack_begin, obstack_specify_allocation_with_arg,
obstack_chunkfun): Update alloc function casts.
* lib/obstack.c (CALL_CHUNKFUN): Update chunkfun cast.
(chunkfun_type, freefun_type): New typdefs.
(_obstack_begin_worker): Split out from ..
(_obstack_begin, _obstack_begin_1): ..here.
---
lib/obstack.c | 77 ++++++++++++++++++++++-------------------------------------
lib/obstack.h | 16 ++++++-------
2 files changed, 36 insertions(+), 57 deletions(-)
diff --git a/lib/obstack.c b/lib/obstack.c
index 2d5dfbc..d9beb9b 100644
--- a/lib/obstack.c
+++ b/lib/obstack.c
@@ -94,7 +94,7 @@ compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
# define CALL_CHUNKFUN(h, size) \
(((h)->use_extra_arg) \
? (*(h)->chunkfun)((h)->extra_arg, (size)) \
- : (*(struct _obstack_chunk *(*)(long))(h)->chunkfun)((size)))
+ : (*(struct _obstack_chunk *(*)(size_t))(h)->chunkfun)((size)))
# define CALL_FREEFUN(h, old_chunk) \
do { \
@@ -113,11 +113,13 @@ compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
Return nonzero if successful, calls obstack_alloc_failed_handler if
allocation fails. */
-int
-_obstack_begin (struct obstack *h,
- int size, int alignment,
- void *(*chunkfun) (long),
- void (*freefun) (void *))
+typedef struct _obstack_chunk * (*chunkfun_type) (void *, size_t);
+typedef void (*freefun_type) (void *, struct _obstack_chunk *);
+
+static int
+_obstack_begin_worker (struct obstack *h,
+ int size, int alignment,
+ chunkfun_type chunkfun, freefun_type freefun)
{
struct _obstack_chunk *chunk; /* points to new chunk */
@@ -140,11 +142,10 @@ _obstack_begin (struct obstack *h,
size = 4096 - extra;
}
- h->chunkfun = (struct _obstack_chunk * (*) (void *, long)) chunkfun;
- h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+ h->chunkfun = 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)
@@ -160,51 +161,29 @@ _obstack_begin (struct obstack *h,
}
int
-_obstack_begin_1 (struct obstack *h, int size, int alignment,
- void *(*chunkfun) (void *, long),
+_obstack_begin (struct obstack *h,
+ int size, int alignment,
+ void *(*chunkfun) (size_t),
+ void (*freefun) (void *))
+{
+ h->use_extra_arg = 0;
+ return _obstack_begin_worker (h, size, alignment,
+ (chunkfun_type) chunkfun,
+ (freefun_type) freefun);
+}
+
+int
+_obstack_begin_1 (struct obstack *h,
+ int size, int alignment,
+ void *(*chunkfun) (void *, size_t),
void (*freefun) (void *, void *),
void *arg)
{
- 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;
+ return _obstack_begin_worker (h, size, alignment,
+ (chunkfun_type) chunkfun,
+ (freefun_type) freefun);
}
/* Allocate a new current chunk for the obstack *H
diff --git a/lib/obstack.h b/lib/obstack.h
index f3a7c77..ef647aa 100644
--- a/lib/obstack.h
+++ b/lib/obstack.h
@@ -156,7 +156,7 @@ struct obstack /* control current object in current chunk */
/* These prototypes vary based on 'use_extra_arg', and we use
casts to the prototypeless function type in all assignments,
but having prototypes here quiets -Wstrict-prototypes. */
- struct _obstack_chunk *(*chunkfun) (void *, long);
+ struct _obstack_chunk *(*chunkfun) (void *, size_t);
void (*freefun) (void *, struct _obstack_chunk *);
void *extra_arg; /* first arg for chunk alloc/dealloc funcs */
unsigned use_extra_arg : 1; /* chunk alloc/dealloc funcs take extra arg */
@@ -174,9 +174,9 @@ struct obstack /* control current object in current chunk */
extern void _obstack_newchunk (struct obstack *, int);
extern void _obstack_free (struct obstack *, void *);
extern int _obstack_begin (struct obstack *, int, int,
- void *(*)(long), void (*)(void *));
+ void *(*)(size_t), void (*)(void *));
extern int _obstack_begin_1 (struct obstack *, int, int,
- void *(*)(void *, long),
+ void *(*)(void *, size_t),
void (*)(void *, void *), void *);
extern int _obstack_memory_used (struct obstack *) __attribute_pure__;
@@ -211,26 +211,26 @@ extern int obstack_exit_failure;
/* To prevent prototype warnings provide complete argument list. */
#define obstack_init(h) \
_obstack_begin ((h), 0, 0, \
- (void *(*)(long))obstack_chunk_alloc, \
+ (void *(*)(size_t))obstack_chunk_alloc, \
(void (*)(void *))obstack_chunk_free)
#define obstack_begin(h, size) \
_obstack_begin ((h), (size), 0, \
- (void *(*)(long))obstack_chunk_alloc, \
+ (void *(*)(size_t))obstack_chunk_alloc, \
(void (*)(void *))obstack_chunk_free)
#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
_obstack_begin ((h), (size), (alignment), \
- (void *(*)(long))(chunkfun), \
+ (void *(*)(size_t))(chunkfun), \
(void (*)(void *))(freefun))
#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
_obstack_begin_1 ((h), (size), (alignment), \
- (void *(*)(void *, long))(chunkfun), \
+ (void *(*)(void *, size_t))(chunkfun), \
(void (*)(void *, void *))(freefun), (arg))
#define obstack_chunkfun(h, newchunkfun) \
- ((h)->chunkfun = (struct _obstack_chunk *(*)(void *, long))(newchunkfun))
+ ((h)->chunkfun = (struct _obstack_chunk *(*)(void *, size_t))(newchunkfun))
#define obstack_freefun(h, newfreefun) \
((h)->freefun = (void (*)(void *, struct _obstack_chunk *))(newfreefun))
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/5] 64-bit obstack support, part 1
2014-10-29 3:32 ` [PATCH 3/5] 64-bit obstack support, part 1 Alan Modra
@ 2014-10-30 19:52 ` Roland McGrath
2014-10-31 0:38 ` Alan Modra
0 siblings, 1 reply; 13+ messages in thread
From: Roland McGrath @ 2014-10-30 19:52 UTC (permalink / raw)
To: Alan Modra; +Cc: libc-alpha, bug-gnulib
It would be easier to review if you separated the very trivial changes from
the others. The size_t change is clearly fine and can be approved quickly.
The refactoring requires more attention.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/5] 64-bit obstack support, part 1
2014-10-30 19:52 ` Roland McGrath
@ 2014-10-31 0:38 ` Alan Modra
0 siblings, 0 replies; 13+ messages in thread
From: Alan Modra @ 2014-10-31 0:38 UTC (permalink / raw)
To: Roland McGrath; +Cc: libc-alpha, bug-gnulib
[-- Attachment #1: Type: text/plain, Size: 344 bytes --]
On Thu, Oct 30, 2014 at 12:52:29PM -0700, Roland McGrath wrote:
> It would be easier to review if you separated the very trivial changes from
> the others. The size_t change is clearly fine and can be approved quickly.
> The refactoring requires more attention.
Split as requested and attached.
--
Alan Modra
Australia Development Lab, IBM
[-- Attachment #2: 0001-64-bit-obstack-support-part-1a.patch --]
[-- Type: text/x-diff, Size: 5919 bytes --]
From fb249df2535a4fcd913589e27cd3c30a60cd5308 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Fri, 31 Oct 2014 10:54:55 +1030
Subject: [PATCH 1/2] 64-bit obstack support, part 1a
a) Correct calls to alloc function, to use a size_t arg. "long" is
just wrong on targets like x86_64-mingw64 where "long" is 32 bits
and "size_t" 64 bits.
* lib/obstack.h (struct obstack <chunkfun>): Correct prototype to
use "size_t" rather than "long".
(_obstack_begin, _obstack_begin1): Likewise.
(obstack_init, obstack_begin, obstack_specify_allocation_with_arg,
obstack_chunkfun): Update alloc function casts.
* lib/obstack.c (CALL_CHUNKFUN): Update chunkfun cast.
(_obstack_begin, _obstack_begin_1): Update chunkfun type.
---
lib/obstack.c | 10 +++++-----
lib/obstack.h | 16 ++++++++--------
2 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/lib/obstack.c b/lib/obstack.c
index 2d5dfbc..dfdb664 100644
--- a/lib/obstack.c
+++ b/lib/obstack.c
@@ -94,7 +94,7 @@ compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
# define CALL_CHUNKFUN(h, size) \
(((h)->use_extra_arg) \
? (*(h)->chunkfun)((h)->extra_arg, (size)) \
- : (*(struct _obstack_chunk *(*)(long))(h)->chunkfun)((size)))
+ : (*(struct _obstack_chunk *(*)(size_t))(h)->chunkfun)((size)))
# define CALL_FREEFUN(h, old_chunk) \
do { \
@@ -116,7 +116,7 @@ compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
int
_obstack_begin (struct obstack *h,
int size, int alignment,
- void *(*chunkfun) (long),
+ void *(*chunkfun) (size_t),
void (*freefun) (void *))
{
struct _obstack_chunk *chunk; /* points to new chunk */
@@ -140,7 +140,7 @@ _obstack_begin (struct obstack *h,
size = 4096 - extra;
}
- h->chunkfun = (struct _obstack_chunk * (*) (void *, long)) chunkfun;
+ h->chunkfun = (struct _obstack_chunk * (*) (void *, size_t)) chunkfun;
h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
h->chunk_size = size;
h->alignment_mask = alignment - 1;
@@ -161,7 +161,7 @@ _obstack_begin (struct obstack *h,
int
_obstack_begin_1 (struct obstack *h, int size, int alignment,
- void *(*chunkfun) (void *, long),
+ void *(*chunkfun) (void *, size_t),
void (*freefun) (void *, void *),
void *arg)
{
@@ -186,7 +186,7 @@ _obstack_begin_1 (struct obstack *h, int size, int alignment,
size = 4096 - extra;
}
- h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
+ h->chunkfun = (struct _obstack_chunk * (*)(void *,size_t)) chunkfun;
h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
h->chunk_size = size;
h->alignment_mask = alignment - 1;
diff --git a/lib/obstack.h b/lib/obstack.h
index f3a7c77..ef647aa 100644
--- a/lib/obstack.h
+++ b/lib/obstack.h
@@ -156,7 +156,7 @@ struct obstack /* control current object in current chunk */
/* These prototypes vary based on 'use_extra_arg', and we use
casts to the prototypeless function type in all assignments,
but having prototypes here quiets -Wstrict-prototypes. */
- struct _obstack_chunk *(*chunkfun) (void *, long);
+ struct _obstack_chunk *(*chunkfun) (void *, size_t);
void (*freefun) (void *, struct _obstack_chunk *);
void *extra_arg; /* first arg for chunk alloc/dealloc funcs */
unsigned use_extra_arg : 1; /* chunk alloc/dealloc funcs take extra arg */
@@ -174,9 +174,9 @@ struct obstack /* control current object in current chunk */
extern void _obstack_newchunk (struct obstack *, int);
extern void _obstack_free (struct obstack *, void *);
extern int _obstack_begin (struct obstack *, int, int,
- void *(*)(long), void (*)(void *));
+ void *(*)(size_t), void (*)(void *));
extern int _obstack_begin_1 (struct obstack *, int, int,
- void *(*)(void *, long),
+ void *(*)(void *, size_t),
void (*)(void *, void *), void *);
extern int _obstack_memory_used (struct obstack *) __attribute_pure__;
@@ -211,26 +211,26 @@ extern int obstack_exit_failure;
/* To prevent prototype warnings provide complete argument list. */
#define obstack_init(h) \
_obstack_begin ((h), 0, 0, \
- (void *(*)(long))obstack_chunk_alloc, \
+ (void *(*)(size_t))obstack_chunk_alloc, \
(void (*)(void *))obstack_chunk_free)
#define obstack_begin(h, size) \
_obstack_begin ((h), (size), 0, \
- (void *(*)(long))obstack_chunk_alloc, \
+ (void *(*)(size_t))obstack_chunk_alloc, \
(void (*)(void *))obstack_chunk_free)
#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
_obstack_begin ((h), (size), (alignment), \
- (void *(*)(long))(chunkfun), \
+ (void *(*)(size_t))(chunkfun), \
(void (*)(void *))(freefun))
#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
_obstack_begin_1 ((h), (size), (alignment), \
- (void *(*)(void *, long))(chunkfun), \
+ (void *(*)(void *, size_t))(chunkfun), \
(void (*)(void *, void *))(freefun), (arg))
#define obstack_chunkfun(h, newchunkfun) \
- ((h)->chunkfun = (struct _obstack_chunk *(*)(void *, long))(newchunkfun))
+ ((h)->chunkfun = (struct _obstack_chunk *(*)(void *, size_t))(newchunkfun))
#define obstack_freefun(h, newfreefun) \
((h)->freefun = (void (*)(void *, struct _obstack_chunk *))(newfreefun))
[-- Attachment #3: 0002-64-bit-obstack-support-part-1b.patch --]
[-- Type: text/x-diff, Size: 4413 bytes --]
From cc881bf50b127aef86c8550bb2b12affbae8f5c5 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Fri, 31 Oct 2014 11:01:49 +1030
Subject: [PATCH 2/2] 64-bit obstack support, part 1b
Consolidate _obstack_begin and _obstack_begin1 code.
* lib/obstack.c (chunkfun_type, freefun_type): New typdefs.
(_obstack_begin_worker): Split out from ..
(_obstack_begin, _obstack_begin_1): ..here.
---
lib/obstack.c | 73 +++++++++++++++++++++--------------------------------------
1 file changed, 26 insertions(+), 47 deletions(-)
diff --git a/lib/obstack.c b/lib/obstack.c
index dfdb664..d9beb9b 100644
--- a/lib/obstack.c
+++ b/lib/obstack.c
@@ -113,11 +113,13 @@ compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
Return nonzero if successful, calls obstack_alloc_failed_handler if
allocation fails. */
-int
-_obstack_begin (struct obstack *h,
- int size, int alignment,
- void *(*chunkfun) (size_t),
- void (*freefun) (void *))
+typedef struct _obstack_chunk * (*chunkfun_type) (void *, size_t);
+typedef void (*freefun_type) (void *, struct _obstack_chunk *);
+
+static int
+_obstack_begin_worker (struct obstack *h,
+ int size, int alignment,
+ chunkfun_type chunkfun, freefun_type freefun)
{
struct _obstack_chunk *chunk; /* points to new chunk */
@@ -140,11 +142,10 @@ _obstack_begin (struct obstack *h,
size = 4096 - extra;
}
- h->chunkfun = (struct _obstack_chunk * (*) (void *, size_t)) chunkfun;
- h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+ h->chunkfun = 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)
@@ -160,51 +161,29 @@ _obstack_begin (struct obstack *h,
}
int
-_obstack_begin_1 (struct obstack *h, int size, int alignment,
+_obstack_begin (struct obstack *h,
+ int size, int alignment,
+ void *(*chunkfun) (size_t),
+ void (*freefun) (void *))
+{
+ h->use_extra_arg = 0;
+ return _obstack_begin_worker (h, size, alignment,
+ (chunkfun_type) chunkfun,
+ (freefun_type) freefun);
+}
+
+int
+_obstack_begin_1 (struct obstack *h,
+ int size, int alignment,
void *(*chunkfun) (void *, size_t),
void (*freefun) (void *, void *),
void *arg)
{
- 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 *,size_t)) 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;
+ return _obstack_begin_worker (h, size, alignment,
+ (chunkfun_type) chunkfun,
+ (freefun_type) freefun);
}
/* Allocate a new current chunk for the obstack *H
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/5] obstack tidy part 1
[not found] <cover.1414461460.git.amodra@gmail.com>
2014-10-29 3:32 ` [PATCH 3/5] 64-bit obstack support, part 1 Alan Modra
@ 2014-10-29 3:32 ` Alan Modra
2014-10-30 19:43 ` Roland McGrath
2014-10-29 3:32 ` [PATCH 4/5] 64-bit obstack support, part 2 Alan Modra
` (3 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Alan Modra @ 2014-10-29 3:32 UTC (permalink / raw)
To: libc-alpha, bug-gnulib
a) Rename temp fields. temp.tempint and temp.tempptr just looks ugly
to me, and result in overlong lines after later patches.
b) Move error handling code, to avoid a forward declaration and to
simplify later patches in this series.
* lib/obstack.h (struct obstack <temp>): Rename fields of union
and update all uses.
* lib/obstack.c: Include stdlib.h earlier.
(obstack_exit_failure, obstack_alloc_failed_handler): Move later
in file.
(print_and_abort): Remove now redundant forward declaration.
---
lib/obstack.c | 35 +++++++++++++++++------------------
lib/obstack.h | 52 ++++++++++++++++++++++++++--------------------------
2 files changed, 43 insertions(+), 44 deletions(-)
diff --git a/lib/obstack.c b/lib/obstack.c
index 598f6aa..66573df 100644
--- a/lib/obstack.c
+++ b/lib/obstack.c
@@ -52,6 +52,7 @@
#ifndef ELIDE_CODE
+# include <stdlib.h>
# include <stdint.h>
/* Determine default alignment. */
@@ -84,24 +85,6 @@ enum
# endif
-/* The functions allocating more room by calling 'obstack_chunk_alloc'
- jump to the handler pointed to by 'obstack_alloc_failed_handler'.
- This can be set to a user defined function which should either
- abort gracefully or use longjump - but shouldn't return. This
- variable by default points to the internal function
- 'print_and_abort'. */
-static _Noreturn void print_and_abort (void);
-void (*obstack_alloc_failed_handler) (void) = print_and_abort;
-
-/* Exit value used when 'print_and_abort' is used. */
-# include <stdlib.h>
-# ifdef _LIBC
-int obstack_exit_failure = EXIT_FAILURE;
-# else
-# include "exitfail.h"
-# define obstack_exit_failure exit_failure
-# endif
-
# ifdef _LIBC
# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
/* A looong time ago (before 1994, anyway; we're not sure) this global variable
@@ -391,6 +374,15 @@ _obstack_memory_used (struct obstack *h)
}
/* Define the error handler. */
+
+/* Exit value used when 'print_and_abort' is used. */
+# ifdef _LIBC
+int obstack_exit_failure = EXIT_FAILURE;
+# else
+# include "exitfail.h"
+# define obstack_exit_failure exit_failure
+# endif
+
# ifdef _LIBC
# include <libintl.h>
# else
@@ -420,4 +412,11 @@ print_and_abort (void)
exit (obstack_exit_failure);
}
+/* The functions allocating more room by calling 'obstack_chunk_alloc'
+ jump to the handler pointed to by 'obstack_alloc_failed_handler'.
+ This can be set to a user defined function which should either
+ abort gracefully or use longjump - but shouldn't return. This
+ variable by default points to the internal function
+ 'print_and_abort'. */
+void (*obstack_alloc_failed_handler) (void) = print_and_abort;
#endif /* !ELIDE_CODE */
diff --git a/lib/obstack.h b/lib/obstack.h
index f92492f..cd90e4e 100644
--- a/lib/obstack.h
+++ b/lib/obstack.h
@@ -159,8 +159,8 @@ struct obstack /* control current object in current chunk */
char *chunk_limit; /* address of char after current chunk */
union
{
- PTR_INT_TYPE tempint;
- void *tempptr;
+ PTR_INT_TYPE i;
+ void *p;
} temp; /* Temporary for some macros. */
int alignment_mask; /* Mask of alignment for each object. */
/* These prototypes vary based on 'use_extra_arg', and we use
@@ -429,23 +429,23 @@ extern int obstack_exit_failure;
but some compilers won't accept it. */
# define obstack_make_room(h, length) \
- ((h)->temp.tempint = (length), \
- (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0))
+ ((h)->temp.i = (length), \
+ (((h)->next_free + (h)->temp.i > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0))
# define obstack_grow(h, where, length) \
- ((h)->temp.tempint = (length), \
- (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \
- memcpy ((h)->next_free, where, (h)->temp.tempint), \
- (h)->next_free += (h)->temp.tempint)
+ ((h)->temp.i = (length), \
+ (((h)->next_free + (h)->temp.i > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0), \
+ memcpy ((h)->next_free, where, (h)->temp.i), \
+ (h)->next_free += (h)->temp.i)
# define obstack_grow0(h, where, length) \
- ((h)->temp.tempint = (length), \
- (((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), (h)->temp.tempint + 1), 0) : 0), \
- memcpy ((h)->next_free, where, (h)->temp.tempint), \
- (h)->next_free += (h)->temp.tempint, \
+ ((h)->temp.i = (length), \
+ (((h)->next_free + (h)->temp.i + 1 > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), (h)->temp.i + 1), 0) : 0), \
+ memcpy ((h)->next_free, where, (h)->temp.i), \
+ (h)->next_free += (h)->temp.i, \
*((h)->next_free)++ = 0)
# define obstack_1grow(h, datum) \
@@ -470,10 +470,10 @@ extern int obstack_exit_failure;
(((int *) ((h)->next_free += sizeof (int)))[-1] = (aint))
# define obstack_blank(h, length) \
- ((h)->temp.tempint = (length), \
- (((h)->chunk_limit - (h)->next_free < (h)->temp.tempint) \
- ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \
- obstack_blank_fast (h, (h)->temp.tempint))
+ ((h)->temp.i = (length), \
+ (((h)->chunk_limit - (h)->next_free < (h)->temp.i) \
+ ? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0), \
+ obstack_blank_fast (h, (h)->temp.i))
# define obstack_alloc(h, length) \
(obstack_blank ((h), (length)), obstack_finish ((h)))
@@ -488,7 +488,7 @@ extern int obstack_exit_failure;
(((h)->next_free == (h)->object_base \
? (((h)->maybe_empty_object = 1), 0) \
: 0), \
- (h)->temp.tempptr = (h)->object_base, \
+ (h)->temp.p = (h)->object_base, \
(h)->next_free \
= __PTR_ALIGN ((h)->object_base, (h)->next_free, \
(h)->alignment_mask), \
@@ -496,15 +496,15 @@ extern int obstack_exit_failure;
> (h)->chunk_limit - (char *) (h)->chunk) \
? ((h)->next_free = (h)->chunk_limit) : 0), \
(h)->object_base = (h)->next_free, \
- (h)->temp.tempptr)
+ (h)->temp.p)
# define obstack_free(h, obj) \
- ((h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk, \
- ((((h)->temp.tempint > 0 \
- && (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk)) \
+ ((h)->temp.i = (char *) (obj) - (char *) (h)->chunk, \
+ ((((h)->temp.i > 0 \
+ && (h)->temp.i < (h)->chunk_limit - (char *) (h)->chunk)) \
? (void) ((h)->next_free = (h)->object_base \
- = (h)->temp.tempint + (char *) (h)->chunk) \
- : (__obstack_free) (h, (h)->temp.tempint + (char *) (h)->chunk)))
+ = (h)->temp.i + (char *) (h)->chunk) \
+ : (__obstack_free) (h, (h)->temp.i + (char *) (h)->chunk)))
#endif /* not __GNUC__ */
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 4/5] 64-bit obstack support, part 2
[not found] <cover.1414461460.git.amodra@gmail.com>
2014-10-29 3:32 ` [PATCH 3/5] 64-bit obstack support, part 1 Alan Modra
2014-10-29 3:32 ` [PATCH 1/5] obstack tidy " Alan Modra
@ 2014-10-29 3:32 ` Alan Modra
2014-10-29 3:32 ` [PATCH 2/5] obstack tidy " Alan Modra
` (2 subsequent siblings)
5 siblings, 0 replies; 13+ messages in thread
From: Alan Modra @ 2014-10-29 3:32 UTC (permalink / raw)
To: libc-alpha, bug-gnulib
This gets us 4G obstack support, without changing ABI compatibility,
apart from possibly introducing some signed/unsigned comparison
warnings in code that uses obstack.h.
a) Replace "int" size parameters, return values, and macro local vars
with _OBSTACK_SIZE_T, an "unsigned int" for now.
b) Make obstack.chunk_size a _CHUNK_SIZE_T, an "unsigned long" for now.
c) Make all obstack macros checking available room use obstack_room.
"next_free + desired > chunk_limit" may wrap the lhs for chunks
allocated near the top of memory.
d) Use unsigned comparisons, and macro locals to support >2G on 32-bit.
* lib/obstack.h (_OBSTACK_SIZE_T): Define. Use throughout
in place of "int" size parameters, return values and local vars.
(_CHUNK_SIZE_T): Define.
(struct obstack): Make chunk_size a _CHUNK_SIZE_T. Make temp
union use an _OBSTACK_SIZE_T integer type.
For __GNUC__ versions of the following macros...
(obstack_room): Rename local var.
(obstack_make_room): Use obstack_room.
(obstack_grow, obstack_grow0, obstack_1grow, obstack_ptr_grow,
obstack_int_grow, obstack_blank): Likewise.
(obstack_finish): Use unsigned comparison when comparing aligned
next_free against chunk_limit.
(obstack_free): Cast OBJ to remove possible const qualifier.
For !__GNUC__ versions of the following macros...
(obstack_make_room): Use obstack_room.
(obstack_grow, obstack_grow0, obstack_1grow, obstack_ptr_grow,
obstack_int_grow, obstack_blank): Likewise.
(obstack_finish): Use unsigned comparision when comparing aligned
next_free against chunk_limit.
(obstack_free): Use temp.p and same comparisons as __GNUC__ version.
* lib/obstack.c (_obstack_begin_worker): Make "size" parameter
_OBSTACK_SIZE_T.
(_obstack_begin, _obstack_begin_1): Likewise.
(_obstack_newchunk): Likewise for length parameter. Use size_t locals.
(_obstack_memory_used): Return and use _OBSTACK_SIZE_T local.
---
lib/obstack.c | 16 +++++------
lib/obstack.h | 89 +++++++++++++++++++++++++++++++----------------------------
2 files changed, 55 insertions(+), 50 deletions(-)
diff --git a/lib/obstack.c b/lib/obstack.c
index d9beb9b..eafb376 100644
--- a/lib/obstack.c
+++ b/lib/obstack.c
@@ -118,7 +118,7 @@ typedef void (*freefun_type) (void *, struct _obstack_chunk *);
static int
_obstack_begin_worker (struct obstack *h,
- int size, int alignment,
+ _OBSTACK_SIZE_T size, int alignment,
chunkfun_type chunkfun, freefun_type freefun)
{
struct _obstack_chunk *chunk; /* points to new chunk */
@@ -162,7 +162,7 @@ _obstack_begin_worker (struct obstack *h,
int
_obstack_begin (struct obstack *h,
- int size, int alignment,
+ _OBSTACK_SIZE_T size, int alignment,
void *(*chunkfun) (size_t),
void (*freefun) (void *))
{
@@ -174,7 +174,7 @@ _obstack_begin (struct obstack *h,
int
_obstack_begin_1 (struct obstack *h,
- int size, int alignment,
+ _OBSTACK_SIZE_T size, int alignment,
void *(*chunkfun) (void *, size_t),
void (*freefun) (void *, void *),
void *arg)
@@ -193,12 +193,12 @@ _obstack_begin_1 (struct obstack *h,
to the beginning of the new one. */
void
-_obstack_newchunk (struct obstack *h, int length)
+_obstack_newchunk (struct obstack *h, _OBSTACK_SIZE_T length)
{
struct _obstack_chunk *old_chunk = h->chunk;
struct _obstack_chunk *new_chunk;
- long new_size;
- long obj_size = h->next_free - h->object_base;
+ size_t new_size;
+ size_t obj_size = h->next_free - h->object_base;
char *object_base;
/* Compute size for new chunk. */
@@ -306,11 +306,11 @@ _obstack_free (struct obstack *h, void *obj)
strong_alias (_obstack_free, obstack_free)
# endif
-int
+_OBSTACK_SIZE_T
_obstack_memory_used (struct obstack *h)
{
struct _obstack_chunk *lp;
- int nbytes = 0;
+ _OBSTACK_SIZE_T nbytes = 0;
for (lp = h->chunk; lp != 0; lp = lp->prev)
{
diff --git a/lib/obstack.h b/lib/obstack.h
index ef647aa..b30cc3b 100644
--- a/lib/obstack.h
+++ b/lib/obstack.h
@@ -106,6 +106,9 @@
#include <stddef.h>
+#define _OBSTACK_SIZE_T unsigned int
+#define _CHUNK_SIZE_T unsigned long
+
/* If B is the base of an object addressed by P, return the result of
aligning P to the next multiple of A + 1. B and P must be of type
char *. A + 1 must be a power of 2. */
@@ -142,14 +145,14 @@ struct _obstack_chunk /* Lives at front of each chunk. */
struct obstack /* control current object in current chunk */
{
- long chunk_size; /* preferred size to allocate chunks in */
+ _CHUNK_SIZE_T 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 */
union
{
- ptrdiff_t i;
+ _OBSTACK_SIZE_T i;
void *p;
} temp; /* Temporary for some macros. */
int alignment_mask; /* Mask of alignment for each object. */
@@ -171,14 +174,15 @@ struct obstack /* control current object in current chunk */
/* Declare the external functions we use; they are in obstack.c. */
-extern void _obstack_newchunk (struct obstack *, int);
+extern void _obstack_newchunk (struct obstack *, _OBSTACK_SIZE_T);
extern void _obstack_free (struct obstack *, void *);
-extern int _obstack_begin (struct obstack *, int, int,
+extern int _obstack_begin (struct obstack *, _OBSTACK_SIZE_T, int,
void *(*)(size_t), void (*)(void *));
-extern int _obstack_begin_1 (struct obstack *, int, int,
+extern int _obstack_begin_1 (struct obstack *, _OBSTACK_SIZE_T, int,
void *(*)(void *, size_t),
void (*)(void *, void *), void *);
-extern int _obstack_memory_used (struct obstack *) __attribute_pure__;
+extern _OBSTACK_SIZE_T _obstack_memory_used (struct obstack *)
+ __attribute_pure__;
/* Error handler called when 'obstack_chunk_alloc' failed to allocate
@@ -254,18 +258,20 @@ extern int obstack_exit_failure;
# define obstack_object_size(OBSTACK) \
__extension__ \
({ struct obstack const *__o = (OBSTACK); \
- (unsigned) (__o->next_free - __o->object_base); })
+ (_OBSTACK_SIZE_T) (__o->next_free - __o->object_base); })
+/* The local variable is named __o1 to avoid a shadowed variable
+ warning when invoked from other obstack macros. */
# define obstack_room(OBSTACK) \
__extension__ \
- ({ struct obstack const *__o = (OBSTACK); \
- (unsigned) (__o->chunk_limit - __o->next_free); })
+ ({ struct obstack const *__o1 = (OBSTACK); \
+ (_OBSTACK_SIZE_T) (__o1->chunk_limit - __o1->next_free); })
# define obstack_make_room(OBSTACK, length) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
- int __len = (length); \
- if (__o->chunk_limit - __o->next_free < __len) \
+ _OBSTACK_SIZE_T __len = (length); \
+ if (obstack_room (__o) < __len) \
_obstack_newchunk (__o, __len); \
(void) 0; })
@@ -280,8 +286,8 @@ extern int obstack_exit_failure;
# define obstack_grow(OBSTACK, where, length) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
- int __len = (length); \
- if (__o->next_free + __len > __o->chunk_limit) \
+ _OBSTACK_SIZE_T __len = (length); \
+ if (obstack_room (__o) < __len) \
_obstack_newchunk (__o, __len); \
memcpy (__o->next_free, where, __len); \
__o->next_free += __len; \
@@ -290,8 +296,8 @@ extern int obstack_exit_failure;
# define obstack_grow0(OBSTACK, where, length) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
- int __len = (length); \
- if (__o->next_free + __len + 1 > __o->chunk_limit) \
+ _OBSTACK_SIZE_T __len = (length); \
+ if (obstack_room (__o) < __len + 1) \
_obstack_newchunk (__o, __len + 1); \
memcpy (__o->next_free, where, __len); \
__o->next_free += __len; \
@@ -301,7 +307,7 @@ extern int obstack_exit_failure;
# define obstack_1grow(OBSTACK, datum) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
- if (__o->next_free + 1 > __o->chunk_limit) \
+ if (obstack_room (__o) < 1) \
_obstack_newchunk (__o, 1); \
obstack_1grow_fast (__o, datum); \
(void) 0; })
@@ -313,14 +319,14 @@ extern int obstack_exit_failure;
# define obstack_ptr_grow(OBSTACK, datum) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
- if (__o->next_free + sizeof (void *) > __o->chunk_limit) \
+ if (obstack_room (__o) < sizeof (void *)) \
_obstack_newchunk (__o, sizeof (void *)); \
obstack_ptr_grow_fast (__o, datum); })
# define obstack_int_grow(OBSTACK, datum) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
- if (__o->next_free + sizeof (int) > __o->chunk_limit) \
+ if (obstack_room (__o) < sizeof (int)) \
_obstack_newchunk (__o, sizeof (int)); \
obstack_int_grow_fast (__o, datum); })
@@ -343,8 +349,8 @@ extern int obstack_exit_failure;
# define obstack_blank(OBSTACK, length) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
- int __len = (length); \
- if (__o->chunk_limit - __o->next_free < __len) \
+ _OBSTACK_SIZE_T __len = (length); \
+ if (obstack_room (__o) < __len) \
_obstack_newchunk (__o, __len); \
obstack_blank_fast (__o, __len); \
(void) 0; })
@@ -367,8 +373,8 @@ extern int obstack_exit_failure;
obstack_grow0 (__h, (where), (length)); \
obstack_finish (__h); })
-/* The local variable is named __o1 to avoid a name conflict
- when obstack_blank is called. */
+/* The local variable is named __o1 to avoid a shadowed variable
+ warning when invoked from other obstack macros, typically obstack_free. */
# define obstack_finish(OBSTACK) \
__extension__ \
({ struct obstack *__o1 = (OBSTACK); \
@@ -378,8 +384,8 @@ extern int obstack_exit_failure;
__o1->next_free \
= __PTR_ALIGN (__o1->object_base, __o1->next_free, \
__o1->alignment_mask); \
- if (__o1->next_free - (char *) __o1->chunk \
- > __o1->chunk_limit - (char *) __o1->chunk) \
+ if ((size_t) (__o1->next_free - (char *) __o1->chunk) \
+ > (size_t) (__o1->chunk_limit - (char *) __o1->chunk)) \
__o1->next_free = __o1->chunk_limit; \
__o1->object_base = __o1->next_free; \
__value; })
@@ -387,7 +393,7 @@ extern int obstack_exit_failure;
# define obstack_free(OBSTACK, OBJ) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
- void *__obj = (OBJ); \
+ void *__obj = (void *) (OBJ); \
if (__obj > (void *) __o->chunk && __obj < (void *) __o->chunk_limit) \
__o->next_free = __o->object_base = (char *) __obj; \
else \
@@ -396,10 +402,10 @@ extern int obstack_exit_failure;
#else /* not __GNUC__ */
# define obstack_object_size(h) \
- ((unsigned) ((h)->next_free - (h)->object_base))
+ ((_OBSTACK_SIZE_T) ((h)->next_free - (h)->object_base))
# define obstack_room(h) \
- ((unsigned) ((h)->chunk_limit - (h)->next_free))
+ ((_OBSTACK_SIZE_T) ((h)->chunk_limit - (h)->next_free))
# define obstack_empty_p(h) \
((h)->chunk->prev == 0 \
@@ -415,36 +421,36 @@ extern int obstack_exit_failure;
# define obstack_make_room(h, length) \
((h)->temp.i = (length), \
- (((h)->next_free + (h)->temp.i > (h)->chunk_limit) \
+ ((obstack_room (h) < (h)->temp.i) \
? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0))
# define obstack_grow(h, where, length) \
((h)->temp.i = (length), \
- (((h)->next_free + (h)->temp.i > (h)->chunk_limit) \
+ ((obstack_room (h) < (h)->temp.i) \
? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0), \
memcpy ((h)->next_free, where, (h)->temp.i), \
(h)->next_free += (h)->temp.i)
# define obstack_grow0(h, where, length) \
((h)->temp.i = (length), \
- (((h)->next_free + (h)->temp.i + 1 > (h)->chunk_limit) \
+ ((obstack_room (h) < (h)->temp.i + 1) \
? (_obstack_newchunk ((h), (h)->temp.i + 1), 0) : 0), \
memcpy ((h)->next_free, where, (h)->temp.i), \
(h)->next_free += (h)->temp.i, \
*((h)->next_free)++ = 0)
# define obstack_1grow(h, datum) \
- ((((h)->next_free + 1 > (h)->chunk_limit) \
+ (((obstack_room (h) < 1) \
? (_obstack_newchunk ((h), 1), 0) : 0), \
obstack_1grow_fast (h, datum))
# define obstack_ptr_grow(h, datum) \
- ((((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
+ (((obstack_room (h) < sizeof (char *)) \
? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
obstack_ptr_grow_fast (h, datum))
# define obstack_int_grow(h, datum) \
- ((((h)->next_free + sizeof (int) > (h)->chunk_limit) \
+ (((obstack_room (h) < sizeof (int)) \
? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
obstack_int_grow_fast (h, datum))
@@ -456,7 +462,7 @@ extern int obstack_exit_failure;
# define obstack_blank(h, length) \
((h)->temp.i = (length), \
- (((h)->chunk_limit - (h)->next_free < (h)->temp.i) \
+ ((obstack_room (h) < (h)->temp.i) \
? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0), \
obstack_blank_fast (h, (h)->temp.i))
@@ -477,19 +483,18 @@ extern int obstack_exit_failure;
(h)->next_free \
= __PTR_ALIGN ((h)->object_base, (h)->next_free, \
(h)->alignment_mask), \
- (((h)->next_free - (char *) (h)->chunk \
- > (h)->chunk_limit - (char *) (h)->chunk) \
+ (((size_t) ((h)->next_free - (char *) (h)->chunk) \
+ > (size_t) ((h)->chunk_limit - (char *) (h)->chunk)) \
? ((h)->next_free = (h)->chunk_limit) : 0), \
(h)->object_base = (h)->next_free, \
(h)->temp.p)
# define obstack_free(h, obj) \
- ((h)->temp.i = (char *) (obj) - (char *) (h)->chunk, \
- ((((h)->temp.i > 0 \
- && (h)->temp.i < (h)->chunk_limit - (char *) (h)->chunk)) \
- ? (void) ((h)->next_free = (h)->object_base \
- = (h)->temp.i + (char *) (h)->chunk) \
- : _obstack_free (h, (h)->temp.i + (char *) (h)->chunk)))
+ ((h)->temp.p = (void *) (obj), \
+ (((h)->temp.p > (void *) (h)->chunk \
+ && (h)->temp.p < (void *) (h)->chunk_limit) \
+ ? (void) ((h)->next_free = (h)->object_base = (char *) (h)->temp.p) \
+ : _obstack_free ((h), (h)->temp.p)))
#endif /* not __GNUC__ */
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 2/5] obstack tidy part 2
[not found] <cover.1414461460.git.amodra@gmail.com>
` (2 preceding siblings ...)
2014-10-29 3:32 ` [PATCH 4/5] 64-bit obstack support, part 2 Alan Modra
@ 2014-10-29 3:32 ` Alan Modra
2014-10-30 19:51 ` Roland McGrath
2014-10-29 3:33 ` [PATCH 5/5] 64-bit obstack support, part 3 Alan Modra
2014-10-29 3:35 ` [PATCH] 64-bit obstack support Alan Modra
5 siblings, 1 reply; 13+ messages in thread
From: Alan Modra @ 2014-10-29 3:32 UTC (permalink / raw)
To: libc-alpha, bug-gnulib
a) Don't be concerned about "not polluting the namespace with stddef.h
symbols" in obstack.h, since gnulib string.h includes stddef.h
anyway, and it seems unlikely that anyone would care.
b) Don't roll our own slow memcpy in _obstack_newchunk.
c) Rename obstack_free to _obstack_free. This makes the naming
consistent with other obstack functions and obviates the need for
__obstack_free. Ancient obstack.c defined both obstack_free and
_obstack_free. We continue to do that for _LIBC via an alias.
d) Miscellaneous macro fixes. The expression used to test for gcc-2.8
is clever, but nowadays gcc warns on undefined macros. You'll get
an undefined macro warning if simulating an old gcc with -U__GNUC__
-U__GNUC_MINOR__ -D__GNUC__=1.
* lib/obstack.h: Include stddef.h unconditionally. Formatting fixes.
(PTR_INT_TYPE): Delete, replace with ptrdiff_t.
(__obstack_free): Delete, update refs.
(_obstack_free): Rename from obstack_free.
(__extension__): Avoid undefined macro warning for __GNUC_MINOR__.
(obstack_object_size, obstack_room): Parenthesise !__GNUC__ versions.
* lib/obstack.c: Don't include stddef.h.
(COPYING_UNIT): Delete.
(_obstack_begin): Formatting fix.
(_obstack_newchunk): Use memcpy to move existing object to new chunk.
(_obstack_free): Rename from __obstack_free, update alias. Move
undef of obstack_free to where it is needed.
---
lib/obstack.c | 47 +++++++----------------------------------------
lib/obstack.h | 53 +++++++++++++++++++----------------------------------
2 files changed, 26 insertions(+), 74 deletions(-)
diff --git a/lib/obstack.c b/lib/obstack.c
index 66573df..2d5dfbc 100644
--- a/lib/obstack.c
+++ b/lib/obstack.c
@@ -47,8 +47,6 @@
# endif
#endif
-#include <stddef.h>
-
#ifndef ELIDE_CODE
@@ -76,14 +74,6 @@ enum
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
-
# ifdef _LIBC
# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
@@ -161,8 +151,7 @@ _obstack_begin (struct obstack *h,
(*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;
+ 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;
@@ -231,8 +220,6 @@ _obstack_newchunk (struct obstack *h, int length)
struct _obstack_chunk *new_chunk;
long new_size;
long obj_size = h->next_free - h->object_base;
- long i;
- long already;
char *object_base;
/* Compute size for new chunk. */
@@ -252,25 +239,8 @@ _obstack_newchunk (struct obstack *h, int length)
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];
+ /* Move the existing object to the new chunk. */
+ memcpy (object_base, h->object_base, obj_size);
/* If the object just copied was the only data in OLD_CHUNK,
free that chunk and remove it from the chain.
@@ -322,10 +292,8 @@ _obstack_allocated_p (struct obstack *h, void *obj)
/* 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
-
void
-__obstack_free (struct obstack *h, void *obj)
+_obstack_free (struct obstack *h, void *obj)
{
struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
struct _obstack_chunk *plp; /* point to previous chunk if any */
@@ -353,11 +321,10 @@ __obstack_free (struct obstack *h, void *obj)
/* obj is not in any of the chunks! */
abort ();
}
-
# ifdef _LIBC
-/* Older versions of libc used a function _obstack_free intended to be
- called by non-GCC compilers. */
-strong_alias (obstack_free, _obstack_free)
+/* Older versions of libc defined both _obstack_free and obstack_free. */
+# undef obstack_free
+strong_alias (_obstack_free, obstack_free)
# endif
int
diff --git a/lib/obstack.h b/lib/obstack.h
index cd90e4e..f3a7c77 100644
--- a/lib/obstack.h
+++ b/lib/obstack.h
@@ -104,17 +104,7 @@
#ifndef _OBSTACK_H
#define _OBSTACK_H 1
-/* We need the type of a pointer subtraction. If __PTRDIFF_TYPE__ is
- defined, as with GNU C, use that; that way we don't pollute the
- namespace with <stddef.h>'s symbols. Otherwise, include <stddef.h>
- and use ptrdiff_t. */
-
-#ifdef __PTRDIFF_TYPE__
-# define PTR_INT_TYPE __PTRDIFF_TYPE__
-#else
-# include <stddef.h>
-# define PTR_INT_TYPE ptrdiff_t
-#endif
+#include <stddef.h>
/* If B is the base of an object addressed by P, return the result of
aligning P to the next multiple of A + 1. B and P must be of type
@@ -122,15 +112,15 @@
#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A)))
-/* Similar to _BPTR_ALIGN (B, P, A), except optimize the common case
+/* Similar to __BPTR_ALIGN (B, P, A), except optimize the common case
where pointers can be converted to integers, aligned as integers,
- and converted back again. If PTR_INT_TYPE is narrower than a
+ and converted back again. If ptrdiff_t is narrower than a
pointer (e.g., the AS/400), play it safe and compute the alignment
relative to B. Otherwise, use the faster strategy of computing the
alignment relative to 0. */
#define __PTR_ALIGN(B, P, A) \
- __BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \
+ __BPTR_ALIGN (sizeof (ptrdiff_t) < sizeof (void *) ? (B) : (char *) 0, \
P, A)
#include <string.h>
@@ -159,7 +149,7 @@ struct obstack /* control current object in current chunk */
char *chunk_limit; /* address of char after current chunk */
union
{
- PTR_INT_TYPE i;
+ ptrdiff_t i;
void *p;
} temp; /* Temporary for some macros. */
int alignment_mask; /* Mask of alignment for each object. */
@@ -182,6 +172,7 @@ struct obstack /* control current object in current chunk */
/* Declare the external functions we use; they are in obstack.c. */
extern void _obstack_newchunk (struct obstack *, int);
+extern void _obstack_free (struct obstack *, void *);
extern int _obstack_begin (struct obstack *, int, int,
void *(*)(long), void (*)(void *));
extern int _obstack_begin_1 (struct obstack *, int, int,
@@ -189,13 +180,6 @@ extern int _obstack_begin_1 (struct obstack *, int, int,
void (*)(void *, void *), void *);
extern int _obstack_memory_used (struct obstack *) __attribute_pure__;
-/* The default name of the function for freeing a chunk is 'obstack_free',
- but gnulib users can override this by defining '__obstack_free'. */
-#ifndef __obstack_free
-# define __obstack_free obstack_free
-#endif
-extern void __obstack_free (struct obstack *, void *);
-
/* Error handler called when 'obstack_chunk_alloc' failed to allocate
more memory. This can be set to a user defined function which
@@ -235,7 +219,7 @@ extern int obstack_exit_failure;
(void *(*)(long))obstack_chunk_alloc, \
(void (*)(void *))obstack_chunk_free)
-#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
+#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
_obstack_begin ((h), (size), (alignment), \
(void *(*)(long))(chunkfun), \
(void (*)(void *))(freefun))
@@ -245,10 +229,10 @@ extern int obstack_exit_failure;
(void *(*)(void *, long))(chunkfun), \
(void (*)(void *, void *))(freefun), (arg))
-#define obstack_chunkfun(h, newchunkfun) \
+#define obstack_chunkfun(h, newchunkfun) \
((h)->chunkfun = (struct _obstack_chunk *(*)(void *, long))(newchunkfun))
-#define obstack_freefun(h, newfreefun) \
+#define obstack_freefun(h, newfreefun) \
((h)->freefun = (void (*)(void *, struct _obstack_chunk *))(newfreefun))
#define obstack_1grow_fast(h, achar) (*((h)->next_free)++ = (achar))
@@ -258,7 +242,7 @@ extern int obstack_exit_failure;
#define obstack_memory_used(h) _obstack_memory_used (h)
#if defined __GNUC__
-# if ! (2 < __GNUC__ + (8 <= __GNUC_MINOR__))
+# if !defined __GNUC_MINOR__ || __GNUC__ * 1000 + __GNUC_MINOR__ < 2008
# define __extension__
# endif
@@ -331,7 +315,7 @@ extern int obstack_exit_failure;
({ struct obstack *__o = (OBSTACK); \
if (__o->next_free + sizeof (void *) > __o->chunk_limit) \
_obstack_newchunk (__o, sizeof (void *)); \
- obstack_ptr_grow_fast (__o, datum); }) \
+ obstack_ptr_grow_fast (__o, datum); })
# define obstack_int_grow(OBSTACK, datum) \
__extension__ \
@@ -406,17 +390,18 @@ extern int obstack_exit_failure;
void *__obj = (OBJ); \
if (__obj > (void *) __o->chunk && __obj < (void *) __o->chunk_limit) \
__o->next_free = __o->object_base = (char *) __obj; \
- else (__obstack_free) (__o, __obj); })
+ else \
+ _obstack_free (__o, __obj); })
#else /* not __GNUC__ */
-# define obstack_object_size(h) \
- (unsigned) ((h)->next_free - (h)->object_base)
+# define obstack_object_size(h) \
+ ((unsigned) ((h)->next_free - (h)->object_base))
# define obstack_room(h) \
- (unsigned) ((h)->chunk_limit - (h)->next_free)
+ ((unsigned) ((h)->chunk_limit - (h)->next_free))
-# define obstack_empty_p(h) \
+# define obstack_empty_p(h) \
((h)->chunk->prev == 0 \
&& (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk, \
(h)->chunk->contents, \
@@ -504,7 +489,7 @@ extern int obstack_exit_failure;
&& (h)->temp.i < (h)->chunk_limit - (char *) (h)->chunk)) \
? (void) ((h)->next_free = (h)->object_base \
= (h)->temp.i + (char *) (h)->chunk) \
- : (__obstack_free) (h, (h)->temp.i + (char *) (h)->chunk)))
+ : _obstack_free (h, (h)->temp.i + (char *) (h)->chunk)))
#endif /* not __GNUC__ */
@@ -512,4 +497,4 @@ extern int obstack_exit_failure;
} /* C++ */
#endif
-#endif /* obstack.h */
+#endif /* _OBSTACK_H */
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/5] obstack tidy part 2
2014-10-29 3:32 ` [PATCH 2/5] obstack tidy " Alan Modra
@ 2014-10-30 19:51 ` Roland McGrath
2014-10-30 23:54 ` Alan Modra
0 siblings, 1 reply; 13+ messages in thread
From: Roland McGrath @ 2014-10-30 19:51 UTC (permalink / raw)
To: Alan Modra; +Cc: libc-alpha, bug-gnulib
> a) Don't be concerned about "not polluting the namespace with stddef.h
> symbols" in obstack.h, since gnulib string.h includes stddef.h
> anyway, and it seems unlikely that anyone would care.
libc is where this sort of constraint is most likely to be important. I
doubt gnulib users care. Since obstack.h is not standard, we are free to
decide we don't care for libc either. But it is not something to be done
lightly. If this change doesn't actually enable anything else you're
doing, please leave it for later as a separate individual item.
> b) Don't roll our own slow memcpy in _obstack_newchunk.
Good change.
> c) Rename obstack_free to _obstack_free. This makes the naming
> consistent with other obstack functions and obviates the need for
> __obstack_free. Ancient obstack.c defined both obstack_free and
> _obstack_free. We continue to do that for _LIBC via an alias.
> d) Miscellaneous macro fixes. The expression used to test for gcc-2.8
> is clever, but nowadays gcc warns on undefined macros. You'll get
> an undefined macro warning if simulating an old gcc with -U__GNUC__
> -U__GNUC_MINOR__ -D__GNUC__=1.
These seem OK to me.
You didn't report what testing you did for the libc build, which is
mandatory for approval. In particular, we have 'make check-abi' to be
concerned with, which is not something relevant to gnulib.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/5] obstack tidy part 2
2014-10-30 19:51 ` Roland McGrath
@ 2014-10-30 23:54 ` Alan Modra
0 siblings, 0 replies; 13+ messages in thread
From: Alan Modra @ 2014-10-30 23:54 UTC (permalink / raw)
To: Roland McGrath; +Cc: libc-alpha, bug-gnulib
On Thu, Oct 30, 2014 at 12:51:11PM -0700, Roland McGrath wrote:
> > a) Don't be concerned about "not polluting the namespace with stddef.h
> > symbols" in obstack.h, since gnulib string.h includes stddef.h
> > anyway, and it seems unlikely that anyone would care.
>
> libc is where this sort of constraint is most likely to be important. I
> doubt gnulib users care. Since obstack.h is not standard, we are free to
> decide we don't care for libc either. But it is not something to be done
> lightly. If this change doesn't actually enable anything else you're
> doing, please leave it for later as a separate individual item.
stddef.h is needed for size_t, used in the next patch of the series.
Hmm, I see most of glibc's public headers that require size_t do so
using "#define __need_size_t". Would the following be acceptable?
#define __need_ptrdiff_t
#define __need_size_t
#include "stddef.h"
Continuing to use PTR_INT_TYPE and inventing another for size_t rather
than using the standard types just seems so 1980 style.
> You didn't report what testing you did for the libc build, which is
> mandatory for approval. In particular, we have 'make check-abi' to be
> concerned with, which is not something relevant to gnulib.
I built both x86_64-linux and i686-linux, and ran "make check". The
cover letter noted that the abilist files need updating for the abi
check to pass. Both builds showed the following diff, with the
expected obstack symbols plus another apparently due to building with
a non-standard prefix.
--- ../sysdeps/unix/sysv/linux/x86_64/64/libc.abilist 2014-07-02 13:52:44.682722675 +0930
+++ /home/alan/build/glibc/libc.symlist 2014-10-27 16:27:51.205030088 +1030
@@ -519 +519 @@ GLIBC_2.2.5
- _nl_default_dirname D 0x12
+ _nl_default_dirname D 0x1c
@@ -1856,0 +1857,8 @@ GLIBC_2.2.6
+GLIBC_2.21
+ GLIBC_2.21 A
+ _obstack_allocated_p F
+ _obstack_begin F
+ _obstack_begin_1 F
+ _obstack_free F
+ _obstack_memory_used F
+ _obstack_newchunk F
I also looked at exported obstack symbols for various other
non-standard builds, and checked that __GI__obstack_newchunk matched
the proper _obstack_newchunk (I had it wrong at one stage).
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 5/5] 64-bit obstack support, part 3
[not found] <cover.1414461460.git.amodra@gmail.com>
` (3 preceding siblings ...)
2014-10-29 3:32 ` [PATCH 2/5] obstack tidy " Alan Modra
@ 2014-10-29 3:33 ` Alan Modra
2014-10-29 3:35 ` [PATCH] 64-bit obstack support Alan Modra
5 siblings, 0 replies; 13+ messages in thread
From: Alan Modra @ 2014-10-29 3:33 UTC (permalink / raw)
To: libc-alpha, bug-gnulib
This finally enables full 64-bit obstack support. The glibc shared library
specific code is removed from obstack.c too, and the error handling code
conditionally compiled under control of another macro,
_OBSTACK_NO_ERROR_HANDLER.
* lib/obstack.h: Include string.h earlier.
(_OBSTACK_INTERFACE_VERSION): Define.
(_OBSTACK_SIZE_T, _CHUNK_SIZE_T): Define as size_t for version 2.
* lib/obstack.c: Don't include shlib-compat.h.
(OBSTACK_INTERFACE_VERSION): Delete.
(_OBSTACK_ELIDE_CODE): Rename from ELIDE_CODE. Define when version 1
glibc code is compatible with version 2. Don't include stdio.h for
__GNU_LIBRARY.
(obstack_exit_failure, print_and_abort, obstack_alloc_failed_handler):
Omit when _OBSTACK_NO_ERROR_HANDLER defined. Include stdio.h here.
(_obstack_compat, _obstack, _obstack_newchunk, obstack_free): Delete
glibc shared library specific source.
---
lib/obstack.c | 83 ++++++++++++++++++++++++-----------------------------------
lib/obstack.h | 21 +++++++++++----
2 files changed, 49 insertions(+), 55 deletions(-)
diff --git a/lib/obstack.c b/lib/obstack.c
index eafb376..183bd0d 100644
--- a/lib/obstack.c
+++ b/lib/obstack.c
@@ -19,16 +19,14 @@
#ifdef _LIBC
# include <obstack.h>
-# include <shlib-compat.h>
#else
# include <config.h>
# include "obstack.h"
#endif
-/* 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
+/* NOTE BEFORE MODIFYING THIS FILE: _OBSTACK_INTERFACE_VERSION in
+ obstack.h must be incremented whenever callers compiled using an old
+ obstack.h can no longer properly call the functions in this file. */
/* 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
@@ -38,18 +36,18 @@
(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
+# if (_GNU_OBSTACK_INTERFACE_VERSION == _OBSTACK_INTERFACE_VERSION \
+ || (_GNU_OBSTACK_INTERFACE_VERSION == 1 \
+ && _OBSTACK_INTERFACE_VERSION == 2 \
+ && defined SIZEOF_INT && defined SIZEOF_SIZE_T \
+ && SIZEOF_INT == SIZEOF_SIZE_T))
+# define _OBSTACK_ELIDE_CODE
# endif
#endif
-#ifndef ELIDE_CODE
-
-
+#ifndef _OBSTACK_ELIDE_CODE
# include <stdlib.h>
# include <stdint.h>
@@ -75,16 +73,6 @@ enum
};
-# ifdef _LIBC
-# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
-/* A looong time ago (before 1994, anyway; we're not sure) this global variable
- was used by non-GNU-C macros to avoid multiple evaluation. The GNU C
- library still exports it because somebody might use it. */
-struct obstack *_obstack_compat = 0;
-compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
-# endif
-# endif
-
/* 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.
@@ -238,9 +226,6 @@ _obstack_newchunk (struct obstack *h, _OBSTACK_SIZE_T length)
/* The new chunk certainly contains no empty object yet. */
h->maybe_empty_object = 0;
}
-# ifdef _LIBC
-libc_hidden_def (_obstack_newchunk)
-# endif
/* Return nonzero if object OBJ has been allocated from obstack H.
This is here for debugging.
@@ -300,11 +285,6 @@ _obstack_free (struct obstack *h, void *obj)
/* obj is not in any of the chunks! */
abort ();
}
-# ifdef _LIBC
-/* Older versions of libc defined both _obstack_free and obstack_free. */
-# undef obstack_free
-strong_alias (_obstack_free, obstack_free)
-# endif
_OBSTACK_SIZE_T
_obstack_memory_used (struct obstack *h)
@@ -319,28 +299,30 @@ _obstack_memory_used (struct obstack *h)
return nbytes;
}
+# ifndef _OBSTACK_NO_ERROR_HANDLER
/* Define the error handler. */
+# include <stdio.h>
/* Exit value used when 'print_and_abort' is used. */
-# ifdef _LIBC
+# ifdef _LIBC
int obstack_exit_failure = EXIT_FAILURE;
-# else
-# include "exitfail.h"
-# define obstack_exit_failure exit_failure
-# endif
+# else
+# include "exitfail.h"
+# define obstack_exit_failure exit_failure
+# endif
-# ifdef _LIBC
-# include <libintl.h>
-# else
-# include "gettext.h"
-# endif
-# ifndef _
-# define _(msgid) gettext (msgid)
-# endif
+# ifdef _LIBC
+# include <libintl.h>
+# else
+# include "gettext.h"
+# endif
+# ifndef _
+# define _(msgid) gettext (msgid)
+# endif
-# ifdef _LIBC
-# include <libio/iolibio.h>
-# endif
+# ifdef _LIBC
+# include <libio/iolibio.h>
+# endif
static _Noreturn void
print_and_abort (void)
@@ -350,11 +332,11 @@ print_and_abort (void)
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
+# ifdef _LIBC
(void) __fxprintf (NULL, "%s\n", _("memory exhausted"));
-# else
+# else
fprintf (stderr, "%s\n", _("memory exhausted"));
-# endif
+# endif
exit (obstack_exit_failure);
}
@@ -365,4 +347,5 @@ print_and_abort (void)
variable by default points to the internal function
'print_and_abort'. */
void (*obstack_alloc_failed_handler) (void) = print_and_abort;
-#endif /* !ELIDE_CODE */
+# endif /* !_OBSTACK_NO_ERROR_HANDLER */
+#endif /* !_OBSTACK_ELIDE_CODE */
diff --git a/lib/obstack.h b/lib/obstack.h
index b30cc3b..9b9f965 100644
--- a/lib/obstack.h
+++ b/lib/obstack.h
@@ -104,10 +104,23 @@
#ifndef _OBSTACK_H
#define _OBSTACK_H 1
-#include <stddef.h>
+#ifndef _OBSTACK_INTERFACE_VERSION
+# define _OBSTACK_INTERFACE_VERSION 2
+#endif
-#define _OBSTACK_SIZE_T unsigned int
-#define _CHUNK_SIZE_T unsigned long
+#include <stddef.h> /* For size_t and ptrdiff_t. */
+#include <string.h> /* For __GNU_LIBRARY__, and memcpy. */
+
+#if _OBSTACK_INTERFACE_VERSION == 1
+/* For binary compatibility with obstack version 1, which used "int"
+ and "long" for these two types. */
+# define _OBSTACK_SIZE_T unsigned int
+# define _CHUNK_SIZE_T unsigned long
+#else
+/* Version 2 with sane types, especially for 64-bit hosts. */
+# define _OBSTACK_SIZE_T size_t
+# define _CHUNK_SIZE_T size_t
+#endif
/* If B is the base of an object addressed by P, return the result of
aligning P to the next multiple of A + 1. B and P must be of type
@@ -126,8 +139,6 @@
__BPTR_ALIGN (sizeof (ptrdiff_t) < sizeof (void *) ? (B) : (char *) 0, \
P, A)
-#include <string.h>
-
#ifndef __attribute_pure__
# define __attribute_pure__ _GL_ATTRIBUTE_PURE
#endif
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH] 64-bit obstack support
[not found] <cover.1414461460.git.amodra@gmail.com>
` (4 preceding siblings ...)
2014-10-29 3:33 ` [PATCH 5/5] 64-bit obstack support, part 3 Alan Modra
@ 2014-10-29 3:35 ` Alan Modra
2014-10-29 18:34 ` Joseph S. Myers
5 siblings, 1 reply; 13+ messages in thread
From: Alan Modra @ 2014-10-29 3:35 UTC (permalink / raw)
To: libc-alpha, bug-gnulib
And >2G on 32-bit.
* include/gnu-versions.h (_GNU_OBSTACK_INTERFACE_VERSION): Bump.
* include/obstack.h: Include shlib-compat.h and gnu-versions.h.
(_OBSTACK_ELIDE_CODE, _OBSTACK_NO_ERROR_HANDLER, _OBSTACK_COMPAT,
_OBSTACK_ALIAS): Define.
(_obstack_allocated_p, _obstack_newchunk, _obstack_free,
_obstack_begin, _obstack_begin_1, _obstack_memory_used): Define.
(_obstack_newchunk): Only use libc_hidden_proto on the version
we will use inside glibc.
* malloc/obstack.h: Import from gnulib.
* malloc/obstack.c: Likewise.
* malloc/obstackv1.c: New file.
* malloc/obstackv2.c: New file.
* malloc/Makefile (routines): Remove obstack. Add obstackv1 and
obstackv2.
(CFLAGS-obstack.c): Don't define.
(CFLAGS-obstackv1.c, CFLAGS-obstackv2.c): Define.
(malloc/Versions): Add GLIBC_2.21 _obstack functions.
* config.h.in (SIZEOF_INT, SIZEOF_SIZE_T): Add.
* configure.in: AC_CHECK_SIZEOF int and size_t.
* configure: Regenerate.
---
config.h.in | 6 ++
configure | 68 +++++++++++++
configure.ac | 4 +
include/gnu-versions.h | 2 +-
include/obstack.h | 76 ++++++++++++++
malloc/Makefile | 5 +-
malloc/Versions | 4 +
malloc/obstack.c | 266 ++++++++++++++++++------------------------------
malloc/obstack.h | 271 +++++++++++++++++++++++++------------------------
malloc/obstackv1.c | 59 +++++++++++
malloc/obstackv2.c | 69 +++++++++++++
11 files changed, 523 insertions(+), 307 deletions(-)
create mode 100644 malloc/obstackv1.c
create mode 100644 malloc/obstackv2.c
diff --git a/config.h.in b/config.h.in
index 20c0825..82cd82b 100644
--- a/config.h.in
+++ b/config.h.in
@@ -200,6 +200,12 @@
/* Define if the linker defines __ehdr_start. */
#undef HAVE_EHDR_START
+/* The size of "int", as computed by sizeof. */
+#undef SIZEOF_INT
+
+/* The size of "size_t", as computed by sizeof. */
+#undef SIZEOF_SIZE_T
+
/*
\f */
diff --git a/configure.ac b/configure.ac
index 82d0896..07b4b0b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1799,6 +1799,10 @@ AC_CHECK_SIZEOF(long double, 0)
sizeof_long_double=$ac_cv_sizeof_long_double
AC_SUBST(sizeof_long_double)
+dnl Determine the size of int and size_t for obstack.h.
+AC_CHECK_SIZEOF([int])
+AC_CHECK_SIZEOF([size_t],,[#include <stddef.h>])
+
CPPUNDEFS=
dnl Check for silly hacked compilers predefining _FORTIFY_SOURCE.
dnl Since we are building the implementations of the fortified functions here,
diff --git a/include/gnu-versions.h b/include/gnu-versions.h
index 6ffbd47..99caf5b 100644
--- a/include/gnu-versions.h
+++ b/include/gnu-versions.h
@@ -43,7 +43,7 @@
remember, if any of these versions change, the libc.so major version
number must change too (so avoid it)! */
-#define _GNU_OBSTACK_INTERFACE_VERSION 1 /* vs malloc/obstack.c */
+#define _GNU_OBSTACK_INTERFACE_VERSION 2 /* vs malloc/obstack.c */
#define _GNU_REGEX_INTERFACE_VERSION 1 /* vs posix/regex.c */
#define _GNU_GLOB_INTERFACE_VERSION 1 /* vs posix/glob.c */
#define _GNU_GETOPT_INTERFACE_VERSION 2 /* vs posix/getopt.c and
diff --git a/include/obstack.h b/include/obstack.h
index 349d59b..b346fba 100644
--- a/include/obstack.h
+++ b/include/obstack.h
@@ -1,3 +1,79 @@
+/* Control compile of obstackv1.c and obstackv2.c
+ Copyright (C) 2014 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef _OBSTACK_C
+/* We are compiling obstackv1.c or obstackv2.c. */
+# include <shlib-compat.h>
+# include <gnu-versions.h>
+
+# if _GNU_OBSTACK_INTERFACE_VERSION == 1
+/* Only build version 1 support. */
+# if _OBSTACK_INTERFACE_VERSION != 1
+# define _OBSTACK_ELIDE_CODE
+# endif
+# elif SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_21)
+# define _OBSTACK_COMPAT
+# if (defined SIZEOF_INT && defined SIZEOF_SIZE_T \
+ && SIZEOF_INT == SIZEOF_SIZE_T)
+/* The version 1 code is ABI compatible with version 2, obstackv1.c is
+ redundant. When compiling obstackv2.c, emit symbols versioned as
+ for version 1 obstacks. */
+# if _OBSTACK_INTERFACE_VERSION == 1
+# define _OBSTACK_ELIDE_CODE
+# else
+# define _OBSTACK_ALIAS
+# endif
+# else /* SIZEOF_INT != SIZEOF_SIZE_T */
+/* Distinct version 1 and version 2 functions are needed, with the
+ exception of the error handler. */
+# if _OBSTACK_INTERFACE_VERSION == 1
+# define _OBSTACK_NO_ERROR_HANDLER
+# endif
+# endif
+# else /* !SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_21) */
+/* We don't want any version 1 support. */
+# if _OBSTACK_INTERFACE_VERSION == 1
+# define _OBSTACK_ELIDE_CODE
+# endif
+# endif
+
+# ifdef _OBSTACK_COMPAT
+# if _OBSTACK_INTERFACE_VERSION == 1
+# define _obstack_allocated_p _obstackv1_allocated_p
+# define _obstack_begin _obstackv1_begin
+# define _obstack_begin_1 _obstackv1_begin_1
+# define _obstack_free _obstackv1_free
+# define _obstack_memory_used _obstackv1_memory_used
+# define _obstack_newchunk _obstackv1_newchunk
+# else
+# define _obstack_allocated_p _obstackv2_allocated_p
+# define _obstack_begin _obstackv2_begin
+# define _obstack_begin_1 _obstackv2_begin_1
+# define _obstack_free _obstackv2_free
+# define _obstack_memory_used _obstackv2_memory_used
+# define _obstack_newchunk _obstackv2_newchunk
+# endif
+# endif
+#endif
+
#include <malloc/obstack.h>
+#if (!defined _OBSTACK_C \
+ || _GNU_OBSTACK_INTERFACE_VERSION == _OBSTACK_INTERFACE_VERSION)
libc_hidden_proto (_obstack_newchunk)
+#endif
diff --git a/malloc/Makefile b/malloc/Makefile
index 9e93523..6879d96 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -30,7 +30,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
tst-pvalloc tst-memalign tst-mallopt
test-srcs = tst-mtrace
-routines = malloc morecore mcheck mtrace obstack
+routines = malloc morecore mcheck mtrace obstackv1 obstackv2
install-lib := libmcheck.a
non-lib.a := libmcheck.a
@@ -103,7 +103,8 @@ endif
include ../Rules
CFLAGS-mcheck-init.c = $(PIC-ccflag)
-CFLAGS-obstack.c = $(uses-callbacks)
+CFLAGS-obstackv1.c = $(uses-callbacks)
+CFLAGS-obstackv2.c = $(uses-callbacks)
$(objpfx)libmcheck.a: $(objpfx)mcheck-init.o
-rm -f $@
diff --git a/malloc/Versions b/malloc/Versions
index 7ca9bdf..1c60d21 100644
--- a/malloc/Versions
+++ b/malloc/Versions
@@ -61,6 +61,10 @@ libc {
GLIBC_2.16 {
aligned_alloc;
}
+ GLIBC_2.21 {
+ _obstack_allocated_p; _obstack_begin; _obstack_begin_1;
+ _obstack_free; _obstack_memory_used; _obstack_newchunk;
+ }
GLIBC_PRIVATE {
# Internal startup hook for libpthread.
__libc_malloc_pthread_startup;
diff --git a/malloc/obstackv1.c b/malloc/obstackv1.c
new file mode 100644
index 0000000..24eaee0
--- /dev/null
+++ b/malloc/obstackv1.c
@@ -0,0 +1,59 @@
+/* obstackv1.c - subroutines used implicitly by object stack macros
+ Copyright (C) 2014 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Build version 1 compatibility support. */
+#define _OBSTACK_INTERFACE_VERSION 1
+#define _OBSTACK_C 1
+
+#include "obstack.c"
+
+#ifndef _OBSTACK_ELIDE_CODE
+
+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_21)
+# undef obstack_free
+strong_alias (_obstack_free, obstackv1_free)
+compat_symbol (libc, obstackv1_free, obstack_free, GLIBC_2_0);
+# endif
+
+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
+/* A looong time ago (before 1994, anyway; we're not sure) this global variable
+ was used by non-GNU-C macros to avoid multiple evaluation. The GNU C
+ library still exports it because somebody might use it. */
+struct obstack *_obstack_compat = 0;
+compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
+# endif
+
+# if _GNU_OBSTACK_INTERFACE_VERSION == 1
+libc_hidden_def (_obstack_newchunk)
+# endif
+
+# ifdef _OBSTACK_COMPAT
+# undef _obstack_allocated_p
+# undef _obstack_begin
+# undef _obstack_begin_1
+# undef _obstack_free
+# undef _obstack_memory_used
+# undef _obstack_newchunk
+compat_symbol (libc, _obstackv1_allocated_p, _obstack_allocated_p, GLIBC_2_0);
+compat_symbol (libc, _obstackv1_begin, _obstack_begin, GLIBC_2_0);
+compat_symbol (libc, _obstackv1_begin_1, _obstack_begin_1, GLIBC_2_0);
+compat_symbol (libc, _obstackv1_free, _obstack_free, GLIBC_2_0);
+compat_symbol (libc, _obstackv1_memory_used, _obstack_memory_used, GLIBC_2_0);
+compat_symbol (libc, _obstackv1_newchunk, _obstack_newchunk, GLIBC_2_0);
+# endif /* _OBSTACK_COMPAT */
+#endif /* _OBSTACK_ELIDE_CODE */
diff --git a/malloc/obstackv2.c b/malloc/obstackv2.c
new file mode 100644
index 0000000..d8be95e
--- /dev/null
+++ b/malloc/obstackv2.c
@@ -0,0 +1,69 @@
+/* obstackv2.c - subroutines used implicitly by object stack macros
+ Copyright (C) 2014 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Build version 2. */
+#define _OBSTACK_INTERFACE_VERSION 2
+#define _OBSTACK_C 1
+
+#include "obstack.c"
+
+#ifndef _OBSTACK_ELIDE_CODE
+
+# ifdef _OBSTACK_ALIAS
+
+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_21)
+# undef obstack_free
+strong_alias (_obstack_free, obstackv1_free)
+compat_symbol (libc, obstackv1_free, obstack_free, GLIBC_2_0);
+# endif
+
+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
+/* A looong time ago (before 1994, anyway; we're not sure) this global variable
+ was used by non-GNU-C macros to avoid multiple evaluation. The GNU C
+ library still exports it because somebody might use it. */
+struct obstack *_obstack_compat = 0;
+compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
+# endif
+# endif /* _OBSTACK_ALIAS */
+
+libc_hidden_def (_obstack_newchunk)
+
+# ifdef _OBSTACK_COMPAT
+# undef _obstack_allocated_p
+# undef _obstack_begin
+# undef _obstack_begin_1
+# undef _obstack_free
+# undef _obstack_memory_used
+# undef _obstack_newchunk
+
+# ifdef _OBSTACK_ALIAS
+# define OB_VER GLIBC_2_0
+# else
+# define OB_VER GLIBC_2_21
+# endif
+versioned_symbol (libc, _obstackv2_allocated_p, _obstack_allocated_p, OB_VER);
+versioned_symbol (libc, _obstackv2_begin, _obstack_begin, OB_VER);
+versioned_symbol (libc, _obstackv2_begin_1, _obstack_begin_1, OB_VER);
+versioned_symbol (libc, _obstackv2_free, _obstack_free, OB_VER);
+versioned_symbol (libc, _obstackv2_memory_used, _obstack_memory_used, OB_VER);
+versioned_symbol (libc, _obstackv2_newchunk, _obstack_newchunk, OB_VER);
+
+extern void _obstack_newchunk (struct obstack *, _OBSTACK_SIZE_T);
+libc_hidden_ver (_obstackv2_newchunk, _obstack_newchunk)
+# endif /* _OBSTACK_COMPAT */
+#endif /* _OBSTACK_ELIDE_CODE */
diff --git a/malloc/obstack.c b/malloc/obstack.c
index fa4fefc..8e247fb 100644
--- a/malloc/obstack.c
+++ b/malloc/obstack.c
@@ -19,16 +19,14 @@
#ifdef _LIBC
# include <obstack.h>
-# include <shlib-compat.h>
#else
# include <config.h>
# include "obstack.h"
#endif
-/* 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
+/* NOTE BEFORE MODIFYING THIS FILE: _OBSTACK_INTERFACE_VERSION in
+ obstack.h must be incremented whenever callers compiled using an old
+ obstack.h can no longer properly call the functions in this file. */
/* 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
@@ -38,20 +36,19 @@
(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
+# if (_GNU_OBSTACK_INTERFACE_VERSION == _OBSTACK_INTERFACE_VERSION \
+ || (_GNU_OBSTACK_INTERFACE_VERSION == 1 \
+ && _OBSTACK_INTERFACE_VERSION == 2 \
+ && defined SIZEOF_INT && defined SIZEOF_SIZE_T \
+ && SIZEOF_INT == SIZEOF_SIZE_T))
+# define _OBSTACK_ELIDE_CODE
# endif
#endif
-#include <stddef.h>
-
-#ifndef ELIDE_CODE
-
-
+#ifndef _OBSTACK_ELIDE_CODE
+# include <stdlib.h>
# include <stdint.h>
/* Determine default alignment. */
@@ -75,42 +72,6 @@ enum
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 functions allocating more room by calling 'obstack_chunk_alloc'
- jump to the handler pointed to by 'obstack_alloc_failed_handler'.
- This can be set to a user defined function which should either
- abort gracefully or use longjump - but shouldn't return. This
- variable by default points to the internal function
- 'print_and_abort'. */
-static _Noreturn void print_and_abort (void);
-void (*obstack_alloc_failed_handler) (void) = print_and_abort;
-
-/* Exit value used when 'print_and_abort' is used. */
-# include <stdlib.h>
-# ifdef _LIBC
-int obstack_exit_failure = EXIT_FAILURE;
-# else
-# include "exitfail.h"
-# define obstack_exit_failure exit_failure
-# endif
-
-# ifdef _LIBC
-# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
-/* A looong time ago (before 1994, anyway; we're not sure) this global variable
- was used by non-GNU-C macros to avoid multiple evaluation. The GNU C
- library still exports it because somebody might use it. */
-struct obstack *_obstack_compat = 0;
-compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
-# endif
-# endif
/* Define a macro that either calls functions with the traditional malloc/free
calling interface, or calls functions with the mmalloc/mfree interface
@@ -121,7 +82,7 @@ compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
# define CALL_CHUNKFUN(h, size) \
(((h)->use_extra_arg) \
? (*(h)->chunkfun)((h)->extra_arg, (size)) \
- : (*(struct _obstack_chunk *(*)(long))(h)->chunkfun)((size)))
+ : (*(struct _obstack_chunk *(*)(size_t))(h)->chunkfun)((size)))
# define CALL_FREEFUN(h, old_chunk) \
do { \
@@ -140,11 +101,13 @@ compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
Return nonzero if successful, calls obstack_alloc_failed_handler if
allocation fails. */
-int
-_obstack_begin (struct obstack *h,
- int size, int alignment,
- void *(*chunkfun) (long),
- void (*freefun) (void *))
+typedef struct _obstack_chunk * (*chunkfun_type) (void *, size_t);
+typedef void (*freefun_type) (void *, struct _obstack_chunk *);
+
+static int
+_obstack_begin_worker (struct obstack *h,
+ _OBSTACK_SIZE_T size, int alignment,
+ chunkfun_type chunkfun, freefun_type freefun)
{
struct _obstack_chunk *chunk; /* points to new chunk */
@@ -167,19 +130,17 @@ _obstack_begin (struct obstack *h,
size = 4096 - extra;
}
- h->chunkfun = (struct _obstack_chunk * (*) (void *, long)) chunkfun;
- h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+ h->chunkfun = 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)
(*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;
+ 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;
@@ -188,51 +149,29 @@ _obstack_begin (struct obstack *h,
}
int
-_obstack_begin_1 (struct obstack *h, int size, int alignment,
- void *(*chunkfun) (void *, long),
- void (*freefun) (void *, void *),
- void *arg)
-{
- 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. */
+_obstack_begin (struct obstack *h,
+ _OBSTACK_SIZE_T size, int alignment,
+ void *(*chunkfun) (size_t),
+ void (*freefun) (void *))
{
- /* 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->use_extra_arg = 0;
+ return _obstack_begin_worker (h, size, alignment,
+ (chunkfun_type) chunkfun,
+ (freefun_type) freefun);
}
- 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;
+int
+_obstack_begin_1 (struct obstack *h,
+ _OBSTACK_SIZE_T size, int alignment,
+ void *(*chunkfun) (void *, size_t),
+ void (*freefun) (void *, void *),
+ void *arg)
+{
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;
+ return _obstack_begin_worker (h, size, alignment,
+ (chunkfun_type) chunkfun,
+ (freefun_type) freefun);
}
/* Allocate a new current chunk for the obstack *H
@@ -242,14 +181,12 @@ _obstack_begin_1 (struct obstack *h, int size, int alignment,
to the beginning of the new one. */
void
-_obstack_newchunk (struct obstack *h, int length)
+_obstack_newchunk (struct obstack *h, _OBSTACK_SIZE_T length)
{
struct _obstack_chunk *old_chunk = h->chunk;
struct _obstack_chunk *new_chunk;
- long new_size;
- long obj_size = h->next_free - h->object_base;
- long i;
- long already;
+ size_t new_size;
+ size_t obj_size = h->next_free - h->object_base;
char *object_base;
/* Compute size for new chunk. */
@@ -269,25 +206,8 @@ _obstack_newchunk (struct obstack *h, int length)
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];
+ /* Move the existing object to the new chunk. */
+ memcpy (object_base, h->object_base, obj_size);
/* If the object just copied was the only data in OLD_CHUNK,
free that chunk and remove it from the chain.
@@ -306,9 +226,6 @@ _obstack_newchunk (struct obstack *h, int length)
/* The new chunk certainly contains no empty object yet. */
h->maybe_empty_object = 0;
}
-# ifdef _LIBC
-libc_hidden_def (_obstack_newchunk)
-# endif
/* Return nonzero if object OBJ has been allocated from obstack H.
This is here for debugging.
@@ -339,10 +256,8 @@ _obstack_allocated_p (struct obstack *h, void *obj)
/* 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
-
void
-__obstack_free (struct obstack *h, void *obj)
+_obstack_free (struct obstack *h, void *obj)
{
struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
struct _obstack_chunk *plp; /* point to previous chunk if any */
@@ -371,17 +286,11 @@ __obstack_free (struct obstack *h, void *obj)
abort ();
}
-# ifdef _LIBC
-/* Older versions of libc used a function _obstack_free intended to be
- called by non-GCC compilers. */
-strong_alias (obstack_free, _obstack_free)
-# endif
-
-int
+_OBSTACK_SIZE_T
_obstack_memory_used (struct obstack *h)
{
struct _obstack_chunk *lp;
- int nbytes = 0;
+ _OBSTACK_SIZE_T nbytes = 0;
for (lp = h->chunk; lp != 0; lp = lp->prev)
{
@@ -390,7 +299,18 @@ _obstack_memory_used (struct obstack *h)
return nbytes;
}
+# ifndef _OBSTACK_NO_ERROR_HANDLER
/* Define the error handler. */
+# include <stdio.h>
+
+/* Exit value used when 'print_and_abort' is used. */
+# ifdef _LIBC
+int obstack_exit_failure = EXIT_FAILURE;
+# else
+# include "exitfail.h"
+# define obstack_exit_failure exit_failure
+# endif
+
# ifdef _LIBC
# include <libintl.h>
# else
@@ -420,4 +340,12 @@ print_and_abort (void)
exit (obstack_exit_failure);
}
-#endif /* !ELIDE_CODE */
+/* The functions allocating more room by calling 'obstack_chunk_alloc'
+ jump to the handler pointed to by 'obstack_alloc_failed_handler'.
+ This can be set to a user defined function which should either
+ abort gracefully or use longjump - but shouldn't return. This
+ variable by default points to the internal function
+ 'print_and_abort'. */
+void (*obstack_alloc_failed_handler) (void) = print_and_abort;
+# endif /* !_OBSTACK_NO_ERROR_HANDLER */
+#endif /* !_OBSTACK_ELIDE_CODE */
diff --git a/malloc/obstack.h b/malloc/obstack.h
index 59ae6e5..909d0d3 100644
--- a/malloc/obstack.h
+++ b/malloc/obstack.h
@@ -104,16 +104,22 @@
#ifndef _OBSTACK_H
#define _OBSTACK_H 1
-/* We need the type of a pointer subtraction. If __PTRDIFF_TYPE__ is
- defined, as with GNU C, use that; that way we don't pollute the
- namespace with <stddef.h>'s symbols. Otherwise, include <stddef.h>
- and use ptrdiff_t. */
+#ifndef _OBSTACK_INTERFACE_VERSION
+# define _OBSTACK_INTERFACE_VERSION 2
+#endif
+
+#include <stddef.h> /* For size_t and ptrdiff_t. */
+#include <string.h> /* For __GNU_LIBRARY__, and memcpy. */
-#ifdef __PTRDIFF_TYPE__
-# define PTR_INT_TYPE __PTRDIFF_TYPE__
+#if _OBSTACK_INTERFACE_VERSION == 1
+/* For binary compatibility with obstack version 1, which used "int"
+ and "long" for these two types. */
+# define _OBSTACK_SIZE_T unsigned int
+# define _CHUNK_SIZE_T unsigned long
#else
-# include <stddef.h>
-# define PTR_INT_TYPE ptrdiff_t
+/* Version 2 with sane types, especially for 64-bit hosts. */
+# define _OBSTACK_SIZE_T size_t
+# define _CHUNK_SIZE_T size_t
#endif
/* If B is the base of an object addressed by P, return the result of
@@ -122,19 +128,17 @@
#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A)))
-/* Similar to _BPTR_ALIGN (B, P, A), except optimize the common case
+/* Similar to __BPTR_ALIGN (B, P, A), except optimize the common case
where pointers can be converted to integers, aligned as integers,
- and converted back again. If PTR_INT_TYPE is narrower than a
+ and converted back again. If ptrdiff_t is narrower than a
pointer (e.g., the AS/400), play it safe and compute the alignment
relative to B. Otherwise, use the faster strategy of computing the
alignment relative to 0. */
#define __PTR_ALIGN(B, P, A) \
- __BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \
+ __BPTR_ALIGN (sizeof (ptrdiff_t) < sizeof (void *) ? (B) : (char *) 0, \
P, A)
-#include <string.h>
-
#ifndef __attribute_pure__
# define __attribute_pure__ _GL_ATTRIBUTE_PURE
#endif
@@ -152,21 +156,21 @@ struct _obstack_chunk /* Lives at front of each chunk. */
struct obstack /* control current object in current chunk */
{
- long chunk_size; /* preferred size to allocate chunks in */
+ _CHUNK_SIZE_T 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 */
union
{
- PTR_INT_TYPE tempint;
- void *tempptr;
+ _OBSTACK_SIZE_T i;
+ void *p;
} temp; /* Temporary for some macros. */
int alignment_mask; /* Mask of alignment for each object. */
/* These prototypes vary based on 'use_extra_arg', and we use
casts to the prototypeless function type in all assignments,
but having prototypes here quiets -Wstrict-prototypes. */
- struct _obstack_chunk *(*chunkfun) (void *, long);
+ struct _obstack_chunk *(*chunkfun) (void *, size_t);
void (*freefun) (void *, struct _obstack_chunk *);
void *extra_arg; /* first arg for chunk alloc/dealloc funcs */
unsigned use_extra_arg : 1; /* chunk alloc/dealloc funcs take extra arg */
@@ -181,20 +185,15 @@ struct obstack /* control current object in current chunk */
/* Declare the external functions we use; they are in obstack.c. */
-extern void _obstack_newchunk (struct obstack *, int);
-extern int _obstack_begin (struct obstack *, int, int,
- void *(*)(long), void (*)(void *));
-extern int _obstack_begin_1 (struct obstack *, int, int,
- void *(*)(void *, long),
+extern void _obstack_newchunk (struct obstack *, _OBSTACK_SIZE_T);
+extern void _obstack_free (struct obstack *, void *);
+extern int _obstack_begin (struct obstack *, _OBSTACK_SIZE_T, int,
+ void *(*)(size_t), void (*)(void *));
+extern int _obstack_begin_1 (struct obstack *, _OBSTACK_SIZE_T, int,
+ void *(*)(void *, size_t),
void (*)(void *, void *), void *);
-extern int _obstack_memory_used (struct obstack *) __attribute_pure__;
-
-/* The default name of the function for freeing a chunk is 'obstack_free',
- but gnulib users can override this by defining '__obstack_free'. */
-#ifndef __obstack_free
-# define __obstack_free obstack_free
-#endif
-extern void __obstack_free (struct obstack *, void *);
+extern _OBSTACK_SIZE_T _obstack_memory_used (struct obstack *)
+ __attribute_pure__;
/* Error handler called when 'obstack_chunk_alloc' failed to allocate
@@ -227,26 +226,26 @@ extern int obstack_exit_failure;
/* To prevent prototype warnings provide complete argument list. */
#define obstack_init(h) \
_obstack_begin ((h), 0, 0, \
- (void *(*)(long))obstack_chunk_alloc, \
+ (void *(*)(size_t))obstack_chunk_alloc, \
(void (*)(void *))obstack_chunk_free)
#define obstack_begin(h, size) \
_obstack_begin ((h), (size), 0, \
- (void *(*)(long))obstack_chunk_alloc, \
+ (void *(*)(size_t))obstack_chunk_alloc, \
(void (*)(void *))obstack_chunk_free)
#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
_obstack_begin ((h), (size), (alignment), \
- (void *(*)(long))(chunkfun), \
+ (void *(*)(size_t))(chunkfun), \
(void (*)(void *))(freefun))
#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
_obstack_begin_1 ((h), (size), (alignment), \
- (void *(*)(void *, long))(chunkfun), \
+ (void *(*)(void *, size_t))(chunkfun), \
(void (*)(void *, void *))(freefun), (arg))
#define obstack_chunkfun(h, newchunkfun) \
- ((h)->chunkfun = (struct _obstack_chunk *(*)(void *, long))(newchunkfun))
+ ((h)->chunkfun = (struct _obstack_chunk *(*)(void *, size_t))(newchunkfun))
#define obstack_freefun(h, newfreefun) \
((h)->freefun = (void (*)(void *, struct _obstack_chunk *))(newfreefun))
@@ -258,7 +257,7 @@ extern int obstack_exit_failure;
#define obstack_memory_used(h) _obstack_memory_used (h)
#if defined __GNUC__
-# if ! (2 < __GNUC__ + (8 <= __GNUC_MINOR__))
+# if !defined __GNUC_MINOR__ || __GNUC__ * 1000 + __GNUC_MINOR__ < 2008
# define __extension__
# endif
@@ -270,18 +269,20 @@ extern int obstack_exit_failure;
# define obstack_object_size(OBSTACK) \
__extension__ \
({ struct obstack const *__o = (OBSTACK); \
- (unsigned) (__o->next_free - __o->object_base); })
+ (_OBSTACK_SIZE_T) (__o->next_free - __o->object_base); })
+/* The local variable is named __o1 to avoid a shadowed variable
+ warning when invoked from other obstack macros. */
# define obstack_room(OBSTACK) \
__extension__ \
- ({ struct obstack const *__o = (OBSTACK); \
- (unsigned) (__o->chunk_limit - __o->next_free); })
+ ({ struct obstack const *__o1 = (OBSTACK); \
+ (_OBSTACK_SIZE_T) (__o1->chunk_limit - __o1->next_free); })
# define obstack_make_room(OBSTACK, length) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
- int __len = (length); \
- if (__o->chunk_limit - __o->next_free < __len) \
+ _OBSTACK_SIZE_T __len = (length); \
+ if (obstack_room (__o) < __len) \
_obstack_newchunk (__o, __len); \
(void) 0; })
@@ -296,8 +297,8 @@ extern int obstack_exit_failure;
# define obstack_grow(OBSTACK, where, length) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
- int __len = (length); \
- if (__o->next_free + __len > __o->chunk_limit) \
+ _OBSTACK_SIZE_T __len = (length); \
+ if (obstack_room (__o) < __len) \
_obstack_newchunk (__o, __len); \
memcpy (__o->next_free, where, __len); \
__o->next_free += __len; \
@@ -306,8 +307,8 @@ extern int obstack_exit_failure;
# define obstack_grow0(OBSTACK, where, length) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
- int __len = (length); \
- if (__o->next_free + __len + 1 > __o->chunk_limit) \
+ _OBSTACK_SIZE_T __len = (length); \
+ if (obstack_room (__o) < __len + 1) \
_obstack_newchunk (__o, __len + 1); \
memcpy (__o->next_free, where, __len); \
__o->next_free += __len; \
@@ -317,7 +318,7 @@ extern int obstack_exit_failure;
# define obstack_1grow(OBSTACK, datum) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
- if (__o->next_free + 1 > __o->chunk_limit) \
+ if (obstack_room (__o) < 1) \
_obstack_newchunk (__o, 1); \
obstack_1grow_fast (__o, datum); \
(void) 0; })
@@ -329,14 +330,14 @@ extern int obstack_exit_failure;
# define obstack_ptr_grow(OBSTACK, datum) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
- if (__o->next_free + sizeof (void *) > __o->chunk_limit) \
+ if (obstack_room (__o) < sizeof (void *)) \
_obstack_newchunk (__o, sizeof (void *)); \
- obstack_ptr_grow_fast (__o, datum); }) \
+ obstack_ptr_grow_fast (__o, datum); })
# define obstack_int_grow(OBSTACK, datum) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
- if (__o->next_free + sizeof (int) > __o->chunk_limit) \
+ if (obstack_room (__o) < sizeof (int)) \
_obstack_newchunk (__o, sizeof (int)); \
obstack_int_grow_fast (__o, datum); })
@@ -359,8 +360,8 @@ extern int obstack_exit_failure;
# define obstack_blank(OBSTACK, length) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
- int __len = (length); \
- if (__o->chunk_limit - __o->next_free < __len) \
+ _OBSTACK_SIZE_T __len = (length); \
+ if (obstack_room (__o) < __len) \
_obstack_newchunk (__o, __len); \
obstack_blank_fast (__o, __len); \
(void) 0; })
@@ -383,8 +384,8 @@ extern int obstack_exit_failure;
obstack_grow0 (__h, (where), (length)); \
obstack_finish (__h); })
-/* The local variable is named __o1 to avoid a name conflict
- when obstack_blank is called. */
+/* The local variable is named __o1 to avoid a shadowed variable
+ warning when invoked from other obstack macros, typically obstack_free. */
# define obstack_finish(OBSTACK) \
__extension__ \
({ struct obstack *__o1 = (OBSTACK); \
@@ -394,8 +395,8 @@ extern int obstack_exit_failure;
__o1->next_free \
= __PTR_ALIGN (__o1->object_base, __o1->next_free, \
__o1->alignment_mask); \
- if (__o1->next_free - (char *) __o1->chunk \
- > __o1->chunk_limit - (char *) __o1->chunk) \
+ if ((size_t) (__o1->next_free - (char *) __o1->chunk) \
+ > (size_t) (__o1->chunk_limit - (char *) __o1->chunk)) \
__o1->next_free = __o1->chunk_limit; \
__o1->object_base = __o1->next_free; \
__value; })
@@ -403,18 +404,19 @@ extern int obstack_exit_failure;
# define obstack_free(OBSTACK, OBJ) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
- void *__obj = (OBJ); \
+ void *__obj = (void *) (OBJ); \
if (__obj > (void *) __o->chunk && __obj < (void *) __o->chunk_limit) \
__o->next_free = __o->object_base = (char *) __obj; \
- else (__obstack_free) (__o, __obj); })
+ else \
+ _obstack_free (__o, __obj); })
#else /* not __GNUC__ */
# define obstack_object_size(h) \
- (unsigned) ((h)->next_free - (h)->object_base)
+ ((_OBSTACK_SIZE_T) ((h)->next_free - (h)->object_base))
# define obstack_room(h) \
- (unsigned) ((h)->chunk_limit - (h)->next_free)
+ ((_OBSTACK_SIZE_T) ((h)->chunk_limit - (h)->next_free))
# define obstack_empty_p(h) \
((h)->chunk->prev == 0 \
@@ -429,37 +431,37 @@ extern int obstack_exit_failure;
but some compilers won't accept it. */
# define obstack_make_room(h, length) \
- ((h)->temp.tempint = (length), \
- (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0))
+ ((h)->temp.i = (length), \
+ ((obstack_room (h) < (h)->temp.i) \
+ ? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0))
# define obstack_grow(h, where, length) \
- ((h)->temp.tempint = (length), \
- (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \
- memcpy ((h)->next_free, where, (h)->temp.tempint), \
- (h)->next_free += (h)->temp.tempint)
+ ((h)->temp.i = (length), \
+ ((obstack_room (h) < (h)->temp.i) \
+ ? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0), \
+ memcpy ((h)->next_free, where, (h)->temp.i), \
+ (h)->next_free += (h)->temp.i)
# define obstack_grow0(h, where, length) \
- ((h)->temp.tempint = (length), \
- (((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), (h)->temp.tempint + 1), 0) : 0), \
- memcpy ((h)->next_free, where, (h)->temp.tempint), \
- (h)->next_free += (h)->temp.tempint, \
+ ((h)->temp.i = (length), \
+ ((obstack_room (h) < (h)->temp.i + 1) \
+ ? (_obstack_newchunk ((h), (h)->temp.i + 1), 0) : 0), \
+ memcpy ((h)->next_free, where, (h)->temp.i), \
+ (h)->next_free += (h)->temp.i, \
*((h)->next_free)++ = 0)
# define obstack_1grow(h, datum) \
- ((((h)->next_free + 1 > (h)->chunk_limit) \
+ (((obstack_room (h) < 1) \
? (_obstack_newchunk ((h), 1), 0) : 0), \
obstack_1grow_fast (h, datum))
# define obstack_ptr_grow(h, datum) \
- ((((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
+ (((obstack_room (h) < sizeof (char *)) \
? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
obstack_ptr_grow_fast (h, datum))
# define obstack_int_grow(h, datum) \
- ((((h)->next_free + sizeof (int) > (h)->chunk_limit) \
+ (((obstack_room (h) < sizeof (int)) \
? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
obstack_int_grow_fast (h, datum))
@@ -470,10 +472,10 @@ extern int obstack_exit_failure;
(((int *) ((h)->next_free += sizeof (int)))[-1] = (aint))
# define obstack_blank(h, length) \
- ((h)->temp.tempint = (length), \
- (((h)->chunk_limit - (h)->next_free < (h)->temp.tempint) \
- ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \
- obstack_blank_fast (h, (h)->temp.tempint))
+ ((h)->temp.i = (length), \
+ ((obstack_room (h) < (h)->temp.i) \
+ ? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0), \
+ obstack_blank_fast (h, (h)->temp.i))
# define obstack_alloc(h, length) \
(obstack_blank ((h), (length)), obstack_finish ((h)))
@@ -488,23 +490,22 @@ extern int obstack_exit_failure;
(((h)->next_free == (h)->object_base \
? (((h)->maybe_empty_object = 1), 0) \
: 0), \
- (h)->temp.tempptr = (h)->object_base, \
+ (h)->temp.p = (h)->object_base, \
(h)->next_free \
= __PTR_ALIGN ((h)->object_base, (h)->next_free, \
(h)->alignment_mask), \
- (((h)->next_free - (char *) (h)->chunk \
- > (h)->chunk_limit - (char *) (h)->chunk) \
+ (((size_t) ((h)->next_free - (char *) (h)->chunk) \
+ > (size_t) ((h)->chunk_limit - (char *) (h)->chunk)) \
? ((h)->next_free = (h)->chunk_limit) : 0), \
(h)->object_base = (h)->next_free, \
- (h)->temp.tempptr)
+ (h)->temp.p)
# define obstack_free(h, obj) \
- ((h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk, \
- ((((h)->temp.tempint > 0 \
- && (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk)) \
- ? (void) ((h)->next_free = (h)->object_base \
- = (h)->temp.tempint + (char *) (h)->chunk) \
- : (__obstack_free) (h, (h)->temp.tempint + (char *) (h)->chunk)))
+ ((h)->temp.p = (void *) (obj), \
+ (((h)->temp.p > (void *) (h)->chunk \
+ && (h)->temp.p < (void *) (h)->chunk_limit) \
+ ? (void) ((h)->next_free = (h)->object_base = (char *) (h)->temp.p) \
+ : _obstack_free ((h), (h)->temp.p)))
#endif /* not __GNUC__ */
@@ -512,4 +513,4 @@ extern int obstack_exit_failure;
} /* C++ */
#endif
-#endif /* obstack.h */
+#endif /* _OBSTACK_H */
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] 64-bit obstack support
2014-10-29 3:35 ` [PATCH] 64-bit obstack support Alan Modra
@ 2014-10-29 18:34 ` Joseph S. Myers
2014-10-30 1:53 ` Alan Modra
0 siblings, 1 reply; 13+ messages in thread
From: Joseph S. Myers @ 2014-10-29 18:34 UTC (permalink / raw)
To: Alan Modra; +Cc: libc-alpha, bug-gnulib
On Wed, 29 Oct 2014, Alan Modra wrote:
> And >2G on 32-bit.
>
[BZ #14483]
in the ChangeLog entry.
--
Joseph S. Myers
joseph@codesourcery.com
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] 64-bit obstack support
2014-10-29 18:34 ` Joseph S. Myers
@ 2014-10-30 1:53 ` Alan Modra
0 siblings, 0 replies; 13+ messages in thread
From: Alan Modra @ 2014-10-30 1:53 UTC (permalink / raw)
To: Joseph S. Myers; +Cc: libc-alpha, bug-gnulib
On Wed, Oct 29, 2014 at 06:34:02PM +0000, Joseph S. Myers wrote:
> On Wed, 29 Oct 2014, Alan Modra wrote:
>
> > And >2G on 32-bit.
> >
>
> [BZ #14483]
>
> in the ChangeLog entry.
Thanks, added. Since the stdalign.h change won't do for glibc, I've
split the glibc patch into two. The first being
Import new obstack support from gnulib
* malloc/obstack.h: Import from gnulib.
* malloc/obstack.c: Likewise.
The second
64-bit obstack support
And >2G on 32-bit.
[BZ #14483]
* include/gnu-versions.h (_GNU_OBSTACK_INTERFACE_VERSION): Bump.
* include/obstack.h: Include shlib-compat.h and gnu-versions.h.
(_OBSTACK_ELIDE_CODE, _OBSTACK_NO_ERROR_HANDLER, _OBSTACK_COMPAT,
_OBSTACK_ALIAS): Define.
(_obstack_allocated_p, _obstack_newchunk, _obstack_free,
_obstack_begin, _obstack_begin_1, _obstack_memory_used): Define.
(_obstack_newchunk): Only use libc_hidden_proto on the version
we will use inside glibc.
* malloc/obstack.c: Revert gnulib commit e8f86ce9, ie. don't
use stdalign.h and alignof.
* malloc/obstackv1.c: New file.
* malloc/obstackv2.c: New file.
* malloc/Makefile (routines): Remove obstack. Add obstackv1 and
obstackv2.
(CFLAGS-obstack.c): Don't define.
(CFLAGS-obstackv1.c, CFLAGS-obstackv2.c): Define.
(malloc/Versions): Add GLIBC_2.21 _obstack functions.
* config.h.in (SIZEOF_INT, SIZEOF_SIZE_T): Add.
* configure.in: AC_CHECK_SIZEOF int and size_t.
* configure: Regenerate.
* manual/memory.texi: Update obstack documentation.
Added manual patch follows. It's missing @safety markup for the
previously undocumented obstack_begin, obstack_specify_allocation, and
obstack_specify_allocation_with_arg macros. I'm hoping someone else
can do that as I'd just be guessing. (Are they even appropriate for
macros?)
diff --git a/manual/memory.texi b/manual/memory.texi
index 0729e70..5ab16b7 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -1922,8 +1922,7 @@ the padding needed to start each object on a suitable boundary.
use obstacks.
* Allocation in an Obstack:: Allocating objects in an obstack.
* Freeing Obstack Objects:: Freeing objects in an obstack.
-* Obstack Functions:: The obstack functions are both
- functions and macros.
+* Obstack Functions:: The obstack functions are really macros.
* Growing Objects:: Making an object bigger by stages.
* Extra Fast Growing:: Extra-high-efficiency (though more
complicated) growing objects.
@@ -1948,7 +1947,7 @@ An obstack is represented by a data structure of type @code{struct
obstack}. This structure has a small fixed size; it records the status
of the obstack and how to find the space in which objects are allocated.
It does not contain any of the objects themselves. You should not try
-to access the contents of the structure directly; use only the functions
+to access the contents of the structure directly; use only the macros
described in this chapter.
@end deftp
@@ -1958,7 +1957,7 @@ of object. Dynamic allocation of obstacks allows your program to have a
variable number of different stacks. (You can even allocate an
obstack structure in another obstack, but this is rarely useful.)
-All the functions that work with obstacks require you to specify which
+All the macros that work with obstacks require you to specify which
obstack to use. You do this with a pointer of type @code{struct obstack
*}. In the following, we often say ``an obstack'' when strictly
speaking the object at hand is such a pointer.
@@ -1978,7 +1977,7 @@ These matters are described in the following section.
@node Preparing for Obstacks
@subsubsection Preparing for Using Obstacks
-Each source file in which you plan to use the obstack functions
+Each source file in which you plan to use obstacks
must include the header file @file{obstack.h}, like this:
@smallexample
@@ -2011,7 +2010,9 @@ larger blocks of memory. @xref{Obstack Chunks}, for full details.
At run time, before the program can use a @code{struct obstack} object
as an obstack, it must initialize the obstack by calling
-@code{obstack_init}.
+@code{obstack_init} or one of its variants, @code{obstack_begin},
+@code{obstack_specify_allocation}, or
+@code{obstack_specify_allocation_with_arg}.
@comment obstack.h
@comment GNU
@@ -2031,10 +2032,10 @@ as an obstack, it must initialize the obstack by calling
@c fxprintf dup @asucorrupt @aculock @acucorrupt
@c exit @acucorrupt?
Initialize obstack @var{obstack-ptr} for allocation of objects. This
-function calls the obstack's @code{obstack_chunk_alloc} function. If
+macro calls the obstack's @code{obstack_chunk_alloc} function. If
allocation of memory fails, the function pointed to by
@code{obstack_alloc_failed_handler} is called. The @code{obstack_init}
-function always returns 1 (Compatibility notice: Former versions of
+macro always returns 1 (Compatibility notice: Former versions of
obstack returned 0 if allocation failed).
@end deftypefun
@@ -2059,6 +2060,29 @@ obstack_init (myobstack_ptr);
@comment obstack.h
@comment GNU
+@deftypefun int obstack_begin (struct obstack *@var{obstack-ptr}, size_t chunk_size)
+Like @code{obstack_init}, but specify an initial chunk of
+@var{chunk_size} bytes.
+@end deftypefun
+
+@comment obstack.h
+@comment GNU
+@deftypefun int obstack_specify_allocation (struct obstack *@var{obstack-ptr}, size_t chunk_size, size_t alignment, void *(*chunkfun) (size_t), void (*freefun) (void *))
+Like @code{obstack_init}, specifying intial chunk size, chunk
+alignment, and memory allocation functions. A @var{chunk_size} or
+@var{alignment} of zero results in the default size or alignment
+respectively being used.
+@end deftypefun
+
+@comment obstack.h
+@comment GNU
+@deftypefun int obstack_specify_allocation_with_arg (struct obstack *@var{obstack-ptr}, size_t chunk_size, size_t alignment, void *(*chunkfun) (void *, size_t), void (*freefun) (void *, void *), void *arg)
+Like @code{obstack_specify_allocation}, but specifying memory
+allocation functions that take an extra first argument, @var{arg}.
+@end deftypefun
+
+@comment obstack.h
+@comment GNU
@defvar obstack_alloc_failed_handler
The value of this variable is a pointer to a function that
@code{obstack} uses when @code{obstack_chunk_alloc} fails to allocate
@@ -2084,7 +2108,7 @@ The most direct way to allocate an object in an obstack is with
@comment obstack.h
@comment GNU
-@deftypefun {void *} obstack_alloc (struct obstack *@var{obstack-ptr}, int @var{size})
+@deftypefun {void *} obstack_alloc (struct obstack *@var{obstack-ptr}, size_t @var{size})
@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}}
@c obstack_alloc @mtsrace:obstack-ptr @acucorrupt @acsmem
@c obstack_blank dup @mtsrace:obstack-ptr @acucorrupt @acsmem
@@ -2092,10 +2116,10 @@ The most direct way to allocate an object in an obstack is with
This allocates an uninitialized block of @var{size} bytes in an obstack
and returns its address. Here @var{obstack-ptr} specifies which obstack
to allocate the block in; it is the address of the @code{struct obstack}
-object which represents the obstack. Each obstack function or macro
+object which represents the obstack. Each obstack macro
requires you to specify an @var{obstack-ptr} as the first argument.
-This function calls the obstack's @code{obstack_chunk_alloc} function if
+This macro calls the obstack's @code{obstack_chunk_alloc} function if
it needs to allocate a new chunk of memory; it calls
@code{obstack_alloc_failed_handler} if allocation of memory by
@code{obstack_chunk_alloc} failed.
@@ -2117,12 +2141,11 @@ copystring (char *string)
@}
@end smallexample
-To allocate a block with specified contents, use the function
-@code{obstack_copy}, declared like this:
+To allocate a block with specified contents, use the macro @code{obstack_copy}.
@comment obstack.h
@comment GNU
-@deftypefun {void *} obstack_copy (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size})
+@deftypefun {void *} obstack_copy (struct obstack *@var{obstack-ptr}, void *@var{address}, size_t @var{size})
@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}}
@c obstack_copy @mtsrace:obstack-ptr @acucorrupt @acsmem
@c obstack_grow dup @mtsrace:obstack-ptr @acucorrupt @acsmem
@@ -2135,7 +2158,7 @@ bytes of data starting at @var{address}. It calls
@comment obstack.h
@comment GNU
-@deftypefun {void *} obstack_copy0 (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size})
+@deftypefun {void *} obstack_copy0 (struct obstack *@var{obstack-ptr}, void *@var{address}, size_t @var{size})
@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}}
@c obstack_copy0 @mtsrace:obstack-ptr @acucorrupt @acsmem
@c obstack_grow0 dup @mtsrace:obstack-ptr @acucorrupt @acsmem
@@ -2144,13 +2167,13 @@ Like @code{obstack_copy}, but appends an extra byte containing a null
character. This extra byte is not counted in the argument @var{size}.
@end deftypefun
-The @code{obstack_copy0} function is convenient for copying a sequence
+The @code{obstack_copy0} macro is convenient for copying a sequence
of characters into an obstack as a null-terminated string. Here is an
example of its use:
@smallexample
char *
-obstack_savestring (char *addr, int size)
+obstack_savestring (char *addr, size_t size)
@{
return obstack_copy0 (&myobstack, addr, size);
@}
@@ -2164,7 +2187,7 @@ Contrast this with the previous example of @code{savestring} using
@subsubsection Freeing Objects in an Obstack
@cindex freeing (obstacks)
-To free an object allocated in an obstack, use the function
+To free an object allocated in an obstack, use the macro
@code{obstack_free}. Since the obstack is a stack of objects, freeing
one object automatically frees all other objects allocated more recently
in the same obstack.
@@ -2200,13 +2223,9 @@ obstacks, or non-obstack allocation, can reuse the space of the chunk.
@subsubsection Obstack Functions and Macros
@cindex macros
-The interfaces for using obstacks may be defined either as functions or
-as macros, depending on the compiler. The obstack facility works with
-all C compilers, including both @w{ISO C} and traditional C, but there are
-precautions you must take if you plan to use compilers other than GNU C.
-
-If you are using an old-fashioned @w{non-ISO C} compiler, all the obstack
-``functions'' are actually defined only as macros. You can call these
+The interfaces for using obstacks are shown here as functions to
+specify the return types and give a hint as to expected argument
+types, but they are really defined as macros. You can call these
macros like functions, but you cannot use them in any other way (for
example, you cannot take their address).
@@ -2224,34 +2243,15 @@ If you use @code{*obstack_list_ptr++} as the obstack pointer argument,
you will get very strange results since the incrementation may occur
several times.
-In @w{ISO C}, each function has both a macro definition and a function
-definition. The function definition is used if you take the address of the
-function without calling it. An ordinary call uses the macro definition by
-default, but you can request the function definition instead by writing the
-function name in parentheses, as shown here:
-
-@smallexample
-char *x;
-void *(*funcp) ();
-/* @r{Use the macro}. */
-x = (char *) obstack_alloc (obptr, size);
-/* @r{Call the function}. */
-x = (char *) (obstack_alloc) (obptr, size);
-/* @r{Take the address of the function}. */
-funcp = obstack_alloc;
-@end smallexample
-
-@noindent
-This is the same situation that exists in @w{ISO C} for the standard library
-functions. @xref{Macro Definitions}.
-
-@strong{Warning:} When you do use the macros, you must observe the
-precaution of avoiding side effects in the first operand, even in @w{ISO C}.
-
If you use the GNU C compiler, this precaution is not necessary, because
various language extensions in GNU C permit defining the macros so as to
compute each argument only once.
+@code{obstack.h} does declare a number of functions,
+@code{_obstack_begin}, @code{_obstack_begin_1},
+@code{_obstack_newchunk}, @code{_obstack_free}, and
+@code{_obstack_memory_used}. You should not call these directly.
+
@node Growing Objects
@subsubsection Growing Objects
@cindex growing objects (in obstacks)
@@ -2261,13 +2261,13 @@ Because memory in obstack chunks is used sequentially, it is possible to
build up an object step by step, adding one or more bytes at a time to the
end of the object. With this technique, you do not need to know how much
data you will put in the object until you come to the end of it. We call
-this the technique of @dfn{growing objects}. The special functions
+this the technique of @dfn{growing objects}. The special macros
for adding data to the growing object are described in this section.
You don't need to do anything special when you start to grow an object.
-Using one of the functions to add data to the object automatically
+Using one of the macros to add data to the object automatically
starts it. However, it is necessary to say explicitly when the object is
-finished. This is done with the function @code{obstack_finish}.
+finished. This is done with @code{obstack_finish}.
The actual address of the object thus built up is not known until the
object is finished. Until then, it always remains possible that you will
@@ -2279,7 +2279,7 @@ already added to the growing object will become part of the other object.
@comment obstack.h
@comment GNU
-@deftypefun void obstack_blank (struct obstack *@var{obstack-ptr}, int @var{size})
+@deftypefun void obstack_blank (struct obstack *@var{obstack-ptr}, size_t @var{size})
@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}}
@c obstack_blank @mtsrace:obstack-ptr @acucorrupt @acsmem
@c _obstack_newchunk @mtsrace:obstack-ptr @acucorrupt @acsmem
@@ -2287,13 +2287,13 @@ already added to the growing object will become part of the other object.
@c *obstack_alloc_failed_handler dup user-supplied
@c *freefun
@c obstack_blank_fast dup @mtsrace:obstack-ptr
-The most basic function for adding to a growing object is
+The most basic macro for adding to a growing object is
@code{obstack_blank}, which adds space without initializing it.
@end deftypefun
@comment obstack.h
@comment GNU
-@deftypefun void obstack_grow (struct obstack *@var{obstack-ptr}, void *@var{data}, int @var{size})
+@deftypefun void obstack_grow (struct obstack *@var{obstack-ptr}, void *@var{data}, size_t @var{size})
@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}}
@c obstack_grow @mtsrace:obstack-ptr @acucorrupt @acsmem
@c _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem
@@ -2306,7 +2306,7 @@ bytes of data to the growing object, copying the contents from
@comment obstack.h
@comment GNU
-@deftypefun void obstack_grow0 (struct obstack *@var{obstack-ptr}, void *@var{data}, int @var{size})
+@deftypefun void obstack_grow0 (struct obstack *@var{obstack-ptr}, void *@var{data}, size_t @var{size})
@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}}
@c obstack_grow0 @mtsrace:obstack-ptr @acucorrupt @acsmem
@c (no sequence point between storing NUL and incrementing next_free)
@@ -2325,7 +2325,7 @@ character.
@c obstack_1grow @mtsrace:obstack-ptr @acucorrupt @acsmem
@c _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem
@c obstack_1grow_fast dup @mtsrace:obstack-ptr @acucorrupt @acsmem
-To add one character at a time, use the function @code{obstack_1grow}.
+To add one character at a time, use @code{obstack_1grow}.
It adds a single byte containing @var{c} to the growing object.
@end deftypefun
@@ -2336,7 +2336,7 @@ It adds a single byte containing @var{c} to the growing object.
@c obstack_ptr_grow @mtsrace:obstack-ptr @acucorrupt @acsmem
@c _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem
@c obstack_ptr_grow_fast dup @mtsrace:obstack-ptr
-Adding the value of a pointer one can use the function
+Adding the value of a pointer one can use
@code{obstack_ptr_grow}. It adds @code{sizeof (void *)} bytes
containing the value of @var{data}.
@end deftypefun
@@ -2348,8 +2348,8 @@ containing the value of @var{data}.
@c obstack_int_grow @mtsrace:obstack-ptr @acucorrupt @acsmem
@c _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem
@c obstack_int_grow_fast dup @mtsrace:obstack-ptr
-A single value of type @code{int} can be added by using the
-@code{obstack_int_grow} function. It adds @code{sizeof (int)} bytes to
+A single value of type @code{int} can be added by using
+@code{obstack_int_grow}. It adds @code{sizeof (int)} bytes to
the growing object and initializes them with the value of @var{data}.
@end deftypefun
@@ -2358,28 +2358,24 @@ the growing object and initializes them with the value of @var{data}.
@deftypefun {void *} obstack_finish (struct obstack *@var{obstack-ptr})
@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{}}}
@c obstack_finish @mtsrace:obstack-ptr @acucorrupt
-When you are finished growing the object, use the function
+When you are finished growing the object, use
@code{obstack_finish} to close it off and return its final address.
Once you have finished the object, the obstack is available for ordinary
allocation or for growing another object.
-
-This function can return a null pointer under the same conditions as
-@code{obstack_alloc} (@pxref{Allocation in an Obstack}).
@end deftypefun
When you build an object by growing it, you will probably need to know
afterward how long it became. You need not keep track of this as you grow
-the object, because you can find out the length from the obstack just
-before finishing the object with the function @code{obstack_object_size},
-declared as follows:
+the object, because you can find out the length from the obstack
+with @code{obstack_object_size}, before finishing the object.
@comment obstack.h
@comment GNU
-@deftypefun int obstack_object_size (struct obstack *@var{obstack-ptr})
+@deftypefun size_t obstack_object_size (struct obstack *@var{obstack-ptr})
@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}}
-This function returns the current size of the growing object, in bytes.
-Remember to call this function @emph{before} finishing the object.
+This macro returns the current size of the growing object, in bytes.
+Remember to call @code{obstack_object_size} @emph{before} finishing the object.
After it is finished, @code{obstack_object_size} will return zero.
@end deftypefun
@@ -2393,41 +2389,36 @@ obstack_free (obstack_ptr, obstack_finish (obstack_ptr));
@noindent
This has no effect if no object was growing.
-@cindex shrinking objects
-You can use @code{obstack_blank} with a negative size argument to make
-the current object smaller. Just don't try to shrink it beyond zero
-length---there's no telling what will happen if you do that.
-
@node Extra Fast Growing
@subsubsection Extra Fast Growing Objects
@cindex efficiency and obstacks
-The usual functions for growing objects incur overhead for checking
+The usual macros for growing objects incur overhead for checking
whether there is room for the new growth in the current chunk. If you
are frequently constructing objects in small steps of growth, this
overhead can be significant.
You can reduce the overhead by using special ``fast growth''
-functions that grow the object without checking. In order to have a
+macros that grow the object without checking. In order to have a
robust program, you must do the checking yourself. If you do this checking
in the simplest way each time you are about to add data to the object, you
have not saved anything, because that is what the ordinary growth
-functions do. But if you can arrange to check less often, or check
+macros do. But if you can arrange to check less often, or check
more efficiently, then you make the program faster.
-The function @code{obstack_room} returns the amount of room available
-in the current chunk. It is declared as follows:
+@code{obstack_room} returns the amount of room available
+in the current chunk.
@comment obstack.h
@comment GNU
-@deftypefun int obstack_room (struct obstack *@var{obstack-ptr})
+@deftypefun size_t obstack_room (struct obstack *@var{obstack-ptr})
@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}}
This returns the number of bytes that can be added safely to the current
growing object (or to an object about to be started) in obstack
-@var{obstack} using the fast growth functions.
+@var{obstack} using the fast growth macros.
@end deftypefun
-While you know there is room, you can use these fast growth functions
+While you know there is room, you can use these fast growth macros
for adding data to a growing object:
@comment obstack.h
@@ -2436,7 +2427,7 @@ for adding data to a growing object:
@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}}
@c obstack_1grow_fast @mtsrace:obstack-ptr @acucorrupt @acsmem
@c (no sequence point between copying c and incrementing next_free)
-The function @code{obstack_1grow_fast} adds one byte containing the
+@code{obstack_1grow_fast} adds one byte containing the
character @var{c} to the growing object in obstack @var{obstack-ptr}.
@end deftypefun
@@ -2445,7 +2436,7 @@ character @var{c} to the growing object in obstack @var{obstack-ptr}.
@deftypefun void obstack_ptr_grow_fast (struct obstack *@var{obstack-ptr}, void *@var{data})
@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}}
@c obstack_ptr_grow_fast @mtsrace:obstack-ptr
-The function @code{obstack_ptr_grow_fast} adds @code{sizeof (void *)}
+@code{obstack_ptr_grow_fast} adds @code{sizeof (void *)}
bytes containing the value of @var{data} to the growing object in
obstack @var{obstack-ptr}.
@end deftypefun
@@ -2455,41 +2446,41 @@ obstack @var{obstack-ptr}.
@deftypefun void obstack_int_grow_fast (struct obstack *@var{obstack-ptr}, int @var{data})
@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}}
@c obstack_int_grow_fast @mtsrace:obstack-ptr
-The function @code{obstack_int_grow_fast} adds @code{sizeof (int)} bytes
+@code{obstack_int_grow_fast} adds @code{sizeof (int)} bytes
containing the value of @var{data} to the growing object in obstack
@var{obstack-ptr}.
@end deftypefun
@comment obstack.h
@comment GNU
-@deftypefun void obstack_blank_fast (struct obstack *@var{obstack-ptr}, int @var{size})
+@deftypefun void obstack_blank_fast (struct obstack *@var{obstack-ptr}, size_t @var{size})
@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}}
@c obstack_blank_fast @mtsrace:obstack-ptr
-The function @code{obstack_blank_fast} adds @var{size} bytes to the
+@code{obstack_blank_fast} adds @var{size} bytes to the
growing object in obstack @var{obstack-ptr} without initializing them.
@end deftypefun
When you check for space using @code{obstack_room} and there is not
-enough room for what you want to add, the fast growth functions
+enough room for what you want to add, the fast growth macros
are not safe. In this case, simply use the corresponding ordinary
-growth function instead. Very soon this will copy the object to a
+growth macro instead. Very soon this will copy the object to a
new chunk; then there will be lots of room available again.
-So, each time you use an ordinary growth function, check afterward for
+So, each time you use an ordinary growth macro, check afterward for
sufficient space using @code{obstack_room}. Once the object is copied
to a new chunk, there will be plenty of space again, so the program will
-start using the fast growth functions again.
+start using the fast growth macros again.
Here is an example:
@smallexample
@group
void
-add_string (struct obstack *obstack, const char *ptr, int len)
+add_string (struct obstack *obstack, const char *ptr, size_t len)
@{
while (len > 0)
@{
- int room = obstack_room (obstack);
+ size_t room = obstack_room (obstack);
if (room == 0)
@{
/* @r{Not enough room. Add one character slowly,}
@@ -2511,12 +2502,17 @@ add_string (struct obstack *obstack, const char *ptr, int len)
@end group
@end smallexample
+@cindex shrinking objects
+You can use @code{obstack_blank_fast} with a negative size argument to make
+the current object smaller. Just don't try to shrink it beyond zero
+length---there's no telling what will happen if you do that.
+
@node Status of an Obstack
@subsubsection Status of an Obstack
@cindex obstack status
@cindex status of obstack
-Here are functions that provide information on the current status of
+Here are macros that provide information on the current status of
allocation in an obstack. You can use them to learn about an object while
still growing it.
@@ -2524,7 +2520,7 @@ still growing it.
@comment GNU
@deftypefun {void *} obstack_base (struct obstack *@var{obstack-ptr})
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acsafe{}}
-This function returns the tentative address of the beginning of the
+This macro returns the tentative address of the beginning of the
currently growing object in @var{obstack-ptr}. If you finish the object
immediately, it will have that address. If you make it larger first, it
may outgrow the current chunk---then its address will change!
@@ -2538,7 +2534,7 @@ chunk).
@comment GNU
@deftypefun {void *} obstack_next_free (struct obstack *@var{obstack-ptr})
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acsafe{}}
-This function returns the address of the first free byte in the current
+This macro returns the address of the first free byte in the current
chunk of obstack @var{obstack-ptr}. This is the end of the currently
growing object. If no object is growing, @code{obstack_next_free}
returns the same value as @code{obstack_base}.
@@ -2546,14 +2542,14 @@ returns the same value as @code{obstack_base}.
@comment obstack.h
@comment GNU
-@deftypefun int obstack_object_size (struct obstack *@var{obstack-ptr})
+@deftypefun size_t obstack_object_size (struct obstack *@var{obstack-ptr})
@c dup
@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}}
-This function returns the size in bytes of the currently growing object.
+This macro returns the size in bytes of the currently growing object.
This is equivalent to
@smallexample
-obstack_next_free (@var{obstack-ptr}) - obstack_base (@var{obstack-ptr})
+((size_t) obstack_next_free (@var{obstack-ptr}) - obstack_base (@var{obstack-ptr}))
@end smallexample
@end deftypefun
@@ -2567,12 +2563,11 @@ specified boundary. By default, this boundary is aligned so that
the object can hold any type of data.
To access an obstack's alignment boundary, use the macro
-@code{obstack_alignment_mask}, whose function prototype looks like
-this:
+@code{obstack_alignment_mask}.
@comment obstack.h
@comment GNU
-@deftypefn Macro int obstack_alignment_mask (struct obstack *@var{obstack-ptr})
+@deftypefn Macro size_t obstack_alignment_mask (struct obstack *@var{obstack-ptr})
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
The value is a bit mask; a bit that is 1 indicates that the corresponding
bit in the address of an object should be 0. The mask value should be one
@@ -2640,7 +2635,7 @@ not to waste too much memory in the portion of the last chunk not yet used.
@comment obstack.h
@comment GNU
-@deftypefn Macro int obstack_chunk_size (struct obstack *@var{obstack-ptr})
+@deftypefn Macro size_t obstack_chunk_size (struct obstack *@var{obstack-ptr})
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
This returns the chunk size of the given obstack.
@end deftypefn
@@ -2659,25 +2654,37 @@ if (obstack_chunk_size (obstack_ptr) < @var{new-chunk-size})
@end smallexample
@node Summary of Obstacks
-@subsubsection Summary of Obstack Functions
+@subsubsection Summary of Obstack Macros
-Here is a summary of all the functions associated with obstacks. Each
+Here is a summary of all the macros associated with obstacks. Each
takes the address of an obstack (@code{struct obstack *}) as its first
argument.
@table @code
-@item void obstack_init (struct obstack *@var{obstack-ptr})
+@item int obstack_init (struct obstack *@var{obstack-ptr})
Initialize use of an obstack. @xref{Creating Obstacks}.
-@item void *obstack_alloc (struct obstack *@var{obstack-ptr}, int @var{size})
+@item int obstack_begin (struct obstack *@var{obstack-ptr}, size_t chunk_size)
+Initialize use of an obstack, with an initial chunk of
+@var{chunk_size} bytes.
+
+@item int obstack_specify_allocation (struct obstack *@var{obstack-ptr}, size_t chunk_size, size_t alignment, void *(*chunkfun) (size_t), void (*freefun) (void *))
+Initialize use of an obstack, specifying intial chunk size, chunk
+alignment, and memory allocation functions.
+
+@item int obstack_specify_allocation_with_arg (struct obstack *@var{obstack-ptr}, size_t chunk_size, size_t alignment, void *(*chunkfun) (void *, size_t), void (*freefun) (void *, void *), void *arg)
+Like @code{obstack_specify_allocation}, but specifying memory
+allocation functions that take an extra first argument, @var{arg}.
+
+@item void *obstack_alloc (struct obstack *@var{obstack-ptr}, size_t @var{size})
Allocate an object of @var{size} uninitialized bytes.
@xref{Allocation in an Obstack}.
-@item void *obstack_copy (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size})
+@item void *obstack_copy (struct obstack *@var{obstack-ptr}, void *@var{address}, size_t @var{size})
Allocate an object of @var{size} bytes, with contents copied from
@var{address}. @xref{Allocation in an Obstack}.
-@item void *obstack_copy0 (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size})
+@item void *obstack_copy0 (struct obstack *@var{obstack-ptr}, void *@var{address}, size_t @var{size})
Allocate an object of @var{size}+1 bytes, with @var{size} of them copied
from @var{address}, followed by a null character at the end.
@xref{Allocation in an Obstack}.
@@ -2686,15 +2693,15 @@ from @var{address}, followed by a null character at the end.
Free @var{object} (and everything allocated in the specified obstack
more recently than @var{object}). @xref{Freeing Obstack Objects}.
-@item void obstack_blank (struct obstack *@var{obstack-ptr}, int @var{size})
+@item void obstack_blank (struct obstack *@var{obstack-ptr}, size_t @var{size})
Add @var{size} uninitialized bytes to a growing object.
@xref{Growing Objects}.
-@item void obstack_grow (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size})
+@item void obstack_grow (struct obstack *@var{obstack-ptr}, void *@var{address}, size_t @var{size})
Add @var{size} bytes, copied from @var{address}, to a growing object.
@xref{Growing Objects}.
-@item void obstack_grow0 (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size})
+@item void obstack_grow0 (struct obstack *@var{obstack-ptr}, void *@var{address}, size_t @var{size})
Add @var{size} bytes, copied from @var{address}, to a growing object,
and then add another byte containing a null character. @xref{Growing
Objects}.
@@ -2707,11 +2714,11 @@ Add one byte containing @var{data-char} to a growing object.
Finalize the object that is growing and return its permanent address.
@xref{Growing Objects}.
-@item int obstack_object_size (struct obstack *@var{obstack-ptr})
+@item size_t obstack_object_size (struct obstack *@var{obstack-ptr})
Get the current size of the currently growing object. @xref{Growing
Objects}.
-@item void obstack_blank_fast (struct obstack *@var{obstack-ptr}, int @var{size})
+@item void obstack_blank_fast (struct obstack *@var{obstack-ptr}, size_t @var{size})
Add @var{size} uninitialized bytes to a growing object without checking
that there is enough room. @xref{Extra Fast Growing}.
@@ -2719,15 +2726,15 @@ that there is enough room. @xref{Extra Fast Growing}.
Add one byte containing @var{data-char} to a growing object without
checking that there is enough room. @xref{Extra Fast Growing}.
-@item int obstack_room (struct obstack *@var{obstack-ptr})
+@item size_t obstack_room (struct obstack *@var{obstack-ptr})
Get the amount of room now available for growing the current object.
@xref{Extra Fast Growing}.
-@item int obstack_alignment_mask (struct obstack *@var{obstack-ptr})
+@item size_t obstack_alignment_mask (struct obstack *@var{obstack-ptr})
The mask used for aligning the beginning of an object. This is an
lvalue. @xref{Obstacks Data Alignment}.
-@item int obstack_chunk_size (struct obstack *@var{obstack-ptr})
+@item size_t obstack_chunk_size (struct obstack *@var{obstack-ptr})
The size for allocating chunks. This is an lvalue. @xref{Obstack Chunks}.
@item void *obstack_base (struct obstack *@var{obstack-ptr})
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 13+ messages in thread