home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD1.bin
/
new
/
util
/
edit
/
jade
/
src
/
values.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-04
|
24KB
|
1,049 lines
/* values.c -- Handling of Lisp data (includes garbage collection)
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 <string.h>
#include <stdlib.h>
#include <assert.h>
#ifdef NEED_MEMORY_H
# include <memory.h>
#endif
/* #define GC_MONITOR_STK */
#define STATIC_SMALL_NUMBERS 256
_PR int value_cmp(VALUE, VALUE);
_PR void princ_val(VALUE, VALUE);
_PR void print_val(VALUE, VALUE);
_PR int nil_cmp(VALUE, VALUE);
_PR VALUE make_string(int);
_PR VALUE string_dupn(const u_char *, int);
_PR VALUE string_dup(const u_char *);
_PR int string_cmp(VALUE, VALUE);
_PR bool set_string_len(VALUE, long);
_PR VALUE make_number(long);
_PR int number_cmp(VALUE, VALUE);
_PR int ptr_cmp(VALUE, VALUE);
_PR void cons_free(VALUE);
_PR int cons_cmp(VALUE, VALUE);
_PR VALUE list_1(VALUE);
_PR VALUE list_2(VALUE, VALUE);
_PR VALUE list_3(VALUE, VALUE, VALUE);
_PR VALUE list_4(VALUE, VALUE, VALUE, VALUE);
_PR VALUE list_5(VALUE, VALUE, VALUE, VALUE, VALUE);
_PR VALUE make_vector(int);
_PR VALUE make_lpos(POS *);
_PR VALUE make_lpos2(long, long);
_PR int lpos_cmp(VALUE, VALUE);
_PR void lpos_prin(VALUE, VALUE);
_PR int vector_cmp(VALUE, VALUE);
_PR void mark_static(VALUE *);
_PR void mark_value(VALUE);
_PR void values_init (void);
_PR void values_init2(void);
_PR void values_kill (void);
ValClass ValueClasses[] = {
{ string_cmp, string_princ, string_print, MKSTR("string") },
{ string_cmp, string_princ, string_print, MKSTR("string") },
{ number_cmp, lisp_prin, lisp_prin, MKSTR("number") },
{ cons_cmp, lisp_prin, lisp_prin, MKSTR("cons") },
{ vector_cmp, lisp_prin, lisp_prin, MKSTR("vector") },
{ symbol_cmp, symbol_princ, symbol_print, MKSTR("symbol") },
{ mark_cmp, mark_prin, mark_prin, MKSTR("mark") },
{ lpos_cmp, lpos_prin, lpos_prin, MKSTR("pos") },
{ ptr_cmp, lisp_prin, lisp_prin, MKSTR("var") },
{ ptr_cmp, lisp_prin, lisp_prin, MKSTR("subr-0") },
{ ptr_cmp, lisp_prin, lisp_prin, MKSTR("subr-1") },
{ ptr_cmp, lisp_prin, lisp_prin, MKSTR("subr-2") },
{ ptr_cmp, lisp_prin, lisp_prin, MKSTR("subr-3") },
{ ptr_cmp, lisp_prin, lisp_prin, MKSTR("subr-4") },
{ ptr_cmp, lisp_prin, lisp_prin, MKSTR("subr-5") },
{ ptr_cmp, lisp_prin, lisp_prin, MKSTR("subr-n") },
{ ptr_cmp, lisp_prin, lisp_prin, MKSTR("special-form") },
{ ptr_cmp, buffer_prin, buffer_prin, MKSTR("buffer") },
{ ptr_cmp, window_prin, window_prin, MKSTR("window") },
{ file_cmp, file_prin, file_prin, MKSTR("file") },
#ifdef HAVE_SUBPROCESSES
{ ptr_cmp, proc_prin, proc_prin, MKSTR("process") },
#else
{ nil_cmp, lisp_prin, lisp_prin, MKSTR("process") },
#endif
{ ptr_cmp, glyphtable_prin, glyphtable_prin, MKSTR("glyph-table") },
{ nil_cmp, lisp_prin, lisp_prin, MKSTR("void") },
};
int
value_cmp(VALUE v1, VALUE v2)
{
if(v1 && v2)
{
/* If the two objects are the same object then they must be
equivalent :-) */
return(v1 == v2 ? 0 : VALUE_CMP(v1, v2));
}
return(1);
}
void
princ_val(VALUE strm, VALUE val)
{
if(val)
PRINC_VAL(strm, val);
}
void
print_val(VALUE strm, VALUE val)
{
if(val)
PRINT_VAL(strm, val);
}
int
nil_cmp(VALUE val1, VALUE val2)
{
if(VTYPE(val1) == VTYPE(val2))
return(0);
return(1);
}
static StrMem lisp_strmem;
_PR VALUE null_string;
VALUE null_string = MKSTR("");
/* Return a string object with room for exactly LEN characters. No extra
byte is allocated for a zero terminator; do this manually if required. */
VALUE
make_string(int len)
{
DynamicString *str;
int memlen = DSTR_SIZE(len);
str = sm_alloc(&lisp_strmem, memlen);
if(str)
{
str->ds_Length = len - 1;
str->ds_Mem[0] = V_DynamicString;
data_after_gc += memlen;
return(VAL(&str->ds_Mem[0]));
}
return(NULL);
}
VALUE
string_dupn(const u_char *src, int slen)
{
String *dst = VSTRING(make_string(slen + 1));
if(dst)
{
memcpy(dst->str_Mem + 1, src, slen);
dst->str_Mem[slen+1] = 0;
}
return(VAL(dst));
}
VALUE
string_dup(const u_char * src)
{
return(string_dupn(src, strlen(src)));
}
int
string_cmp(VALUE v1, VALUE v2)
{
if(STRINGP(v1) && STRINGP(v2))
return(strcmp(VSTR(v1), VSTR(v2)));
return(1);
}
static void
string_sweep(void)
{
int bucket;
MemChunk *mlc;
for(bucket = 0; bucket < NUMBUCKETS; bucket++)
{
MemChunk **freelist = &lisp_strmem.sm_MemBuckets[bucket].mbu_FreeList;
MemBlock *mbl = (MemBlock *)lisp_strmem.sm_MemBuckets[bucket].mbu_MemBlocks.mlh_Head;
MemBlock *nxt;
int chnksiz = MCHNK_SIZE((bucket + 1) * GRAIN);
int numchnks = lisp_strmem.sm_ChunksPerBlock[bucket];
*freelist = NULL;
while((nxt = (MemBlock *)mbl->mbl_Node.mln_Succ))
{
MemChunk *mc = mbl->mbl_Chunks;
int j;
for(j = 0; j < numchnks; j++)
{
if(mc->mc_BlkType != MBT_FREE)
{
register DynamicString *ds = (DynamicString *)mc->mc_Mem.mem;
if(ds->ds_Mem[0] & GC_MARK_BIT)
ds->ds_Mem[0] &= ~GC_MARK_BIT;
else
{
mc->mc_BlkType = MBT_FREE;
mc->mc_Mem.nextfree = *freelist;
*freelist = mc;
}
}
mc = (MemChunk *)((char *)mc + chnksiz);
}
mbl = nxt;
}
}
mlc = lisp_strmem.sm_MallocChain;
lisp_strmem.sm_MallocChain = NULL;
while(mlc)
{
MemChunk *nxtmlc = mlc->mc_Header.next;
register DynamicString *ds = (DynamicString *)mlc->mc_Mem.mem;
if(ds->ds_Mem[0] == V_DynamicString)
myfree(mlc);
else
{
ds->ds_Mem[0] = V_DynamicString;
mlc->mc_Header.next = lisp_strmem.sm_MallocChain;
lisp_strmem.sm_MallocChain = mlc;
}
mlc = nxtmlc;
}
}
/* Sets the length-field of the dynamic string STR to LEN. */
bool
set_string_len(VALUE str, long len)
{
if(VTYPEP(str, V_DynamicString))
{
DSTRING_HDR(str)->ds_Length = len;
return(TRUE);
}
return(FALSE);
}
static NumberBlk *number_block_chain;
static Number *number_freelist;
static int allocated_numbers, used_numbers;
#ifdef STATIC_SMALL_NUMBERS
static Number small_numbers[STATIC_SMALL_NUMBERS];
#endif
VALUE
make_number(long n)
{
Number *num;
#ifdef STATIC_SMALL_NUMBERS
if((n < STATIC_SMALL_NUMBERS) && (n >= 0))
return(VAL(&small_numbers[n]));
#endif
if(!(num = number_freelist))
{
NumberBlk *nb = mymalloc(sizeof(NumberBlk));
if(nb)
{
int i;
allocated_numbers += NUMBERBLK_SIZE;
nb->nb_Next = number_block_chain;
number_block_chain = nb;
for(i = 0; i < (NUMBERBLK_SIZE - 1); i++)
nb->nb_Numbers[i].num_Data.next = &nb->nb_Numbers[i + 1];
nb->nb_Numbers[i].num_Data.next = number_freelist;
number_freelist = nb->nb_Numbers;
}
num = number_freelist;
}
number_freelist = num->num_Data.next;
num->num_Type = V_Number;
num->num_Data.number = n;
used_numbers++;
data_after_gc += sizeof(Number);
return(VAL(num));
}
static void
number_sweep(void)
{
NumberBlk *nb = number_block_chain;
int i;
number_freelist = NULL;
used_numbers = 0;
while(nb)
{
NumberBlk *nxt = nb->nb_Next;
for(i = 0; i < NUMBERBLK_SIZE; i++)
{
if(!GC_MARKEDP(VAL(&nb->nb_Numbers[i])))
{
nb->nb_Numbers[i].num_Data.next = number_freelist;
number_freelist = &nb->nb_Numbers[i];
}
else
{
GC_CLR(VAL(&nb->nb_Numbers[i]));
used_numbers++;
}
}
nb = nxt;
}
#ifdef STATIC_SMALL_NUMBERS
for(i = 0; i < STATIC_SMALL_NUMBERS; i++)
GC_CLR(VAL(&small_numbers[i]));
#endif
}
int
number_cmp(VALUE v1, VALUE v2)
{
if(VTYPE(v1) == VTYPE(v2))
retu