/* Random utility Lisp functions.
- Copyright (C) 1985, 86, 87, 93, 94, 95, 97, 98, 99, 2000, 2001, 02, 03, 2004
- Free Software Foundation, Inc.
+ Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1997, 1998, 1999, 2000,
+ 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Emacs.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include <config.h>
#endif
#include <time.h>
-#ifndef MAC_OSX
-/* On Mac OS X, defining this conflicts with precompiled headers. */
+#ifndef MAC_OS
+/* On Mac OS, defining this conflicts with precompiled headers. */
/* Note on some machines this defines `vector' as a typedef,
so make sure we don't use that name in this file. */
extern int minibuffer_auto_raise;
extern Lisp_Object minibuf_window;
extern Lisp_Object Vlocale_coding_system;
+extern int load_in_progress;
Lisp_Object Qstring_lessp, Qprovide, Qrequire;
Lisp_Object Qyes_or_no_p_history;
return val;
}
-/* This does not check for quits. That is safe
- since it must terminate. */
+/* This does not check for quits. That is safe since it must terminate. */
DEFUN ("safe-length", Fsafe_length, Ssafe_length, 1, 1, 0,
doc: /* Return the length of a list, but avoid error or infinite loop.
copy_sub_char_table (arg)
Lisp_Object arg;
{
- Lisp_Object copy = make_sub_char_table (XCHAR_TABLE (arg)->defalt);
+ Lisp_Object copy = make_sub_char_table (Qnil);
int i;
+ XCHAR_TABLE (copy)->defalt = XCHAR_TABLE (arg)->defalt;
/* Copy all the contents. */
bcopy (XCHAR_TABLE (arg)->contents, XCHAR_TABLE (copy)->contents,
SUB_CHAR_TABLE_ORDINARY_SLOTS * sizeof (Lisp_Object));
struct textprop_rec *textprops = NULL;
/* Number of elments in textprops. */
int num_textprops = 0;
+ USE_SAFE_ALLOCA;
tail = Qnil;
prev = Qnil;
if (STRINGP (val))
- textprops
- = (struct textprop_rec *) alloca (sizeof (struct textprop_rec) * nargs);
+ SAFE_ALLOCA (textprops, struct textprop_rec *, sizeof (struct textprop_rec) * nargs);
for (argnum = 0; argnum < nargs; argnum++)
{
}
else
{
- XSETFASTINT (elt, SREF (this, thisindex++));
+ XSETFASTINT (elt, SREF (this, thisindex)); thisindex++;
if (some_multibyte
&& (XINT (elt) >= 0240
|| (XINT (elt) >= 0200
last_to_end = textprops[argnum].to + SCHARS (this);
}
}
+
+ SAFE_FREE ();
return val;
}
\f
0, 1);
ret = make_multibyte_string (buf, SCHARS (string), nbytes);
- SAFE_FREE (nbytes);
+ SAFE_FREE ();
return ret;
}
str_to_multibyte (buf, nbytes, SBYTES (string));
ret = make_multibyte_string (buf, SCHARS (string), nbytes);
- SAFE_FREE (nbytes);
+ SAFE_FREE ();
return ret;
}
1, 0);
ret = make_unibyte_string (buf, nchars);
- SAFE_FREE (nchars);
+ SAFE_FREE ();
return ret;
}
Otherwise it is a newly created string, with no text properties.
If STRING is unibyte and contains an individual 8-bit byte (i.e. not
part of a multibyte form), it is converted to the corresponding
-multibyte character of charset `eight-bit-control' or `eight-bit-graphic'. */)
+multibyte character of charset `eight-bit-control' or `eight-bit-graphic'.
+Beware, this often doesn't really do what you think it does.
+It is similar to (decode-coding-string STRING 'emacs-mule-unix).
+If you're not sure, whether to use `string-as-multibyte' or
+`string-to-multibyte', use `string-to-multibyte'. Beware:
+ (aref (string-as-multibyte "\\201") 0) -> 129 (aka ?\\201)
+ (aref (string-as-multibyte "\\300") 0) -> 192 (aka ?\\300)
+ (aref (string-as-multibyte "\\300\\201") 0) -> 192 (aka ?\\300)
+ (aref (string-as-multibyte "\\300\\201") 1) -> 129 (aka ?\\201)
+but
+ (aref (string-as-multibyte "\\201\\300") 0) -> 2240
+ (aref (string-as-multibyte "\\201\\300") 1) -> <error> */)
(string)
Lisp_Object string;
{
Characters 0200 through 0237 are converted to eight-bit-control
characters of the same character code. Characters 0240 through 0377
are converted to eight-bit-graphic characters of the same character
-codes. */)
+codes.
+This is similar to (decode-coding-string STRING 'binary) */)
(string)
Lisp_Object string;
{
DEFUN ("memq", Fmemq, Smemq, 2, 2, 0,
doc: /* Return non-nil if ELT is an element of LIST.
-Comparison done with EQ. The value is actually the tail of LIST
+Comparison done with `eq'. The value is actually the tail of LIST
whose car is ELT. */)
(elt, list)
Lisp_Object elt, list;
DEFUN ("sort", Fsort, Ssort, 2, 2, 0,
doc: /* Sort LIST, stably, comparing elements using PREDICATE.
Returns the sorted list. LIST is modified by side effects.
-PREDICATE is called with two elements of LIST, and should return t
+PREDICATE is called with two elements of LIST, and should return non-nil
if the first element is "less" than the second. */)
(list, predicate)
Lisp_Object list, predicate;
}
\f
+#if 0 /* Unsafe version. */
DEFUN ("plist-get", Fplist_get, Splist_get, 2, 2, 0,
doc: /* Extract a value from a property list.
PLIST is a property list, which is a list of the form
return Qnil;
}
+#endif
+
+/* This does not check for quits. That is safe since it must terminate. */
+
+DEFUN ("plist-get", Fplist_get, Splist_get, 2, 2, 0,
+ doc: /* Extract a value from a property list.
+PLIST is a property list, which is a list of the form
+\(PROP1 VALUE1 PROP2 VALUE2...). This function returns the value
+corresponding to the given PROP, or nil if PROP is not one of the
+properties on the list. This function never signals an error. */)
+ (plist, prop)
+ Lisp_Object plist;
+ Lisp_Object prop;
+{
+ Lisp_Object tail, halftail;
+
+ /* halftail is used to detect circular lists. */
+ tail = halftail = plist;
+ while (CONSP (tail) && CONSP (XCDR (tail)))
+ {
+ if (EQ (prop, XCAR (tail)))
+ return XCAR (XCDR (tail));
+
+ tail = XCDR (XCDR (tail));
+ halftail = XCDR (halftail);
+ if (EQ (tail, halftail))
+ break;
+ }
+
+ return Qnil;
+}
DEFUN ("get", Fget, Sget, 2, 2, 0,
doc: /* Return the value of SYMBOL's PROPNAME property.
return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
}
\f
+static Lisp_Object
+char_table_range (table, from, to, defalt)
+ Lisp_Object table;
+ int from, to;
+ Lisp_Object defalt;
+{
+ Lisp_Object val;
+
+ if (! NILP (XCHAR_TABLE (table)->defalt))
+ defalt = XCHAR_TABLE (table)->defalt;
+ val = XCHAR_TABLE (table)->contents[from];
+ if (SUB_CHAR_TABLE_P (val))
+ val = char_table_range (val, 32, 127, defalt);
+ else if (NILP (val))
+ val = defalt;
+ for (from++; from <= to; from++)
+ {
+ Lisp_Object this_val;
+
+ this_val = XCHAR_TABLE (table)->contents[from];
+ if (SUB_CHAR_TABLE_P (this_val))
+ this_val = char_table_range (this_val, 32, 127, defalt);
+ else if (NILP (this_val))
+ this_val = defalt;
+ if (! EQ (val, this_val))
+ error ("Characters in the range have inconsistent values");
+ }
+ return val;
+}
+
+
DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
2, 2, 0,
doc: /* Return the value in CHAR-TABLE for a range of characters RANGE.
-RANGE should be nil (for the default value)
+RANGE should be nil (for the default value),
a vector which identifies a character set or a row of a character set,
-a character set name, or a character code. */)
+a character set name, or a character code.
+If the characters in the specified range have different values,
+an error is signaled.
+
+Note that this function doesn't check the parent of CHAR-TABLE. */)
(char_table, range)
Lisp_Object char_table, range;
{
+ int charset_id, c1 = 0, c2 = 0;
+ int size, i;
+ Lisp_Object ch, val, current_default;
+
CHECK_CHAR_TABLE (char_table);
if (EQ (range, Qnil))
return XCHAR_TABLE (char_table)->defalt;
- else if (INTEGERP (range))
- return Faref (char_table, range);
+ if (INTEGERP (range))
+ {
+ int c = XINT (range);
+ if (! CHAR_VALID_P (c, 0))
+ error ("Invalid character code: %d", c);
+ ch = range;
+ SPLIT_CHAR (c, charset_id, c1, c2);
+ }
else if (SYMBOLP (range))
{
Lisp_Object charset_info;
charset_info = Fget (range, Qcharset);
CHECK_VECTOR (charset_info);
-
- return Faref (char_table,
- make_number (XINT (XVECTOR (charset_info)->contents[0])
- + 128));
+ charset_id = XINT (XVECTOR (charset_info)->contents[0]);
+ ch = Fmake_char_internal (make_number (charset_id),
+ make_number (0), make_number (0));
}
else if (VECTORP (range))
{
- if (XVECTOR (range)->size == 1)
- return Faref (char_table,
- make_number (XINT (XVECTOR (range)->contents[0]) + 128));
- else
+ size = ASIZE (range);
+ if (size == 0)
+ args_out_of_range (range, make_number (0));
+ CHECK_NUMBER (AREF (range, 0));
+ charset_id = XINT (AREF (range, 0));
+ if (size > 1)
{
- int size = XVECTOR (range)->size;
- Lisp_Object *val = XVECTOR (range)->contents;
- Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
- size <= 1 ? Qnil : val[1],
- size <= 2 ? Qnil : val[2]);
- return Faref (char_table, ch);
+ CHECK_NUMBER (AREF (range, 1));
+ c1 = XINT (AREF (range, 1));
+ if (size > 2)
+ {
+ CHECK_NUMBER (AREF (range, 2));
+ c2 = XINT (AREF (range, 2));
+ }
}
+
+ /* This checks if charset_id, c0, and c1 are all valid or not. */
+ ch = Fmake_char_internal (make_number (charset_id),
+ make_number (c1), make_number (c2));
}
else
error ("Invalid RANGE argument to `char-table-range'");
- return Qt;
+
+ if (c1 > 0 && (CHARSET_DIMENSION (charset_id) == 1 || c2 > 0))
+ {
+ /* Fully specified character. */
+ Lisp_Object parent = XCHAR_TABLE (char_table)->parent;
+
+ XCHAR_TABLE (char_table)->parent = Qnil;
+ val = Faref (char_table, ch);
+ XCHAR_TABLE (char_table)->parent = parent;
+ return val;
+ }
+
+ current_default = XCHAR_TABLE (char_table)->defalt;
+ if (charset_id == CHARSET_ASCII
+ || charset_id == CHARSET_8_BIT_CONTROL
+ || charset_id == CHARSET_8_BIT_GRAPHIC)
+ {
+ int from, to, defalt;
+
+ if (charset_id == CHARSET_ASCII)
+ from = 0, to = 127, defalt = CHAR_TABLE_DEFAULT_SLOT_ASCII;
+ else if (charset_id == CHARSET_8_BIT_CONTROL)
+ from = 128, to = 159, defalt = CHAR_TABLE_DEFAULT_SLOT_8_BIT_CONTROL;
+ else
+ from = 160, to = 255, defalt = CHAR_TABLE_DEFAULT_SLOT_8_BIT_GRAPHIC;
+ if (! NILP (XCHAR_TABLE (char_table)->contents[defalt]))
+ current_default = XCHAR_TABLE (char_table)->contents[defalt];
+ return char_table_range (char_table, from, to, current_default);
+ }
+
+ val = XCHAR_TABLE (char_table)->contents[128 + charset_id];
+ if (! SUB_CHAR_TABLE_P (val))
+ return (NILP (val) ? current_default : val);
+ if (! NILP (XCHAR_TABLE (val)->defalt))
+ current_default = XCHAR_TABLE (val)->defalt;
+ if (c1 == 0)
+ return char_table_range (val, 32, 127, current_default);
+ val = XCHAR_TABLE (val)->contents[c1];
+ if (! SUB_CHAR_TABLE_P (val))
+ return (NILP (val) ? current_default : val);
+ if (! NILP (XCHAR_TABLE (val)->defalt))
+ current_default = XCHAR_TABLE (val)->defalt;
+ return char_table_range (val, 32, 127, current_default);
}
DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
if (EQ (range, Qt))
for (i = 0; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
- XCHAR_TABLE (char_table)->contents[i] = value;
+ {
+ /* Don't set these special slots used for default values of
+ ascii, eight-bit-control, and eight-bit-graphic. */
+ if (i != CHAR_TABLE_DEFAULT_SLOT_ASCII
+ && i != CHAR_TABLE_DEFAULT_SLOT_8_BIT_CONTROL
+ && i != CHAR_TABLE_DEFAULT_SLOT_8_BIT_GRAPHIC)
+ XCHAR_TABLE (char_table)->contents[i] = value;
+ }
else if (EQ (range, Qnil))
XCHAR_TABLE (char_table)->defalt = value;
else if (SYMBOLP (range))
Faset (char_table, range, value);
else if (VECTORP (range))
{
- if (XVECTOR (range)->size == 1)
- return Faset (char_table,
- make_number (XINT (XVECTOR (range)->contents[0]) + 128),
- value);
- else
- {
- int size = XVECTOR (range)->size;
- Lisp_Object *val = XVECTOR (range)->contents;
- Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
- size <= 1 ? Qnil : val[1],
- size <= 2 ? Qnil : val[2]);
- return Faset (char_table, ch, value);
- }
+ int size = XVECTOR (range)->size;
+ Lisp_Object *val = XVECTOR (range)->contents;
+ Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
+ size <= 1 ? Qnil : val[1],
+ size <= 2 ? Qnil : val[2]);
+ Faset (char_table, ch, value);
}
else
error ("Invalid RANGE argument to `set-char-table-range'");
Sset_char_table_default, 3, 3, 0,
doc: /* Set the default value in CHAR-TABLE for generic character CH to VALUE.
The generic character specifies the group of characters.
+If CH is a normal character, set the default value for a group of
+characters to which CH belongs.
See also the documentation of `make-char'. */)
(char_table, ch, value)
Lisp_Object char_table, ch, value;
if (! CHARSET_VALID_P (charset))
invalid_character (c);
- if (charset == CHARSET_ASCII)
- return (XCHAR_TABLE (char_table)->defalt = value);
+ if (SINGLE_BYTE_CHAR_P (c))
+ {
+ /* We use special slots for the default values of single byte
+ characters. */
+ int default_slot
+ = (c < 0x80 ? CHAR_TABLE_DEFAULT_SLOT_ASCII
+ : c < 0xA0 ? CHAR_TABLE_DEFAULT_SLOT_8_BIT_CONTROL
+ : CHAR_TABLE_DEFAULT_SLOT_8_BIT_GRAPHIC);
+
+ return (XCHAR_TABLE (char_table)->contents[default_slot] = value);
+ }
/* Even if C is not a generic char, we had better behave as if a
generic char is specified. */
if (!CHARSET_DEFINED_P (charset) || CHARSET_DIMENSION (charset) == 1)
code1 = 0;
temp = XCHAR_TABLE (char_table)->contents[charset + 128];
+ if (! SUB_CHAR_TABLE_P (temp))
+ {
+ temp = make_sub_char_table (temp);
+ XCHAR_TABLE (char_table)->contents[charset + 128] = temp;
+ }
if (!code1)
{
- if (SUB_CHAR_TABLE_P (temp))
- XCHAR_TABLE (temp)->defalt = value;
- else
- XCHAR_TABLE (char_table)->contents[charset + 128] = value;
+ XCHAR_TABLE (temp)->defalt = value;
return value;
}
- if (SUB_CHAR_TABLE_P (temp))
- char_table = temp;
- else
- char_table = (XCHAR_TABLE (char_table)->contents[charset + 128]
- = make_sub_char_table (temp));
+ char_table = temp;
temp = XCHAR_TABLE (char_table)->contents[code1];
if (SUB_CHAR_TABLE_P (temp))
XCHAR_TABLE (temp)->defalt = value;
int depth;
{
int i, to;
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+
+ GCPRO4 (arg, table, subtable, function);
if (depth == 0)
{
#if 0 /* If the char table has entries for higher characters,
we should report them. */
if (NILP (current_buffer->enable_multibyte_characters))
- return;
+ {
+ UNGCPRO;
+ return;
+ }
#endif
to = CHAR_TABLE_ORDINARY_SLOTS;
}
call2 (function, make_number (c), elt);
}
}
+ UNGCPRO;
}
static void void_call2 P_ ((Lisp_Object a, Lisp_Object b, Lisp_Object c));
else /* Must be a list, since Flength did not get an error */
{
tail = seq;
- for (i = 0; i < leni; i++)
+ for (i = 0; i < leni && CONSP (tail); i++)
{
- dummy = call1 (fn, Fcar (tail));
+ dummy = call1 (fn, XCAR (tail));
if (vals)
vals[i] = dummy;
tail = XCDR (tail);
mapcar1 (leni, args, function, sequence);
UNGCPRO;
- for (i = leni - 1; i >= 0; i--)
+ for (i = leni - 1; i > 0; i--)
args[i + i] = args[i];
for (i = 1; i < nargs; i += 2)
args[i] = separator;
ret = Fconcat (nargs, args);
- SAFE_FREE_LISP (nargs);
+ SAFE_FREE ();
return ret;
}
mapcar1 (leni, args, function, sequence);
ret = Flist (leni, args);
- SAFE_FREE_LISP (leni);
+ SAFE_FREE ();
return ret;
}
Fcons (Fcons (build_string ("No"), Qnil),
Qnil));
menu = Fcons (prompt, pane);
- obj = Fx_popup_dialog (Qt, menu);
+ obj = Fx_popup_dialog (Qt, menu, Qnil);
answer = !NILP (obj);
break;
}
Qnil));
GCPRO1 (pane);
menu = Fcons (prompt, pane);
- obj = Fx_popup_dialog (Qt, menu);
+ obj = Fx_popup_dialog (Qt, menu, Qnil);
UNGCPRO;
return obj;
}
{
ans = Fdowncase (Fread_from_minibuffer (prompt, Qnil, Qnil, Qnil,
Qyes_or_no_p_history, Qnil,
- Qnil));
+ Qnil, Qnil));
if (SCHARS (ans) == 3 && !strcmp (SDATA (ans), "yes"))
{
UNGCPRO;
CHECK_SYMBOL (feature);
+ /* Record the presence of `require' in this file
+ even if the feature specified is already loaded.
+ But not more than once in any file,
+ and not when we aren't loading a file. */
+ if (load_in_progress)
+ {
+ tem = Fcons (Qrequire, feature);
+ if (NILP (Fmember (tem, Vcurrent_load_list)))
+ LOADHIST_ATTACH (tem);
+ }
tem = Fmemq (feature, Vfeatures);
if (NILP (tem))
int count = SPECPDL_INDEX ();
int nesting = 0;
- LOADHIST_ATTACH (Fcons (Qrequire, feature));
-
/* This is to make sure that loadup.el gives a clear picture
of what files are preloaded and when. */
if (! NILP (Vpurify_flag))
if (encoded_length < 0)
{
/* The encoding wasn't possible. */
- SAFE_FREE (allength);
+ SAFE_FREE ();
error ("Multibyte character in data for base64 encoding");
}
and delete the old. (Insert first in order to preserve markers.) */
SET_PT_BOTH (XFASTINT (beg), ibeg);
insert (encoded, encoded_length);
- SAFE_FREE (allength);
+ SAFE_FREE ();
del_range_byte (ibeg + encoded_length, iend + encoded_length, 1);
/* If point was outside of the region, restore it exactly; else just
if (encoded_length < 0)
{
/* The encoding wasn't possible. */
- SAFE_FREE (allength);
+ SAFE_FREE ();
error ("Multibyte character in data for base64 encoding");
}
encoded_string = make_unibyte_string (encoded, encoded_length);
- SAFE_FREE (allength);
+ SAFE_FREE ();
return encoded_string;
}
if (decoded_length < 0)
{
/* The decoding wasn't possible. */
- SAFE_FREE (allength);
+ SAFE_FREE ();
error ("Invalid base64 data");
}
and delete the old. (Insert first in order to preserve markers.) */
TEMP_SET_PT_BOTH (XFASTINT (beg), ibeg);
insert_1_both (decoded, inserted_chars, decoded_length, 0, 1, 0);
- SAFE_FREE (allength);
+ SAFE_FREE ();
/* Delete the original text. */
del_range_both (PT, PT_BYTE, XFASTINT (end) + inserted_chars,
else
decoded_string = Qnil;
- SAFE_FREE (length);
+ SAFE_FREE ();
if (!STRINGP (decoded_string))
error ("Invalid base64 data");
h->count = make_number (XFASTINT (h->count) - 1);
}
+ else
+ {
+ prev = idx;
+ }
}
else
{
hash = XUINT (obj);
break;
- case Lisp_Symbol:
- hash = sxhash_string (SDATA (SYMBOL_NAME (obj)),
- SCHARS (SYMBOL_NAME (obj)));
- break;
-
case Lisp_Misc:
hash = XUINT (obj);
break;
+ case Lisp_Symbol:
+ obj = SYMBOL_NAME (obj);
+ /* Fall through. */
+
case Lisp_String:
hash = sxhash_string (SDATA (obj), SCHARS (obj));
break;
DEFUN ("maphash", Fmaphash, Smaphash, 2, 2, 0,
doc: /* Call FUNCTION for all entries in hash table TABLE.
-FUNCTION is called with 2 arguments KEY and VALUE. */)
+FUNCTION is called with two arguments, KEY and VALUE. */)
(function, table)
Lisp_Object function, table;
{