/* Primitive operations on Lisp data types for GNU Emacs Lisp interpreter.
- Copyright (C) 1985,86,88,93,94,95,97,98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1985,86,88,93,94,95,97,98,99,2000 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "lisp.h"
#include "puresize.h"
#include "charset.h"
-
-#ifndef standalone
#include "buffer.h"
#include "keyboard.h"
#include "frame.h"
-#endif
-
#include "syssignal.h"
-#ifdef LISP_FLOAT_TYPE
-
#ifdef STDC_HEADERS
#include <float.h>
#endif
#endif
#include <math.h>
-#endif /* LISP_FLOAT_TYPE */
#if !defined (atof)
extern double atof ();
#endif /* !atof */
-/* Nonzero means it is an error to set a symbol whose name starts with
- colon. */
-int keyword_symbols_constant_flag;
-
Lisp_Object Qnil, Qt, Qquote, Qlambda, Qsubr, Qunbound;
Lisp_Object Qerror_conditions, Qerror_message, Qtop_level;
Lisp_Object Qerror, Qquit, Qwrong_type_argument, Qargs_out_of_range;
Lisp_Object Qrange_error, Qdomain_error, Qsingularity_error;
Lisp_Object Qoverflow_error, Qunderflow_error;
-#ifdef LISP_FLOAT_TYPE
Lisp_Object Qfloatp;
Lisp_Object Qnumberp, Qnumber_or_marker_p;
-#endif
static Lisp_Object Qinteger, Qsymbol, Qstring, Qcons, Qmarker, Qoverlay;
static Lisp_Object Qfloat, Qwindow_configuration, Qwindow;
Lisp_Object Qprocess;
static Lisp_Object Qcompiled_function, Qbuffer, Qframe, Qvector;
static Lisp_Object Qchar_table, Qbool_vector, Qhash_table;
+static Lisp_Object Qsubrp, Qmany, Qunevalled;
static Lisp_Object swap_in_symval_forwarding ();
return Qhash_table;
return Qvector;
-#ifdef LISP_FLOAT_TYPE
case Lisp_Float:
return Qfloat;
-#endif
default:
abort ();
return Qnil;
}
-#ifdef LISP_FLOAT_TYPE
DEFUN ("floatp", Ffloatp, Sfloatp, 1, 1, 0,
"Return t if OBJECT is a floating point number.")
(object)
return Qt;
return Qnil;
}
-#endif /* LISP_FLOAT_TYPE */
+
\f
/* Extract and set components of lists */
CHECK_SYMBOL (symbol, 0);
if (NILP (symbol) || EQ (symbol, Qt)
|| (XSYMBOL (symbol)->name->data[0] == ':'
- && EQ (XSYMBOL (symbol)->obarray, initial_obarray)
- && keyword_symbols_constant_flag))
+ && EQ (XSYMBOL (symbol)->obarray, initial_obarray)))
return Fsignal (Qsetting_constant, Fcons (symbol, Qnil));
Fset (symbol, Qunbound);
return symbol;
return newplist;
}
+DEFUN ("subr-arity", Fsubr_arity, Ssubr_arity, 1, 1, 0,
+ "Return minimum and maximum number of args allowed for SUBR.\n\
+SUBR must be a built-in function.\n\
+The returned value is a pair (MIN . MAX). MIN is the minimum number\n\
+of args. MAX is the maximum number or the symbol `many', for a\n\
+function with `&rest' args, or `unevalled' for a special form.")
+ (subr)
+ Lisp_Object subr;
+{
+ short minargs, maxargs;
+ if (!SUBRP (subr))
+ wrong_type_argument (Qsubrp, subr);
+ minargs = XSUBR (subr)->min_args;
+ maxargs = XSUBR (subr)->max_args;
+ if (maxargs == MANY)
+ return Fcons (make_number (minargs), Qmany);
+ else if (maxargs == UNEVALLED)
+ return Fcons (make_number (minargs), Qunevalled);
+ else
+ return Fcons (make_number (minargs), make_number (maxargs));
+}
+
\f
/* Getting and setting values of symbols */
case Lisp_Misc_Buffer_Objfwd:
offset = XBUFFER_OBJFWD (valcontents)->offset;
- return *(Lisp_Object *)(offset + (char *)current_buffer);
+ return PER_BUFFER_VALUE (current_buffer, offset);
case Lisp_Misc_Kboard_Objfwd:
offset = XKBOARD_OBJFWD (valcontents)->offset;
int offset = XBUFFER_OBJFWD (valcontents)->offset;
Lisp_Object type;
- type = *(Lisp_Object *)(offset + (char *)&buffer_local_types);
+ type = PER_BUFFER_TYPE (offset);
if (XINT (type) == -1)
error ("Variable %s is read-only", XSYMBOL (symbol)->name->data);
&& XTYPE (newval) != XINT (type))
buffer_slot_type_mismatch (offset);
- *(Lisp_Object *)(offset + (char *)current_buffer) = newval;
+ PER_BUFFER_VALUE (current_buffer, offset) = newval;
}
break;
}
}
-/* Set up the buffer-local symbol SYMBOL for validity in the current buffer.
- VALCONTENTS is the contents of its value cell.
- Return the value forwarded one step past the buffer-local indicator. */
+/* Set up SYMBOL to refer to its global binding.
+ This makes it safe to alter the status of other bindings. */
-static Lisp_Object
-swap_in_symval_forwarding (symbol, valcontents)
- Lisp_Object symbol, valcontents;
+void
+swap_in_global_binding (symbol)
+ Lisp_Object symbol;
{
- /* valcontents is a pointer to a struct resembling the cons
- (REALVALUE BUFFER CURRENT-ALIST-ELEMENT . DEFAULT-VALUE)).
+ Lisp_Object valcontents, cdr;
+
+ valcontents = XSYMBOL (symbol)->value;
+ if (!BUFFER_LOCAL_VALUEP (valcontents)
+ && !SOME_BUFFER_LOCAL_VALUEP (valcontents))
+ abort ();
+ cdr = XBUFFER_LOCAL_VALUE (valcontents)->cdr;
- CURRENT-ALIST-ELEMENT is a pointer to an element of BUFFER's
- local_var_alist, that being the element whose car is this
- variable. Or it can be a pointer to the
- (CURRENT-ALIST-ELEMENT . DEFAULT-VALUE), if BUFFER does not have
- an element in its alist for this variable.
+ /* Unload the previously loaded binding. */
+ Fsetcdr (XCAR (cdr),
+ do_symval_forwarding (XBUFFER_LOCAL_VALUE (valcontents)->realvalue));
+
+ /* Select the global binding in the symbol. */
+ XCAR (cdr) = cdr;
+ store_symval_forwarding (symbol, valcontents, XCDR (cdr));
- If the current buffer is not BUFFER, we store the current
- REALVALUE value into CURRENT-ALIST-ELEMENT, then find the
- appropriate alist element for the buffer now current and set up
- CURRENT-ALIST-ELEMENT. Then we set REALVALUE out of that
- element, and store into BUFFER.
+ /* Indicate that the global binding is set up now. */
+ XBUFFER_LOCAL_VALUE (valcontents)->frame = Qnil;
+ XBUFFER_LOCAL_VALUE (valcontents)->buffer = Qnil;
+ XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame = 0;
+ XBUFFER_LOCAL_VALUE (valcontents)->found_for_buffer = 0;
+}
- Note that REALVALUE can be a forwarding pointer. */
+/* Set up the buffer-local symbol SYMBOL for validity in the current buffer.
+ VALCONTENTS is the contents of its value cell,
+ which points to a struct Lisp_Buffer_Local_Value.
+
+ Return the value forwarded one step past the buffer-local stage.
+ This could be another forwarding pointer. */
+static Lisp_Object
+swap_in_symval_forwarding (symbol, valcontents)
+ Lisp_Object symbol, valcontents;
+{
register Lisp_Object tem1;
tem1 = XBUFFER_LOCAL_VALUE (valcontents)->buffer;
- if (NILP (tem1) || current_buffer != XBUFFER (tem1)
- || !EQ (selected_frame, XBUFFER_LOCAL_VALUE (valcontents)->frame))
+ if (NILP (tem1)
+ || current_buffer != XBUFFER (tem1)
+ || (XBUFFER_LOCAL_VALUE (valcontents)->check_frame
+ && ! EQ (selected_frame, XBUFFER_LOCAL_VALUE (valcontents)->frame)))
{
+ /* Unload the previously loaded binding. */
tem1 = XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr);
Fsetcdr (tem1,
do_symval_forwarding (XBUFFER_LOCAL_VALUE (valcontents)->realvalue));
+ /* Choose the new binding. */
tem1 = assq_no_quit (symbol, current_buffer->local_var_alist);
XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame = 0;
XBUFFER_LOCAL_VALUE (valcontents)->found_for_buffer = 0;
else
XBUFFER_LOCAL_VALUE (valcontents)->found_for_buffer = 1;
+ /* Load the new binding. */
XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr) = tem1;
XSETBUFFER (XBUFFER_LOCAL_VALUE (valcontents)->buffer, current_buffer);
XBUFFER_LOCAL_VALUE (valcontents)->frame = selected_frame;
return *XOBJFWD (valcontents)->objvar;
case Lisp_Misc_Buffer_Objfwd:
- return *(Lisp_Object *)(XBUFFER_OBJFWD (valcontents)->offset
- + (char *)current_buffer);
+ return PER_BUFFER_VALUE (current_buffer,
+ XBUFFER_OBJFWD (valcontents)->offset);
case Lisp_Misc_Kboard_Objfwd:
return *(Lisp_Object *)(XKBOARD_OBJFWD (valcontents)->offset
struct specbinding *p;
for (p = specpdl_ptr - 1; p >= specpdl; p--)
- if (p->func == 0 && CONSP (p->symbol)
+ if (p->func == 0
+ && CONSP (p->symbol)
+ && EQ (symbol, XCAR (p->symbol))
&& XBUFFER (XCDR (XCDR (p->symbol))) == current_buffer)
return 1;
{
int voide = EQ (newval, Qunbound);
- register Lisp_Object valcontents, tem1, current_alist_element;
+ register Lisp_Object valcontents, innercontents, tem1, current_alist_element;
if (buf == 0)
buf = current_buffer;
if (NILP (symbol) || EQ (symbol, Qt)
|| (XSYMBOL (symbol)->name->data[0] == ':'
&& EQ (XSYMBOL (symbol)->obarray, initial_obarray)
- && keyword_symbols_constant_flag && ! EQ (newval, symbol)))
+ && !EQ (newval, symbol)))
return Fsignal (Qsetting_constant, Fcons (symbol, Qnil));
- valcontents = XSYMBOL (symbol)->value;
+
+ innercontents = valcontents = XSYMBOL (symbol)->value;
if (BUFFER_OBJFWDP (valcontents))
{
- register int idx = XBUFFER_OBJFWD (valcontents)->offset;
- register int mask = XINT (*((Lisp_Object *)
- (idx + (char *)&buffer_local_flags)));
- if (mask > 0 && ! bindflag
- && ! let_shadows_buffer_binding_p (symbol))
- buf->local_var_flags |= mask;
+ int offset = XBUFFER_OBJFWD (valcontents)->offset;
+ int idx = PER_BUFFER_IDX (offset);
+ if (idx > 0
+ && !bindflag
+ && !let_shadows_buffer_binding_p (symbol))
+ SET_PER_BUFFER_VALUE_P (buf, idx, 1);
}
else if (BUFFER_LOCAL_VALUEP (valcontents)
|| SOME_BUFFER_LOCAL_VALUEP (valcontents))
{
- /* valcontents is actually a pointer to a struct resembling a cons,
- with contents something like:
- (REALVALUE BUFFER CURRENT-ALIST-ELEMENT . DEFAULT-VALUE).
-
- BUFFER is the last buffer for which this symbol's value was
- made up to date.
-
- CURRENT-ALIST-ELEMENT is a pointer to an element of BUFFER's
- local_var_alist, that being the element whose car is this
- variable. Or it can be a pointer to the
- (CURRENT-ALIST-ELEMENT . DEFAULT-VALUE), if BUFFER does not
- have an element in its alist for this variable (that is, if
- BUFFER sees the default value of this variable).
-
- If we want to examine or set the value and BUFFER is current,
- we just examine or set REALVALUE. If BUFFER is not current, we
- store the current REALVALUE value into CURRENT-ALIST-ELEMENT,
- then find the appropriate alist element for the buffer now
- current and set up CURRENT-ALIST-ELEMENT. Then we set
- REALVALUE out of that element, and store into BUFFER.
-
- If we are setting the variable and the current buffer does
- not have an alist entry for this variable, an alist entry is
- created.
-
- Note that REALVALUE can be a forwarding pointer. Each time
- it is examined or set, forwarding must be done. */
-
- /* What value are we caching right now? */
+ /* valcontents is a struct Lisp_Buffer_Local_Value. */
+
+ /* What binding is loaded right now? */
current_alist_element
= XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr);
/* If the current buffer is not the buffer whose binding is
- currently cached, or if it's a Lisp_Buffer_Local_Value and
- we're looking at the default value, the cache is invalid; we
- need to write it out, and find the new CURRENT-ALIST-ELEMENT. */
- if (XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame
- ? !EQ (selected_frame, XBUFFER_LOCAL_VALUE (valcontents)->frame)
- : (buf != XBUFFER (XBUFFER_LOCAL_VALUE (valcontents)->buffer)
- || (BUFFER_LOCAL_VALUEP (valcontents)
- && EQ (XCAR (current_alist_element),
- current_alist_element))))
+ loaded, or if there may be frame-local bindings and the frame
+ isn't the right one, or if it's a Lisp_Buffer_Local_Value and
+ the default binding is loaded, the loaded binding may be the
+ wrong one. */
+ if (!BUFFERP (XBUFFER_LOCAL_VALUE (valcontents)->buffer)
+ || buf != XBUFFER (XBUFFER_LOCAL_VALUE (valcontents)->buffer)
+ || (XBUFFER_LOCAL_VALUE (valcontents)->check_frame
+ && !EQ (selected_frame, XBUFFER_LOCAL_VALUE (valcontents)->frame))
+ || (BUFFER_LOCAL_VALUEP (valcontents)
+ && EQ (XCAR (current_alist_element),
+ current_alist_element)))
{
- /* Write out the cached value for the old buffer; copy it
- back to its alist element. This works if the current
- buffer only sees the default value, too. */
+ /* The currently loaded binding is not necessarily valid.
+ We need to unload it, and choose a new binding. */
+
+ /* Write out `realvalue' to the old loaded binding. */
Fsetcdr (current_alist_element,
do_symval_forwarding (XBUFFER_LOCAL_VALUE (valcontents)->realvalue));
- /* Find the new value for CURRENT-ALIST-ELEMENT. */
+ /* Find the new binding. */
tem1 = Fassq (symbol, buf->local_var_alist);
XBUFFER_LOCAL_VALUE (valcontents)->found_for_buffer = 1;
XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame = 0;
and we're not within a let that was made for this buffer,
create a new buffer-local binding for the variable.
That means, give this buffer a new assoc for a local value
- and set CURRENT-ALIST-ELEMENT to point to that. */
+ and load that binding. */
else
{
tem1 = Fcons (symbol, Fcdr (current_alist_element));
}
}
- /* Cache the new buffer's assoc in CURRENT-ALIST-ELEMENT. */
+ /* Record which binding is now loaded. */
XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr)
= tem1;
- /* Set BUFFER and FRAME for binding now loaded. */
+ /* Set `buffer' and `frame' slots for thebinding now loaded. */
XSETBUFFER (XBUFFER_LOCAL_VALUE (valcontents)->buffer, buf);
XBUFFER_LOCAL_VALUE (valcontents)->frame = selected_frame;
}
- valcontents = XBUFFER_LOCAL_VALUE (valcontents)->realvalue;
+ innercontents = XBUFFER_LOCAL_VALUE (valcontents)->realvalue;
}
/* If storing void (making the symbol void), forward only through
if (voide)
store_symval_forwarding (symbol, Qnil, newval);
else
- store_symval_forwarding (symbol, valcontents, newval);
+ store_symval_forwarding (symbol, innercontents, newval);
+
+ /* If we just set a variable whose current binding is frame-local,
+ store the new value in the frame parameter too. */
+
+ if (BUFFER_LOCAL_VALUEP (valcontents)
+ || SOME_BUFFER_LOCAL_VALUEP (valcontents))
+ {
+ /* What binding is loaded right now? */
+ current_alist_element
+ = XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr);
+
+ /* If the current buffer is not the buffer whose binding is
+ loaded, or if there may be frame-local bindings and the frame
+ isn't the right one, or if it's a Lisp_Buffer_Local_Value and
+ the default binding is loaded, the loaded binding may be the
+ wrong one. */
+ if (XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame)
+ XCDR (current_alist_element) = newval;
+ }
return newval;
}
rather than letting do_symval_forwarding get the current value. */
if (BUFFER_OBJFWDP (valcontents))
{
- register int idx = XBUFFER_OBJFWD (valcontents)->offset;
-
- if (XINT (*(Lisp_Object *) (idx + (char *) &buffer_local_flags)) != 0)
- return *(Lisp_Object *)(idx + (char *) &buffer_defaults);
+ int offset = XBUFFER_OBJFWD (valcontents)->offset;
+ if (PER_BUFFER_IDX (offset) != 0)
+ return PER_BUFFER_DEFAULT (offset);
}
/* Handle user-created local variables. */
{
/* If var is set up for a buffer that lacks a local value for it,
the current value is nominally the default value.
- But the current value slot may be more up to date, since
+ But the `realvalue' slot may be more up to date, since
ordinary setq stores just that slot. So use that. */
Lisp_Object current_alist_element, alist_element_car;
current_alist_element
variables. */
if (BUFFER_OBJFWDP (valcontents))
{
- register int idx = XBUFFER_OBJFWD (valcontents)->offset;
- register struct buffer *b;
- register int mask = XINT (*((Lisp_Object *)
- (idx + (char *)&buffer_local_flags)));
+ int offset = XBUFFER_OBJFWD (valcontents)->offset;
+ int idx = PER_BUFFER_IDX (offset);
- *(Lisp_Object *)(idx + (char *) &buffer_defaults) = value;
+ PER_BUFFER_DEFAULT (offset) = value;
/* If this variable is not always local in all buffers,
set it in the buffers that don't nominally have a local value. */
- if (mask > 0)
+ if (idx > 0)
{
+ struct buffer *b;
+
for (b = all_buffers; b; b = b->next)
- if (!(b->local_var_flags & mask))
- *(Lisp_Object *)(idx + (char *) b) = value;
+ if (!PER_BUFFER_VALUE_P (b, idx))
+ PER_BUFFER_VALUE (b, offset) = value;
}
return value;
}
&& !SOME_BUFFER_LOCAL_VALUEP (valcontents))
return Fset (symbol, value);
- /* Store new value into the DEFAULT-VALUE slot */
+ /* Store new value into the DEFAULT-VALUE slot. */
XCDR (XBUFFER_LOCAL_VALUE (valcontents)->cdr) = value;
- /* If that slot is current, we must set the REALVALUE slot too */
+ /* If the default binding is now loaded, set the REALVALUE slot too. */
current_alist_element
= XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr);
alist_element_buffer = Fcar (current_alist_element);
DEFUN ("make-variable-buffer-local", Fmake_variable_buffer_local, Smake_variable_buffer_local,
1, 1, "vMake Variable Buffer Local: ",
- "Make VARIABLE have a separate value for each buffer.\n\
-At any time, the value for the current buffer is in effect.\n\
-There is also a default value which is seen in any buffer which has not yet\n\
-set its own value.\n\
-Using `set' or `setq' to set the variable causes it to have a separate value\n\
-for the current buffer if it was previously using the default value.\n\
+ "Make VARIABLE become buffer-local whenever it is set.\n\
+At any time, the value for the current buffer is in effect,\n\
+unless the variable has never been set in this buffer,\n\
+in which case the default value is in effect.\n\
+Note that binding the variable with `let', or setting it while\n\
+a `let'-style binding made in this buffer is in effect,\n\
+does not make the variable buffer-local.\n\
+\n\
The function `default-value' gets the default value and `set-default' sets it.")
(variable)
register Lisp_Object variable;
XBUFFER_LOCAL_VALUE (newval)->realvalue = XSYMBOL (variable)->value;
XBUFFER_LOCAL_VALUE (newval)->buffer = Fcurrent_buffer ();
XBUFFER_LOCAL_VALUE (newval)->frame = Qnil;
- XBUFFER_LOCAL_VALUE (newval)->found_for_buffer = 1;
+ XBUFFER_LOCAL_VALUE (newval)->found_for_buffer = 0;
XBUFFER_LOCAL_VALUE (newval)->found_for_frame = 0;
XBUFFER_LOCAL_VALUE (newval)->check_frame = 0;
XBUFFER_LOCAL_VALUE (newval)->cdr = tem;
Fset (variable, (EQ (tem, Qt) ? Fsymbol_value (variable) : Qunbound));
return variable;
}
- /* Make sure symbol is set up to hold per-buffer values */
+ /* Make sure symbol is set up to hold per-buffer values. */
if (!SOME_BUFFER_LOCAL_VALUEP (valcontents))
{
Lisp_Object newval;
XBUFFER_LOCAL_VALUE (newval)->cdr = tem;
XSYMBOL (variable)->value = newval;
}
- /* Make sure this buffer has its own value of symbol */
+ /* Make sure this buffer has its own value of symbol. */
tem = Fassq (variable, current_buffer->local_var_alist);
if (NILP (tem))
{
current_buffer->local_var_alist);
/* Make sure symbol does not think it is set up for this buffer;
- force it to look once again for this buffer's value */
+ force it to look once again for this buffer's value. */
{
Lisp_Object *pvalbuf;
}
}
- /* If the symbol forwards into a C variable, then swap in the
- variable for this buffer immediately. If C code modifies the
- variable before we swap in, then that new value will clobber the
- default value the next time we swap. */
+ /* If the symbol forwards into a C variable, then load the binding
+ for this buffer now. If C code modifies the variable before we
+ load the binding in, then that new value will clobber the default
+ binding the next time we unload it. */
valcontents = XBUFFER_LOCAL_VALUE (XSYMBOL (variable)->value)->realvalue;
if (INTFWDP (valcontents) || BOOLFWDP (valcontents) || OBJFWDP (valcontents))
swap_in_symval_forwarding (variable, XSYMBOL (variable)->value);
if (BUFFER_OBJFWDP (valcontents))
{
- register int idx = XBUFFER_OBJFWD (valcontents)->offset;
- register int mask = XINT (*((Lisp_Object*)
- (idx + (char *)&buffer_local_flags)));
+ int offset = XBUFFER_OBJFWD (valcontents)->offset;
+ int idx = PER_BUFFER_IDX (offset);
- if (mask > 0)
+ if (idx > 0)
{
- *(Lisp_Object *)(idx + (char *) current_buffer)
- = *(Lisp_Object *)(idx + (char *) &buffer_defaults);
- current_buffer->local_var_flags &= ~mask;
+ SET_PER_BUFFER_VALUE_P (current_buffer, idx, 0);
+ PER_BUFFER_VALUE (current_buffer, offset)
+ = PER_BUFFER_DEFAULT (offset);
}
return variable;
}
&& !SOME_BUFFER_LOCAL_VALUEP (valcontents))
return variable;
- /* Get rid of this buffer's alist element, if any */
+ /* Get rid of this buffer's alist element, if any. */
tem = Fassq (variable, current_buffer->local_var_alist);
if (!NILP (tem))
current_buffer->local_var_alist
= Fdelq (tem, current_buffer->local_var_alist);
- /* If the symbol is set up for the current buffer, recompute its
- value. We have to do it now, or else forwarded objects won't
- work right. */
+ /* If the symbol is set up with the current buffer's binding
+ loaded, recompute its value. We have to do it now, or else
+ forwarded objects won't work right. */
{
Lisp_Object *pvalbuf;
valcontents = XSYMBOL (variable)->value;
if (BUFFER_LOCAL_VALUEP (valcontents)
|| SOME_BUFFER_LOCAL_VALUEP (valcontents))
- return variable;
+ {
+ XBUFFER_LOCAL_VALUE (valcontents)->check_frame = 1;
+ return variable;
+ }
if (EQ (valcontents, Qunbound))
XSYMBOL (variable)->value = Qnil;
if (BUFFER_OBJFWDP (valcontents))
{
int offset = XBUFFER_OBJFWD (valcontents)->offset;
- int mask = XINT (*(Lisp_Object *)(offset + (char *)&buffer_local_flags));
- if (mask == -1 || (buf->local_var_flags & mask))
+ int idx = PER_BUFFER_IDX (offset);
+ if (idx == -1 || PER_BUFFER_VALUE_P (buf, idx))
return Qt;
}
return Qnil;
int code[4], i;
Lisp_Object sub_table;
- SPLIT_NON_ASCII_CHAR (idxval, code[0], code[1], code[2]);
+ SPLIT_CHAR (idxval, code[0], code[1], code[2]);
if (code[1] < 32) code[1] = -1;
else if (code[2] < 32) code[2] = -1;
}
}
+/* Don't use alloca for relocating string data larger than this, lest
+ we overflow their stack. The value is the same as what used in
+ fns.c for base64 handling. */
+#define MAX_ALLOCA 16*1024
+
DEFUN ("aset", Faset, Saset, 3, 3, 0,
"Store into the element of ARRAY at index IDX the value NEWELT.\n\
ARRAY may be a vector, a string, a char-table or a bool-vector.\n\
int code[4], i;
Lisp_Object val;
- SPLIT_NON_ASCII_CHAR (idxval, code[0], code[1], code[2]);
+ SPLIT_CHAR (idxval, code[0], code[1], code[2]);
if (code[1] < 32) code[1] = -1;
else if (code[2] < 32) code[2] = -1;
}
else if (STRING_MULTIBYTE (array))
{
- int idxval_byte, new_len, actual_len;
- int prev_byte;
- unsigned char *p, workbuf[MAX_MULTIBYTE_LENGTH], *str = workbuf;
+ int idxval_byte, prev_bytes, new_bytes;
+ unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *p0 = workbuf, *p1;
if (idxval < 0 || idxval >= XSTRING (array)->size)
args_out_of_range (array, idx);
+ CHECK_NUMBER (newelt, 2);
idxval_byte = string_char_to_byte (array, idxval);
- p = &XSTRING (array)->data[idxval_byte];
-
- actual_len = MULTIBYTE_FORM_LENGTH (p, STRING_BYTES (XSTRING (array)));
- CHECK_NUMBER (newelt, 2);
- new_len = CHAR_STRING (XINT (newelt), str);
- if (actual_len != new_len)
- error ("Attempt to change byte length of a string");
-
- /* We can't accept a change causing byte combining. */
- if (!ASCII_BYTE_P (*str)
- && ((idxval > 0 && !CHAR_HEAD_P (*str)
- && (prev_byte = string_char_to_byte (array, idxval - 1),
- BYTES_BY_CHAR_HEAD (XSTRING (array)->data[prev_byte])
- > idxval_byte - prev_byte))
- || (idxval < XSTRING (array)->size - 1
- && !CHAR_HEAD_P (p[actual_len])
- && new_len < BYTES_BY_CHAR_HEAD (*str))))
- error ("Attempt to change char length of a string");
- while (new_len--)
- *p++ = *str++;
+ p1 = &XSTRING (array)->data[idxval_byte];
+ PARSE_MULTIBYTE_SEQ (p1, nbytes - idxval_byte, prev_bytes);
+ new_bytes = CHAR_STRING (XINT (newelt), p0);
+ if (prev_bytes != new_bytes)
+ {
+ /* We must relocate the string data. */
+ int nchars = XSTRING (array)->size;
+ int nbytes = STRING_BYTES (XSTRING (array));
+ unsigned char *str;
+
+ str = (nbytes <= MAX_ALLOCA
+ ? (unsigned char *) alloca (nbytes)
+ : (unsigned char *) xmalloc (nbytes));
+ bcopy (XSTRING (array)->data, str, nbytes);
+ allocate_string_data (XSTRING (array), nchars,
+ nbytes + new_bytes - prev_bytes);
+ bcopy (str, XSTRING (array)->data, idxval_byte);
+ p1 = XSTRING (array)->data + idxval_byte;
+ bcopy (str + idxval_byte + prev_bytes, p1 + new_bytes,
+ nbytes - (idxval_byte + prev_bytes));
+ if (nbytes > MAX_ALLOCA)
+ xfree (str);
+ clear_string_char_byte_cache ();
+ }
+ while (new_bytes--)
+ *p1++ = *p0++;
}
else
{
if (idxval < 0 || idxval >= XSTRING (array)->size)
args_out_of_range (array, idx);
CHECK_NUMBER (newelt, 2);
- XSTRING (array)->data[idxval] = XINT (newelt);
+
+ if (XINT (newelt) < 0 || SINGLE_BYTE_CHAR_P (XINT (newelt)))
+ XSTRING (array)->data[idxval] = XINT (newelt);
+ else
+ {
+ /* We must relocate the string data while converting it to
+ multibyte. */
+ int idxval_byte, prev_bytes, new_bytes;
+ unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *p0 = workbuf, *p1;
+ unsigned char *origstr = XSTRING (array)->data, *str;
+ int nchars, nbytes;
+
+ nchars = XSTRING (array)->size;
+ nbytes = idxval_byte = count_size_as_multibyte (origstr, idxval);
+ nbytes += count_size_as_multibyte (origstr + idxval,
+ nchars - idxval);
+ str = (nbytes <= MAX_ALLOCA
+ ? (unsigned char *) alloca (nbytes)
+ : (unsigned char *) xmalloc (nbytes));
+ copy_text (XSTRING (array)->data, str, nchars, 0, 1);
+ PARSE_MULTIBYTE_SEQ (str + idxval_byte, nbytes - idxval_byte,
+ prev_bytes);
+ new_bytes = CHAR_STRING (XINT (newelt), p0);
+ allocate_string_data (XSTRING (array), nchars,
+ nbytes + new_bytes - prev_bytes);
+ bcopy (str, XSTRING (array)->data, idxval_byte);
+ p1 = XSTRING (array)->data + idxval_byte;
+ while (new_bytes--)
+ *p1++ = *p0++;
+ bcopy (str + idxval_byte + prev_bytes, p1,
+ nbytes - (idxval_byte + prev_bytes));
+ if (nbytes > MAX_ALLOCA)
+ xfree (str);
+ clear_string_char_byte_cache ();
+ }
}
return newelt;
double f1, f2;
int floatp = 0;
-#ifdef LISP_FLOAT_TYPE
CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (num1, 0);
CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (num2, 0);
f1 = (FLOATP (num1)) ? XFLOAT_DATA (num1) : XINT (num1);
f2 = (FLOATP (num2)) ? XFLOAT_DATA (num2) : XINT (num2);
}
-#else
- CHECK_NUMBER_COERCE_MARKER (num1, 0);
- CHECK_NUMBER_COERCE_MARKER (num2, 0);
-#endif /* LISP_FLOAT_TYPE */
switch (comparison)
{
(number)
register Lisp_Object number;
{
-#ifdef LISP_FLOAT_TYPE
CHECK_NUMBER_OR_FLOAT (number, 0);
if (FLOATP (number))
return Qt;
return Qnil;
}
-#else
- CHECK_NUMBER (number, 0);
-#endif /* LISP_FLOAT_TYPE */
if (!XINT (number))
return Qt;
{
char buffer[VALBITS];
-#ifndef LISP_FLOAT_TYPE
- CHECK_NUMBER (number, 0);
-#else
CHECK_NUMBER_OR_FLOAT (number, 0);
if (FLOATP (number))
float_to_string (pigbuf, XFLOAT_DATA (number));
return build_string (pigbuf);
}
-#endif /* LISP_FLOAT_TYPE */
if (sizeof (int) == sizeof (EMACS_INT))
sprintf (buffer, "%d", XINT (number));
register Lisp_Object string, base;
{
register unsigned char *p;
- register int b, v = 0;
- int negative = 1;
+ register int b;
+ int sign = 1;
+ Lisp_Object val;
CHECK_STRING (string, 0);
Fsignal (Qargs_out_of_range, Fcons (base, Qnil));
}
- p = XSTRING (string)->data;
-
/* Skip any whitespace at the front of the number. Some versions of
atoi do this anyway, so we might as well make Emacs lisp consistent. */
+ p = XSTRING (string)->data;
while (*p == ' ' || *p == '\t')
p++;
if (*p == '-')
{
- negative = -1;
+ sign = -1;
p++;
}
else if (*p == '+')
p++;
-#ifdef LISP_FLOAT_TYPE
if (isfloat_string (p) && b == 10)
- return make_float (negative * atof (p));
-#endif /* LISP_FLOAT_TYPE */
-
- while (1)
+ val = make_float (sign * atof (p));
+ else
{
- int digit = digit_to_number (*p++, b);
- if (digit < 0)
- break;
- v = v * b + digit;
+ double v = 0;
+
+ while (1)
+ {
+ int digit = digit_to_number (*p++, b);
+ if (digit < 0)
+ break;
+ v = v * b + digit;
+ }
+
+ if (v > (EMACS_UINT) (VALMASK >> 1))
+ val = make_float (sign * v);
+ else
+ val = make_number (sign * (int) v);
}
-
- return make_number (negative * v);
+
+ return val;
}
\f
for (argnum = 0; argnum < nargs; argnum++)
{
val = args[argnum]; /* using args[argnum] as argument to CHECK_NUMBER_... */
-#ifdef LISP_FLOAT_TYPE
CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (val, argnum);
if (FLOATP (val)) /* time to do serious math */
return (float_arith_driver ((double) accum, argnum, code,
nargs, args));
-#else
- CHECK_NUMBER_COERCE_MARKER (val, argnum);
-#endif /* LISP_FLOAT_TYPE */
args[argnum] = val; /* runs into a compiler bug. */
next = XINT (args[argnum]);
switch (SWITCH_ENUM_CAST (code))
#undef isnan
#define isnan(x) ((x) != (x))
-#ifdef LISP_FLOAT_TYPE
-
Lisp_Object
float_arith_driver (accum, argnum, code, nargs, args)
double accum;
return make_float (accum);
}
-#endif /* LISP_FLOAT_TYPE */
+
DEFUN ("+", Fplus, Splus, 0, MANY, 0,
"Return sum of any number of arguments, which are numbers or markers.")
Lisp_Object val;
EMACS_INT i1, i2;
-#ifdef LISP_FLOAT_TYPE
CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (x, 0);
CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (y, 1);
if (FLOATP (x) || FLOATP (y))
return fmod_float (x, y);
-#else /* not LISP_FLOAT_TYPE */
- CHECK_NUMBER_COERCE_MARKER (x, 0);
- CHECK_NUMBER_COERCE_MARKER (y, 1);
-#endif /* not LISP_FLOAT_TYPE */
-
i1 = XINT (x);
i2 = XINT (y);
(number)
register Lisp_Object number;
{
-#ifdef LISP_FLOAT_TYPE
CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (number, 0);
if (FLOATP (number))
return (make_float (1.0 + XFLOAT_DATA (number)));
-#else
- CHECK_NUMBER_COERCE_MARKER (number, 0);
-#endif /* LISP_FLOAT_TYPE */
XSETINT (number, XINT (number) + 1);
return number;
(number)
register Lisp_Object number;
{
-#ifdef LISP_FLOAT_TYPE
CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (number, 0);
if (FLOATP (number))
return (make_float (-1.0 + XFLOAT_DATA (number)));
-#else
- CHECK_NUMBER_COERCE_MARKER (number, 0);
-#endif /* LISP_FLOAT_TYPE */
XSETINT (number, XINT (number) - 1);
return number;
Qboundp = intern ("boundp");
Qfboundp = intern ("fboundp");
-#ifdef LISP_FLOAT_TYPE
Qfloatp = intern ("floatp");
Qnumberp = intern ("numberp");
Qnumber_or_marker_p = intern ("number-or-marker-p");
-#endif /* LISP_FLOAT_TYPE */
Qchar_table_p = intern ("char-table-p");
Qvector_or_char_table_p = intern ("vector-or-char-table-p");
+ Qsubrp = intern ("subrp");
+ Qunevalled = intern ("unevalled");
+ Qmany = intern ("many");
+
Qcdr = intern ("cdr");
/* Handle automatic advice activation */
Fput (Qtext_read_only, Qerror_message,
build_string ("Text is read-only"));
-#ifdef LISP_FLOAT_TYPE
Qrange_error = intern ("range-error");
Qdomain_error = intern ("domain-error");
Qsingularity_error = intern ("singularity-error");
staticpro (&Qsingularity_error);
staticpro (&Qoverflow_error);
staticpro (&Qunderflow_error);
-#endif /* LISP_FLOAT_TYPE */
staticpro (&Qnil);
staticpro (&Qt);
staticpro (&Qmarkerp);
staticpro (&Qbuffer_or_string_p);
staticpro (&Qinteger_or_marker_p);
-#ifdef LISP_FLOAT_TYPE
staticpro (&Qfloatp);
staticpro (&Qnumberp);
staticpro (&Qnumber_or_marker_p);
-#endif /* LISP_FLOAT_TYPE */
staticpro (&Qchar_table_p);
staticpro (&Qvector_or_char_table_p);
+ staticpro (&Qsubrp);
+ staticpro (&Qmany);
+ staticpro (&Qunevalled);
staticpro (&Qboundp);
staticpro (&Qfboundp);
staticpro (&Qbool_vector);
staticpro (&Qhash_table);
- DEFVAR_BOOL ("keyword-symbols-constant-flag", &keyword_symbols_constant_flag,
- "Non-nil means it is an error to set a keyword symbol.\n\
-A keyword symbol is a symbol whose name starts with a colon (`:').");
- keyword_symbols_constant_flag = 1;
-
defsubr (&Seq);
defsubr (&Snull);
defsubr (&Stype_of);
defsubr (&Sinteger_or_marker_p);
defsubr (&Snumberp);
defsubr (&Snumber_or_marker_p);
-#ifdef LISP_FLOAT_TYPE
defsubr (&Sfloatp);
-#endif /* LISP_FLOAT_TYPE */
defsubr (&Snatnump);
defsubr (&Ssymbolp);
defsubr (&Skeywordp);
defsubr (&Sadd1);
defsubr (&Ssub1);
defsubr (&Slognot);
+ defsubr (&Ssubr_arity);
XSYMBOL (Qwholenump)->function = XSYMBOL (Qnatnump)->function;
}