Convert cpplib to use libiberty/hashtab.c.

* cpplib.h (struct cpp_reader): Make hashtab and
	all_include_files of type 'struct htab *'.  Delete HASHSIZE
	and ALL_INCLUDE_HASHSIZE macros.

	* cpphash.h: Update prototypes.
	(struct hashnode): Remove next, prev, and bucket_hdr members.
	Make length a size_t.  Add hash member.
	(struct ihash): Remove next member.  Add hash member.  Make
	name a flexible array member.

	* cppfiles.c: Include hashtab.h.
	(include_hash): Delete.
	(IHASHSIZE): New macro.
	(hash_IHASH, eq_IHASH, _cpp_init_include_hash): New functions.
	(cpp_included): Do the hash lookup here.
	(_cpp_find_include_file): Rewrite.
	(cpp_read_file): Put the "fake" hash entry into the hash
	table.  Honor the control_macro, if it turns out we've seen
	the file before.  Don't push the buffer here.
	(_cpp_read_include_file): Push the buffer here.
	(OMODES): New macro.  Use it whenever we call open(2).

	* cpphash.c: Include hashtab.h.
	(hash_HASHNODE, eq_HASHNODE, del_HASHNODE, dump_hash_helper,
	_cpp_init_macro_hash, _cpp_dump_macro_hash, _cpp_make_hashnode,
	_cpp_lookup_slot): New functions.
	(HASHSIZE): new macro.
	(hashf, _cpp_install, _cpp_delete_macro): Delete.
	(_cpp_lookup): Use hashtab.h routines.

	* cppinit.c: Include hashtab.h.
	(cpp_reader_init): Call _cpp_init_macro_hash and
	_cpp_init_include_hash.  Don't allocate hashtab directly.
	(cpp_cleanup): Just call htab_delete on pfile->hashtab and
	pfile->all_include_files.
	(initialize_builtins): Use _cpp_make_hashnode and
	htab_find_slot to add hash entries.
	(cpp_finish): Just call _cpp_dump_macro_hash.
	* cpplib.c: Include hashtab.h.
	(do_define): Use _cpp_lookup_slot and _cpp_make_hashnode to
	create hash entries.
	(do_pragma_poison, do_assert): Likewise.
	(do_include): Don't push the buffer here.  Don't increment
	system_include_depth unless _cpp_read_include_file succeeds.
	(do_undef, do_unassert): Use _cpp_lookup_slot and htab_clear_slot
	or htab_remove_elt.
	(do_pragma_implementation): Use alloca to create copy.

	* Makefile.in: Update dependencies.

From-SVN: r32497
This commit is contained in:
Zack Weinberg 2000-03-12 23:46:05 +00:00 committed by Zack Weinberg
parent 6973bf5482
commit d35364d13e
8 changed files with 457 additions and 395 deletions

View File

@ -1,3 +1,57 @@
2000-03-12 Zack Weinberg <zack@wolery.cumb.org>
Convert cpplib to use libiberty/hashtab.c.
* cpplib.h (struct cpp_reader): Make hashtab and
all_include_files of type 'struct htab *'. Delete HASHSIZE
and ALL_INCLUDE_HASHSIZE macros.
* cpphash.h: Update prototypes.
(struct hashnode): Remove next, prev, and bucket_hdr members.
Make length a size_t. Add hash member.
(struct ihash): Remove next member. Add hash member. Make
name a flexible array member.
* cppfiles.c: Include hashtab.h.
(include_hash): Delete.
(IHASHSIZE): New macro.
(hash_IHASH, eq_IHASH, _cpp_init_include_hash): New functions.
(cpp_included): Do the hash lookup here.
(_cpp_find_include_file): Rewrite.
(cpp_read_file): Put the "fake" hash entry into the hash
table. Honor the control_macro, if it turns out we've seen
the file before. Don't push the buffer here.
(_cpp_read_include_file): Push the buffer here.
(OMODES): New macro. Use it whenever we call open(2).
* cpphash.c: Include hashtab.h.
(hash_HASHNODE, eq_HASHNODE, del_HASHNODE, dump_hash_helper,
_cpp_init_macro_hash, _cpp_dump_macro_hash, _cpp_make_hashnode,
_cpp_lookup_slot): New functions.
(HASHSIZE): new macro.
(hashf, _cpp_install, _cpp_delete_macro): Delete.
(_cpp_lookup): Use hashtab.h routines.
* cppinit.c: Include hashtab.h.
(cpp_reader_init): Call _cpp_init_macro_hash and
_cpp_init_include_hash. Don't allocate hashtab directly.
(cpp_cleanup): Just call htab_delete on pfile->hashtab and
pfile->all_include_files.
(initialize_builtins): Use _cpp_make_hashnode and
htab_find_slot to add hash entries.
(cpp_finish): Just call _cpp_dump_macro_hash.
* cpplib.c: Include hashtab.h.
(do_define): Use _cpp_lookup_slot and _cpp_make_hashnode to
create hash entries.
(do_pragma_poison, do_assert): Likewise.
(do_include): Don't push the buffer here. Don't increment
system_include_depth unless _cpp_read_include_file succeeds.
(do_undef, do_unassert): Use _cpp_lookup_slot and htab_clear_slot
or htab_remove_elt.
(do_pragma_implementation): Use alloca to create copy.
* Makefile.in: Update dependencies.
2000-03-12 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* cppinit.c (cl_directive_handler): More K&R fixing.

View File

@ -2029,6 +2029,7 @@ LIBCPP_OBJS = cpplib.o cpphash.o cpperror.o cppexp.o cppfiles.o \
prefix.o version.o mbchar.o @extra_cpp_objs@
LIBCPP_DEPS = cpplib.h cpphash.h intl.h system.h
HASHTAB_H = $(srcdir)/../include/hashtab.h
# All the other archives built/used by this makefile are for targets. This
# one is strictly for the host.
@ -2042,17 +2043,17 @@ cppmain$(exeext): cppmain.o intl.o libcpp.a $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o cppmain$(exeext) cppmain.o \
intl.o libcpp.a $(LIBS)
cppmain.o: cppmain.c $(CONFIG_H) cpplib.h intl.h system.h
cppmain.o: cppmain.c $(CONFIG_H) cpplib.h intl.h system.h
cppulp.o: cppulp.c $(CONFIG_H) system.h output.h
cpplib.o: cpplib.c $(CONFIG_H) $(LIBCPP_DEPS) mkdeps.h
cpphash.o: cpphash.c $(CONFIG_H) $(LIBCPP_DEPS) version.h
cppulp.o: cppulp.c $(CONFIG_H) system.h output.h
cpperror.o: cpperror.c $(CONFIG_H) $(LIBCPP_DEPS)
cppexp.o: cppexp.c $(CONFIG_H) $(LIBCPP_DEPS)
cppfiles.o: cppfiles.c $(CONFIG_H) $(LIBCPP_DEPS)
cppfiles.o: cppfiles.c $(CONFIG_H) $(LIBCPP_DEPS) $(HASHTAB_H)
cpphash.o: cpphash.c $(CONFIG_H) $(LIBCPP_DEPS) $(HASHTAB_H) version.h
cpplib.o: cpplib.c $(CONFIG_H) $(LIBCPP_DEPS) $(HASHTAB_H) mkdeps.h
cppinit.o: cppinit.c $(CONFIG_H) cpplib.h intl.h system.h \
cpphash.h prefix.h output.h Makefile version.h mkdeps.h
cppinit.o: cppinit.c $(CONFIG_H) $(LIBCPP_DEPS) $(HASHTAB_H) mkdeps.h \
prefix.h output.h Makefile version.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(PREPROCESSOR_DEFINES) \
-c `echo $(srcdir)/cppinit.c | sed 's,^\./,,'`

View File

@ -28,9 +28,9 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "system.h"
#include "cpplib.h"
#include "cpphash.h"
#include "hashtab.h"
#include "intl.h"
static IHASH *include_hash PARAMS ((cpp_reader *, const char *, int));
static IHASH *redundant_include_p PARAMS ((cpp_reader *, IHASH *,
struct file_name_list *));
static struct file_name_map *read_name_map
@ -42,6 +42,10 @@ static long read_and_prescan PARAMS ((cpp_reader *, cpp_buffer *,
int, size_t));
static struct file_name_list *actual_directory
PARAMS ((cpp_reader *, const char *));
static unsigned int hash_IHASH PARAMS ((const void *));
static int eq_IHASH PARAMS ((const void *, const void *));
static void init_input_buffer PARAMS ((cpp_reader *, int, struct stat *));
static int file_cleanup PARAMS ((cpp_buffer *, cpp_reader *));
static U_CHAR *find_position PARAMS ((U_CHAR *, U_CHAR *, unsigned long *));
@ -50,50 +54,57 @@ static U_CHAR *find_position PARAMS ((U_CHAR *, U_CHAR *, unsigned long *));
static void hack_vms_include_specification PARAMS ((char *));
#endif
/* Initial size of include hash table. */
#define IHASHSIZE 50
#ifndef INCLUDE_LEN_FUDGE
#define INCLUDE_LEN_FUDGE 0
#endif
/* Look up or add an entry to the table of all includes. This table
is indexed by the name as it appears in the #include line. The
->next_this_file chain stores all different files with the same
#include name (there are at least three ways this can happen). The
hash function could probably be improved a bit. */
/* Open files in nonblocking mode, so we don't get stuck if someone
clever has asked cpp to process /dev/rmt0. _cpp_read_include_file
will check that we have a real file to work with. Also take care
not to acquire a controlling terminal by mistake (this can't happen
on sane systems, but paranoia is a virtue). */
#define OMODES O_RDONLY|O_NONBLOCK|O_NOCTTY
static IHASH *
include_hash (pfile, fname, add)
cpp_reader *pfile;
const char *fname;
int add;
/* Calculate hash of an IHASH entry. */
static unsigned int
hash_IHASH (x)
const void *x;
{
unsigned int hash = 0;
IHASH *l, *m;
const char *f = fname;
IHASH *i = (IHASH *)x;
unsigned int r = 0, len = 0;
const U_CHAR *s = i->nshort;
while (*f)
hash += *f++;
if (i->hash != (unsigned long)-1)
return i->hash;
l = pfile->all_include_files[hash % ALL_INCLUDE_HASHSIZE];
m = 0;
for (; l; m = l, l = l->next)
if (!strcmp (l->nshort, fname))
return l;
do
len++, r = r * 67 + (*s++ - 113);
while (*s && *s != '.');
i->hash = r + len;
return r + len;
}
if (!add)
return 0;
l = (IHASH *) xmalloc (sizeof (IHASH));
l->next = NULL;
l->next_this_file = NULL;
l->foundhere = NULL;
l->buf = NULL;
l->limit = NULL;
if (m)
m->next = l;
else
pfile->all_include_files[hash % ALL_INCLUDE_HASHSIZE] = l;
return l;
/* Compare an existing IHASH structure with a potential one. */
static int
eq_IHASH (x, y)
const void *x;
const void *y;
{
const U_CHAR *a = ((const IHASH *)x)->nshort;
const U_CHAR *b = ((const IHASH *)y)->nshort;
return !strcmp (a, b);
}
/* Init the hash table. In here so it can see the hash and eq functions. */
void
_cpp_init_include_hash (pfile)
cpp_reader *pfile;
{
pfile->all_include_files
= htab_create (IHASHSIZE, hash_IHASH, eq_IHASH, free);
}
/* Return 0 if the file pointed to by IHASH has never been included before,
@ -152,9 +163,10 @@ cpp_included (pfile, fname)
cpp_reader *pfile;
const char *fname;
{
IHASH *ptr;
ptr = include_hash (pfile, fname, 0);
IHASH dummy, *ptr;
dummy.nshort = fname;
dummy.hash = -1;
ptr = htab_find (pfile->all_include_files, (const void *)&dummy);
return (ptr != NULL);
}
@ -164,10 +176,7 @@ file_cleanup (pbuf, pfile)
cpp_reader *pfile;
{
if (pbuf->buf)
{
free ((PTR) pbuf->buf);
pbuf->buf = 0;
}
free ((PTR) pbuf->buf);
if (pfile->system_include_depth)
pfile->system_include_depth--;
return 0;
@ -178,7 +187,7 @@ file_cleanup (pbuf, pfile)
(because it was included already and it's marked idempotent),
-1 if an error occurred, or a file descriptor open on the file.
*IHASH is set to point to the include hash entry for this file, and
*BEFORE is 1 if the file was included before (but needs to be read
*BEFORE is set to 1 if the file was included before (but needs to be read
again). */
int
_cpp_find_include_file (pfile, fname, search_start, ihash, before)
@ -188,97 +197,82 @@ _cpp_find_include_file (pfile, fname, search_start, ihash, before)
IHASH **ihash;
int *before;
{
struct file_name_list *l;
IHASH *ih, *jh;
int f, len;
struct file_name_list *path;
IHASH *ih, **slot;
IHASH dummy;
int f;
char *name;
ih = include_hash (pfile, fname, 1);
jh = redundant_include_p (pfile, ih,
fname[0] == '/' ? ABSOLUTE_PATH : search_start);
if (jh != 0)
dummy.hash = -1;
dummy.nshort = fname;
path = (fname[0] == '/') ? ABSOLUTE_PATH : search_start;
slot = (IHASH **) htab_find_slot (pfile->all_include_files,
(const void *)&dummy, 1);
if (*slot && (ih = redundant_include_p (pfile, *slot, path)))
{
*before = 1;
*ihash = jh;
if (jh == (IHASH *)-1)
if (ih == (IHASH *)-1)
return -2;
else
return open (jh->name, O_RDONLY, 0666);
*before = 1;
*ihash = ih;
return open (ih->name, OMODES);
}
if (ih->foundhere)
/* A file is already known by this name, but it's not the same file.
Allocate another include_hash block and add it to the next_this_file
chain. */
if (path == ABSOLUTE_PATH)
{
jh = (IHASH *) xmalloc (sizeof (IHASH));
while (ih->next_this_file) ih = ih->next_this_file;
ih->next_this_file = jh;
jh = ih;
ih = ih->next_this_file;
ih->next = NULL;
ih->next_this_file = NULL;
ih->buf = NULL;
ih->limit = NULL;
name = (char *) fname;
f = open (name, OMODES);
}
else
{
/* Search directory path, trying to open the file. */
name = alloca (strlen (fname) + pfile->max_include_len
+ 2 + INCLUDE_LEN_FUDGE);
do
{
memcpy (name, path->name, path->nlen);
name[path->nlen] = '/';
strcpy (&name[path->nlen+1], fname);
_cpp_simplify_pathname (name);
if (CPP_OPTIONS (pfile)->remap)
name = remap_filename (pfile, name, path);
f = open (name, OMODES);
#ifdef EACCES
if (f == -1 && errno == EACCES)
{
cpp_error (pfile,
"included file `%s' exists but is not readable",
name);
return -1;
}
#endif
if (f >= 0)
break;
path = path->next;
}
while (path);
}
if (f == -1)
return -1;
ih = (IHASH *) xmalloc (sizeof (IHASH) + strlen (name));
strcpy ((char *)ih->name, name);
ih->foundhere = path;
if (path == ABSOLUTE_PATH)
ih->nshort = ih->name;
else
ih->nshort = strstr (ih->name, fname);
ih->control_macro = NULL;
ih->hash = dummy.hash;
ih->next_this_file = *slot;
*slot = ih;
*before = 0;
*ihash = ih;
ih->name = NULL;
ih->nshort = xstrdup (fname);
ih->control_macro = NULL;
/* If the pathname is absolute, just open it. */
if (fname[0] == '/')
{
ih->foundhere = ABSOLUTE_PATH;
ih->name = ih->nshort;
return open (ih->name, O_RDONLY, 0666);
}
/* Search directory path, trying to open the file. */
len = strlen (fname);
name = xmalloc (len + pfile->max_include_len + 2 + INCLUDE_LEN_FUDGE);
for (l = search_start; l; l = l->next)
{
memcpy (name, l->name, l->nlen);
name[l->nlen] = '/';
strcpy (&name[l->nlen+1], fname);
_cpp_simplify_pathname (name);
if (CPP_OPTIONS (pfile)->remap)
name = remap_filename (pfile, name, l);
f = open (name, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666);
#ifdef EACCES
if (f == -1 && errno == EACCES)
{
cpp_error(pfile, "included file `%s' exists but is not readable",
name);
return -1;
}
#endif
if (f >= 0)
{
ih->foundhere = l;
ih->name = xrealloc (name, strlen (name) + 1);
return f;
}
}
if (jh)
{
jh->next_this_file = NULL;
free (ih);
}
free (name);
*ihash = (IHASH *)-1;
return -1;
return f;
}
/* The file_name_map structure holds a mapping of file names for a
@ -482,54 +476,41 @@ cpp_read_file (pfile, fname)
cpp_reader *pfile;
const char *fname;
{
IHASH *ih_fake;
IHASH *ih, **slot;
IHASH dummy;
int f;
if (fname == NULL || *fname == 0)
if (fname == NULL)
fname = "";
dummy.hash = -1;
dummy.nshort = fname;
slot = (IHASH **) htab_find_slot (pfile->all_include_files,
(const void *) &dummy, 1);
if (*slot && (ih = redundant_include_p (pfile, *slot, ABSOLUTE_PATH)))
{
fname = "";
f = 0;
if (ih == (IHASH *)-1)
return 1; /* Already included. */
}
else
{
ih = (IHASH *) xmalloc (sizeof (IHASH) + strlen (fname));
ih->control_macro = 0;
ih->foundhere = ABSOLUTE_PATH; /* well sort of ... */
ih->hash = dummy.hash;
strcpy ((char *)ih->name, fname);
ih->nshort = ih->name;
ih->next_this_file = *slot;
*slot = ih;
}
/* Open the file in nonblocking mode, so we don't get stuck if
someone clever has asked cpp to process /dev/rmt0.
_cpp_read_include_file will check that we have a real file to
work with. Also take care not to acquire a controlling terminal
by mistake (this can't happen on sane systems, but paranoia is a
virtue). */
else if ((f = open (fname, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666)) < 0)
{
cpp_notice_from_errno (pfile, fname);
return 0;
}
if (*fname == '\0')
f = 0;
else
f = open (fname, OMODES);
/* Push the buffer. */
if (!cpp_push_buffer (pfile, NULL, 0))
goto failed_push;
/* Gin up an include_hash structure for this file and feed it
to finclude. */
ih_fake = (IHASH *) xmalloc (sizeof (IHASH));
ih_fake->next = 0;
ih_fake->next_this_file = 0;
ih_fake->foundhere = ABSOLUTE_PATH; /* well sort of ... */
ih_fake->name = fname;
ih_fake->control_macro = 0;
ih_fake->buf = (char *)-1;
ih_fake->limit = 0;
if (!_cpp_read_include_file (pfile, f, ih_fake))
goto failed_finclude;
return 1;
failed_finclude:
/* If finclude fails, it pops the buffer. */
free (ih_fake);
failed_push:
if (f)
close (f);
return 0;
return _cpp_read_include_file (pfile, f, ih);
}
/* Read the contents of FD into the buffer on the top of PFILE's stack.
@ -549,13 +530,16 @@ _cpp_read_include_file (pfile, fd, ihash)
long length;
cpp_buffer *fp;
fp = cpp_push_buffer (pfile, NULL, 0);
if (fp == 0)
goto push_fail;
if (fstat (fd, &st) < 0)
goto perror_fail;
if (fcntl (fd, F_SETFL, 0) == -1) /* turn off nonblocking mode */
goto perror_fail;
fp = CPP_BUFFER (pfile);
/* If fd points to a plain file, we know how big it is, so we can
allocate the buffer all at once. If fd is a pipe or terminal, we
can't. Most C source files are 4k or less, so we guess that. If
@ -632,12 +616,14 @@ _cpp_read_include_file (pfile, fd, ihash)
fp->actual_dir = actual_directory (pfile, ihash->name);
pfile->input_stack_listing_current = 0;
pfile->only_seen_white = 2;
return 1;
perror_fail:
cpp_error_from_errno (pfile, ihash->name);
fail:
cpp_pop_buffer (pfile);
push_fail:
close (fd);
return 0;
}
@ -1485,7 +1471,7 @@ hack_vms_include_specification (fullname)
if (check_filename_before_returning)
{
f = open (fullname, O_RDONLY, 0666);
f = open (fullname, OMODES);
if (f >= 0)
{
/* The file name is OK as it is, so return it as is. */

View File

@ -27,10 +27,15 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "system.h"
#include "cpplib.h"
#include "cpphash.h"
#include "hashtab.h"
#include "version.h"
#undef abort
static unsigned int hashf PARAMS ((const U_CHAR *, int));
static unsigned int hash_HASHNODE PARAMS ((const void *));
static int eq_HASHNODE PARAMS ((const void *, const void *));
static void del_HASHNODE PARAMS ((void *));
static int dump_hash_helper PARAMS ((void *, void *));
static int comp_def_part PARAMS ((int, U_CHAR *, int, U_CHAR *,
int, int));
static void push_macro_expansion PARAMS ((cpp_reader *,
@ -45,6 +50,9 @@ static void special_symbol PARAMS ((HASHNODE *, cpp_reader *));
#define FORWARD(N) CPP_FORWARD (CPP_BUFFER (pfile), (N))
#define PEEKC() CPP_BUF_PEEK (CPP_BUFFER (pfile))
/* Initial hash table size. (It can grow if necessary - see hashtab.c.) */
#define HASHSIZE 500
/* The arglist structure is built by create_definition to tell
collect_expansion where the argument names begin. That
is, for a define like "#define f(x,y,z) foo+x-bar*y", the arglist
@ -92,28 +100,81 @@ struct argdata
int stringified_length;
};
/* Calculate hash function on a string. */
/* Calculate hash of a HASHNODE structure. */
static unsigned int
hashf (s, len)
register const U_CHAR *s;
register int len;
hash_HASHNODE (x)
const void *x;
{
unsigned int n = len;
unsigned int r = 0;
HASHNODE *h = (HASHNODE *)x;
const U_CHAR *s = h->name;
unsigned int len = h->length;
unsigned int n = len, r = 0;
if (h->hash != (unsigned long)-1)
return h->hash;
do
r = r * 67 + (*s++ - 113);
while (--n);
h->hash = r + len;
return r + len;
}
/* Find the most recent hash node for name "name" (ending with first
non-identifier char) installed by cpp_install
/* Compare two HASHNODE structures. */
static int
eq_HASHNODE (x, y)
const void *x;
const void *y;
{
const HASHNODE *a = (const HASHNODE *)x;
const HASHNODE *b = (const HASHNODE *)y;
return (a->length == b->length
&& !strncmp (a->name, b->name, a->length));
}
/* Destroy a HASHNODE. */
static void
del_HASHNODE (x)
void *x;
{
HASHNODE *h = (HASHNODE *)x;
if (h->type == T_MACRO)
_cpp_free_definition (h->value.defn);
free ((void *) h->name);
free (h);
}
/* Allocate and initialize a HASHNODE structure.
Caller must fill in the value field. */
HASHNODE *
_cpp_make_hashnode (name, len, type, hash)
const U_CHAR *name;
size_t len;
enum node_type type;
unsigned long hash;
{
HASHNODE *hp = (HASHNODE *) xmalloc (sizeof (HASHNODE));
U_CHAR *p = xmalloc (len + 1);
hp->type = type;
hp->length = len;
hp->name = p;
hp->hash = hash;
memcpy (p, name, len);
p[len] = 0;
return hp;
}
/* Find the hash node for name "name", which ends at the first
non-identifier char.
If LEN is >= 0, it is the length of the name.
Otherwise, compute the length by scanning the entire name. */
Otherwise, compute the length now. */
HASHNODE *
_cpp_lookup (pfile, name, len)
@ -121,9 +182,8 @@ _cpp_lookup (pfile, name, len)
const U_CHAR *name;
int len;
{
register const U_CHAR *bp;
register HASHNODE *bucket;
register unsigned int hash;
const U_CHAR *bp;
HASHNODE dummy;
if (len < 0)
{
@ -131,16 +191,49 @@ _cpp_lookup (pfile, name, len)
len = bp - name;
}
hash = hashf (name, len) % HASHSIZE;
dummy.name = name;
dummy.length = len;
dummy.hash = -1;
bucket = pfile->hashtab[hash];
while (bucket)
return (HASHNODE *) htab_find (pfile->hashtab, (void *)&dummy);
}
/* Find the hashtable slot for name "name". Used to insert or delete. */
HASHNODE **
_cpp_lookup_slot (pfile, name, len, insert, hash)
cpp_reader *pfile;
const U_CHAR *name;
int len;
int insert;
unsigned long *hash;
{
const U_CHAR *bp;
HASHNODE dummy;
HASHNODE **slot;
if (len < 0)
{
if (bucket->length == len && strncmp (bucket->name, name, len) == 0)
return bucket;
bucket = bucket->next;
for (bp = name; is_idchar (*bp); bp++);
len = bp - name;
}
return (HASHNODE *) 0;
dummy.name = name;
dummy.length = len;
dummy.hash = -1;
slot = (HASHNODE **) htab_find_slot (pfile->hashtab, (void *)&dummy, insert);
if (insert)
*hash = dummy.hash;
return slot;
}
/* Init the hash table. In here so it can see the hash and eq functions. */
void
_cpp_init_macro_hash (pfile)
cpp_reader *pfile;
{
pfile->hashtab = htab_create (HASHSIZE, hash_HASHNODE,
eq_HASHNODE, del_HASHNODE);
}
/* Free a DEFINITION structure. Used by delete_macro, and by
@ -162,86 +255,6 @@ _cpp_free_definition (d)
free (d);
}
/*
* Delete a hash node. Some weirdness to free junk from macros.
* More such weirdness will have to be added if you define more hash
* types that need it.
*/
void
_cpp_delete_macro (hp)
HASHNODE *hp;
{
if (hp->prev != NULL)
hp->prev->next = hp->next;
if (hp->next != NULL)
hp->next->prev = hp->prev;
/* make sure that the bucket chain header that
the deleted guy was on points to the right thing afterwards. */
if (hp == *hp->bucket_hdr)
*hp->bucket_hdr = hp->next;
if (hp->type == T_MACRO)
_cpp_free_definition (hp->value.defn);
free (hp);
}
/* Install a name in the main hash table, even if it is already there.
Name stops with first non alphanumeric, except leading '#'.
Caller must check against redefinition if that is desired.
delete_macro () removes things installed by cpp_install () in fifo order.
this is important because of the `defined' special symbol used
in #if, and also if pushdef/popdef directives are ever implemented.
If LEN is >= 0, it is the length of the name.
Otherwise, compute the length by scanning the entire name.
If HASH is >= 0, it is the precomputed hash code.
Otherwise, compute the hash code. */
HASHNODE *
_cpp_install (pfile, name, len, type, value)
cpp_reader *pfile;
const U_CHAR *name;
int len;
enum node_type type;
const char *value;
{
register HASHNODE *hp;
register int i, bucket;
register const U_CHAR *p;
unsigned int hash;
if (len < 0)
{
p = name;
while (is_idchar(*p))
p++;
len = p - name;
}
hash = hashf (name, len) % HASHSIZE;
i = sizeof (HASHNODE) + len + 1;
hp = (HASHNODE *) xmalloc (i);
bucket = hash;
hp->bucket_hdr = &pfile->hashtab[bucket];
hp->next = pfile->hashtab[bucket];
pfile->hashtab[bucket] = hp;
hp->prev = NULL;
if (hp->next != NULL)
hp->next->prev = hp;
hp->type = type;
hp->length = len;
hp->value.cpval = value;
hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE);
memcpy (hp->name, name, len);
hp->name[len] = 0;
return hp;
}
static int
macro_cleanup (pbuf, pfile)
cpp_buffer *pbuf;
@ -255,7 +268,6 @@ macro_cleanup (pbuf, pfile)
return 0;
}
/* Read a replacement list for a macro, and build the DEFINITION
structure. ARGLIST specifies the formal parameters to look for in
the text of the definition. If ARGLIST is null, this is an
@ -503,7 +515,6 @@ collect_expansion (pfile, arglist)
while (here > last && is_hspace (pfile->token_buffer [here-1]))
here--;
CPP_SET_WRITTEN (pfile, here);
CPP_NUL_TERMINATE (pfile);
len = CPP_WRITTEN (pfile) - start + 1;
/* space for no-concat markers at either end */
@ -1666,8 +1677,27 @@ _cpp_dump_definition (pfile, sym, len, defn)
if (*x == '\r') x += 2, i -= 2;
if (i > 0) CPP_PUTS (pfile, x, i);
}
if (pfile->lineno == 0)
CPP_PUTC (pfile, '\n');
CPP_NUL_TERMINATE (pfile);
}
/* Dump out the hash table. */
static int
dump_hash_helper (h, p)
void *h;
void *p;
{
HASHNODE *hp = (HASHNODE *)h;
cpp_reader *pfile = (cpp_reader *)p;
_cpp_dump_definition (pfile, hp->name, hp->length, hp->value.defn);
return 1;
}
void
_cpp_dump_macro_hash (pfile)
cpp_reader *pfile;
{
htab_traverse (pfile->hashtab, dump_hash_helper, pfile);
}

View File

@ -132,15 +132,11 @@ union hashval
typedef struct hashnode HASHNODE;
struct hashnode
{
struct hashnode *next; /* double links for easy deletion */
struct hashnode *prev;
struct hashnode **bucket_hdr; /* also, a back pointer to this node's hash
chain is kept, in case the node is the head
of the chain and gets deleted. */
enum node_type type; /* type of special token */
int length; /* length of token, for quick comparison */
U_CHAR *name; /* the actual name */
const U_CHAR *name; /* the actual name */
size_t length; /* length of token, for quick comparison */
unsigned long hash; /* cached hash value */
union hashval value; /* pointer to expansion, or whatever */
enum node_type type; /* type of special token */
};
/* List of directories to look for include files in. */
@ -169,7 +165,6 @@ struct file_name_list
#include statement) which is stored in *nshort. */
struct ihash
{
struct ihash *next;
/* Next file with the same short name but a
different (partial) pathname). */
struct ihash *next_this_file;
@ -177,12 +172,13 @@ struct ihash
/* Location of the file in the include search path.
Used for include_next */
struct file_name_list *foundhere;
const char *name; /* (partial) pathname of file */
const char *nshort; /* name of file as referenced in #include */
unsigned long hash; /* save hash value for future reference */
const char *nshort; /* name of file as referenced in #include;
points into name[] */
const U_CHAR *control_macro; /* macro, if any, preventing reinclusion -
see redundant_include_p */
char *buf, *limit; /* for file content cache,
not yet implemented */
const char name[1]; /* (partial) pathname of file */
};
typedef struct ihash IHASH;
@ -247,19 +243,23 @@ extern unsigned char _cpp_IStable[256];
(CPP_OPTIONS (PFILE)->pedantic && !CPP_BUFFER (pfile)->system_header_p)
/* In cpphash.c */
extern HASHNODE *_cpp_install PARAMS ((cpp_reader *, const U_CHAR *, int,
enum node_type, const char *));
extern HASHNODE *_cpp_lookup PARAMS ((cpp_reader *, const U_CHAR *, int));
extern void _cpp_free_definition PARAMS ((DEFINITION *));
extern void _cpp_delete_macro PARAMS ((HASHNODE *));
extern DEFINITION *_cpp_create_definition
PARAMS ((cpp_reader *, int));
extern int _cpp_compare_defs PARAMS ((cpp_reader *, DEFINITION *,
DEFINITION *));
extern void _cpp_macroexpand PARAMS ((cpp_reader *, HASHNODE *));
extern void _cpp_dump_definition PARAMS ((cpp_reader *, const U_CHAR *, long,
DEFINITION *));
extern HASHNODE *_cpp_make_hashnode PARAMS ((const U_CHAR *, size_t,
enum node_type,
unsigned long));
extern HASHNODE *_cpp_lookup PARAMS ((cpp_reader *,
const U_CHAR *, int));
extern HASHNODE **_cpp_lookup_slot PARAMS ((cpp_reader *,
const U_CHAR *, int, int,
unsigned long *));
extern void _cpp_free_definition PARAMS ((DEFINITION *));
extern DEFINITION *_cpp_create_definition PARAMS ((cpp_reader *, int));
extern void _cpp_dump_definition PARAMS ((cpp_reader *, const U_CHAR *,
long, DEFINITION *));
extern int _cpp_compare_defs PARAMS ((cpp_reader *, DEFINITION *,
DEFINITION *));
extern void _cpp_macroexpand PARAMS ((cpp_reader *, HASHNODE *));
extern void _cpp_init_macro_hash PARAMS ((cpp_reader *));
extern void _cpp_dump_macro_hash PARAMS ((cpp_reader *));
/* In cppfiles.c */
extern void _cpp_simplify_pathname PARAMS ((char *));
@ -267,6 +267,7 @@ extern int _cpp_find_include_file PARAMS ((cpp_reader *, const char *,
struct file_name_list *,
IHASH **, int *));
extern int _cpp_read_include_file PARAMS ((cpp_reader *, int, IHASH *));
extern void _cpp_init_include_hash PARAMS ((cpp_reader *));
/* In cppexp.c */
extern int _cpp_parse_expr PARAMS ((cpp_reader *));

View File

@ -28,6 +28,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "prefix.h"
#include "intl.h"
#include "version.h"
#include "hashtab.h"
#include "mkdeps.h"
/* Predefined symbols, built-in macros, and the default include path. */
@ -554,7 +555,8 @@ cpp_reader_init (pfile)
pfile->token_buffer = (U_CHAR *) xmalloc (pfile->token_buffer_size);
CPP_SET_WRITTEN (pfile, 0);
pfile->hashtab = (HASHNODE **) xcalloc (HASHSIZE, sizeof (HASHNODE *));
_cpp_init_macro_hash (pfile);
_cpp_init_include_hash (pfile);
}
/* Free resources used by PFILE.
@ -563,7 +565,6 @@ void
cpp_cleanup (pfile)
cpp_reader *pfile;
{
int i;
while (CPP_BUFFER (pfile) != NULL)
cpp_pop_buffer (pfile);
@ -584,25 +585,8 @@ cpp_cleanup (pfile)
if (pfile->deps)
deps_free (pfile->deps);
for (i = ALL_INCLUDE_HASHSIZE; --i >= 0; )
{
IHASH *imp, *next;
for (imp = pfile->all_include_files[i]; imp; imp = next)
{
next = imp->next;
free ((PTR) imp->name);
free ((PTR) imp->nshort);
free (imp);
}
pfile->all_include_files[i] = 0;
}
for (i = HASHSIZE; --i >= 0;)
{
while (pfile->hashtab[i])
_cpp_delete_macro (pfile->hashtab[i]);
}
free (pfile->hashtab);
htab_delete (pfile->hashtab);
htab_delete (pfile->all_include_files);
}
@ -654,7 +638,6 @@ static const struct builtin builtin_array[] =
/* Subroutine of cpp_start_read; reads the builtins table above and
enters the macros into the hash table. */
static void
initialize_builtins (pfile)
cpp_reader *pfile;
@ -662,6 +645,7 @@ initialize_builtins (pfile)
int len;
const struct builtin *b;
const char *val;
HASHNODE *hp;
for(b = builtin_array; b->name; b++)
{
if ((b->flags & STDC) && CPP_TRADITIONAL (pfile))
@ -670,7 +654,10 @@ initialize_builtins (pfile)
val = (b->flags & ULP) ? user_label_prefix : b->value;
len = strlen (b->name);
_cpp_install (pfile, b->name, len, b->type, val);
hp = _cpp_make_hashnode (b->name, len, b->type, -1);
hp->value.cpval = val;
*(htab_find_slot (pfile->hashtab, (void *)hp, 1)) = hp;
if ((b->flags & DUMP) && CPP_OPTIONS (pfile)->debug_output)
dump_special_to_buffer (pfile, b->name);
}
@ -1015,20 +1002,7 @@ cpp_finish (pfile)
}
if (opts->dump_macros == dump_only)
{
int i;
HASHNODE *h;
for (i = HASHSIZE; --i >= 0;)
{
for (h = pfile->hashtab[i]; h; h = h->next)
if (h->type == T_MACRO)
{
_cpp_dump_definition (pfile, h->name, h->length,
h->value.defn);
CPP_PUTC (pfile, '\n');
}
}
}
_cpp_dump_macro_hash (pfile);
}
static void

View File

@ -24,6 +24,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "cpplib.h"
#include "cpphash.h"
#include "hashtab.h"
#include "intl.h"
#include "mkdeps.h"
@ -659,9 +660,10 @@ do_define (pfile, keyword)
cpp_reader *pfile;
const struct directive *keyword ATTRIBUTE_UNUSED;
{
HASHNODE *hp;
HASHNODE **slot;
DEFINITION *def;
long here;
unsigned long hash;
int len, c;
int funlike = 0;
U_CHAR *sym;
@ -692,9 +694,11 @@ do_define (pfile, keyword)
if (def == 0)
return 0;
if ((hp = _cpp_lookup (pfile, sym, len)) != NULL)
slot = _cpp_lookup_slot (pfile, sym, len, 1, &hash);
if (*slot)
{
int ok;
HASHNODE *hp = *slot;
/* Redefining a macro is ok if the definitions are the same. */
if (hp->type == T_MACRO)
@ -729,7 +733,11 @@ do_define (pfile, keyword)
}
}
else
_cpp_install (pfile, sym, len, T_MACRO, (char *) def);
{
HASHNODE *hp = _cpp_make_hashnode (sym, len, T_MACRO, hash);
hp->value.defn = def;
*slot = hp;
}
if (CPP_OPTIONS (pfile)->debug_output
|| CPP_OPTIONS (pfile)->dump_macros == dump_definitions)
@ -1260,21 +1268,12 @@ do_include (pfile, keyword)
if (importing)
ihash->control_macro = (const U_CHAR *) "";
if (cpp_push_buffer (pfile, NULL, 0) == NULL)
{
close (fd);
return 0;
}
if (angle_brackets)
pfile->system_include_depth++; /* Decremented in file_cleanup. */
if (_cpp_read_include_file (pfile, fd, ihash))
{
output_line_command (pfile, enter_file);
pfile->only_seen_white = 2;
if (angle_brackets)
pfile->system_include_depth++; /* Decremented in file_cleanup. */
}
return 0;
}
@ -1435,7 +1434,7 @@ do_undef (pfile, keyword)
const struct directive *keyword;
{
int len;
HASHNODE *hp;
HASHNODE **slot;
U_CHAR *buf, *name, *limit;
int c;
long here = CPP_WRITTEN (pfile);
@ -1468,8 +1467,10 @@ do_undef (pfile, keyword)
}
CPP_SET_WRITTEN (pfile, here);
while ((hp = _cpp_lookup (pfile, name, len)) != NULL)
slot = _cpp_lookup_slot (pfile, name, len, 0, 0);
if (slot)
{
HASHNODE *hp = *slot;
/* If we are generating additional info for debugging (with -g) we
need to pass through all effective #undef commands. */
if (CPP_OPTIONS (pfile)->debug_output && keyword)
@ -1480,7 +1481,8 @@ do_undef (pfile, keyword)
{
if (hp->type != T_MACRO)
cpp_warning (pfile, "undefining `%s'", hp->name);
_cpp_delete_macro (hp);
htab_clear_slot (pfile->hashtab, (void **)slot);
}
}
@ -1692,6 +1694,7 @@ do_pragma_implementation (pfile)
long written = CPP_WRITTEN (pfile);
U_CHAR *name;
U_CHAR *copy;
size_t len;
token = get_directive_token (pfile);
if (token == CPP_VSPACE)
@ -1703,14 +1706,15 @@ do_pragma_implementation (pfile)
}
name = pfile->token_buffer + written + 1;
copy = (U_CHAR *) xstrdup (name);
copy[strlen(copy)] = '\0'; /* trim trailing quote */
len = strlen (name);
copy = (U_CHAR *) alloca (len);
memcpy (copy, name, len - 1);
copy[len] = '\0'; /* trim trailing quote */
if (cpp_included (pfile, copy))
cpp_warning (pfile,
"`#pragma implementation' for `%s' appears after file is included",
copy);
free (copy);
return 0;
}
@ -1721,11 +1725,13 @@ do_pragma_poison (pfile)
/* Poison these symbols so that all subsequent usage produces an
error message. */
U_CHAR *p;
HASHNODE *hp;
HASHNODE **slot;
long written;
size_t len;
enum cpp_token token;
int writeit;
unsigned long hash;
/* As a rule, don't include #pragma poison commands in output,
unless the user asks for them. */
writeit = (CPP_OPTIONS (pfile)->debug_output
@ -1747,8 +1753,10 @@ do_pragma_poison (pfile)
p = pfile->token_buffer + written;
len = strlen (p);
if ((hp = _cpp_lookup (pfile, p, len)))
slot = _cpp_lookup_slot (pfile, p, len, 1, &hash);
if (*slot)
{
HASHNODE *hp = *slot;
if (hp->type != T_POISON)
{
cpp_warning (pfile, "poisoning existing macro `%s'", p);
@ -1759,7 +1767,11 @@ do_pragma_poison (pfile)
}
}
else
_cpp_install (pfile, p, len, T_POISON, 0);
{
HASHNODE *hp = _cpp_make_hashnode (p, len, T_POISON, hash);
hp->value.cpval = 0;
*slot = hp;
}
if (writeit)
CPP_PUTC (pfile, ' ');
}
@ -3025,7 +3037,9 @@ do_assert (pfile, keyword)
U_CHAR *sym;
int ret, c;
HASHNODE *base, *this;
int baselen, thislen;
HASHNODE **bslot, **tslot;
size_t blen, tlen;
unsigned long bhash, thash;
if (CPP_PEDANTIC (pfile) && CPP_OPTIONS (pfile)->done_initializing)
cpp_pedwarn (pfile, "ANSI C does not allow `#assert'");
@ -3049,27 +3063,30 @@ do_assert (pfile, keyword)
goto error;
}
thislen = strlen (sym);
baselen = (U_CHAR *) strchr (sym, '(') - sym;
this = _cpp_lookup (pfile, sym, thislen);
if (this)
tlen = strlen (sym);
blen = (U_CHAR *) strchr (sym, '(') - sym;
tslot = _cpp_lookup_slot (pfile, sym, tlen, 1, &thash);
if (*tslot)
{
cpp_warning (pfile, "`%s' re-asserted", sym);
goto error;
}
base = _cpp_lookup (pfile, sym, baselen);
if (! base)
base = _cpp_install (pfile, sym, baselen, T_ASSERT, 0);
else if (base->type != T_ASSERT)
{
/* Token clash - but with what?! */
cpp_ice (pfile, "base->type != T_ASSERT in do_assert");
goto error;
}
this = _cpp_install (pfile, sym, thislen, T_ASSERT,
(char *)base->value.aschain);
bslot = _cpp_lookup_slot (pfile, sym, blen, 1, &bhash);
if (! *bslot)
*bslot = base = _cpp_make_hashnode (sym, blen, T_ASSERT, bhash);
else
{
base = *bslot;
if (base->type != T_ASSERT)
{
/* Token clash - but with what?! */
cpp_ice (pfile, "base->type != T_ASSERT in do_assert");
goto error;
}
}
*tslot = this = _cpp_make_hashnode (sym, tlen, T_ASSERT, thash);
this->value.aschain = base->value.aschain;
base->value.aschain = this;
pfile->limit = sym; /* Pop */
@ -3118,9 +3135,9 @@ do_unassert (pfile, keyword)
for (this = base->value.aschain; this; this = next)
{
next = this->value.aschain;
_cpp_delete_macro (this);
htab_remove_elt (pfile->hashtab, this);
}
_cpp_delete_macro (base);
htab_remove_elt (pfile->hashtab, base);
}
else
{
@ -3135,10 +3152,11 @@ do_unassert (pfile, keyword)
next = next->value.aschain;
next->value.aschain = this->value.aschain;
_cpp_delete_macro (this);
htab_remove_elt (pfile->hashtab, this);
if (base->value.aschain == NULL)
_cpp_delete_macro (base); /* Last answer for this predicate deleted. */
/* Last answer for this predicate deleted. */
htab_remove_elt (pfile->hashtab, base);
}
pfile->limit = sym; /* Pop */

View File

@ -121,6 +121,7 @@ struct cpp_buffer
};
struct file_name_map_list;
struct htab;
/* Maximum nesting of cpp_buffers. We use a static limit, partly for
efficiency, and partly to limit runaway recursion. */
@ -155,12 +156,10 @@ struct cpp_reader
int buffer_stack_depth;
/* Hash table of macros and assertions. See cpphash.c */
#define HASHSIZE 1403
struct hashnode **hashtab;
struct htab *hashtab;
/* Hash table of other included files. See cppfiles.c */
#define ALL_INCLUDE_HASHSIZE 71
struct ihash *all_include_files[ALL_INCLUDE_HASHSIZE];
struct htab *all_include_files;
/* Chain of `actual directory' file_name_list entries,
for "" inclusion. */
@ -503,7 +502,6 @@ extern void output_line_command PARAMS ((cpp_reader *,
extern int cpp_included PARAMS ((cpp_reader *, const char *));
extern int cpp_read_file PARAMS ((cpp_reader *, const char *));
#ifdef __cplusplus
}
#endif