home *** CD-ROM | disk | FTP | other *** search
- /* 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 of
- * the list `oldList'. `oldList' is structured like,
- * ((symbol . oldvalue) ...)
- * returns the new version of `oldList'
- */
- VALUE
- bindsymbol(VALUE oldList, VALUE symbol, VALUE newVal)
- {
- /* Oops, this doesn't work with buffer or window local symbols (or at
- least, it doesn't work how you expect, it always binds to the default
- value!). This needs fixing. */
- VALUE newbl = cmd_cons(cmd_cons(symbol, sym_nil), oldList);
- if(newbl)
- {
- if(VSYM(symbol)->sym_Value && VTYPEP(VSYM(symbol)->sym_Value, V_Var))
- {
- /* Special code for binding V_Var variables */
- VCDR(VCAR(newbl)) = VVARFUN(VSYM(symbol)->sym_Value)(NULL);
- VVARFUN(VSYM(symbol)->sym_Value)(newVal);
- }
- else
- {
- VCDR(VCAR(newbl)) = VSYM(symbol)->sym_Value;
- VSYM(symbol)->sym_Value = newVal;
- }
- }
- return(newbl);
- }
-
- /*
- * Undoes what the above function does.
- */
- void
- unbindsymbols(VALUE oldList)
- {
- while(CONSP(oldList))
- {
- VALUE car = VCAR(oldList);
- VALUE sym = VCAR(car);
- if(VSYM(sym)->sym_Value && VTYPEP(VSYM(sym)->sym_Value, V_Var))
- /* Unbind a V_Var variable */
- VVARFUN(VSYM(sym)->sym_Value)(VCDR(car));
- else
- VSYM(sym)->sym_Value = VCDR(car);
- oldList = VCDR(oldList);
- }
- }
-
- _PR VALUE cmd_symbol_value(VALUE);
- DEFUN("symbol-value", cmd_symbol_value, subr_symbol_value, (VALUE sym), V_Subr1, DOC_symbol_value) /*
- ::doc:symbol_value::
- (symbol-value SYMBOL)
- Returns the value of SYMBOL, if SYMBOL is flagged as having buffer-local
- values look for one of those first.
- ::end:: */
- {
- VALUE val;
- DECLARE1(sym, SYMBOLP);
- if((VSYM(sym)->sym_Flags & SF_BUFFER_LOCAL)
- && (val = cmd_assq(sym, CurrVW->vw_Tx->tx_LocalVariables))
- && CONSP(val))
- {
- val = VCDR(val);
- }
- else if((VSYM(sym)->sym_Flags & SF_WIN_LOCAL)
- && (val = cmd_assq(sym, CurrVW->vw_LocalVariables))
- && CONSP(val))
- {
- val = VCDR(val);
- }
- else
- val = VSYM(sym)->sym_Value;
- if(val && (VTYPE(val) == V_Var))
- val = VVARFUN(val)(NULL);
- return(val);
- }
-
- _PR VALUE cmd_set(VALUE, VALUE);
- DEFUN("set", cmd_set, subr_set, (VALUE sym, VALUE val), V_Subr2, DOC_set) /*
- ::doc:set::
- (set SYMBOL VALUE)
- Sets the value of SYMBOL to VALUE, if SYMBOL is flagged as having buffer-
- local values then set that value. Returns VALUE.
- ::end:: */
- {
- DECLARE1(sym, SYMBOLP);
- if(VSYM(sym)->sym_Flags & SF_CONSTANT)
- return(cmd_signal(sym_setting_constant, LIST_1(sym)));
- if(VSYM(sym)->sym_Flags & SF_BUFFER_LOCAL)
- {
- TX *tx = CurrVW->vw_Tx;
- VALUE tmp;
- if((tmp = cmd_assq(sym, tx->tx_LocalVariables)) && CONSP(tmp))
- VCDR(tmp) = val;
- else
- tx->tx_LocalVariables = cmd_cons(cmd_cons(sym, val), tx->tx_LocalVariables);
- return(val);
- }
- else if(VSYM(sym)->sym_Flags & SF_WIN_LOCAL)
- {
- VALUE tmp;
- if((tmp = cmd_assq(sym, CurrVW->vw_LocalVariables)) && CONSP(tmp))
- VCDR(tmp) = val;
- else
- CurrVW->vw_LocalVariables = cmd_cons(cmd_cons(sym, val), CurrVW->vw_LocalVariables);
- return(val);
- }
- if(VSYM(sym)->sym_Value && (VTYPE(VSYM(sym)->sym_Value) == V_Var))
- VVARFUN(VSYM(sym)->sym_Value)(val);
- else
- VSYM(sym)->sym_Value = val;
- return(val);
- }
-
- _PR VALUE cmd_setplist(VALUE, VALUE);
- DEFUN("setplist", cmd_setplist, subr_setplist, (VALUE sym, VALUE prop), V_Subr2, DOC_setplist) /*
- ::doc:setplist::
- (setplist SYMBOL PROP-LIST)
- Sets the property list of SYMBOL to PROP-LIST, returns PROP-LIST.
- ::end:: */
- {
- DECLARE1(sym, SYMBOLP);
- VSYM(sym)->sym_PropList = prop;
- return(prop);
- }
-
- _PR VALUE cmd_symbol_name(VALUE);
- DEFUN("symbol-name", cmd_symbol_name, subr_symbol_name, (VALUE sym), V_Subr1, DOC_symbol_name) /*
- ::doc:symbol_name::
- (symbol-name SYMBOL)
- Returns the print-name of SYMBOL.
- ::end:: */
- {
- DECLARE1(sym, SYMBOLP);
- return(VSYM(sym)->sym_Name);
- }
-
- _PR VALUE cmd_symbol_function(VALUE);
- DEFUN("symbol-function", cmd_symbol_function, subr_symbol_function, (VALUE sym), V_Subr1, DOC_symbol_function) /*
- ::doc:symbol_function::
- (symbol-function SYMBOL)
- Returns the function value of SYMBOL.
- ::end:: */
- {
- DECLARE1(sym, SYMBOLP);
- return(VSYM(sym)->sym_Function);
- }
-
- _PR VALUE cmd_fboundp(VALUE);
- DEFUN("fboundp", cmd_fboundp, subr_fboundp, (VALUE sym), V_Subr1, DOC_fboundp) /*
- ::doc:fboundp::
- (fboundp SYMBOL)
- Returns t if the function-slot of SYMBOL has a value.
- ::end:: */
- {
- DECLARE1(sym, SYMBOLP);
- if(cmd_symbol_function(sym))
- return(sym_t);
- return(sym_nil);
- }
-
- _PR VALUE cmd_boundp(VALUE);
- DEFUN("boundp", cmd_boundp, subr_boundp, (VALUE sym), V_Subr1, DOC_boundp) /*
- ::doc:boundp::
- (boundp SYMBOL)
- Returns t if SYMBOL has a value as a variable.
- ::end:: */
- {
- if(cmd_symbol_value(sym))
- return(sym_t);
- return(sym_nil);
- }
-
- _PR VALUE cmd_symbol_plist(VALUE);
- DEFUN("symbol-plist", cmd_symbol_plist, subr_symbol_plist, (VALUE sym), V_Subr1, DOC_symbol_plist) /*
- ::doc:symbol_plist::
- (symbol-plist SYMBOL)
- Returns the property-list of SYMBOL.
- ::end:: */
- {
- DECLARE1(sym, SYMBOLP);
- return(VSYM(sym)->sym_PropList);
- }
-
- _PR VALUE cmd_gensym(void);
- DEFUN("gensym", cmd_gensym, subr_gensym, (void), V_Subr0, DOC_gensym) /*
- ::doc:gensym::
- (gensym)
- Returns a new (non-interned) symbol with a unique print name.
- ::end:: */
- {
- static int counter;
- char buf[20];
- counter++;
- sprintf(buf, "G%04d", counter);
- return(cmd_make_symbol(valstrdup(buf)));
- }
-
- _PR VALUE cmd_symbolp(VALUE);
- DEFUN("symbolp", cmd_symbolp, subr_symbolp, (VALUE sym), V_Subr1, DOC_symbolp) /*
- ::doc:symbolp::
- (symbolp ARG)
- Returns t if ARG is a symbol.
- ::end:: */
- {
- if(SYMBOLP(sym))
- return(sym_t);
- return(sym_nil);
- }
-
- _PR VALUE cmd_setq(VALUE);
- DEFUN("setq", cmd_setq, subr_setq, (VALUE args), V_SF, DOC_setq) /*
- ::doc:setq::
- (setq { SYMBOL FORM }...) <SPECIAL-FORM>
- Sets the value of each SYMBOL to the value of its corresponding FORM
- evaluated, returns the value of the last evaluation. ie,
- (setq x 1 y (symbol-name 'nil))
- => "nil"
- x
- => 1
- y
- => "nil"
- ::end:: */
- {
- VALUE res = sym_nil;
- GCVAL gcv_args;
- PUSHGC(gcv_args, args);
- while(CONSP(args) && CONSP(VCDR(args)) && SYMBOLP(VCAR(args)))
- {
- if(!(res = cmd_eval(VCAR(VCDR(args)))))
- goto end;
- if(!cmd_set(VCAR(args), res))
- {
- res = NULL;
- goto end;
- }
- args = VCDR(VCDR(args));
- }
- end:
- POPGC;
- return(res);
- }
-
- _PR VALUE cmd_fset(VALUE, VALUE);
- DEFUN("fset", cmd_fset, subr_fset, (VALUE sym, VALUE val), V_Subr2, DOC_fset) /*
- ::doc:fset::
- (fset SYMBOL VALUE)
- Sets the function value of SYMBOL to VALUE, returns VALUE.
- ::end:: */
- {
- DECLARE1(sym, SYMBOLP);
- VSYM(sym)->sym_Function = val;
- return(val);
- }
-
- _PR VALUE cmd_makunbound(VALUE);
- DEFUN("makunbound", cmd_makunbound, subr_makunbound, (VALUE sym), V_Subr1, DOC_makunbound) /*
- ::doc:makunbound::
- (makunbound SYMBOL)
- Make SYMBOL have no value as a variable.
- ::end:: */
- {
- DECLARE1(sym, SYMBOLP);
- VSYM(sym)->sym_Value = NULL;
- return(sym);
- }
-
- _PR VALUE cmd_fmakunbound(VALUE);
- DEFUN("fmakunbound", cmd_fmakunbound, subr_fmakunbound, (VALUE sym), V_Subr1, DOC_fmakunbound) /*
- ::doc:fmakunbound::
- (fmakunbound SYMBOL)
- Make the function slot of SYMBOL have no value.
- ::end:: */
- {
- DECLARE1(sym, SYMBOLP);
- VSYM(sym)->sym_Function = NULL;
- return(sym);
- }
-
- _PR VALUE cmd_let(VALUE);
- DEFUN("let", cmd_let, subr_let, (VALUE args), V_SF, DOC_let) /*
- ::doc:let::
- (let (SYMBOL-BINDINGS...) BODY...) <SPECIAL-FORM>
- Binds temporary values to symbols while BODY is being evaluated.
- Each SYMBOL-BINDING is either a symbol, in which case that symbol is bound to
- nil, or a list. The symbol at the head of this list is bound to the progn'ed
- value of the forms making up the tail. ie,
- (let
- ((foo 1 2 3)
- bar)
- (cons foo bar))
- => (3 . nil)
-
- All values of the new bindings are evaluated before any symbols are bound.
- ::end:: */
- {
- VALUE tmp, *store, oldvals, res = NULL;
- int numsyms = 0;
- if(!CONSP(args))
- return(NULL);
- oldvals = sym_nil;
- for(tmp = VCAR(args); CONSP(tmp); numsyms++)
- tmp = VCDR(tmp);
- if(numsyms == 0)
- return(cmd_progn(VCDR(args)));
- else if((store = mystralloc(sizeof(VALUE) * numsyms)))
- {
- int i;
- GCVAL gcv_args;
- GCVALN gcv_store;
- PUSHGC(gcv_args, args);
- PUSHGCN(gcv_store, store, 0);
- i = 0;
- tmp = VCAR(args);
- while(CONSP(tmp))
- {
- if(CONSP(VCAR(tmp)))
- {
- if(!(store[i] = cmd_progn(VCDR(VCAR(tmp)))))
- {
- POPGCN; POPGC;
- goto end;
- }
- }
- else
- store[i] = sym_nil;
- tmp = VCDR(tmp);
- i++;
- gcv_store.gcv_N = i;
- }
- POPGCN;
- POPGC;
- i = 0;
- tmp = VCAR(args);
- while(CONSP(tmp))
- {
- VALUE sym;
- switch(VTYPE(VCAR(tmp)))
- {
- case V_Symbol:
- sym = VCAR(tmp);
- break;
- case V_Cons:
- sym = VCAR(VCAR(tmp));
- if(SYMBOLP(sym))
- break;
- /* FALL THROUGH */
- default:
- cmd_signal(sym_error, LIST_1(MKSTR("No symbol to bind to in let")));
- goto end;
- }
- if(!(oldvals = bindsymbol(oldvals, sym, store[i])))
- goto end;
- tmp = VCDR(tmp);
- i++;
- }
- PUSHGC(gcv_args, oldvals);
- res = cmd_progn(VCDR(args));
- POPGC;
- end:
- mystrfree(store);
- unbindsymbols(oldvals);
- return(res);
- }
- return(NULL);
- }
- _PR VALUE cmd_letstar(VALUE);
- DEFUN("let*", cmd_letstar, subr_letstar, (VALUE args), V_SF, DOC_letstar) /*
- ::doc:letstar::
- (let* (SYMBOL-BINDINGS...) BODY...) <SPECIAL-FORM>
- Binds temporary values to symbols while BODY is being evaluated.
- Each SYMBOL-BINDING is either a symbol, in which case that symbol is bound to
- nil, or a list. The symbol at the head of this list is bound to the progn'ed
- value of the forms making up the tail. ie,
- (let*
- ((foo 1 2 3)
- bar)
- (cons foo bar))
- => (3 . nil)
-
- The value of each binding is evaluated just before that symbol is bound,
- this means that,
- (setq x 'foo)
- (let*
- ((x 10)
- (y x))
- (cons x y))
- => (10 . 10)
- ::end:: */
- {
- VALUE binds, res = NULL;
- VALUE oldvals = sym_nil;
- GCVAL gcv_args, gcv_oldvals;
- if(!CONSP(args))
- return(NULL);
- binds = VCAR(args);
- PUSHGC(gcv_args, args);
- PUSHGC(gcv_oldvals, oldvals);
- while(CONSP(binds))
- {
- if(CONSP(VCAR(binds)))
- {
- if(SYMBOLP(VCAR(VCAR(binds))))
- {
- VALUE val;
- if(!(val = cmd_progn(VCDR(VCAR(binds)))))
- goto error;
- if(!(oldvals = bindsymbol(oldvals, VCAR(VCAR(binds)), val)))
- goto error;
- }
- }
- else
- {
- if(!(oldvals = bindsymbol(oldvals, VCAR(binds), sym_nil)))
- goto error;
- }
- binds = VCDR(binds);
- }
- res = cmd_progn(VCDR(args));
- error:
- POPGC; POPGC;
- unbindsymbols(oldvals);
- return(res);
- }
-
- _PR VALUE cmd_get(VALUE, VALUE);
- DEFUN("get", cmd_get, subr_get, (VALUE sym, VALUE prop), V_Subr2, DOC_get) /*
- ::doc:get::
- (get SYMBOL PROPERTY)
- Returns the value of SYMBOL's property PROPERTY. See `put'.
- ::end:: */
- {
- VALUE plist;
- DECLARE1(sym, SYMBOLP);
- plist = VSYM(sym)->sym_PropList;
- while(CONSP(plist) && CONSP(VCDR(plist)))
- {
- if(VCAR(plist) == prop)
- return(VCAR(VCDR(plist)));
- plist = VCDR(VCDR(plist));
- }
- return(sym_nil);
- }
-
- _PR VALUE cmd_put(VALUE, VALUE, VALUE);
- DEFUN("put", cmd_put, subr_put, (VALUE sym, VALUE prop, VALUE val), V_Subr3, DOC_put) /*
- ::doc:put::
- (put SYMBOL PROPERTY VALUE)
- Sets the value of SYMBOL's property PROPERTY to VALUE, this value can be
- retrieved with the `get' function.
- ::end:: */
- {
- VALUE plist;
- DECLARE1(sym, SYMBOLP);
- plist = VSYM(sym)->sym_PropList;
- while(CONSP(plist) && CONSP(VCDR(plist)))
- {
- if(VCAR(plist) == prop)
- {
- VCAR(VCDR(plist)) = val;
- return(val);
- }
- plist = VCDR(VCDR(plist));
- }
- plist = cmd_cons(prop, cmd_cons(val, VSYM(sym)->sym_PropList));
- if(plist)
- {
- VSYM(sym)->sym_PropList = plist;
- return(val);
- }
- return(NULL);
- }
-
- _PR VALUE cmd_buffer_variables(VALUE);
- DEFUN("buffer-variables", cmd_buffer_variables, subr_buffer_variables, (VALUE tx), V_Subr1, DOC_buffer_variables) /*
- ::doc:buffer_variables::
- (buffer-variables [BUFFER])
- Returns a list of (SYMBOL . VALUE) bindings which take effect when the
- current buffer is BUFFER.
- ::end:: */
- {
- if(!BUFFERP(tx))
- tx = CurrVW->vw_Tx;
- return(VTX(tx)->tx_LocalVariables);
- }
-
- _PR VALUE cmd_window_variables(VALUE);
- DEFUN("window-variables", cmd_window_variables, subr_window_variables, (VALUE vw), V_Subr1, DOC_window_variables) /*
- ::doc:window_variables::
- (window-variables [WINDOW])
- Returns a list of (SYMBOL . VALUE) bindings which take effect when the
- current window is WINDOW.
- ::end:: */
- {
- if(!WINDOWP(vw))
- vw = CurrVW;
- return(VWIN(vw)->vw_LocalVariables);
- }
-
- _PR VALUE cmd_apropos(VALUE, VALUE, VALUE);
- DEFUN("apropos", cmd_apropos, subr_apropos, (VALUE re, VALUE pred, VALUE ob), V_Subr3, DOC_apropos) /*
- ::doc:apropos::
- (apropos REGEXP [PREDICATE] [OBARRAY])
- Returns a list of symbols from OBARRAY (or the default) whose print-name
- matches the regular-expression REGEXP. If PREDICATE is given and non-nil,
- each symbol which matches is applied to the function PREDICATE, if the value
- is non-nil it is considered a match.
- ::end:: */
- {
- regexp *prog;
- DECLARE1(re, STRINGP);
- if(!VECTORP(ob))
- ob = ObArray;
- prog = regcomp(VSTR(re));
- if(prog)
- {
- VALUE last = sym_nil;
- int i;
- GCVAL gcv_last, gcv_ob, gcv_pred;
- PUSHGC(gcv_last, last);
- PUSHGC(gcv_ob, ob);
- PUSHGC(gcv_pred, pred);
- for(i = 0; i < VVECT(ob)->vc_Size; i++)
- {
- Symbol *chain = VVECT(ob)->vc_Array[i];
- while(chain)
- {
- if(regexec(prog, VSTR(chain->sym_Name)))
- {
- if(pred && !NILP(pred))
- {
- VALUE tmp;
- if(!(tmp = funcall(pred, LIST_1(chain))) || NILP(tmp))
- goto next;
- }
- last = cmd_cons(chain, last);
- }
- next:
- chain = chain->sym_Next;
- }
- }
- POPGC; POPGC; POPGC;
- free(prog);
- return(last);
- }
- return(NULL);
- }
-
- _PR VALUE cmd_set_buffer_variable(VALUE sym, VALUE stat);
- DEFUN("set-buffer-variable", cmd_set_buffer_variable, subr_set_buffer_variable, (VALUE sym, VALUE stat), V_Subr2, DOC_set_buffer_variable) /*
- ::doc:set_buffer_variable::
- (set-buffer-variable SYMBOL)
- Flags that SYMBOL might have a value local to each buffer.
- ::end:: */
- {
- DECLARE1(sym, SYMBOLP);
- if(NILP(stat))
- VSYM(sym)->sym_Flags |= SF_BUFFER_LOCAL;
- else
- VSYM(sym)->sym_Flags &= ~SF_BUFFER_LOCAL;
- return(sym);
- }
- _PR VALUE cmd_buffer_variable_p(VALUE sym);
- DEFUN("buffer-variable-p", cmd_buffer_variable_p, subr_buffer_variable_p, (VALUE sym), V_Subr1, DOC_buffer_variable_p) /*
- ::doc:buffer_variable_p::
- (buffer-variable-p SYMBOL)
- Returns t if `set-buffer-variable' has been called on this symbol.
- ::end:: */
- {
- DECLARE1(sym, SYMBOLP);
- if(VSYM(sym)->sym_Flags & SF_BUFFER_LOCAL)
- return(sym_t);
- return(sym_nil);
- }
-
- _PR VALUE cmd_set_window_variable(VALUE sym, VALUE stat);
- DEFUN("set-window-variable", cmd_set_window_variable, subr_set_window_variable, (VALUE sym, VALUE stat), V_Subr2, DOC_set_window_variable) /*
- ::doc:set_window_variable::
- (set-window-variable SYMBOL)
- Flags that SYMBOL might have a value local to each window.
- ::end:: */
- {
- DECLARE1(sym, SYMBOLP);
- if(NILP(stat))
- VSYM(sym)->sym_Flags |= SF_WIN_LOCAL;
- else
- VSYM(sym)->sym_Flags &= ~SF_WIN_LOCAL;
- return(sym);
- }
- _PR VALUE cmd_window_variable_p(VALUE sym);
- DEFUN("window-variable-p", cmd_window_variable_p, subr_window_variable_p, (VALUE sym), V_Subr1, DOC_window_variable_p) /*
- ::doc:window_variable_p::
- (window-variable-p SYMBOL)
- Returns t if `set-window-variable' has been called on this symbol.
- ::end:: */
- {
- DECLARE1(sym, SYMBOLP);
- if(VSYM(sym)->sym_Flags & SF_WIN_LOCAL)
- return(sym_t);
- return(sym_nil);
- }
-
- _PR VALUE cmd_set_const_variable(VALUE sym, VALUE stat);
- DEFUN("set-const-variable", cmd_set_const_variable, subr_set_const_variable, (VALUE sym, VALUE stat), V_Subr2, DOC_set_const_variable) /*
- ::doc:set_const_variable::
- (set-const-variable SYMBOL)
- Flags that the value of SYMBOL may not be changed.
- ::end:: */
- {
- DECLARE1(sym, SYMBOLP);
- if(NILP(stat))
- VSYM(sym)->sym_Flags |= SF_CONSTANT;
- else
- VSYM(sym)->sym_Flags &= ~SF_CONSTANT;
- return(sym);
- }
- _PR VALUE cmd_const_variable_p(VALUE sym);
- DEFUN("const-variable-p", cmd_const_variable_p, subr_const_variable_p, (VALUE sym), V_Subr1, DOC_const_variable_p) /*
- ::doc:const_variable_p::
- (const-variable-p SYMBOL)
- Return t is `set-const-variable' has been called on SYMBOL.
- ::end:: */
- {
- DECLARE1(sym, SYMBOLP);
- if(VSYM(sym)->sym_Flags & SF_CONSTANT)
- return(sym_t);
- return(sym_nil);
- }
-
- _PR VALUE cmd_trace(VALUE sym);
- DEFUN("trace", cmd_trace, subr_trace, (VALUE sym), V_Subr1, DOC_trace) /*
- ::doc:trace::
- (trace SYMBOL)
- Flag that whenever SYMBOL is evaluated (as a variable or a function) the
- debugger is entered.
- ::end:: */
- {
- DECLARE1(sym, SYMBOLP);
- VSYM(sym)->sym_Flags |= SF_DEBUG;
- return(sym);
- }
- _PR VALUE cmd_untrace(VALUE sym);
- DEFUN("untrace", cmd_untrace, subr_untrace, (VALUE sym), V_Subr1, DOC_untrace) /*
- ::doc:untrace::
- (untrace SYMBOL)
- Cancel the effect of (trace SYMBOL).
- ::end:: */
- {
- DECLARE1(sym, SYMBOLP);
- VSYM(sym)->sym_Flags &= ~SF_DEBUG;
- return(sym);
- }
-
- int
- symbols_init(void)
- {
- ObArray = newvector(OBSIZE);
- if(ObArray)
- {
- markstatic(&ObArray);
-
- /* fiddly details of initialising the first symbol */
- sym_nil = cmd_intern(MKSTR("nil"), ObArray);
- markstatic(&sym_nil);
- VSYM(sym_nil)->sym_Value = sym_nil;
- VSYM(sym_nil)->sym_PropList = sym_nil;
-
- INTERN(sym_t, "t");
- VSYM(sym_t)->sym_Value = sym_t;
- INTERN(sym_variable_documentation, "variable-documentation");
- ADD_SUBR(subr_make_symbol);
- ADD_SUBR(subr_make_obarray);
- ADD_SUBR(subr_find_symbol);
- ADD_SUBR(subr_intern_symbol);
- ADD_SUBR(subr_intern);
- ADD_SUBR(subr_unintern);
- ADD_SUBR(subr_symbol_value);
- ADD_SUBR(subr_set);
- ADD_SUBR(subr_setplist);
- ADD_SUBR(subr_symbol_name);
- ADD_SUBR(subr_symbol_function);
- ADD_SUBR(subr_fboundp);
- ADD_SUBR(subr_boundp);
- ADD_SUBR(subr_symbol_plist);
- ADD_SUBR(subr_gensym);
- ADD_SUBR(subr_symbolp);
- ADD_SUBR(subr_setq);
- ADD_SUBR(subr_fset);
- ADD_SUBR(subr_makunbound);
- ADD_SUBR(subr_fmakunbound);
- ADD_SUBR(subr_let);
- ADD_SUBR(subr_letstar);
- ADD_SUBR(subr_get);
- ADD_SUBR(subr_put);
- ADD_SUBR(subr_buffer_variables);
- ADD_SUBR(subr_window_variables);
- ADD_SUBR(subr_apropos);
- ADD_SUBR(subr_set_buffer_variable);
- ADD_SUBR(subr_buffer_variable_p);
- ADD_SUBR(subr_set_window_variable);
- ADD_SUBR(subr_window_variable_p);
- ADD_SUBR(subr_set_const_variable);
- ADD_SUBR(subr_const_variable_p);
- ADD_SUBR(subr_trace);
- ADD_SUBR(subr_untrace);
- return(TRUE);
- }
- return(FALSE);
- }
- void
- symbols_kill(void)
- {
- SymbolBlk *sb = SymbolBlkChain;
- while(sb)
- {
- SymbolBlk *nxt = sb->sb_Next;
- myfree(sb);
- sb = nxt;
- }
- }
-