/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.stanford.edu/ http://chuck.cs.princeton.edu/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A.-----------------------------------------------------------------------------*///-----------------------------------------------------------------------------// file: chuck_table.cpp// desc: chuck table implementation for parsers//// No algorithm should use these functions directly, because// programming with void* is too error-prone. Instead,// each module should make "wrapper" functions that take// well-typed arguments and call the TAB_ functions.//// copyright (c) 1997 Andrew W. Appel.//// original author: Andrew Appel (appel@cs.princeton.edu)// modified: Ge Wang (gewang@cs.princeton.edu)// date: Autumn 2002//-----------------------------------------------------------------------------#include "chuck_table.h"#include "chuck_utils.h"#include <stdio.h>#include <string.h>#define TABSIZE 65437typedef struct binder_ *binder;struct binder_ {void *key; void *value; binder next; void *prevtop;};struct TAB_table_ { unsigned long size; binder * table; void * top; TAB_eq_func eq_func; TAB_hash_func hash_func;};static binder Binder(void *key, void *value, binder next, void *prevtop){ binder b = (binder)checked_malloc(sizeof(struct binder_)); b->key = key; b->value=value; b->next=next; b->prevtop = prevtop; return b;}TAB_table TAB_empty(void){ return TAB_empty2(TABSIZE);}TAB_table TAB_empty2( unsigned long s ){ TAB_table t = (TAB_table)checked_malloc(sizeof(struct TAB_table_)); unsigned long i; t->table = (binder *)checked_malloc(sizeof(binder)*s); t->size = s; t->top = NULL; t->eq_func = NULL; t->hash_func = NULL; for( i = 0; i < s; i++ ) t->table[i] = NULL; return t;}TAB_table TAB_empty3( TAB_eq_func eq, TAB_hash_func hash, unsigned long s ){ TAB_table t = TAB_empty2(s); t->eq_func = eq; t->hash_func = hash; return t;}void TAB_delete( TAB_table t ){ unsigned long i; binder p = NULL, n = NULL; for(i = 0; i < t->size; i++ ) { p = t->table[i]; while( p ) { n = p->next; free(p); p = n; } } // free the table free( t->table ); free( t );}/* The cast from pointer to integer in the expression * ((unsigned)key) % TABSIZE * may lead to a warning message. However, the code is safe, * and will still operate correctly. This line is just hashing * a pointer value into an integer value, and no matter how the * conversion is done, as long as it is done consistently, a * reasonable and repeatable index into the table will result. */void TAB_enter(TAB_table t, void *key, void *value){ t_CKINT index; t_CKUINT hval = (t_CKUINT)key; assert(t && key); if( t->hash_func ) hval = (t_CKUINT)t->hash_func(key); index = hval % t->size; t->table[index] = Binder(key, value, t->table[index], t->top); t->top = key;}void *TAB_look(TAB_table t, void *key){ t_CKINT index; t_CKUINT hval = (t_CKUINT)key; binder b; assert(t && key); if( t->hash_func ) hval = (t_CKUINT)t->hash_func(key); index= hval % t->size; if( !t->eq_func ) { for(b=t->table[index]; b; b=b->next) if (b->key==key) return b->value; } else { for(b=t->table[index]; b; b=b->next) if (t->eq_func(b->key, key)) return b->value; } return NULL;}void *TAB_pop(TAB_table t){ void *k; binder b; long index; t_CKUINT hval; assert (t); k = t->top; assert (k); hval = (t_CKUINT)k; if(t->hash_func) hval = (t_CKUINT)t->hash_func(k); index = hval % t->size; b = t->table[index]; assert(b); t->table[index] = b->next; t->top=b->prevtop; return b->key;}void *TAB_topv(TAB_table t){ void *k; binder b; t_CKINT index; t_CKUINT hval; assert(t); k = t->top; assert(k); hval = (t_CKUINT)k; if(t->hash_func) hval = (t_CKUINT)t->hash_func(k); index = hval % t->size; b = t->table[index]; assert(b); return b->value;}void TAB_dump(TAB_table t, void (*show)(void *key, void *value)){ void *k = t->top; t_CKINT index = ((t_CKUINT)k) % t->size; binder b = t->table[index]; if (b==NULL) return; t->table[index]=b->next; t->top=b->prevtop; show(b->key,b->value); TAB_dump(t,show); assert(t->top == b->prevtop && t->table[index]==b->next); t->top=k; t->table[index]=b;}long str_eq( void * lhs, void * rhs ){ return !strcmp( (char *)lhs, (char *)rhs );}long str_hash( void * str ){ unsigned long h=0; char *s; for(s=(char *)str; *s; s++) h = h*65599 + *s; return h;}
/*----------------------------------------------------------------------------
ChucK Concurrent, On-the-fly Audio Programming Language
Compiler and Virtual Machine
Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
http://chuck.stanford.edu/
http://chuck.cs.princeton.edu/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
U.S.A.
-----------------------------------------------------------------------------*/
//-----------------------------------------------------------------------------
// file: chuck_table.cpp
// desc: chuck table implementation for parsers
//
// No algorithm should use these functions directly, because
// programming with void* is too error-prone. Instead,
// each module should make "wrapper" functions that take
// well-typed arguments and call the TAB_ functions.
//
// copyright (c) 1997 Andrew W. Appel.
//
// original author: Andrew Appel (appel@cs.princeton.edu)
// modified: Ge Wang (gewang@cs.princeton.edu)
// date: Autumn 2002
//-----------------------------------------------------------------------------
#include "chuck_table.h"
#include "chuck_utils.h"
#include <stdio.h>
#include <string.h>
#define TABSIZE 65437
typedef struct binder_ *binder;
struct binder_ {void *key; void *value; binder next; void *prevtop;};
struct TAB_table_ {
unsigned long size;
binder * table;
void * top;
TAB_eq_func eq_func;
TAB_hash_func hash_func;
};
static binder Binder(void *key, void *value, binder next, void *prevtop)
{
binder b = (binder)checked_malloc(sizeof(struct binder_));
b->key = key; b->value=value; b->next=next; b->prevtop = prevtop;
return b;
}
TAB_table TAB_empty(void)
{
return TAB_empty2(TABSIZE);
}
TAB_table TAB_empty2( unsigned long s )
{
TAB_table t = (TAB_table)checked_malloc(sizeof(struct TAB_table_));
unsigned long i;
t->table = (binder *)checked_malloc(sizeof(binder)*s);
t->size = s;
t->top = NULL;
t->eq_func = NULL;
t->hash_func = NULL;
for( i = 0; i < s; i++ )
t->table[i] = NULL;
return t;
}
TAB_table TAB_empty3( TAB_eq_func eq, TAB_hash_func hash, unsigned long s )
{
TAB_table t = TAB_empty2(s);
t->eq_func = eq;
t->hash_func = hash;
return t;
}
void TAB_delete( TAB_table t )
{
unsigned long i;
binder p = NULL, n = NULL;
for(i = 0; i < t->size; i++ )
{
p = t->table[i];
while( p )
{
n = p->next;
free(p);
p = n;
}
}
// free the table
free( t->table );
free( t );
}
/* The cast from pointer to integer in the expression
* ((unsigned)key) % TABSIZE
* may lead to a warning message. However, the code is safe,
* and will still operate correctly. This line is just hashing
* a pointer value into an integer value, and no matter how the
* conversion is done, as long as it is done consistently, a
* reasonable and repeatable index into the table will result.
*/
void TAB_enter(TAB_table t, void *key, void *value)
{
t_CKINT index;
t_CKUINT hval = (t_CKUINT)key;
assert(t && key);
if( t->hash_func )
hval = (t_CKUINT)t->hash_func(key);
index = hval % t->size;
t->table[index] = Binder(key, value, t->table[index], t->top);
t->top = key;
}
void *TAB_look(TAB_table t, void *key)
{
t_CKINT index;
t_CKUINT hval = (t_CKUINT)key;
binder b;
assert(t && key);
if( t->hash_func )
hval = (t_CKUINT)t->hash_func(key);
index= hval % t->size;
if( !t->eq_func )
{
for(b=t->table[index]; b; b=b->next)
if (b->key==key) return b->value;
}
else
{
for(b=t->table[index]; b; b=b->next)
if (t->eq_func(b->key, key)) return b->value;
}
return NULL;
}
void *TAB_pop(TAB_table t)
{
void *k; binder b; long index;
t_CKUINT hval;
assert (t);
k = t->top;
assert (k);
hval = (t_CKUINT)k;
if(t->hash_func) hval = (t_CKUINT)t->hash_func(k);
index = hval % t->size;
b = t->table[index];
assert(b);
t->table[index] = b->next;
t->top=b->prevtop;
return b->key;
}
void *TAB_topv(TAB_table t)
{
void *k; binder b; t_CKINT index;
t_CKUINT hval;
assert(t);
k = t->top;
assert(k);
hval = (t_CKUINT)k;
if(t->hash_func) hval = (t_CKUINT)t->hash_func(k);
index = hval % t->size;
b = t->table[index];
assert(b);
return b->value;
}
void TAB_dump(TAB_table t, void (*show)(void *key, void *value))
{
void *k = t->top;
t_CKINT index = ((t_CKUINT)k) % t->size;
binder b = t->table[index];
if (b==NULL) return;
t->table[index]=b->next;
t->top=b->prevtop;
show(b->key,b->value);
TAB_dump(t,show);
assert(t->top == b->prevtop && t->table[index]==b->next);
t->top=k;
t->table[index]=b;
}
long str_eq( void * lhs, void * rhs )
{
return !strcmp( (char *)lhs, (char *)rhs );
}
long str_hash( void * str )
{
unsigned long h=0; char *s;
for(s=(char *)str; *s; s++)
h = h*65599 + *s;
return h;
}