aboutsummaryrefslogtreecommitdiffstats
path: root/src/fns.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fns.c')
-rw-r--r--src/fns.c268
1 files changed, 239 insertions, 29 deletions
diff --git a/src/fns.c b/src/fns.c
index 33c02598359..e891fdbf1d5 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -24,6 +24,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
24#include <time.h> 24#include <time.h>
25 25
26#include <intprops.h> 26#include <intprops.h>
27#include <vla.h>
27 28
28#include "lisp.h" 29#include "lisp.h"
29#include "commands.h" 30#include "commands.h"
@@ -41,6 +42,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
41#endif 42#endif
42 43
43Lisp_Object Qstring_lessp; 44Lisp_Object Qstring_lessp;
45static Lisp_Object Qstring_collate_lessp, Qstring_collate_equalp;
44static Lisp_Object Qprovide, Qrequire; 46static Lisp_Object Qprovide, Qrequire;
45static Lisp_Object Qyes_or_no_p_history; 47static Lisp_Object Qyes_or_no_p_history;
46Lisp_Object Qcursor_in_echo_area; 48Lisp_Object Qcursor_in_echo_area;
@@ -49,6 +51,8 @@ static Lisp_Object Qcodeset, Qdays, Qmonths, Qpaper;
49 51
50static Lisp_Object Qmd5, Qsha1, Qsha224, Qsha256, Qsha384, Qsha512; 52static Lisp_Object Qmd5, Qsha1, Qsha224, Qsha256, Qsha384, Qsha512;
51 53
54static void sort_vector_copy (Lisp_Object, ptrdiff_t,
55 Lisp_Object [restrict], Lisp_Object [restrict]);
52static bool internal_equal (Lisp_Object, Lisp_Object, int, bool, Lisp_Object); 56static bool internal_equal (Lisp_Object, Lisp_Object, int, bool, Lisp_Object);
53 57
54DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0, 58DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
@@ -343,6 +347,100 @@ Symbols are also allowed; their print names are used instead. */)
343 } 347 }
344 return i1 < SCHARS (s2) ? Qt : Qnil; 348 return i1 < SCHARS (s2) ? Qt : Qnil;
345} 349}
350
351DEFUN ("string-collate-lessp", Fstring_collate_lessp, Sstring_collate_lessp, 2, 4, 0,
352 doc: /* Return t if first arg string is less than second in collation order.
353Symbols are also allowed; their print names are used instead.
354
355This function obeys the conventions for collation order in your
356locale settings. For example, punctuation and whitespace characters
357might be considered less significant for sorting:
358
359\(sort '\("11" "12" "1 1" "1 2" "1.1" "1.2") 'string-collate-lessp)
360 => \("11" "1 1" "1.1" "12" "1 2" "1.2")
361
362The optional argument LOCALE, a string, overrides the setting of your
363current locale identifier for collation. The value is system
364dependent; a LOCALE \"en_US.UTF-8\" is applicable on POSIX systems,
365while it would be, e.g., \"enu_USA.1252\" on MS-Windows systems.
366
367If IGNORE-CASE is non-nil, characters are converted to lower-case
368before comparing them.
369
370To emulate Unicode-compliant collation on MS-Windows systems,
371bind `w32-collate-ignore-punctuation' to a non-nil value, since
372the codeset part of the locale cannot be \"UTF-8\" on MS-Windows.
373
374If your system does not support a locale environment, this function
375behaves like `string-lessp'. */)
376 (Lisp_Object s1, Lisp_Object s2, Lisp_Object locale, Lisp_Object ignore_case)
377{
378#if defined __STDC_ISO_10646__ || defined WINDOWSNT
379 /* Check parameters. */
380 if (SYMBOLP (s1))
381 s1 = SYMBOL_NAME (s1);
382 if (SYMBOLP (s2))
383 s2 = SYMBOL_NAME (s2);
384 CHECK_STRING (s1);
385 CHECK_STRING (s2);
386 if (!NILP (locale))
387 CHECK_STRING (locale);
388
389 return (str_collate (s1, s2, locale, ignore_case) < 0) ? Qt : Qnil;
390
391#else /* !__STDC_ISO_10646__, !WINDOWSNT */
392 return Fstring_lessp (s1, s2);
393#endif /* !__STDC_ISO_10646__, !WINDOWSNT */
394}
395
396DEFUN ("string-collate-equalp", Fstring_collate_equalp, Sstring_collate_equalp, 2, 4, 0,
397 doc: /* Return t if two strings have identical contents.
398Symbols are also allowed; their print names are used instead.
399
400This function obeys the conventions for collation order in your locale
401settings. For example, characters with different coding points but
402the same meaning might be considered as equal, like different grave
403accent Unicode characters:
404
405\(string-collate-equalp \(string ?\\uFF40) \(string ?\\u1FEF))
406 => t
407
408The optional argument LOCALE, a string, overrides the setting of your
409current locale identifier for collation. The value is system
410dependent; a LOCALE \"en_US.UTF-8\" is applicable on POSIX systems,
411while it would be \"enu_USA.1252\" on MS Windows systems.
412
413If IGNORE-CASE is non-nil, characters are converted to lower-case
414before comparing them.
415
416To emulate Unicode-compliant collation on MS-Windows systems,
417bind `w32-collate-ignore-punctuation' to a non-nil value, since
418the codeset part of the locale cannot be \"UTF-8\" on MS-Windows.
419
420If your system does not support a locale environment, this function
421behaves like `string-equal'.
422
423Do NOT use this function to compare file names for equality, only
424for sorting them. */)
425 (Lisp_Object s1, Lisp_Object s2, Lisp_Object locale, Lisp_Object ignore_case)
426{
427#if defined __STDC_ISO_10646__ || defined WINDOWSNT
428 /* Check parameters. */
429 if (SYMBOLP (s1))
430 s1 = SYMBOL_NAME (s1);
431 if (SYMBOLP (s2))
432 s2 = SYMBOL_NAME (s2);
433 CHECK_STRING (s1);
434 CHECK_STRING (s2);
435 if (!NILP (locale))
436 CHECK_STRING (locale);
437
438 return (str_collate (s1, s2, locale, ignore_case) == 0) ? Qt : Qnil;
439
440#else /* !__STDC_ISO_10646__, !WINDOWSNT */
441 return Fstring_equal (s1, s2);
442#endif /* !__STDC_ISO_10646__, !WINDOWSNT */
443}
346 444
347static Lisp_Object concat (ptrdiff_t nargs, Lisp_Object *args, 445static Lisp_Object concat (ptrdiff_t nargs, Lisp_Object *args,
348 enum Lisp_Type target_type, bool last_special); 446 enum Lisp_Type target_type, bool last_special);
@@ -1773,13 +1871,12 @@ See also the function `nreverse', which is used more often. */)
1773 wrong_type_argument (Qsequencep, seq); 1871 wrong_type_argument (Qsequencep, seq);
1774 return new; 1872 return new;
1775} 1873}
1776 1874
1777DEFUN ("sort", Fsort, Ssort, 2, 2, 0, 1875/* Sort LIST using PREDICATE, preserving original order of elements
1778 doc: /* Sort LIST, stably, comparing elements using PREDICATE. 1876 considered as equal. */
1779Returns the sorted list. LIST is modified by side effects. 1877
1780PREDICATE is called with two elements of LIST, and should return non-nil 1878static Lisp_Object
1781if the first element should sort before the second. */) 1879sort_list (Lisp_Object list, Lisp_Object predicate)
1782 (Lisp_Object list, Lisp_Object predicate)
1783{ 1880{
1784 Lisp_Object front, back; 1881 Lisp_Object front, back;
1785 register Lisp_Object len, tem; 1882 register Lisp_Object len, tem;
@@ -1804,6 +1901,126 @@ if the first element should sort before the second. */)
1804 return merge (front, back, predicate); 1901 return merge (front, back, predicate);
1805} 1902}
1806 1903
1904/* Using PRED to compare, return whether A and B are in order.
1905 Compare stably when A appeared before B in the input. */
1906static bool
1907inorder (Lisp_Object pred, Lisp_Object a, Lisp_Object b)
1908{
1909 return NILP (call2 (pred, b, a));
1910}
1911
1912/* Using PRED to compare, merge from ALEN-length A and BLEN-length B
1913 into DEST. Argument arrays must be nonempty and must not overlap,
1914 except that B might be the last part of DEST. */
1915static void
1916merge_vectors (Lisp_Object pred,
1917 ptrdiff_t alen, Lisp_Object const a[restrict VLA_ELEMS (alen)],
1918 ptrdiff_t blen, Lisp_Object const b[VLA_ELEMS (blen)],
1919 Lisp_Object dest[VLA_ELEMS (alen + blen)])
1920{
1921 eassume (0 < alen && 0 < blen);
1922 Lisp_Object const *alim = a + alen;
1923 Lisp_Object const *blim = b + blen;
1924
1925 while (true)
1926 {
1927 if (inorder (pred, a[0], b[0]))
1928 {
1929 *dest++ = *a++;
1930 if (a == alim)
1931 {
1932 if (dest != b)
1933 memcpy (dest, b, (blim - b) * sizeof *dest);
1934 return;
1935 }
1936 }
1937 else
1938 {
1939 *dest++ = *b++;
1940 if (b == blim)
1941 {
1942 memcpy (dest, a, (alim - a) * sizeof *dest);
1943 return;
1944 }
1945 }
1946 }
1947}
1948
1949/* Using PRED to compare, sort LEN-length VEC in place, using TMP for
1950 temporary storage. LEN must be at least 2. */
1951static void
1952sort_vector_inplace (Lisp_Object pred, ptrdiff_t len,
1953 Lisp_Object vec[restrict VLA_ELEMS (len)],
1954 Lisp_Object tmp[restrict VLA_ELEMS (len >> 1)])
1955{
1956 eassume (2 <= len);
1957 ptrdiff_t halflen = len >> 1;
1958 sort_vector_copy (pred, halflen, vec, tmp);
1959 if (1 < len - halflen)
1960 sort_vector_inplace (pred, len - halflen, vec + halflen, vec);
1961 merge_vectors (pred, halflen, tmp, len - halflen, vec + halflen, vec);
1962}
1963
1964/* Using PRED to compare, sort from LEN-length SRC into DST.
1965 Len must be positive. */
1966static void
1967sort_vector_copy (Lisp_Object pred, ptrdiff_t len,
1968 Lisp_Object src[restrict VLA_ELEMS (len)],
1969 Lisp_Object dest[restrict VLA_ELEMS (len)])
1970{
1971 eassume (0 < len);
1972 ptrdiff_t halflen = len >> 1;
1973 if (halflen < 1)
1974 dest[0] = src[0];
1975 else
1976 {
1977 if (1 < halflen)
1978 sort_vector_inplace (pred, halflen, src, dest);
1979 if (1 < len - halflen)
1980 sort_vector_inplace (pred, len - halflen, src + halflen, dest);
1981 merge_vectors (pred, halflen, src, len - halflen, src + halflen, dest);
1982 }
1983}
1984
1985/* Sort VECTOR in place using PREDICATE, preserving original order of
1986 elements considered as equal. */
1987
1988static void
1989sort_vector (Lisp_Object vector, Lisp_Object predicate)
1990{
1991 ptrdiff_t len = ASIZE (vector);
1992 if (len < 2)
1993 return;
1994 ptrdiff_t halflen = len >> 1;
1995 Lisp_Object *tmp;
1996 struct gcpro gcpro1, gcpro2;
1997 GCPRO2 (vector, predicate);
1998 USE_SAFE_ALLOCA;
1999 SAFE_ALLOCA_LISP (tmp, halflen);
2000 for (ptrdiff_t i = 0; i < halflen; i++)
2001 tmp[i] = make_number (0);
2002 sort_vector_inplace (predicate, len, XVECTOR (vector)->contents, tmp);
2003 SAFE_FREE ();
2004 UNGCPRO;
2005}
2006
2007DEFUN ("sort", Fsort, Ssort, 2, 2, 0,
2008 doc: /* Sort SEQ, stably, comparing elements using PREDICATE.
2009Returns the sorted sequence. SEQ should be a list or vector. SEQ is
2010modified by side effects. PREDICATE is called with two elements of
2011SEQ, and should return non-nil if the first element should sort before
2012the second. */)
2013 (Lisp_Object seq, Lisp_Object predicate)
2014{
2015 if (CONSP (seq))
2016 seq = sort_list (seq, predicate);
2017 else if (VECTORP (seq))
2018 sort_vector (seq, predicate);
2019 else if (!NILP (seq))
2020 wrong_type_argument (Qsequencep, seq);
2021 return seq;
2022}
2023
1807Lisp_Object 2024Lisp_Object
1808merge (Lisp_Object org_l1, Lisp_Object org_l2, Lisp_Object pred) 2025merge (Lisp_Object org_l1, Lisp_Object org_l2, Lisp_Object pred)
1809{ 2026{
@@ -1841,8 +2058,7 @@ merge (Lisp_Object org_l1, Lisp_Object org_l2, Lisp_Object pred)
1841 Fsetcdr (tail, l1); 2058 Fsetcdr (tail, l1);
1842 return value; 2059 return value;
1843 } 2060 }
1844 tem = call2 (pred, Fcar (l2), Fcar (l1)); 2061 if (inorder (pred, Fcar (l1), Fcar (l2)))
1845 if (NILP (tem))
1846 { 2062 {
1847 tem = l1; 2063 tem = l1;
1848 l1 = Fcdr (l1); 2064 l1 = Fcdr (l1);
@@ -2490,8 +2706,7 @@ If dialog boxes are supported, a dialog box will be used
2490if `last-nonmenu-event' is nil, and `use-dialog-box' is non-nil. */) 2706if `last-nonmenu-event' is nil, and `use-dialog-box' is non-nil. */)
2491 (Lisp_Object prompt) 2707 (Lisp_Object prompt)
2492{ 2708{
2493 register Lisp_Object ans; 2709 Lisp_Object ans;
2494 Lisp_Object args[2];
2495 struct gcpro gcpro1; 2710 struct gcpro gcpro1;
2496 2711
2497 CHECK_STRING (prompt); 2712 CHECK_STRING (prompt);
@@ -2510,10 +2725,8 @@ if `last-nonmenu-event' is nil, and `use-dialog-box' is non-nil. */)
2510 return obj; 2725 return obj;
2511 } 2726 }
2512 2727
2513 args[0] = prompt; 2728 AUTO_STRING (yes_or_no, "(yes or no) ");
2514 args[1] = build_string ("(yes or no) "); 2729 prompt = Fconcat (2, (Lisp_Object []) {prompt, yes_or_no});
2515 prompt = Fconcat (2, args);
2516
2517 GCPRO1 (prompt); 2730 GCPRO1 (prompt);
2518 2731
2519 while (1) 2732 while (1)
@@ -3071,7 +3284,6 @@ into shorter lines. */)
3071 if (encoded_length < 0) 3284 if (encoded_length < 0)
3072 { 3285 {
3073 /* The encoding wasn't possible. */ 3286 /* The encoding wasn't possible. */
3074 SAFE_FREE ();
3075 error ("Multibyte character in data for base64 encoding"); 3287 error ("Multibyte character in data for base64 encoding");
3076 } 3288 }
3077 3289
@@ -3216,7 +3428,6 @@ If the region can't be decoded, signal an error and don't modify the buffer. */
3216 if (decoded_length < 0) 3428 if (decoded_length < 0)
3217 { 3429 {
3218 /* The decoding wasn't possible. */ 3430 /* The decoding wasn't possible. */
3219 SAFE_FREE ();
3220 error ("Invalid base64 data"); 3431 error ("Invalid base64 data");
3221 } 3432 }
3222 3433
@@ -3784,12 +3995,9 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h)
3784#ifdef ENABLE_CHECKING 3995#ifdef ENABLE_CHECKING
3785 if (HASH_TABLE_P (Vpurify_flag) 3996 if (HASH_TABLE_P (Vpurify_flag)
3786 && XHASH_TABLE (Vpurify_flag) == h) 3997 && XHASH_TABLE (Vpurify_flag) == h)
3787 { 3998 Fmessage (2, ((Lisp_Object [])
3788 Lisp_Object args[2]; 3999 { build_string ("Growing hash table to: %d"),
3789 args[0] = build_string ("Growing hash table to: %d"); 4000 make_number (new_size) }));
3790 args[1] = make_number (new_size);
3791 Fmessage (2, args);
3792 }
3793#endif 4001#endif
3794 4002
3795 set_hash_key_and_value (h, larger_vector (h->key_and_value, 4003 set_hash_key_and_value (h, larger_vector (h->key_and_value,
@@ -4269,13 +4477,10 @@ sxhash (Lisp_Object obj, int depth)
4269 break; 4477 break;
4270 4478
4271 case Lisp_Misc: 4479 case Lisp_Misc:
4480 case Lisp_Symbol:
4272 hash = XHASH (obj); 4481 hash = XHASH (obj);
4273 break; 4482 break;
4274 4483
4275 case Lisp_Symbol:
4276 obj = SYMBOL_NAME (obj);
4277 /* Fall through. */
4278
4279 case Lisp_String: 4484 case Lisp_String:
4280 hash = sxhash_string (SSDATA (obj), SBYTES (obj)); 4485 hash = sxhash_string (SSDATA (obj), SBYTES (obj));
4281 break; 4486 break;
@@ -4363,12 +4568,12 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */)
4363{ 4568{
4364 Lisp_Object test, size, rehash_size, rehash_threshold, weak; 4569 Lisp_Object test, size, rehash_size, rehash_threshold, weak;
4365 struct hash_table_test testdesc; 4570 struct hash_table_test testdesc;
4366 char *used;
4367 ptrdiff_t i; 4571 ptrdiff_t i;
4572 USE_SAFE_ALLOCA;
4368 4573
4369 /* The vector `used' is used to keep track of arguments that 4574 /* The vector `used' is used to keep track of arguments that
4370 have been consumed. */ 4575 have been consumed. */
4371 used = alloca (nargs * sizeof *used); 4576 char *used = SAFE_ALLOCA (nargs * sizeof *used);
4372 memset (used, 0, nargs * sizeof *used); 4577 memset (used, 0, nargs * sizeof *used);
4373 4578
4374 /* See if there's a `:test TEST' among the arguments. */ 4579 /* See if there's a `:test TEST' among the arguments. */
@@ -4435,6 +4640,7 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */)
4435 if (!used[i]) 4640 if (!used[i])
4436 signal_error ("Invalid argument list", args[i]); 4641 signal_error ("Invalid argument list", args[i]);
4437 4642
4643 SAFE_FREE ();
4438 return make_hash_table (testdesc, size, rehash_size, rehash_threshold, weak); 4644 return make_hash_table (testdesc, size, rehash_size, rehash_threshold, weak);
4439} 4645}
4440 4646
@@ -4919,6 +5125,8 @@ syms_of_fns (void)
4919 defsubr (&Sdefine_hash_table_test); 5125 defsubr (&Sdefine_hash_table_test);
4920 5126
4921 DEFSYM (Qstring_lessp, "string-lessp"); 5127 DEFSYM (Qstring_lessp, "string-lessp");
5128 DEFSYM (Qstring_collate_lessp, "string-collate-lessp");
5129 DEFSYM (Qstring_collate_equalp, "string-collate-equalp");
4922 DEFSYM (Qprovide, "provide"); 5130 DEFSYM (Qprovide, "provide");
4923 DEFSYM (Qrequire, "require"); 5131 DEFSYM (Qrequire, "require");
4924 DEFSYM (Qyes_or_no_p_history, "yes-or-no-p-history"); 5132 DEFSYM (Qyes_or_no_p_history, "yes-or-no-p-history");
@@ -4972,6 +5180,8 @@ this variable. */);
4972 defsubr (&Sstring_equal); 5180 defsubr (&Sstring_equal);
4973 defsubr (&Scompare_strings); 5181 defsubr (&Scompare_strings);
4974 defsubr (&Sstring_lessp); 5182 defsubr (&Sstring_lessp);
5183 defsubr (&Sstring_collate_lessp);
5184 defsubr (&Sstring_collate_equalp);
4975 defsubr (&Sappend); 5185 defsubr (&Sappend);
4976 defsubr (&Sconcat); 5186 defsubr (&Sconcat);
4977 defsubr (&Svconcat); 5187 defsubr (&Svconcat);