home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD1.bin
/
new
/
util
/
edit
/
jade
/
src
/
symbols.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-04
|
30KB
|
1,194 lines
/* symbols.c -- Lisp symbol handling
Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
This file is part of Jade.
Jade is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Jade 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 Jade; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "jade.h"
#include "jade_protos.h"
#include "regexp/regexp.h"
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
/* The special value which signifies the end of a hash-bucket chain.
It can be any Lisp object which isn't a symbol. */
#define OB_NIL null_string
_PR void symbol_sweep(void);
_PR int symbol_cmp(VALUE, VALUE);
_PR void symbol_princ(VALUE, VALUE);
_PR void symbol_print(VALUE, VALUE);
_PR VALUE add_subr(XSubr *);
_PR VALUE add_const_num(VALUE, long);
_PR void intern_static(VALUE *, VALUE);
_PR VALUE bind_symbol(VALUE, VALUE, VALUE);
_PR void unbind_symbols(VALUE);
_PR int symbols_init(void);
_PR void symbols_kill(void);
/* Main storage of symbols. */
_PR VALUE obarray;
VALUE obarray;
_PR VALUE sym_nil, sym_t;
VALUE sym_nil, sym_t;
_PR VALUE sym_variable_documentation;
VALUE sym_variable_documentation;
/* This value is stored in the cells of a symbol to denote a void object. */
_PR VALUE void_value;
static LispObject void_object = { V_Void };
VALUE void_value = &void_object;
static SymbolBlk *symbol_block_chain;
static Symbol *symbol_freelist;
_PR int allocated_symbols, used_symbols;
int allocated_symbols, used_symbols;
_PR VALUE cmd_make_symbol(VALUE);
DEFUN("make-symbol", cmd_make_symbol, subr_make_symbol, (VALUE name), V_Subr1, DOC_make_symbol) /*
::doc:make_symbol::
make-symbol NAME
Returns a new, uninterned, symbol with print-name NAME. It's value and
function definition are both void and it has a nil property-list.
::end:: */
{
VALUE sym;
DECLARE1(name, STRINGP);
if(!symbol_freelist)
{
SymbolBlk *sb = mycalloc(sizeof(SymbolBlk));
if(sb)
{
int i;
allocated_symbols += SYMBOLBLK_SIZE;
sb->sb_Next = symbol_block_chain;
symbol_block_chain = sb;
for(i = 0; i < (SYMBOLBLK_SIZE - 1); i++)
sb->sb_Symbols[i].sym_Next = VAL(&sb->sb_Symbols[i + 1]);
sb->sb_Symbols[i].sym_Next = VAL(symbol_freelist);
symbol_freelist = sb->sb_Symbols;
}
}
if((sym = VAL(symbol_freelist)))
{
symbol_freelist = VSYM(VSYM(sym)->sym_Next);
VSYM(sym)->sym_Next = NULL;
VSYM(sym)->sym_Type = V_Symbol;
VSYM(sym)->sym_Flags = 0;
VSYM(sym)->sym_Name = name;
VSYM(sym)->sym_Value = void_value;
VSYM(sym)->sym_Function = void_value;
VSYM(sym)->sym_PropList = sym_nil;
used_symbols++;
data_after_gc += sizeof(Symbol);
}
return(sym);
}
void
symbol_sweep(void)
{
SymbolBlk *sb = symbol_block_chain;
symbol_freelist = NULL;
used_symbols = 0;
while(sb)
{
int i;
SymbolBlk *nxt = sb->sb_Next;
for(i = 0; i < SYMBOLBLK_SIZE; i++)
{
if(!GC_MARKEDP(VAL(&sb->sb_Symbols[i])))
{
sb->sb_Symbols[i].sym_Next = VAL(symbol_freelist);
symbol_freelist = &sb->sb_Symbols[i];
}
else
{
GC_CLR(VAL(&sb->sb_Symbols[i]));
used_symbols++;
}
}
sb = nxt;
}
}
int
symbol_cmp(VALUE v1, VALUE v2)
{
if(VTYPE(v1) == VTYPE(v2))
return(!(VSYM(v1) == VSYM(v2)));
return(1);
}
void
symbol_princ(VALUE strm, VALUE obj)
{
stream_puts(strm, VSTR(VSYM(obj)->sym_Name), -1, TRUE);
}
void
symbol_print(VALUE strm, VALUE obj)
{
u_char *s = VSTR(VSYM(obj)->sym_Name);
u_char c;
while((c = *s++))
{
switch(c)
{
case ' ':
case '\t':
case '\n':
case '\f':
case '(':
case ')':
case '[':
case ']':
case '\'':
case '"':
case ';':
case '\\':
case '|':
stream_putc(strm, (int)'\\');
break;
default:
if(iscntrl(c))
stream_putc(strm, (int)'\\');
break;
}
stream_putc(strm, (int)c);
}
}
VALUE
add_subr(XSubr *subr)
{
VALUE sym = cmd_intern(subr->subr_Name, obarray);
if(sym)
{
if(subr->subr_Type == V_Var)
{
VSYM(sym)->sym_Value = VAL(subr);
VSYM(sym)->sym_PropList = cmd_cons(sym_variable_documentation, cmd_cons(make_number(subr->subr_DocIndex), VSYM(sym)->sym_PropList));
}
else
VSYM(sym)->sym_Function = VAL(subr);
}
return(sym);
}
VALUE
add_const_num(VALUE name, long num)
{
VALUE sym = cmd_intern(name, obarray);
if(sym)
{
VSYM(sym)->sym_Value = make_number(num);
VSYM(sym)->sym_Flags |= SF_CONSTANT;
}
return(sym);
}
void
intern_static(VALUE *symp, VALUE name)
{
if((*symp = cmd_intern(name, sym_nil)))
mark_static(symp);
else
abort();
}
static INLINE u_long
hash(u_char *str)
{
register u_long value = 0;
while(*str)
value = (value * 33) + *str++;
return(value);
}
_PR VALUE cmd_make_obarray(VALUE);
DEFUN("make-obarray", cmd_make_obarray, subr_make_obarray, (VALUE size), V_Subr1, DOC_make_obarray) /*
::doc:make_obarray::
make-obarray SIZE
Creates a new structure for storing symbols in. This is basically a vector
with a few slight differences (all elements initialised to a special value).
::end:: */
{
DECLARE1(size, NUMBERP);
return(cmd_make_vector(size, OB_NIL));
}
_PR VALUE cmd_find_symbol(VALUE, VALUE);
DEFUN("find-symbol", cmd_find_symbol, subr_find_symbol, (VALUE name, VALUE ob), V_Subr2, DOC_find_symbol) /*
::doc:find_symbol::
find-symbol NAME [OBARRAY]
Returns the symbol with print-name NAME, found by searching OBARRAY (or
the default `obarray' if nil), or nil if no such symbol exists.
::end:: */
{
int vsize;
DECLARE1(name, STRINGP);
if(!VECTORP(ob))
ob = obarray;
if((vsize = VVECT(ob)->vc_Size) == 0)
return(sym_nil);
ob = VVECT(ob)->vc_Array[hash(VSTR(name)) % vsize];
while(SYMBOLP(ob))
{
if(!strcmp(VSTR(name), VSTR(VSYM(ob)->sym_Name)))
return(ob);
ob = VSYM(ob)->sym_Next;
}
return(sym_nil);
}
_PR VALUE cmd_intern_symbol(VALUE, VALUE);
DEFUN("intern-symbol", cmd_intern_symbol, subr_intern_symbol, (VALUE sym, VALUE ob), V_Subr2, DOC_intern_symbol) /*
::doc:intern_symbol::
intern-symbol SYMBOL [OBARRAY]
Stores SYMBOL in OBARRAY (or the default). If SYMBOL has already been interned
somewhere an error is signalled.
::end:: */
{
int vsize, hashid;
DECLARE1(sym, SYMBOLP);
if(VSYM(sym)->sym_Next != NULL)
{
cmd_signal(sym_error, list_2(MKSTR("Symbol is already interned"), sym));
return(NULL);
}
if(!VECTORP(ob))
ob = obarray;
if((vsize = VVECT(ob)->vc_Size) == 0)
return(NULL);
hashid = hash(VSTR(VSYM(sym)->sym_Name)) % vsize;
VSYM(sym)->sym_Next = VVECT(ob)->vc_Array[hashid];
VVECT(ob)->vc_Array[hashid] = sym;
return(sym);
}
_PR VALUE cmd_intern(VALUE, VALUE);
DEFUN("intern", cmd_intern, subr_intern, (VALUE name, VALUE ob), V_Subr2, DOC_intern) /*
::doc:intern::
intern NAME [OBARRAY]
If a symbol with print-name exists in OBARRAY (or the default) return it.
Else use `(make-symbol NAME)' to create a new symbol, intern that into the
OBARRAY, then return it.
::end:: */
{
VALUE sym;
DECLARE1(name, STRINGP);
if(!(sym = cmd_find_symbol(name, ob))
|| (NILP(sym) && strcmp(VSTR(name), "nil")))
{
sym = cmd_make_symbol(name);
if(sym)
return(cmd_intern_symbol(sym, ob));
}
return(sym);
}
_PR VALUE cmd_unintern(VALUE, VALUE);
DEFUN("unintern", cmd_unintern, subr_unintern, (VALUE sym, VALUE ob), V_Subr2, DOC_unintern) /*
::doc:unintern::
unintern SYMBOL [OBARRAY]
Removes SYMBOL from OBARRAY (or the default). Use this with caution.
::end:: */
{
VALUE list;
int vsize, hashid;
DECLARE1(sym, SYMBOLP);
if(!VECTORP(ob))
ob = obarray;
if((vsize = VVECT(ob)->vc_Size) == 0)
return(NULL);
hashid = hash(VSTR(VSYM(sym)->sym_Name)) % vsize;
list = VVECT(ob)->vc_Array[hashid];