mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-21 02:03:03 +00:00
Introduce obstacks.
Change each use of `faction' into a use of `action_obstack'. * lib/obstack.h, lib/obstack.c: New files. * src/files.c (faction): Remove. (action_obstack): New. Adjust all dependencies.
This commit is contained in:
10
ChangeLog
10
ChangeLog
@@ -1,3 +1,13 @@
|
|||||||
|
2000-11-01 Akim Demaille <akim@epita.fr>
|
||||||
|
|
||||||
|
Introduce obstacks.
|
||||||
|
Change each use of `faction' into a use of `action_obstack'.
|
||||||
|
|
||||||
|
* lib/obstack.h, lib/obstack.c: New files.
|
||||||
|
* src/files.c (faction): Remove.
|
||||||
|
(action_obstack): New.
|
||||||
|
Adjust all dependencies.
|
||||||
|
|
||||||
2000-10-20 Akim Demaille <akim@epita.fr>
|
2000-10-20 Akim Demaille <akim@epita.fr>
|
||||||
|
|
||||||
* lib/quote.h (PARAMS): New macro. Use it.
|
* lib/quote.h (PARAMS): New macro. Use it.
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ INCLUDES = -I.. -I$(srcdir) -I../intl
|
|||||||
libbison_a_SOURCES = \
|
libbison_a_SOURCES = \
|
||||||
error.c error.h \
|
error.c error.h \
|
||||||
getopt.h getopt.c getopt1.c \
|
getopt.h getopt.c getopt1.c \
|
||||||
|
obstack.h obstack.c \
|
||||||
quote.h quote.c quotearg.h quotearg.c \
|
quote.h quote.c quotearg.h quotearg.c \
|
||||||
xalloc.h xmalloc.c xstrdup.c
|
xalloc.h xmalloc.c xstrdup.c
|
||||||
|
|
||||||
|
|||||||
604
lib/obstack.c
Normal file
604
lib/obstack.c
Normal file
@@ -0,0 +1,604 @@
|
|||||||
|
/* obstack.c - subroutines used implicitly by object stack macros
|
||||||
|
Copyright (C) 1988-1994,96,97,98,99,2000 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU C Library. Its master source is NOT part of
|
||||||
|
the C library, however. The master source lives in /gd/gnu/lib.
|
||||||
|
|
||||||
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 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
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||||
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "obstack.h"
|
||||||
|
|
||||||
|
/* NOTE BEFORE MODIFYING THIS FILE: This version number must be
|
||||||
|
incremented whenever callers compiled using an old obstack.h can no
|
||||||
|
longer properly call the functions in this obstack.c. */
|
||||||
|
#define OBSTACK_INTERFACE_VERSION 1
|
||||||
|
|
||||||
|
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||||
|
actually compiling the library itself, and the installed library
|
||||||
|
supports the same library interface we do. This code is part of the GNU
|
||||||
|
C Library, but also included in many other GNU distributions. Compiling
|
||||||
|
and linking in this code is a waste when using the GNU C library
|
||||||
|
(especially if it is a shared library). Rather than having every GNU
|
||||||
|
program understand `configure --with-gnu-libc' and omit the object
|
||||||
|
files, it is simpler to just do this in the source for each such file. */
|
||||||
|
|
||||||
|
#include <stdio.h> /* Random thing to get __GNU_LIBRARY__. */
|
||||||
|
#if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
|
||||||
|
#include <gnu-versions.h>
|
||||||
|
#if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
|
||||||
|
#define ELIDE_CODE
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef ELIDE_CODE
|
||||||
|
|
||||||
|
|
||||||
|
#if defined (__STDC__) && __STDC__
|
||||||
|
#define POINTER void *
|
||||||
|
#else
|
||||||
|
#define POINTER char *
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Determine default alignment. */
|
||||||
|
struct fooalign {char x; double d;};
|
||||||
|
#define DEFAULT_ALIGNMENT \
|
||||||
|
((PTR_INT_TYPE) ((char *) &((struct fooalign *) 0)->d - (char *) 0))
|
||||||
|
/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
|
||||||
|
But in fact it might be less smart and round addresses to as much as
|
||||||
|
DEFAULT_ROUNDING. So we prepare for it to do that. */
|
||||||
|
union fooround {long x; double d;};
|
||||||
|
#define DEFAULT_ROUNDING (sizeof (union fooround))
|
||||||
|
|
||||||
|
/* When we copy a long block of data, this is the unit to do it with.
|
||||||
|
On some machines, copying successive ints does not work;
|
||||||
|
in such a case, redefine COPYING_UNIT to `long' (if that works)
|
||||||
|
or `char' as a last resort. */
|
||||||
|
#ifndef COPYING_UNIT
|
||||||
|
#define COPYING_UNIT int
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* The 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'. */
|
||||||
|
#if defined (__STDC__) && __STDC__
|
||||||
|
static void print_and_abort (void);
|
||||||
|
void (*obstack_alloc_failed_handler) (void) = print_and_abort;
|
||||||
|
#else
|
||||||
|
static void print_and_abort ();
|
||||||
|
void (*obstack_alloc_failed_handler) () = print_and_abort;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Exit value used when `print_and_abort' is used. */
|
||||||
|
#if defined __GNU_LIBRARY__ || defined HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifndef EXIT_FAILURE
|
||||||
|
#define EXIT_FAILURE 1
|
||||||
|
#endif
|
||||||
|
int obstack_exit_failure = EXIT_FAILURE;
|
||||||
|
|
||||||
|
/* The non-GNU-C macros copy the obstack into this global variable
|
||||||
|
to avoid multiple evaluation. */
|
||||||
|
|
||||||
|
struct obstack *_obstack;
|
||||||
|
|
||||||
|
/* Define a macro that either calls functions with the traditional malloc/free
|
||||||
|
calling interface, or calls functions with the mmalloc/mfree interface
|
||||||
|
(that adds an extra first argument), based on the state of use_extra_arg.
|
||||||
|
For free, do not use ?:, since some compilers, like the MIPS compilers,
|
||||||
|
do not allow (expr) ? void : void. */
|
||||||
|
|
||||||
|
#if defined (__STDC__) && __STDC__
|
||||||
|
#define CALL_CHUNKFUN(h, size) \
|
||||||
|
(((h) -> use_extra_arg) \
|
||||||
|
? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
|
||||||
|
: (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
|
||||||
|
|
||||||
|
#define CALL_FREEFUN(h, old_chunk) \
|
||||||
|
do { \
|
||||||
|
if ((h) -> use_extra_arg) \
|
||||||
|
(*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
|
||||||
|
else \
|
||||||
|
(*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define CALL_CHUNKFUN(h, size) \
|
||||||
|
(((h) -> use_extra_arg) \
|
||||||
|
? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
|
||||||
|
: (*(struct _obstack_chunk *(*) ()) (h)->chunkfun) ((size)))
|
||||||
|
|
||||||
|
#define CALL_FREEFUN(h, old_chunk) \
|
||||||
|
do { \
|
||||||
|
if ((h) -> use_extra_arg) \
|
||||||
|
(*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
|
||||||
|
else \
|
||||||
|
(*(void (*) ()) (h)->freefun) ((old_chunk)); \
|
||||||
|
} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
|
||||||
|
Objects start on multiples of ALIGNMENT (0 means use default).
|
||||||
|
CHUNKFUN is the function to use to allocate chunks,
|
||||||
|
and FREEFUN the function to free them.
|
||||||
|
|
||||||
|
Return nonzero if successful, calls obstack_alloc_failed_handler if
|
||||||
|
allocation fails. */
|
||||||
|
|
||||||
|
int
|
||||||
|
_obstack_begin (h, size, alignment, chunkfun, freefun)
|
||||||
|
struct obstack *h;
|
||||||
|
int size;
|
||||||
|
int alignment;
|
||||||
|
#if defined (__STDC__) && __STDC__
|
||||||
|
POINTER (*chunkfun) (long);
|
||||||
|
void (*freefun) (void *);
|
||||||
|
#else
|
||||||
|
POINTER (*chunkfun) ();
|
||||||
|
void (*freefun) ();
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
register struct _obstack_chunk *chunk; /* points to new chunk */
|
||||||
|
|
||||||
|
if (alignment == 0)
|
||||||
|
alignment = (int) 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined (__STDC__) && __STDC__
|
||||||
|
h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
|
||||||
|
h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
|
||||||
|
#else
|
||||||
|
h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
|
||||||
|
h->freefun = freefun;
|
||||||
|
#endif
|
||||||
|
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 = chunk->contents;
|
||||||
|
h->chunk_limit = chunk->limit
|
||||||
|
= (char *) chunk + h->chunk_size;
|
||||||
|
chunk->prev = 0;
|
||||||
|
/* The initial chunk now contains no empty object. */
|
||||||
|
h->maybe_empty_object = 0;
|
||||||
|
h->alloc_failed = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg)
|
||||||
|
struct obstack *h;
|
||||||
|
int size;
|
||||||
|
int alignment;
|
||||||
|
#if defined (__STDC__) && __STDC__
|
||||||
|
POINTER (*chunkfun) (POINTER, long);
|
||||||
|
void (*freefun) (POINTER, POINTER);
|
||||||
|
#else
|
||||||
|
POINTER (*chunkfun) ();
|
||||||
|
void (*freefun) ();
|
||||||
|
#endif
|
||||||
|
POINTER arg;
|
||||||
|
{
|
||||||
|
register struct _obstack_chunk *chunk; /* points to new chunk */
|
||||||
|
|
||||||
|
if (alignment == 0)
|
||||||
|
alignment = (int) 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__STDC__) && __STDC__
|
||||||
|
h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
|
||||||
|
h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
|
||||||
|
#else
|
||||||
|
h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
|
||||||
|
h->freefun = freefun;
|
||||||
|
#endif
|
||||||
|
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 = chunk->contents;
|
||||||
|
h->chunk_limit = chunk->limit
|
||||||
|
= (char *) chunk + h->chunk_size;
|
||||||
|
chunk->prev = 0;
|
||||||
|
/* The initial chunk now contains no empty object. */
|
||||||
|
h->maybe_empty_object = 0;
|
||||||
|
h->alloc_failed = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate a new current chunk for the obstack *H
|
||||||
|
on the assumption that LENGTH bytes need to be added
|
||||||
|
to the current object, or a new object of length LENGTH allocated.
|
||||||
|
Copies any partial object from the end of the old chunk
|
||||||
|
to the beginning of the new one. */
|
||||||
|
|
||||||
|
void
|
||||||
|
_obstack_newchunk (h, length)
|
||||||
|
struct obstack *h;
|
||||||
|
int length;
|
||||||
|
{
|
||||||
|
register struct _obstack_chunk *old_chunk = h->chunk;
|
||||||
|
register struct _obstack_chunk *new_chunk;
|
||||||
|
register long new_size;
|
||||||
|
register long obj_size = h->next_free - h->object_base;
|
||||||
|
register long i;
|
||||||
|
long already;
|
||||||
|
char *object_base;
|
||||||
|
|
||||||
|
/* Compute size for new chunk. */
|
||||||
|
new_size = (obj_size + length) + (obj_size >> 3) + h->alignment_mask + 100;
|
||||||
|
if (new_size < h->chunk_size)
|
||||||
|
new_size = h->chunk_size;
|
||||||
|
|
||||||
|
/* Allocate and initialize the new chunk. */
|
||||||
|
new_chunk = CALL_CHUNKFUN (h, new_size);
|
||||||
|
if (!new_chunk)
|
||||||
|
(*obstack_alloc_failed_handler) ();
|
||||||
|
h->chunk = new_chunk;
|
||||||
|
new_chunk->prev = old_chunk;
|
||||||
|
new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
|
||||||
|
|
||||||
|
/* Compute an aligned object_base in the new chunk */
|
||||||
|
object_base =
|
||||||
|
__INT_TO_PTR ((__PTR_TO_INT (new_chunk->contents) + h->alignment_mask)
|
||||||
|
& ~ (h->alignment_mask));
|
||||||
|
|
||||||
|
/* Move the existing object to the new chunk.
|
||||||
|
Word at a time is fast and is safe if the object
|
||||||
|
is sufficiently aligned. */
|
||||||
|
if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
|
||||||
|
{
|
||||||
|
for (i = obj_size / sizeof (COPYING_UNIT) - 1;
|
||||||
|
i >= 0; i--)
|
||||||
|
((COPYING_UNIT *)object_base)[i]
|
||||||
|
= ((COPYING_UNIT *)h->object_base)[i];
|
||||||
|
/* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
|
||||||
|
but that can cross a page boundary on a machine
|
||||||
|
which does not do strict alignment for COPYING_UNITS. */
|
||||||
|
already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
already = 0;
|
||||||
|
/* Copy remaining bytes one by one. */
|
||||||
|
for (i = already; i < obj_size; i++)
|
||||||
|
object_base[i] = h->object_base[i];
|
||||||
|
|
||||||
|
/* If the object just copied was the only data in OLD_CHUNK,
|
||||||
|
free that chunk and remove it from the chain.
|
||||||
|
But not if that chunk might contain an empty object. */
|
||||||
|
if (h->object_base == old_chunk->contents && ! h->maybe_empty_object)
|
||||||
|
{
|
||||||
|
new_chunk->prev = old_chunk->prev;
|
||||||
|
CALL_FREEFUN (h, old_chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
h->object_base = object_base;
|
||||||
|
h->next_free = h->object_base + obj_size;
|
||||||
|
/* The new chunk certainly contains no empty object yet. */
|
||||||
|
h->maybe_empty_object = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return nonzero if object OBJ has been allocated from obstack H.
|
||||||
|
This is here for debugging.
|
||||||
|
If you use it in a program, you are probably losing. */
|
||||||
|
|
||||||
|
#if defined (__STDC__) && __STDC__
|
||||||
|
/* Suppress -Wmissing-prototypes warning. We don't want to declare this in
|
||||||
|
obstack.h because it is just for debugging. */
|
||||||
|
int _obstack_allocated_p (struct obstack *h, POINTER obj);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
_obstack_allocated_p (h, obj)
|
||||||
|
struct obstack *h;
|
||||||
|
POINTER obj;
|
||||||
|
{
|
||||||
|
register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
|
||||||
|
register struct _obstack_chunk *plp; /* point to previous chunk if any */
|
||||||
|
|
||||||
|
lp = (h)->chunk;
|
||||||
|
/* We use >= rather than > since the object cannot be exactly at
|
||||||
|
the beginning of the chunk but might be an empty object exactly
|
||||||
|
at the end of an adjacent chunk. */
|
||||||
|
while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
|
||||||
|
{
|
||||||
|
plp = lp->prev;
|
||||||
|
lp = plp;
|
||||||
|
}
|
||||||
|
return lp != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free objects in obstack H, including OBJ and everything allocate
|
||||||
|
more recently than OBJ. If OBJ is zero, free everything in H. */
|
||||||
|
|
||||||
|
#undef obstack_free
|
||||||
|
|
||||||
|
/* This function has two names with identical definitions.
|
||||||
|
This is the first one, called from non-ANSI code. */
|
||||||
|
|
||||||
|
void
|
||||||
|
_obstack_free (h, obj)
|
||||||
|
struct obstack *h;
|
||||||
|
POINTER obj;
|
||||||
|
{
|
||||||
|
register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
|
||||||
|
register struct _obstack_chunk *plp; /* point to previous chunk if any */
|
||||||
|
|
||||||
|
lp = h->chunk;
|
||||||
|
/* We use >= because there cannot be an object at the beginning of a chunk.
|
||||||
|
But there can be an empty object at that address
|
||||||
|
at the end of another chunk. */
|
||||||
|
while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
|
||||||
|
{
|
||||||
|
plp = lp->prev;
|
||||||
|
CALL_FREEFUN (h, lp);
|
||||||
|
lp = plp;
|
||||||
|
/* If we switch chunks, we can't tell whether the new current
|
||||||
|
chunk contains an empty object, so assume that it may. */
|
||||||
|
h->maybe_empty_object = 1;
|
||||||
|
}
|
||||||
|
if (lp)
|
||||||
|
{
|
||||||
|
h->object_base = h->next_free = (char *) (obj);
|
||||||
|
h->chunk_limit = lp->limit;
|
||||||
|
h->chunk = lp;
|
||||||
|
}
|
||||||
|
else if (obj != 0)
|
||||||
|
/* obj is not in any of the chunks! */
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function is used from ANSI code. */
|
||||||
|
|
||||||
|
void
|
||||||
|
obstack_free (h, obj)
|
||||||
|
struct obstack *h;
|
||||||
|
POINTER obj;
|
||||||
|
{
|
||||||
|
register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
|
||||||
|
register struct _obstack_chunk *plp; /* point to previous chunk if any */
|
||||||
|
|
||||||
|
lp = h->chunk;
|
||||||
|
/* We use >= because there cannot be an object at the beginning of a chunk.
|
||||||
|
But there can be an empty object at that address
|
||||||
|
at the end of another chunk. */
|
||||||
|
while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
|
||||||
|
{
|
||||||
|
plp = lp->prev;
|
||||||
|
CALL_FREEFUN (h, lp);
|
||||||
|
lp = plp;
|
||||||
|
/* If we switch chunks, we can't tell whether the new current
|
||||||
|
chunk contains an empty object, so assume that it may. */
|
||||||
|
h->maybe_empty_object = 1;
|
||||||
|
}
|
||||||
|
if (lp)
|
||||||
|
{
|
||||||
|
h->object_base = h->next_free = (char *) (obj);
|
||||||
|
h->chunk_limit = lp->limit;
|
||||||
|
h->chunk = lp;
|
||||||
|
}
|
||||||
|
else if (obj != 0)
|
||||||
|
/* obj is not in any of the chunks! */
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_obstack_memory_used (h)
|
||||||
|
struct obstack *h;
|
||||||
|
{
|
||||||
|
register struct _obstack_chunk* lp;
|
||||||
|
register int nbytes = 0;
|
||||||
|
|
||||||
|
for (lp = h->chunk; lp != 0; lp = lp->prev)
|
||||||
|
{
|
||||||
|
nbytes += lp->limit - (char *) lp;
|
||||||
|
}
|
||||||
|
return nbytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Define the error handler. */
|
||||||
|
#ifndef _
|
||||||
|
# if defined HAVE_LIBINTL_H || defined _LIBC
|
||||||
|
# include <libintl.h>
|
||||||
|
# ifndef _
|
||||||
|
# define _(Str) gettext (Str)
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# define _(Str) (Str)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#if defined _LIBC && defined USE_IN_LIBIO
|
||||||
|
# include <libio/iolibio.h>
|
||||||
|
# define fputs(s, f) _IO_fputs (s, f)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_and_abort ()
|
||||||
|
{
|
||||||
|
fputs (_("memory exhausted"), stderr);
|
||||||
|
fputc ('\n', stderr);
|
||||||
|
exit (obstack_exit_failure);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* These are now turned off because the applications do not use it
|
||||||
|
and it uses bcopy via obstack_grow, which causes trouble on sysV. */
|
||||||
|
|
||||||
|
/* Now define the functional versions of the obstack macros.
|
||||||
|
Define them to simply use the corresponding macros to do the job. */
|
||||||
|
|
||||||
|
#if defined (__STDC__) && __STDC__
|
||||||
|
/* These function definitions do not work with non-ANSI preprocessors;
|
||||||
|
they won't pass through the macro names in parentheses. */
|
||||||
|
|
||||||
|
/* The function names appear in parentheses in order to prevent
|
||||||
|
the macro-definitions of the names from being expanded there. */
|
||||||
|
|
||||||
|
POINTER (obstack_base) (obstack)
|
||||||
|
struct obstack *obstack;
|
||||||
|
{
|
||||||
|
return obstack_base (obstack);
|
||||||
|
}
|
||||||
|
|
||||||
|
POINTER (obstack_next_free) (obstack)
|
||||||
|
struct obstack *obstack;
|
||||||
|
{
|
||||||
|
return obstack_next_free (obstack);
|
||||||
|
}
|
||||||
|
|
||||||
|
int (obstack_object_size) (obstack)
|
||||||
|
struct obstack *obstack;
|
||||||
|
{
|
||||||
|
return obstack_object_size (obstack);
|
||||||
|
}
|
||||||
|
|
||||||
|
int (obstack_room) (obstack)
|
||||||
|
struct obstack *obstack;
|
||||||
|
{
|
||||||
|
return obstack_room (obstack);
|
||||||
|
}
|
||||||
|
|
||||||
|
int (obstack_make_room) (obstack, length)
|
||||||
|
struct obstack *obstack;
|
||||||
|
int length;
|
||||||
|
{
|
||||||
|
return obstack_make_room (obstack, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void (obstack_grow) (obstack, pointer, length)
|
||||||
|
struct obstack *obstack;
|
||||||
|
POINTER pointer;
|
||||||
|
int length;
|
||||||
|
{
|
||||||
|
obstack_grow (obstack, pointer, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void (obstack_grow0) (obstack, pointer, length)
|
||||||
|
struct obstack *obstack;
|
||||||
|
POINTER pointer;
|
||||||
|
int length;
|
||||||
|
{
|
||||||
|
obstack_grow0 (obstack, pointer, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void (obstack_1grow) (obstack, character)
|
||||||
|
struct obstack *obstack;
|
||||||
|
int character;
|
||||||
|
{
|
||||||
|
obstack_1grow (obstack, character);
|
||||||
|
}
|
||||||
|
|
||||||
|
void (obstack_blank) (obstack, length)
|
||||||
|
struct obstack *obstack;
|
||||||
|
int length;
|
||||||
|
{
|
||||||
|
obstack_blank (obstack, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void (obstack_1grow_fast) (obstack, character)
|
||||||
|
struct obstack *obstack;
|
||||||
|
int character;
|
||||||
|
{
|
||||||
|
obstack_1grow_fast (obstack, character);
|
||||||
|
}
|
||||||
|
|
||||||
|
void (obstack_blank_fast) (obstack, length)
|
||||||
|
struct obstack *obstack;
|
||||||
|
int length;
|
||||||
|
{
|
||||||
|
obstack_blank_fast (obstack, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
POINTER (obstack_finish) (obstack)
|
||||||
|
struct obstack *obstack;
|
||||||
|
{
|
||||||
|
return obstack_finish (obstack);
|
||||||
|
}
|
||||||
|
|
||||||
|
POINTER (obstack_alloc) (obstack, length)
|
||||||
|
struct obstack *obstack;
|
||||||
|
int length;
|
||||||
|
{
|
||||||
|
return obstack_alloc (obstack, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
POINTER (obstack_copy) (obstack, pointer, length)
|
||||||
|
struct obstack *obstack;
|
||||||
|
POINTER pointer;
|
||||||
|
int length;
|
||||||
|
{
|
||||||
|
return obstack_copy (obstack, pointer, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
POINTER (obstack_copy0) (obstack, pointer, length)
|
||||||
|
struct obstack *obstack;
|
||||||
|
POINTER pointer;
|
||||||
|
int length;
|
||||||
|
{
|
||||||
|
return obstack_copy0 (obstack, pointer, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __STDC__ */
|
||||||
|
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
|
#endif /* !ELIDE_CODE */
|
||||||
593
lib/obstack.h
Normal file
593
lib/obstack.h
Normal file
@@ -0,0 +1,593 @@
|
|||||||
|
/* obstack.h - object stack macros
|
||||||
|
Copyright (C) 1988,89,90,91,92,93,94,96,97,98,99 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of the GNU C Library. Its master source is NOT part of
|
||||||
|
the C library, however. The master source lives in /gd/gnu/lib.
|
||||||
|
|
||||||
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 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
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||||
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
/* Summary:
|
||||||
|
|
||||||
|
All the apparent functions defined here are macros. The idea
|
||||||
|
is that you would use these pre-tested macros to solve a
|
||||||
|
very specific set of problems, and they would run fast.
|
||||||
|
Caution: no side-effects in arguments please!! They may be
|
||||||
|
evaluated MANY times!!
|
||||||
|
|
||||||
|
These macros operate a stack of objects. Each object starts life
|
||||||
|
small, and may grow to maturity. (Consider building a word syllable
|
||||||
|
by syllable.) An object can move while it is growing. Once it has
|
||||||
|
been "finished" it never changes address again. So the "top of the
|
||||||
|
stack" is typically an immature growing object, while the rest of the
|
||||||
|
stack is of mature, fixed size and fixed address objects.
|
||||||
|
|
||||||
|
These routines grab large chunks of memory, using a function you
|
||||||
|
supply, called `obstack_chunk_alloc'. On occasion, they free chunks,
|
||||||
|
by calling `obstack_chunk_free'. You must define them and declare
|
||||||
|
them before using any obstack macros.
|
||||||
|
|
||||||
|
Each independent stack is represented by a `struct obstack'.
|
||||||
|
Each of the obstack macros expects a pointer to such a structure
|
||||||
|
as the first argument.
|
||||||
|
|
||||||
|
One motivation for this package is the problem of growing char strings
|
||||||
|
in symbol tables. Unless you are "fascist pig with a read-only mind"
|
||||||
|
--Gosper's immortal quote from HAKMEM item 154, out of context--you
|
||||||
|
would not like to put any arbitrary upper limit on the length of your
|
||||||
|
symbols.
|
||||||
|
|
||||||
|
In practice this often means you will build many short symbols and a
|
||||||
|
few long symbols. At the time you are reading a symbol you don't know
|
||||||
|
how long it is. One traditional method is to read a symbol into a
|
||||||
|
buffer, realloc()ating the buffer every time you try to read a symbol
|
||||||
|
that is longer than the buffer. This is beaut, but you still will
|
||||||
|
want to copy the symbol from the buffer to a more permanent
|
||||||
|
symbol-table entry say about half the time.
|
||||||
|
|
||||||
|
With obstacks, you can work differently. Use one obstack for all symbol
|
||||||
|
names. As you read a symbol, grow the name in the obstack gradually.
|
||||||
|
When the name is complete, finalize it. Then, if the symbol exists already,
|
||||||
|
free the newly read name.
|
||||||
|
|
||||||
|
The way we do this is to take a large chunk, allocating memory from
|
||||||
|
low addresses. When you want to build a symbol in the chunk you just
|
||||||
|
add chars above the current "high water mark" in the chunk. When you
|
||||||
|
have finished adding chars, because you got to the end of the symbol,
|
||||||
|
you know how long the chars are, and you can create a new object.
|
||||||
|
Mostly the chars will not burst over the highest address of the chunk,
|
||||||
|
because you would typically expect a chunk to be (say) 100 times as
|
||||||
|
long as an average object.
|
||||||
|
|
||||||
|
In case that isn't clear, when we have enough chars to make up
|
||||||
|
the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
|
||||||
|
so we just point to it where it lies. No moving of chars is
|
||||||
|
needed and this is the second win: potentially long strings need
|
||||||
|
never be explicitly shuffled. Once an object is formed, it does not
|
||||||
|
change its address during its lifetime.
|
||||||
|
|
||||||
|
When the chars burst over a chunk boundary, we allocate a larger
|
||||||
|
chunk, and then copy the partly formed object from the end of the old
|
||||||
|
chunk to the beginning of the new larger chunk. We then carry on
|
||||||
|
accreting characters to the end of the object as we normally would.
|
||||||
|
|
||||||
|
A special macro is provided to add a single char at a time to a
|
||||||
|
growing object. This allows the use of register variables, which
|
||||||
|
break the ordinary 'growth' macro.
|
||||||
|
|
||||||
|
Summary:
|
||||||
|
We allocate large chunks.
|
||||||
|
We carve out one object at a time from the current chunk.
|
||||||
|
Once carved, an object never moves.
|
||||||
|
We are free to append data of any size to the currently
|
||||||
|
growing object.
|
||||||
|
Exactly one object is growing in an obstack at any one time.
|
||||||
|
You can run one obstack per control block.
|
||||||
|
You may have as many control blocks as you dare.
|
||||||
|
Because of the way we do it, you can `unwind' an obstack
|
||||||
|
back to a previous state. (You may remove objects much
|
||||||
|
as you would with a stack.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Don't do the contents of this file more than once. */
|
||||||
|
|
||||||
|
#ifndef _OBSTACK_H
|
||||||
|
#define _OBSTACK_H 1
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* We use subtraction of (char *) 0 instead of casting to int
|
||||||
|
because on word-addressable machines a simple cast to int
|
||||||
|
may ignore the byte-within-word field of the pointer. */
|
||||||
|
|
||||||
|
#ifndef __PTR_TO_INT
|
||||||
|
# define __PTR_TO_INT(P) ((P) - (char *) 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __INT_TO_PTR
|
||||||
|
# define __INT_TO_PTR(P) ((P) + (char *) 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* We need the type of the resulting object. 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, if <stddef.h> is
|
||||||
|
available, include it and use ptrdiff_t. In traditional C, long is
|
||||||
|
the best that we can do. */
|
||||||
|
|
||||||
|
#ifdef __PTRDIFF_TYPE__
|
||||||
|
# define PTR_INT_TYPE __PTRDIFF_TYPE__
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_STDDEF_H
|
||||||
|
# include <stddef.h>
|
||||||
|
# define PTR_INT_TYPE ptrdiff_t
|
||||||
|
# else
|
||||||
|
# define PTR_INT_TYPE long
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined _LIBC || defined HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
# define _obstack_memcpy(To, From, N) memcpy ((To), (From), (N))
|
||||||
|
#else
|
||||||
|
# ifdef memcpy
|
||||||
|
# define _obstack_memcpy(To, From, N) memcpy ((To), (From), (N))
|
||||||
|
# else
|
||||||
|
# define _obstack_memcpy(To, From, N) bcopy ((From), (To), (N))
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct _obstack_chunk /* Lives at front of each chunk. */
|
||||||
|
{
|
||||||
|
char *limit; /* 1 past end of this chunk */
|
||||||
|
struct _obstack_chunk *prev; /* address of prior chunk or NULL */
|
||||||
|
char contents[4]; /* objects begin here */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct obstack /* control current object in current chunk */
|
||||||
|
{
|
||||||
|
long chunk_size; /* preferred size to allocate chunks in */
|
||||||
|
struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */
|
||||||
|
char *object_base; /* address of object we are building */
|
||||||
|
char *next_free; /* where to add next char to current object */
|
||||||
|
char *chunk_limit; /* address of char after current chunk */
|
||||||
|
PTR_INT_TYPE temp; /* Temporary for some macros. */
|
||||||
|
int alignment_mask; /* Mask of alignment for each object. */
|
||||||
|
#if defined __STDC__ && __STDC__
|
||||||
|
/* 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);
|
||||||
|
void (*freefun) (void *, struct _obstack_chunk *);
|
||||||
|
void *extra_arg; /* first arg for chunk alloc/dealloc funcs */
|
||||||
|
#else
|
||||||
|
struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */
|
||||||
|
void (*freefun) (); /* User's function to free a chunk. */
|
||||||
|
char *extra_arg; /* first arg for chunk alloc/dealloc funcs */
|
||||||
|
#endif
|
||||||
|
unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */
|
||||||
|
unsigned maybe_empty_object:1;/* There is a possibility that the current
|
||||||
|
chunk contains a zero-length object. This
|
||||||
|
prevents freeing the chunk if we allocate
|
||||||
|
a bigger chunk to replace it. */
|
||||||
|
unsigned alloc_failed:1; /* No longer used, as we now call the failed
|
||||||
|
handler on error, but retained for binary
|
||||||
|
compatibility. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Declare the external functions we use; they are in obstack.c. */
|
||||||
|
|
||||||
|
#if defined __STDC__ && __STDC__
|
||||||
|
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,
|
||||||
|
void *(*) (void *, long),
|
||||||
|
void (*) (void *, void *), void *);
|
||||||
|
extern int _obstack_memory_used (struct obstack *);
|
||||||
|
#else
|
||||||
|
extern void _obstack_newchunk ();
|
||||||
|
extern void _obstack_free ();
|
||||||
|
extern int _obstack_begin ();
|
||||||
|
extern int _obstack_begin_1 ();
|
||||||
|
extern int _obstack_memory_used ();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined __STDC__ && __STDC__
|
||||||
|
|
||||||
|
/* Do the function-declarations after the structs
|
||||||
|
but before defining the macros. */
|
||||||
|
|
||||||
|
void obstack_init (struct obstack *obstack);
|
||||||
|
|
||||||
|
void * obstack_alloc (struct obstack *obstack, int size);
|
||||||
|
|
||||||
|
void * obstack_copy (struct obstack *obstack, void *address, int size);
|
||||||
|
void * obstack_copy0 (struct obstack *obstack, void *address, int size);
|
||||||
|
|
||||||
|
void obstack_free (struct obstack *obstack, void *block);
|
||||||
|
|
||||||
|
void obstack_blank (struct obstack *obstack, int size);
|
||||||
|
|
||||||
|
void obstack_grow (struct obstack *obstack, void *data, int size);
|
||||||
|
void obstack_grow0 (struct obstack *obstack, void *data, int size);
|
||||||
|
|
||||||
|
void obstack_1grow (struct obstack *obstack, int data_char);
|
||||||
|
void obstack_ptr_grow (struct obstack *obstack, void *data);
|
||||||
|
void obstack_int_grow (struct obstack *obstack, int data);
|
||||||
|
|
||||||
|
void * obstack_finish (struct obstack *obstack);
|
||||||
|
|
||||||
|
int obstack_object_size (struct obstack *obstack);
|
||||||
|
|
||||||
|
int obstack_room (struct obstack *obstack);
|
||||||
|
void obstack_make_room (struct obstack *obstack, int size);
|
||||||
|
void obstack_1grow_fast (struct obstack *obstack, int data_char);
|
||||||
|
void obstack_ptr_grow_fast (struct obstack *obstack, void *data);
|
||||||
|
void obstack_int_grow_fast (struct obstack *obstack, int data);
|
||||||
|
void obstack_blank_fast (struct obstack *obstack, int size);
|
||||||
|
|
||||||
|
void * obstack_base (struct obstack *obstack);
|
||||||
|
void * obstack_next_free (struct obstack *obstack);
|
||||||
|
int obstack_alignment_mask (struct obstack *obstack);
|
||||||
|
int obstack_chunk_size (struct obstack *obstack);
|
||||||
|
int obstack_memory_used (struct obstack *obstack);
|
||||||
|
|
||||||
|
#endif /* __STDC__ */
|
||||||
|
|
||||||
|
/* Non-ANSI C cannot really support alternative functions for these macros,
|
||||||
|
so we do not declare them. */
|
||||||
|
|
||||||
|
/* Error handler called when `obstack_chunk_alloc' failed to allocate
|
||||||
|
more memory. This can be set to a user defined function which
|
||||||
|
should either abort gracefully or use longjump - but shouldn't
|
||||||
|
return. The default action is to print a message and abort. */
|
||||||
|
#if defined __STDC__ && __STDC__
|
||||||
|
extern void (*obstack_alloc_failed_handler) (void);
|
||||||
|
#else
|
||||||
|
extern void (*obstack_alloc_failed_handler) ();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Exit value used when `print_and_abort' is used. */
|
||||||
|
extern int obstack_exit_failure;
|
||||||
|
|
||||||
|
/* Pointer to beginning of object being allocated or to be allocated next.
|
||||||
|
Note that this might not be the final address of the object
|
||||||
|
because a new chunk might be needed to hold the final size. */
|
||||||
|
|
||||||
|
#define obstack_base(h) ((h)->object_base)
|
||||||
|
|
||||||
|
/* Size for allocating ordinary chunks. */
|
||||||
|
|
||||||
|
#define obstack_chunk_size(h) ((h)->chunk_size)
|
||||||
|
|
||||||
|
/* Pointer to next byte not yet allocated in current chunk. */
|
||||||
|
|
||||||
|
#define obstack_next_free(h) ((h)->next_free)
|
||||||
|
|
||||||
|
/* Mask specifying low bits that should be clear in address of an object. */
|
||||||
|
|
||||||
|
#define obstack_alignment_mask(h) ((h)->alignment_mask)
|
||||||
|
|
||||||
|
/* To prevent prototype warnings provide complete argument list in
|
||||||
|
standard C version. */
|
||||||
|
#if defined __STDC__ && __STDC__
|
||||||
|
|
||||||
|
# define obstack_init(h) \
|
||||||
|
_obstack_begin ((h), 0, 0, \
|
||||||
|
(void *(*) (long)) obstack_chunk_alloc, (void (*) (void *)) obstack_chunk_free)
|
||||||
|
|
||||||
|
# define obstack_begin(h, size) \
|
||||||
|
_obstack_begin ((h), (size), 0, \
|
||||||
|
(void *(*) (long)) 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 (*) (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 *, void *)) (freefun), (arg))
|
||||||
|
|
||||||
|
# define obstack_chunkfun(h, newchunkfun) \
|
||||||
|
((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun))
|
||||||
|
|
||||||
|
# define obstack_freefun(h, newfreefun) \
|
||||||
|
((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun))
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# define obstack_init(h) \
|
||||||
|
_obstack_begin ((h), 0, 0, \
|
||||||
|
(void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free)
|
||||||
|
|
||||||
|
# define obstack_begin(h, size) \
|
||||||
|
_obstack_begin ((h), (size), 0, \
|
||||||
|
(void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free)
|
||||||
|
|
||||||
|
# define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
|
||||||
|
_obstack_begin ((h), (size), (alignment), \
|
||||||
|
(void *(*) ()) (chunkfun), (void (*) ()) (freefun))
|
||||||
|
|
||||||
|
# define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
|
||||||
|
_obstack_begin_1 ((h), (size), (alignment), \
|
||||||
|
(void *(*) ()) (chunkfun), (void (*) ()) (freefun), (arg))
|
||||||
|
|
||||||
|
# define obstack_chunkfun(h, newchunkfun) \
|
||||||
|
((h) -> chunkfun = (struct _obstack_chunk *(*)()) (newchunkfun))
|
||||||
|
|
||||||
|
# define obstack_freefun(h, newfreefun) \
|
||||||
|
((h) -> freefun = (void (*)()) (newfreefun))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
|
||||||
|
|
||||||
|
#define obstack_blank_fast(h,n) ((h)->next_free += (n))
|
||||||
|
|
||||||
|
#define obstack_memory_used(h) _obstack_memory_used (h)
|
||||||
|
|
||||||
|
#if defined __GNUC__ && defined __STDC__ && __STDC__
|
||||||
|
/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and
|
||||||
|
does not implement __extension__. But that compiler doesn't define
|
||||||
|
__GNUC_MINOR__. */
|
||||||
|
# if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__)
|
||||||
|
# define __extension__
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* For GNU C, if not -traditional,
|
||||||
|
we can define these macros to compute all args only once
|
||||||
|
without using a global variable.
|
||||||
|
Also, we can avoid using the `temp' slot, to make faster code. */
|
||||||
|
|
||||||
|
# define obstack_object_size(OBSTACK) \
|
||||||
|
__extension__ \
|
||||||
|
({ struct obstack *__o = (OBSTACK); \
|
||||||
|
(unsigned) (__o->next_free - __o->object_base); })
|
||||||
|
|
||||||
|
# define obstack_room(OBSTACK) \
|
||||||
|
__extension__ \
|
||||||
|
({ struct obstack *__o = (OBSTACK); \
|
||||||
|
(unsigned) (__o->chunk_limit - __o->next_free); })
|
||||||
|
|
||||||
|
# define obstack_make_room(OBSTACK,length) \
|
||||||
|
__extension__ \
|
||||||
|
({ struct obstack *__o = (OBSTACK); \
|
||||||
|
int __len = (length); \
|
||||||
|
if (__o->chunk_limit - __o->next_free < __len) \
|
||||||
|
_obstack_newchunk (__o, __len); \
|
||||||
|
(void) 0; })
|
||||||
|
|
||||||
|
# define obstack_empty_p(OBSTACK) \
|
||||||
|
__extension__ \
|
||||||
|
({ struct obstack *__o = (OBSTACK); \
|
||||||
|
(__o->chunk->prev == 0 && __o->next_free - __o->chunk->contents == 0); })
|
||||||
|
|
||||||
|
# define obstack_grow(OBSTACK,where,length) \
|
||||||
|
__extension__ \
|
||||||
|
({ struct obstack *__o = (OBSTACK); \
|
||||||
|
int __len = (length); \
|
||||||
|
if (__o->next_free + __len > __o->chunk_limit) \
|
||||||
|
_obstack_newchunk (__o, __len); \
|
||||||
|
_obstack_memcpy (__o->next_free, (char *) (where), __len); \
|
||||||
|
__o->next_free += __len; \
|
||||||
|
(void) 0; })
|
||||||
|
|
||||||
|
# define obstack_grow0(OBSTACK,where,length) \
|
||||||
|
__extension__ \
|
||||||
|
({ struct obstack *__o = (OBSTACK); \
|
||||||
|
int __len = (length); \
|
||||||
|
if (__o->next_free + __len + 1 > __o->chunk_limit) \
|
||||||
|
_obstack_newchunk (__o, __len + 1); \
|
||||||
|
_obstack_memcpy (__o->next_free, (char *) (where), __len); \
|
||||||
|
__o->next_free += __len; \
|
||||||
|
*(__o->next_free)++ = 0; \
|
||||||
|
(void) 0; })
|
||||||
|
|
||||||
|
# define obstack_1grow(OBSTACK,datum) \
|
||||||
|
__extension__ \
|
||||||
|
({ struct obstack *__o = (OBSTACK); \
|
||||||
|
if (__o->next_free + 1 > __o->chunk_limit) \
|
||||||
|
_obstack_newchunk (__o, 1); \
|
||||||
|
*(__o->next_free)++ = (datum); \
|
||||||
|
(void) 0; })
|
||||||
|
|
||||||
|
/* These assume that the obstack alignment is good enough for pointers or ints,
|
||||||
|
and that the data added so far to the current object
|
||||||
|
shares that much alignment. */
|
||||||
|
|
||||||
|
# define obstack_ptr_grow(OBSTACK,datum) \
|
||||||
|
__extension__ \
|
||||||
|
({ struct obstack *__o = (OBSTACK); \
|
||||||
|
if (__o->next_free + sizeof (void *) > __o->chunk_limit) \
|
||||||
|
_obstack_newchunk (__o, sizeof (void *)); \
|
||||||
|
*((void **)__o->next_free)++ = ((void *)datum); \
|
||||||
|
(void) 0; })
|
||||||
|
|
||||||
|
# define obstack_int_grow(OBSTACK,datum) \
|
||||||
|
__extension__ \
|
||||||
|
({ struct obstack *__o = (OBSTACK); \
|
||||||
|
if (__o->next_free + sizeof (int) > __o->chunk_limit) \
|
||||||
|
_obstack_newchunk (__o, sizeof (int)); \
|
||||||
|
*((int *)__o->next_free)++ = ((int)datum); \
|
||||||
|
(void) 0; })
|
||||||
|
|
||||||
|
# define obstack_ptr_grow_fast(h,aptr) (*((void **) (h)->next_free)++ = (void *)aptr)
|
||||||
|
# define obstack_int_grow_fast(h,aint) (*((int *) (h)->next_free)++ = (int) aint)
|
||||||
|
|
||||||
|
# define obstack_blank(OBSTACK,length) \
|
||||||
|
__extension__ \
|
||||||
|
({ struct obstack *__o = (OBSTACK); \
|
||||||
|
int __len = (length); \
|
||||||
|
if (__o->chunk_limit - __o->next_free < __len) \
|
||||||
|
_obstack_newchunk (__o, __len); \
|
||||||
|
__o->next_free += __len; \
|
||||||
|
(void) 0; })
|
||||||
|
|
||||||
|
# define obstack_alloc(OBSTACK,length) \
|
||||||
|
__extension__ \
|
||||||
|
({ struct obstack *__h = (OBSTACK); \
|
||||||
|
obstack_blank (__h, (length)); \
|
||||||
|
obstack_finish (__h); })
|
||||||
|
|
||||||
|
# define obstack_copy(OBSTACK,where,length) \
|
||||||
|
__extension__ \
|
||||||
|
({ struct obstack *__h = (OBSTACK); \
|
||||||
|
obstack_grow (__h, (where), (length)); \
|
||||||
|
obstack_finish (__h); })
|
||||||
|
|
||||||
|
# define obstack_copy0(OBSTACK,where,length) \
|
||||||
|
__extension__ \
|
||||||
|
({ struct obstack *__h = (OBSTACK); \
|
||||||
|
obstack_grow0 (__h, (where), (length)); \
|
||||||
|
obstack_finish (__h); })
|
||||||
|
|
||||||
|
/* The local variable is named __o1 to avoid a name conflict
|
||||||
|
when obstack_blank is called. */
|
||||||
|
# define obstack_finish(OBSTACK) \
|
||||||
|
__extension__ \
|
||||||
|
({ struct obstack *__o1 = (OBSTACK); \
|
||||||
|
void *value; \
|
||||||
|
value = (void *) __o1->object_base; \
|
||||||
|
if (__o1->next_free == value) \
|
||||||
|
__o1->maybe_empty_object = 1; \
|
||||||
|
__o1->next_free \
|
||||||
|
= __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\
|
||||||
|
& ~ (__o1->alignment_mask)); \
|
||||||
|
if (__o1->next_free - (char *)__o1->chunk \
|
||||||
|
> __o1->chunk_limit - (char *)__o1->chunk) \
|
||||||
|
__o1->next_free = __o1->chunk_limit; \
|
||||||
|
__o1->object_base = __o1->next_free; \
|
||||||
|
value; })
|
||||||
|
|
||||||
|
# define obstack_free(OBSTACK, OBJ) \
|
||||||
|
__extension__ \
|
||||||
|
({ struct obstack *__o = (OBSTACK); \
|
||||||
|
void *__obj = (OBJ); \
|
||||||
|
if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
|
||||||
|
__o->next_free = __o->object_base = (char *)__obj; \
|
||||||
|
else (obstack_free) (__o, __obj); })
|
||||||
|
|
||||||
|
#else /* not __GNUC__ or not __STDC__ */
|
||||||
|
|
||||||
|
# define obstack_object_size(h) \
|
||||||
|
(unsigned) ((h)->next_free - (h)->object_base)
|
||||||
|
|
||||||
|
# define obstack_room(h) \
|
||||||
|
(unsigned) ((h)->chunk_limit - (h)->next_free)
|
||||||
|
|
||||||
|
# define obstack_empty_p(h) \
|
||||||
|
((h)->chunk->prev == 0 && (h)->next_free - (h)->chunk->contents == 0)
|
||||||
|
|
||||||
|
/* Note that the call to _obstack_newchunk is enclosed in (..., 0)
|
||||||
|
so that we can avoid having void expressions
|
||||||
|
in the arms of the conditional expression.
|
||||||
|
Casting the third operand to void was tried before,
|
||||||
|
but some compilers won't accept it. */
|
||||||
|
|
||||||
|
# define obstack_make_room(h,length) \
|
||||||
|
( (h)->temp = (length), \
|
||||||
|
(((h)->next_free + (h)->temp > (h)->chunk_limit) \
|
||||||
|
? (_obstack_newchunk ((h), (h)->temp), 0) : 0))
|
||||||
|
|
||||||
|
# define obstack_grow(h,where,length) \
|
||||||
|
( (h)->temp = (length), \
|
||||||
|
(((h)->next_free + (h)->temp > (h)->chunk_limit) \
|
||||||
|
? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
|
||||||
|
_obstack_memcpy ((h)->next_free, (char *) (where), (h)->temp), \
|
||||||
|
(h)->next_free += (h)->temp)
|
||||||
|
|
||||||
|
# define obstack_grow0(h,where,length) \
|
||||||
|
( (h)->temp = (length), \
|
||||||
|
(((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \
|
||||||
|
? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \
|
||||||
|
_obstack_memcpy ((h)->next_free, (char *) (where), (h)->temp), \
|
||||||
|
(h)->next_free += (h)->temp, \
|
||||||
|
*((h)->next_free)++ = 0)
|
||||||
|
|
||||||
|
# define obstack_1grow(h,datum) \
|
||||||
|
( (((h)->next_free + 1 > (h)->chunk_limit) \
|
||||||
|
? (_obstack_newchunk ((h), 1), 0) : 0), \
|
||||||
|
(*((h)->next_free)++ = (datum)))
|
||||||
|
|
||||||
|
# define obstack_ptr_grow(h,datum) \
|
||||||
|
( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
|
||||||
|
? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
|
||||||
|
(*((char **) (((h)->next_free+=sizeof(char *))-sizeof(char *))) = ((char *) datum)))
|
||||||
|
|
||||||
|
# define obstack_int_grow(h,datum) \
|
||||||
|
( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \
|
||||||
|
? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
|
||||||
|
(*((int *) (((h)->next_free+=sizeof(int))-sizeof(int))) = ((int) datum)))
|
||||||
|
|
||||||
|
# define obstack_ptr_grow_fast(h,aptr) (*((char **) (h)->next_free)++ = (char *) aptr)
|
||||||
|
# define obstack_int_grow_fast(h,aint) (*((int *) (h)->next_free)++ = (int) aint)
|
||||||
|
|
||||||
|
# define obstack_blank(h,length) \
|
||||||
|
( (h)->temp = (length), \
|
||||||
|
(((h)->chunk_limit - (h)->next_free < (h)->temp) \
|
||||||
|
? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
|
||||||
|
((h)->next_free += (h)->temp))
|
||||||
|
|
||||||
|
# define obstack_alloc(h,length) \
|
||||||
|
(obstack_blank ((h), (length)), obstack_finish ((h)))
|
||||||
|
|
||||||
|
# define obstack_copy(h,where,length) \
|
||||||
|
(obstack_grow ((h), (where), (length)), obstack_finish ((h)))
|
||||||
|
|
||||||
|
# define obstack_copy0(h,where,length) \
|
||||||
|
(obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
|
||||||
|
|
||||||
|
# define obstack_finish(h) \
|
||||||
|
( ((h)->next_free == (h)->object_base \
|
||||||
|
? (((h)->maybe_empty_object = 1), 0) \
|
||||||
|
: 0), \
|
||||||
|
(h)->temp = __PTR_TO_INT ((h)->object_base), \
|
||||||
|
(h)->next_free \
|
||||||
|
= __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \
|
||||||
|
& ~ ((h)->alignment_mask)), \
|
||||||
|
(((h)->next_free - (char *) (h)->chunk \
|
||||||
|
> (h)->chunk_limit - (char *) (h)->chunk) \
|
||||||
|
? ((h)->next_free = (h)->chunk_limit) : 0), \
|
||||||
|
(h)->object_base = (h)->next_free, \
|
||||||
|
__INT_TO_PTR ((h)->temp))
|
||||||
|
|
||||||
|
# if defined __STDC__ && __STDC__
|
||||||
|
# define obstack_free(h,obj) \
|
||||||
|
( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \
|
||||||
|
(((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
|
||||||
|
? (int) ((h)->next_free = (h)->object_base \
|
||||||
|
= (h)->temp + (char *) (h)->chunk) \
|
||||||
|
: (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0)))
|
||||||
|
# else
|
||||||
|
# define obstack_free(h,obj) \
|
||||||
|
( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \
|
||||||
|
(((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
|
||||||
|
? (int) ((h)->next_free = (h)->object_base \
|
||||||
|
= (h)->temp + (char *) (h)->chunk) \
|
||||||
|
: (_obstack_free ((h), (h)->temp + (char *) (h)->chunk), 0)))
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif /* not __GNUC__ or not __STDC__ */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* C++ */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* obstack.h */
|
||||||
29
src/files.c
29
src/files.c
@@ -1,5 +1,5 @@
|
|||||||
/* Open and close files for bison,
|
/* Open and close files for bison,
|
||||||
Copyright (C) 1984, 1986, 1989, 1992, 2000 Free Software Foundation, Inc.
|
Copyright 1984, 1986, 1989, 1992, 2000 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of Bison, the GNU Compiler Compiler.
|
This file is part of Bison, the GNU Compiler Compiler.
|
||||||
|
|
||||||
@@ -53,9 +53,10 @@ FILE *fdefines = NULL;
|
|||||||
FILE *ftable = NULL;
|
FILE *ftable = NULL;
|
||||||
FILE *fattrs = NULL;
|
FILE *fattrs = NULL;
|
||||||
FILE *fguard = NULL;
|
FILE *fguard = NULL;
|
||||||
FILE *faction = NULL;
|
|
||||||
FILE *fparser = NULL;
|
FILE *fparser = NULL;
|
||||||
|
|
||||||
|
struct obstack action_obstack;
|
||||||
|
|
||||||
/* File name specified with -o for the output file, or 0 if no -o. */
|
/* File name specified with -o for the output file, or 0 if no -o. */
|
||||||
char *spec_outfile;
|
char *spec_outfile;
|
||||||
|
|
||||||
@@ -289,25 +290,18 @@ open_files (void)
|
|||||||
{
|
{
|
||||||
/* use permanent name for actions file */
|
/* use permanent name for actions file */
|
||||||
actfile = stringappend (name_base, short_base_length, ".act");
|
actfile = stringappend (name_base, short_base_length, ".act");
|
||||||
faction = xfopen (actfile, "w");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MSDOS
|
#ifdef MSDOS
|
||||||
if (!no_parser_flag)
|
|
||||||
actfile = mktemp (stringappend (tmp_base, tmp_len, "acXXXXXX"));
|
|
||||||
tmpattrsfile = mktemp (stringappend (tmp_base, tmp_len, "atXXXXXX"));
|
tmpattrsfile = mktemp (stringappend (tmp_base, tmp_len, "atXXXXXX"));
|
||||||
tmptabfile = mktemp (stringappend (tmp_base, tmp_len, "taXXXXXX"));
|
tmptabfile = mktemp (stringappend (tmp_base, tmp_len, "taXXXXXX"));
|
||||||
tmpdefsfile = mktemp (stringappend (tmp_base, tmp_len, "deXXXXXX"));
|
tmpdefsfile = mktemp (stringappend (tmp_base, tmp_len, "deXXXXXX"));
|
||||||
#else
|
#else
|
||||||
if (!no_parser_flag)
|
|
||||||
actfile = mktemp (stringappend (tmp_base, tmp_len, "act.XXXXXX"));
|
|
||||||
tmpattrsfile = mktemp (stringappend (tmp_base, tmp_len, "attrs.XXXXXX"));
|
tmpattrsfile = mktemp (stringappend (tmp_base, tmp_len, "attrs.XXXXXX"));
|
||||||
tmptabfile = mktemp (stringappend (tmp_base, tmp_len, "tab.XXXXXX"));
|
tmptabfile = mktemp (stringappend (tmp_base, tmp_len, "tab.XXXXXX"));
|
||||||
tmpdefsfile = mktemp (stringappend (tmp_base, tmp_len, "defs.XXXXXX"));
|
tmpdefsfile = mktemp (stringappend (tmp_base, tmp_len, "defs.XXXXXX"));
|
||||||
#endif /* not MSDOS */
|
#endif /* not MSDOS */
|
||||||
|
|
||||||
if (!no_parser_flag)
|
|
||||||
faction = xfopen (actfile, "w+");
|
|
||||||
fattrs = xfopen (tmpattrsfile, "w+");
|
fattrs = xfopen (tmpattrsfile, "w+");
|
||||||
ftable = xfopen (tmptabfile, "w+");
|
ftable = xfopen (tmptabfile, "w+");
|
||||||
|
|
||||||
@@ -318,8 +312,6 @@ open_files (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !(defined (MSDOS) || (defined(_WIN32) && !defined(__CYGWIN32__)))
|
#if !(defined (MSDOS) || (defined(_WIN32) && !defined(__CYGWIN32__)))
|
||||||
if (!no_parser_flag)
|
|
||||||
unlink (actfile);
|
|
||||||
unlink (tmpattrsfile);
|
unlink (tmpattrsfile);
|
||||||
unlink (tmptabfile);
|
unlink (tmptabfile);
|
||||||
unlink (tmpdefsfile);
|
unlink (tmpdefsfile);
|
||||||
@@ -343,6 +335,9 @@ open_files (void)
|
|||||||
guardfile = stringappend (name_base, short_base_length, ".guard.c");
|
guardfile = stringappend (name_base, short_base_length, ".guard.c");
|
||||||
#endif /* not MSDOS */
|
#endif /* not MSDOS */
|
||||||
#endif /* not VMS */
|
#endif /* not VMS */
|
||||||
|
|
||||||
|
/* Setup the action obstack. */
|
||||||
|
obstack_init (&action_obstack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -397,7 +392,6 @@ open_extra_files (void)
|
|||||||
void
|
void
|
||||||
done (void)
|
done (void)
|
||||||
{
|
{
|
||||||
xfclose (faction);
|
|
||||||
xfclose (fattrs);
|
xfclose (fattrs);
|
||||||
xfclose (fguard);
|
xfclose (fguard);
|
||||||
xfclose (finput);
|
xfclose (finput);
|
||||||
@@ -429,9 +423,14 @@ done (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (no_parser_flag)
|
||||||
|
{
|
||||||
|
FILE *faction = xfopen (actfile, "w");
|
||||||
|
size_t size = obstack_object_size (&action_obstack);
|
||||||
|
fwrite (obstack_finish (&action_obstack), 1, size, faction);
|
||||||
|
fclose (faction);
|
||||||
|
}
|
||||||
#if defined (VMS) & !defined (__VMS_POSIX)
|
#if defined (VMS) & !defined (__VMS_POSIX)
|
||||||
if (faction && !no_parser_flag)
|
|
||||||
delete (actfile);
|
|
||||||
if (fattrs)
|
if (fattrs)
|
||||||
delete (tmpattrsfile);
|
delete (tmpattrsfile);
|
||||||
if (ftable)
|
if (ftable)
|
||||||
@@ -442,8 +441,6 @@ done (void)
|
|||||||
sys$exit(SS$_ABORT); */
|
sys$exit(SS$_ABORT); */
|
||||||
#else
|
#else
|
||||||
#if (defined (MSDOS) || (defined(_WIN32) && !defined(__CYGWIN32__)))
|
#if (defined (MSDOS) || (defined(_WIN32) && !defined(__CYGWIN32__)))
|
||||||
if (actfile && !no_parser_flag)
|
|
||||||
unlink (actfile);
|
|
||||||
if (tmpattrsfile)
|
if (tmpattrsfile)
|
||||||
unlink (tmpattrsfile);
|
unlink (tmpattrsfile);
|
||||||
if (tmptabfile)
|
if (tmptabfile)
|
||||||
|
|||||||
11
src/files.h
11
src/files.h
@@ -1,5 +1,7 @@
|
|||||||
|
#ifndef FILES_H_
|
||||||
|
# define FILES_H_
|
||||||
/* File names and variables for bison,
|
/* File names and variables for bison,
|
||||||
Copyright (C) 1984, 1989, 2000 Free Software Foundation, Inc.
|
Copyright 1984, 1989, 2000 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of Bison, the GNU Compiler Compiler.
|
This file is part of Bison, the GNU Compiler Compiler.
|
||||||
|
|
||||||
@@ -18,7 +20,6 @@
|
|||||||
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
Boston, MA 02111-1307, USA. */
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
|
||||||
/* These two should be pathnames for opening the sample parser files.
|
/* These two should be pathnames for opening the sample parser files.
|
||||||
When bison is installed, they should be absolute pathnames.
|
When bison is installed, they should be absolute pathnames.
|
||||||
XPFILE1 and XPFILE2 normally come from config.h. */
|
XPFILE1 and XPFILE2 normally come from config.h. */
|
||||||
@@ -33,7 +34,6 @@ extern FILE *ftable; /* output the tables and the parser */
|
|||||||
extern FILE *fattrs; /* if semantic parser, output a .h file that defines YYSTYPE */
|
extern FILE *fattrs; /* if semantic parser, output a .h file that defines YYSTYPE */
|
||||||
/* and also contains all the %{ ... %} definitions. */
|
/* and also contains all the %{ ... %} definitions. */
|
||||||
extern FILE *fguard; /* if semantic parser, output yyguard, containing all the guard code */
|
extern FILE *fguard; /* if semantic parser, output yyguard, containing all the guard code */
|
||||||
extern FILE *faction; /* output all the action code; precise form depends on which parser */
|
|
||||||
extern FILE *fparser; /* read the parser to copy into ftable */
|
extern FILE *fparser; /* read the parser to copy into ftable */
|
||||||
|
|
||||||
/* File name specified with -o for the output file, or 0 if no -o. */
|
/* File name specified with -o for the output file, or 0 if no -o. */
|
||||||
@@ -44,6 +44,10 @@ extern char *spec_name_prefix; /* for -a, from getargs.c */
|
|||||||
/* File name pfx specified with -b, or 0 if no -b. */
|
/* File name pfx specified with -b, or 0 if no -b. */
|
||||||
extern char *spec_file_prefix;
|
extern char *spec_file_prefix;
|
||||||
|
|
||||||
|
/* Output all the action code; precise form depends on which parser. */
|
||||||
|
extern struct obstack action_obstack;
|
||||||
|
|
||||||
|
|
||||||
extern char *infile;
|
extern char *infile;
|
||||||
extern int lineno;
|
extern int lineno;
|
||||||
extern char *outfile;
|
extern char *outfile;
|
||||||
@@ -57,3 +61,4 @@ void open_files PARAMS((void));
|
|||||||
void open_extra_files PARAMS((void));
|
void open_extra_files PARAMS((void));
|
||||||
|
|
||||||
void done PARAMS((void));
|
void done PARAMS((void));
|
||||||
|
#endif /* !FILES_H_ */
|
||||||
|
|||||||
57
src/output.c
57
src/output.c
@@ -1,5 +1,5 @@
|
|||||||
/* Output the generated parsing program for bison,
|
/* Output the generated parsing program for bison,
|
||||||
Copyright (C) 1984, 1986, 1989, 1992, 2000 Free Software Foundation, Inc.
|
Copyright 1984, 1986, 1989, 1992, 2000 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of Bison, the GNU Compiler Compiler.
|
This file is part of Bison, the GNU Compiler Compiler.
|
||||||
|
|
||||||
@@ -91,6 +91,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
#include "obstack.h"
|
||||||
#include "getargs.h"
|
#include "getargs.h"
|
||||||
#include "xalloc.h"
|
#include "xalloc.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
@@ -214,6 +215,23 @@ register YYLTYPE *yylsp;\n\
|
|||||||
switch (n)\n\
|
switch (n)\n\
|
||||||
{"
|
{"
|
||||||
|
|
||||||
|
#define ACTSTR_PROLOGUE \
|
||||||
|
"\n\
|
||||||
|
#include \""
|
||||||
|
|
||||||
|
#define ACTSTR_EPILOGUE \
|
||||||
|
"\"\n\
|
||||||
|
extern YYSTYPE yyval;\n\
|
||||||
|
extern int yychar;\n\
|
||||||
|
\n\
|
||||||
|
yyaction(n, yyvsp, yylsp)\n\
|
||||||
|
register int n;\n\
|
||||||
|
register YYSTYPE *yyvsp;\n\
|
||||||
|
register YYLTYPE *yylsp;\n\
|
||||||
|
{\n\
|
||||||
|
switch (n)\n\
|
||||||
|
{"
|
||||||
|
|
||||||
#define ACTSTR_SIMPLE "\n switch (yyn) {\n"
|
#define ACTSTR_SIMPLE "\n switch (yyn) {\n"
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -225,7 +243,20 @@ output_headers (void)
|
|||||||
if (no_parser_flag)
|
if (no_parser_flag)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fprintf (faction, (semantic_parser ? ACTSTR : ACTSTR_SIMPLE), attrsfile);
|
if (semantic_parser)
|
||||||
|
{
|
||||||
|
obstack_grow_literal_string (&action_obstack,
|
||||||
|
ACTSTR_PROLOGUE);
|
||||||
|
obstack_grow (&action_obstack,
|
||||||
|
attrsfile, strlen (attrsfile));
|
||||||
|
obstack_grow_literal_string (&action_obstack,
|
||||||
|
ACTSTR_EPILOGUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
obstack_grow_literal_string (&action_obstack, ACTSTR_SIMPLE);
|
||||||
|
}
|
||||||
|
|
||||||
/* if (semantic_parser) JF moved this below
|
/* if (semantic_parser) JF moved this below
|
||||||
fprintf(ftable, "#include \"%s\"\n", attrsfile);
|
fprintf(ftable, "#include \"%s\"\n", attrsfile);
|
||||||
fprintf(ftable, "#include <stdio.h>\n\n");
|
fprintf(ftable, "#include <stdio.h>\n\n");
|
||||||
@@ -255,14 +286,18 @@ output_trailers (void)
|
|||||||
if (semantic_parser)
|
if (semantic_parser)
|
||||||
fprintf (fguard, "\n }\n}\n");
|
fprintf (fguard, "\n }\n}\n");
|
||||||
|
|
||||||
fprintf (faction, "\n");
|
obstack_1grow (&action_obstack, '\n');
|
||||||
|
|
||||||
if (no_parser_flag)
|
if (no_parser_flag)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (semantic_parser)
|
if (semantic_parser)
|
||||||
fprintf (faction, " }\n");
|
{
|
||||||
fprintf (faction, "}\n");
|
obstack_grow_literal_string (&action_obstack,
|
||||||
|
" }\n");
|
||||||
|
}
|
||||||
|
obstack_grow_literal_string (&action_obstack,
|
||||||
|
"}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1201,15 +1236,17 @@ output_parser (void)
|
|||||||
for (; c != '\n' && c != EOF; c = getc (fpars))
|
for (; c != '\n' && c != EOF; c = getc (fpars))
|
||||||
if (write_line)
|
if (write_line)
|
||||||
{
|
{
|
||||||
|
/* `$' in the parser file indicates where to put the
|
||||||
|
actions. Copy them in at this point. */
|
||||||
if (c == '$')
|
if (c == '$')
|
||||||
{
|
{
|
||||||
|
size_t size = obstack_object_size (&action_obstack);
|
||||||
|
|
||||||
number_of_dollar_signs++;
|
number_of_dollar_signs++;
|
||||||
assert (number_of_dollar_signs == 1);
|
assert (number_of_dollar_signs == 1);
|
||||||
/* `$' in the parser file indicates where to put the actions.
|
fwrite (obstack_finish (&action_obstack),
|
||||||
Copy them in at this point. */
|
1, size, ftable);
|
||||||
rewind (faction);
|
|
||||||
for (c = getc (faction); c != EOF; c = getc (faction))
|
|
||||||
putc (c, ftable);
|
|
||||||
/* Skip the end of the line containing `$'. */
|
/* Skip the end of the line containing `$'. */
|
||||||
write_line = 0;
|
write_line = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
166
src/reader.c
166
src/reader.c
@@ -1,5 +1,5 @@
|
|||||||
/* Input parser for bison
|
/* Input parser for bison
|
||||||
Copyright (C) 1984, 1986, 1989, 1992, 1998, 2000
|
Copyright 1984, 1986, 1989, 1992, 1998, 2000
|
||||||
Free Software Foundation, Inc.
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of Bison, the GNU Compiler Compiler.
|
This file is part of Bison, the GNU Compiler Compiler.
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
#include "obstack.h"
|
||||||
#include "getargs.h"
|
#include "getargs.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "xalloc.h"
|
#include "xalloc.h"
|
||||||
@@ -151,17 +152,21 @@ get_type_name (int n, symbol_list * rule)
|
|||||||
return rp->sym->type_name;
|
return rp->sym->type_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------.
|
/*-----------------------------------------------------------------.
|
||||||
| Dump the string from FINPUT to FOUTPUT. MATCH is the delimiter of |
|
| Dump the string from FIN to FOUT and OOUT if non null. MATCH is |
|
||||||
| the string (either ' or "). |
|
| the delimiter of the string (either ' or "). |
|
||||||
`-------------------------------------------------------------------*/
|
`-----------------------------------------------------------------*/
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
copy_string (FILE *fin, FILE *fout, int match)
|
copy_string (FILE *fin, FILE *fout, struct obstack *oout, int match)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
putc (match, fout);
|
if (fout)
|
||||||
|
putc (match, fout);
|
||||||
|
if (oout)
|
||||||
|
obstack_1grow (oout, match);
|
||||||
|
|
||||||
c = getc (fin);
|
c = getc (fin);
|
||||||
|
|
||||||
while (c != match)
|
while (c != match)
|
||||||
@@ -176,14 +181,21 @@ copy_string (FILE *fin, FILE *fout, int match)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
putc (c, fout);
|
if (fout)
|
||||||
|
putc (c, fout);
|
||||||
|
if (oout)
|
||||||
|
obstack_1grow (oout, c);
|
||||||
|
|
||||||
if (c == '\\')
|
if (c == '\\')
|
||||||
{
|
{
|
||||||
c = getc (fin);
|
c = getc (fin);
|
||||||
if (c == EOF)
|
if (c == EOF)
|
||||||
fatal (_("unterminated string at end of file"));
|
fatal (_("unterminated string at end of file"));
|
||||||
putc (c, fout);
|
if (fout)
|
||||||
|
putc (c, fout);
|
||||||
|
if (oout)
|
||||||
|
obstack_1grow (oout, c);
|
||||||
|
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
lineno++;
|
lineno++;
|
||||||
}
|
}
|
||||||
@@ -191,7 +203,10 @@ copy_string (FILE *fin, FILE *fout, int match)
|
|||||||
c = getc (fin);
|
c = getc (fin);
|
||||||
}
|
}
|
||||||
|
|
||||||
putc (c, fout);
|
if (fout)
|
||||||
|
putc (c, fout);
|
||||||
|
if (oout)
|
||||||
|
obstack_1grow (oout, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -204,16 +219,19 @@ copy_string (FILE *fin, FILE *fout, int match)
|
|||||||
`----------------------------------------------------------------*/
|
`----------------------------------------------------------------*/
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
copy_comment2 (FILE *fin, FILE *out1, FILE *out2)
|
copy_comment2 (FILE *fin, FILE *out1, FILE *out2, struct obstack *oout)
|
||||||
{
|
{
|
||||||
int cplus_comment;
|
int cplus_comment;
|
||||||
int ended;
|
int ended;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
/* We read a `/', output it. */
|
/* We read a `/', output it. */
|
||||||
putc ('/', out1);
|
if (out1)
|
||||||
|
putc ('/', out1);
|
||||||
if (out2)
|
if (out2)
|
||||||
putc ('/', out2);
|
putc ('/', out2);
|
||||||
|
if (oout)
|
||||||
|
obstack_1grow (oout, '/');
|
||||||
|
|
||||||
switch ((c = getc (fin)))
|
switch ((c = getc (fin)))
|
||||||
{
|
{
|
||||||
@@ -228,9 +246,12 @@ copy_comment2 (FILE *fin, FILE *out1, FILE *out2)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
putc (c, out1);
|
if (out1)
|
||||||
|
putc (c, out1);
|
||||||
if (out2)
|
if (out2)
|
||||||
putc (c, out2);
|
putc (c, out2);
|
||||||
|
if (oout)
|
||||||
|
obstack_1grow (oout, c);
|
||||||
c = getc (fin);
|
c = getc (fin);
|
||||||
|
|
||||||
ended = 0;
|
ended = 0;
|
||||||
@@ -240,26 +261,35 @@ copy_comment2 (FILE *fin, FILE *out1, FILE *out2)
|
|||||||
{
|
{
|
||||||
while (c == '*')
|
while (c == '*')
|
||||||
{
|
{
|
||||||
putc (c, out1);
|
if (out1)
|
||||||
|
putc (c, out1);
|
||||||
if (out2)
|
if (out2)
|
||||||
putc (c, out2);
|
putc (c, out2);
|
||||||
|
if (oout)
|
||||||
|
obstack_1grow (oout, c);
|
||||||
c = getc (fin);
|
c = getc (fin);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == '/')
|
if (c == '/')
|
||||||
{
|
{
|
||||||
putc (c, out1);
|
if (out1)
|
||||||
|
putc (c, out1);
|
||||||
if (out2)
|
if (out2)
|
||||||
putc (c, out2);
|
putc (c, out2);
|
||||||
|
if (oout)
|
||||||
|
obstack_1grow (oout, c);
|
||||||
ended = 1;
|
ended = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (c == '\n')
|
else if (c == '\n')
|
||||||
{
|
{
|
||||||
lineno++;
|
lineno++;
|
||||||
putc (c, out1);
|
if (out1)
|
||||||
|
putc (c, out1);
|
||||||
if (out2)
|
if (out2)
|
||||||
putc (c, out2);
|
putc (c, out2);
|
||||||
|
if (oout)
|
||||||
|
obstack_1grow (oout, c);
|
||||||
if (cplus_comment)
|
if (cplus_comment)
|
||||||
ended = 1;
|
ended = 1;
|
||||||
else
|
else
|
||||||
@@ -269,9 +299,12 @@ copy_comment2 (FILE *fin, FILE *out1, FILE *out2)
|
|||||||
fatal (_("unterminated comment"));
|
fatal (_("unterminated comment"));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
putc (c, out1);
|
if (out1)
|
||||||
|
putc (c, out1);
|
||||||
if (out2)
|
if (out2)
|
||||||
putc (c, out2);
|
putc (c, out2);
|
||||||
|
if (oout)
|
||||||
|
obstack_1grow (oout, c);
|
||||||
c = getc (fin);
|
c = getc (fin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -284,9 +317,9 @@ copy_comment2 (FILE *fin, FILE *out1, FILE *out2)
|
|||||||
`-------------------------------------------------------------------*/
|
`-------------------------------------------------------------------*/
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
copy_comment (FILE *fin, FILE *fout)
|
copy_comment (FILE *fin, FILE *fout, struct obstack *oout)
|
||||||
{
|
{
|
||||||
copy_comment2 (fin, fout, NULL);
|
copy_comment2 (fin, fout, NULL, oout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -298,24 +331,32 @@ copy_comment (FILE *fin, FILE *fout)
|
|||||||
`-----------------------------------------------------------------*/
|
`-----------------------------------------------------------------*/
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
copy_at (FILE *fin, FILE *fout, int stack_offset)
|
copy_at (FILE *fin, FILE *fout, struct obstack *oout, int stack_offset)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
c = getc (fin);
|
c = getc (fin);
|
||||||
if (c == '$')
|
if (c == '$')
|
||||||
{
|
{
|
||||||
fprintf (fout, "yyloc");
|
if (fout)
|
||||||
|
fprintf (fout, "yyloc");
|
||||||
|
if (oout)
|
||||||
|
obstack_grow_literal_string (oout, "yylloc");
|
||||||
locations_flag = 1;
|
locations_flag = 1;
|
||||||
}
|
}
|
||||||
else if (isdigit (c) || c == '-')
|
else if (isdigit (c) || c == '-')
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
char buf[4096];
|
||||||
|
|
||||||
ungetc (c, fin);
|
ungetc (c, fin);
|
||||||
n = read_signed_integer (fin);
|
n = read_signed_integer (fin);
|
||||||
|
|
||||||
fprintf (fout, "yylsp[%d]", n - stack_offset);
|
sprintf (buf, "yylsp[%d]", n - stack_offset);
|
||||||
|
if (fout)
|
||||||
|
fputs (buf, fout);
|
||||||
|
if (oout)
|
||||||
|
obstack_grow (oout, buf, strlen (buf));
|
||||||
locations_flag = 1;
|
locations_flag = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -338,7 +379,7 @@ copy_at (FILE *fin, FILE *fout, int stack_offset)
|
|||||||
`-------------------------------------------------------------------*/
|
`-------------------------------------------------------------------*/
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
copy_dollar (FILE *fin, FILE *fout,
|
copy_dollar (FILE *fin, FILE *fout, struct obstack *oout,
|
||||||
symbol_list *rule, int stack_offset)
|
symbol_list *rule, int stack_offset)
|
||||||
{
|
{
|
||||||
int c = getc (fin);
|
int c = getc (fin);
|
||||||
@@ -355,11 +396,20 @@ copy_dollar (FILE *fin, FILE *fout,
|
|||||||
|
|
||||||
if (c == '$')
|
if (c == '$')
|
||||||
{
|
{
|
||||||
fprintf (fout, "yyval");
|
if (fout)
|
||||||
|
fputs ("yyval", fout);
|
||||||
|
if (oout)
|
||||||
|
obstack_grow_literal_string (oout, "yyval");
|
||||||
|
|
||||||
if (!type_name)
|
if (!type_name)
|
||||||
type_name = get_type_name (0, rule);
|
type_name = get_type_name (0, rule);
|
||||||
if (type_name)
|
if (type_name)
|
||||||
fprintf (fout, ".%s", type_name);
|
{
|
||||||
|
if (fout)
|
||||||
|
fprintf (fout, ".%s", type_name);
|
||||||
|
if (oout)
|
||||||
|
obstack_fgrow1 (oout, ".%s", type_name);
|
||||||
|
}
|
||||||
if (!type_name && typed)
|
if (!type_name && typed)
|
||||||
complain (_("$$ of `%s' has no declared type"),
|
complain (_("$$ of `%s' has no declared type"),
|
||||||
rule->sym->tag);
|
rule->sym->tag);
|
||||||
@@ -373,9 +423,18 @@ copy_dollar (FILE *fin, FILE *fout,
|
|||||||
if (!type_name && n > 0)
|
if (!type_name && n > 0)
|
||||||
type_name = get_type_name (n, rule);
|
type_name = get_type_name (n, rule);
|
||||||
|
|
||||||
fprintf (fout, "yyvsp[%d]", n - stack_offset);
|
if (fout)
|
||||||
|
fprintf (fout, "yyvsp[%d]", n - stack_offset);
|
||||||
|
if (oout)
|
||||||
|
obstack_fgrow1 (oout, "yyvsp[%d]", n - stack_offset);
|
||||||
|
|
||||||
if (type_name)
|
if (type_name)
|
||||||
fprintf (fout, ".%s", type_name);
|
{
|
||||||
|
if (fout)
|
||||||
|
fprintf (fout, ".%s", type_name);
|
||||||
|
if (oout)
|
||||||
|
obstack_fgrow1 (oout, ".%s", type_name);
|
||||||
|
}
|
||||||
if (!type_name && typed)
|
if (!type_name && typed)
|
||||||
complain (_("$%d of `%s' has no declared type"),
|
complain (_("$%d of `%s' has no declared type"),
|
||||||
n, rule->sym->tag);
|
n, rule->sym->tag);
|
||||||
@@ -422,11 +481,11 @@ copy_definition (void)
|
|||||||
|
|
||||||
case '\'':
|
case '\'':
|
||||||
case '"':
|
case '"':
|
||||||
copy_string (finput, fattrs, c);
|
copy_string (finput, fattrs, 0, c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '/':
|
case '/':
|
||||||
copy_comment (finput, fattrs);
|
copy_comment (finput, fattrs, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EOF:
|
case EOF:
|
||||||
@@ -744,7 +803,7 @@ parse_union_decl (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '/':
|
case '/':
|
||||||
copy_comment2 (finput, fattrs, fdefines);
|
copy_comment2 (finput, fattrs, fdefines, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '{':
|
case '{':
|
||||||
@@ -984,15 +1043,21 @@ copy_action (symbol_list *rule, int stack_offset)
|
|||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
int count;
|
int count;
|
||||||
|
char buf[4096];
|
||||||
|
|
||||||
/* offset is always 0 if parser has already popped the stack pointer */
|
/* offset is always 0 if parser has already popped the stack pointer */
|
||||||
if (semantic_parser)
|
if (semantic_parser)
|
||||||
stack_offset = 0;
|
stack_offset = 0;
|
||||||
|
|
||||||
fprintf (faction, "\ncase %d:\n", nrules);
|
sprintf (buf, "\ncase %d:\n", nrules);
|
||||||
|
obstack_grow (&action_obstack, buf, strlen (buf));
|
||||||
|
|
||||||
if (!no_lines_flag)
|
if (!no_lines_flag)
|
||||||
fprintf (faction, "#line %d \"%s\"\n", lineno, infile);
|
{
|
||||||
putc ('{', faction);
|
sprintf (buf, "#line %d \"%s\"\n", lineno, infile);
|
||||||
|
obstack_grow (&action_obstack, buf, strlen (buf));
|
||||||
|
}
|
||||||
|
obstack_1grow (&action_obstack, '{');
|
||||||
|
|
||||||
count = 1;
|
count = 1;
|
||||||
c = getc (finput);
|
c = getc (finput);
|
||||||
@@ -1004,37 +1069,39 @@ copy_action (symbol_list *rule, int stack_offset)
|
|||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case '\n':
|
case '\n':
|
||||||
putc (c, faction);
|
obstack_1grow (&action_obstack, c);
|
||||||
lineno++;
|
lineno++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '{':
|
case '{':
|
||||||
putc (c, faction);
|
obstack_1grow (&action_obstack, c);
|
||||||
count++;
|
count++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\'':
|
case '\'':
|
||||||
case '"':
|
case '"':
|
||||||
copy_string (finput, faction, c);
|
copy_string (finput, 0, &action_obstack, c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '/':
|
case '/':
|
||||||
copy_comment (finput, faction);
|
copy_comment (finput, 0, &action_obstack);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '$':
|
case '$':
|
||||||
copy_dollar (finput, faction, rule, stack_offset);
|
copy_dollar (finput, 0, &action_obstack,
|
||||||
|
rule, stack_offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '@':
|
case '@':
|
||||||
copy_at (finput, faction, stack_offset);
|
copy_at (finput, 0, &action_obstack,
|
||||||
|
stack_offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EOF:
|
case EOF:
|
||||||
fatal (_("unmatched %s"), "`{'");
|
fatal (_("unmatched %s"), "`{'");
|
||||||
|
|
||||||
default:
|
default:
|
||||||
putc (c, faction);
|
obstack_1grow (&action_obstack, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
c = getc (finput);
|
c = getc (finput);
|
||||||
@@ -1044,12 +1111,13 @@ copy_action (symbol_list *rule, int stack_offset)
|
|||||||
|
|
||||||
if (--count)
|
if (--count)
|
||||||
{
|
{
|
||||||
putc (c, faction);
|
obstack_1grow (&action_obstack, c);
|
||||||
c = getc (finput);
|
c = getc (finput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf (faction, ";\n break;}");
|
obstack_grow_literal_string (&action_obstack,
|
||||||
|
";\n break;}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------.
|
/*-------------------------------------------------------------------.
|
||||||
@@ -1108,19 +1176,19 @@ copy_guard (symbol_list *rule, int stack_offset)
|
|||||||
|
|
||||||
case '\'':
|
case '\'':
|
||||||
case '"':
|
case '"':
|
||||||
copy_string (finput, fguard, c);
|
copy_string (finput, fguard, 0, c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '/':
|
case '/':
|
||||||
copy_comment (finput, fguard);
|
copy_comment (finput, fguard, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '$':
|
case '$':
|
||||||
copy_dollar (finput, fguard, rule, stack_offset);
|
copy_dollar (finput, fguard, 0, rule, stack_offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '@':
|
case '@':
|
||||||
copy_at (finput, fguard, stack_offset);
|
copy_at (finput, fguard, 0, stack_offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EOF:
|
case EOF:
|
||||||
@@ -1823,9 +1891,9 @@ packgram (void)
|
|||||||
/*-------------------------------------------------------------------.
|
/*-------------------------------------------------------------------.
|
||||||
| Read in the grammar specification and record it in the format |
|
| Read in the grammar specification and record it in the format |
|
||||||
| described in gram.h. All guards are copied into the FGUARD file |
|
| described in gram.h. All guards are copied into the FGUARD file |
|
||||||
| and all actions into FACTION, in each case forming the body of a C |
|
| and all actions into ACTION_OBSTACK, in each case forming the body |
|
||||||
| function (YYGUARD or YYACTION) which contains a switch statement |
|
| of a C function (YYGUARD or YYACTION) which contains a switch |
|
||||||
| to decide which guard or action to execute. |
|
| statement to decide which guard or action to execute. |
|
||||||
`-------------------------------------------------------------------*/
|
`-------------------------------------------------------------------*/
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
19
src/system.h
19
src/system.h
@@ -161,3 +161,22 @@ extern int errno;
|
|||||||
# define FALSE (0)
|
# define FALSE (0)
|
||||||
#endif
|
#endif
|
||||||
typedef int bool;
|
typedef int bool;
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------.
|
||||||
|
| Obstacks. |
|
||||||
|
`-----------*/
|
||||||
|
|
||||||
|
#define obstack_chunk_alloc xmalloc
|
||||||
|
#define obstack_chunk_free free
|
||||||
|
#include "obstack.h"
|
||||||
|
|
||||||
|
#define obstack_grow_literal_string(Obs, Str) \
|
||||||
|
obstack_grow (Obs, Str, sizeof (Str) - 1)
|
||||||
|
|
||||||
|
#define obstack_fgrow1(Obs, Format, Arg1) \
|
||||||
|
do { \
|
||||||
|
char buf[4096]; \
|
||||||
|
sprintf (buf, Format, Arg1); \
|
||||||
|
obstack_grow (Obs, buf, strlen (buf)); \
|
||||||
|
} while (0)
|
||||||
|
|||||||
Reference in New Issue
Block a user