home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 4
/
FreshFish_May-June1994.bin
/
bbs
/
may94
/
util
/
edit
/
jade.lha
/
Jade
/
src
/
symbols.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-19
|
27KB
|
1,050 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>
_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 addsubr(VALUE);
_PR VALUE addconstnum(VALUE, long);
_PR void internstatic(VALUE *, VALUE);
_PR VALUE bindsymbol(VALUE, VALUE, VALUE);
_PR void unbindsymbols(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;
static SymbolBlk *SymbolBlkChain;
static Symbol *SymbolFreeList;
_PR int AllocatedSymbols, UsedSymbols;
int AllocatedSymbols, UsedSymbols;
_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(!SymbolFreeList)
{
SymbolBlk *sb = mycalloc(sizeof(SymbolBlk));
if(sb)
{
int i;
AllocatedSymbols += SYMBOLBLK_SIZE;
sb->sb_Next = SymbolBlkChain;
SymbolBlkChain = sb;
for(i = 0; i < (SYMBOLBLK_SIZE - 1); i++)
sb->sb_Symbols[i].sym_Next = &sb->sb_Symbols[i + 1];
sb->sb_Symbols[i].sym_Next = SymbolFreeList;
SymbolFreeList = sb->sb_Symbols;
}
}
if((sym = SymbolFreeList))
{
SymbolFreeList = 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 = NULL;
VSYM(sym)->sym_Function = NULL;
VSYM(sym)->sym_PropList = sym_nil;
UsedSymbols++;
DataAfterGC += sizeof(Symbol);
}
return(sym);
}
void
symbol_sweep(void)
{
SymbolBlk *sb = SymbolBlkChain;
SymbolFreeList = NULL;
UsedSymbols = 0;
while(sb)
{
int i;
SymbolBlk *nxt = sb->sb_Next;
for(i = 0; i < SYMBOLBLK_SIZE; i++)
{
if(!GC_MARKEDP(&sb->sb_Symbols[i]))
{
sb->sb_Symbols[i].sym_Next = SymbolFreeList;
SymbolFreeList = &sb->sb_Symbols[i];
}
else
{
GC_CLR(&sb->sb_Symbols[i]);
UsedSymbols++;
}
}
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)
{
streamputs(strm, VSTR(VSYM(obj)->sym_Name), 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 '|':
streamputc(strm, (int)'\\');
break;
default:
if(iscntrl(c))
streamputc(strm, (int)'\\');
break;
}
streamputc(strm, (int)c);
}
}
VALUE
addsubr(VALUE subr)
{
VALUE sym = cmd_intern(VSUBR(subr)->subr_Name, ObArray);
if(sym)
{
if(VSUBR(subr)->subr_Type == V_Var)
{
VSYM(sym)->sym_Value = subr;
VSYM(sym)->sym_PropList = cmd_cons(sym_variable_documentation, cmd_cons(newnumber(VSUBR(subr)->subr_DocIndex), VSYM(sym)->sym_PropList));
}
else
VSYM(sym)->sym_Function = subr;
}
return(sym);
}
VALUE
addconstnum(VALUE name, long num)
{
VALUE sym = cmd_intern(name, ObArray);
if(sym)
{
VSYM(sym)->sym_Value = newnumber(num);
VSYM(sym)->sym_Flags |= SF_CONSTANT;
}
return(sym);
}
void
internstatic(VALUE *symp, VALUE name)
{
if((*symp = cmd_intern(name, sym_nil)))
markstatic(symp);
else
abort();
}
static INLINE u_long
hash(u_char *str)
{
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 pointers initialised to NULL).
::end:: */
{
DECLARE1(size, NUMBERP);
return(newvector(VNUM(size)));
}
_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(ob && 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_Flags & SF_INTERNED)
{
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;
VSYM(sym)->sym_Flags |= SF_INTERNED;
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:: */
{
Symbol *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];
VVECT(ob)->vc_Array[hashid] = NULL;
while(list)
{
Symbol *nxt = list->sym_Next;
if(list != sym)
{
list->sym_Next = VVECT(ob)->vc_Array[hashid];
VVECT(ob)->vc_Array[hashid] = list;
}
list = nxt;
}
/* This is probably unnecessary. */
VSYM(sym)->sym_Next = NULL;
VSYM(sym)->sym_Flags &= ~SF_INTERNED;
return(sym);
}
/*
* This give a symbol a new value, saving the old one onto the front