1 /* Random utility Lisp functions.
2 Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc.
3 Copyright (C) 1995, 1996 Ben Wing.
5 This file is part of SXEmacs
7 SXEmacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 SXEmacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 /* Synched up with: Mule 2.0, FSF 19.30. */
23 /* This file has been Mule-ized. */
25 /* Note: FSF 19.30 has bool vectors. We have bit vectors. */
27 /* Hacked on for Mule by Ben Wing, December 1994, January 1995. */
31 /* Note on some machines this defines `vector' as a typedef,
32 so make sure we don't use that name in this file. */
42 #include "ui/device.h"
43 #include "events/events.h"
47 #include "ui/insdel.h"
49 /* for the categorial views */
52 /* for all the map* funs */
56 /* NOTE: This symbol is also used in lread.c */
57 #define FEATUREP_SYNTAX
59 Lisp_Object Qstring_lessp, Qstring_greaterp;
60 Lisp_Object Qidentity;
62 static int internal_old_equal(Lisp_Object, Lisp_Object, int);
63 Lisp_Object safe_copy_tree(Lisp_Object arg, Lisp_Object vecp, int depth);
64 int internal_equalp(Lisp_Object, Lisp_Object, int);
66 static Lisp_Object mark_bit_vector(Lisp_Object obj)
72 print_bit_vector(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
75 Lisp_Bit_Vector *v = XBIT_VECTOR(obj);
76 size_t len = bit_vector_length(v);
79 if (INTP(Vprint_length))
80 last = min((EMACS_INT) len, XINT(Vprint_length));
81 write_c_string("#*", printcharfun);
82 for (i = 0; i < last; i++) {
83 if (bit_vector_bit(v, i))
84 write_c_string("1", printcharfun);
86 write_c_string("0", printcharfun);
90 write_c_string("...", printcharfun);
93 static int bit_vector_equal(Lisp_Object obj1, Lisp_Object obj2, int depth)
95 Lisp_Bit_Vector *v1 = XBIT_VECTOR(obj1);
96 Lisp_Bit_Vector *v2 = XBIT_VECTOR(obj2);
98 return ((bit_vector_length(v1) == bit_vector_length(v2)) &&
99 !memcmp(v1->bits, v2->bits,
100 BIT_VECTOR_LONG_STORAGE(bit_vector_length(v1)) *
104 static unsigned long bit_vector_hash(Lisp_Object obj, int depth)
106 Lisp_Bit_Vector *v = XBIT_VECTOR(obj);
107 return HASH2(bit_vector_length(v),
109 BIT_VECTOR_LONG_STORAGE(bit_vector_length(v)) *
113 static size_t size_bit_vector(const void *lheader)
115 const Lisp_Bit_Vector *v = (const Lisp_Bit_Vector *) lheader;
116 return FLEXIBLE_ARRAY_STRUCT_SIZEOF(Lisp_Bit_Vector, unsigned long,
118 BIT_VECTOR_LONG_STORAGE
119 (bit_vector_length(v)));
122 static const struct lrecord_description bit_vector_description[] = {
123 {XD_LISP_OBJECT, offsetof(Lisp_Bit_Vector, next)},
127 DEFINE_BASIC_LRECORD_SEQUENCE_IMPLEMENTATION("bit-vector", bit_vector,
128 mark_bit_vector, print_bit_vector,
131 bit_vector_description,
132 size_bit_vector, Lisp_Bit_Vector);
134 DEFUN("identity", Fidentity, 1, 1, 0, /*
135 Return the argument unchanged.
142 extern long get_random(void);
143 extern void seed_random(long arg);
145 DEFUN("random", Frandom, 0, 1, 0, /*
146 Return a pseudo-random number.
147 All integers representable in Lisp are equally likely.
148 On most systems, this is 31 bits' worth.
150 With positive integer argument LIMIT, return random number
151 in interval [0,LIMIT). LIMIT can be a big integer, in which
152 case the range of possible values is extended.
154 With argument t, set the random number seed from the
155 current time and pid.
160 unsigned long denominator;
163 seed_random(getpid() + time(NULL));
164 if (NATNUMP(limit) && !ZEROP(limit)) {
165 /* Try to take our random number from the higher bits of VAL,
166 not the lower, since (says Gentzel) the low bits of `random'
167 are less random than the higher ones. We do this by using the
168 quotient rather than the remainder. At the high end of the RNG
169 it's possible to get a quotient larger than limit; discarding
170 these values eliminates the bias that would otherwise appear
171 when using a large limit. */
172 denominator = ((unsigned long)1 << INT_VALBITS) / XINT(limit);
174 val = get_random() / denominator;
175 while (val >= XINT(limit));
176 } else if (ZEROP(limit)) {
177 return wrong_type_argument(Qpositivep, limit);
178 #if defined HAVE_MPZ && defined WITH_GMP
179 } else if (BIGZP(limit)) {
183 if (bigz_sign(XBIGZ_DATA(limit)) <= 0)
184 return wrong_type_argument(Qpositivep, limit);
188 bigz_random(bz, XBIGZ_DATA(limit));
189 result = ent_mpz_downgrade_maybe(bz);
193 #endif /* HAVE_MPZ */
197 return make_int(val);
200 #if defined(WITH_GMP) && defined(HAVE_MPZ)
201 DEFUN("randomb", Frandomb, 1, 1, 0, /*
202 Return a uniform pseudo-random number in the range [0, 2^LIMIT).
210 CHECK_INTEGER(limit);
212 if (NILP(Fnonnegativep(limit)))
213 return wrong_type_argument(Qnonnegativep, limit);
214 else if (INTP(limit))
216 else if (BIGZP(limit) && bigz_fits_ulong_p(XBIGZ_DATA(limit)))
217 limui = bigz_to_ulong(XBIGZ_DATA(limit));
219 return wrong_type_argument(Qintegerp, limit);
223 mpz_urandomb(bz, random_state, limui);
224 result = make_bigz_bz(bz);
229 #endif /* HAVE_MPZ */
232 /* Random data-structure functions */
234 #ifdef LOSING_BYTECODE
236 /* #### Delete this shit */
238 /* Charcount is a misnomer here as we might be dealing with the
239 length of a vector or list, but emphasizes that we're not dealing
240 with Bytecounts in strings */
241 static Charcount length_with_bytecode_hack(Lisp_Object seq)
243 if (!COMPILED_FUNCTIONP(seq))
244 return XINT(Flength(seq));
246 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION(seq);
248 return (f->flags.interactivep ? COMPILED_INTERACTIVE :
249 f->flags.domainp ? COMPILED_DOMAIN :
255 #endif /* LOSING_BYTECODE */
257 void check_losing_bytecode(const char *function, Lisp_Object seq)
259 if (COMPILED_FUNCTIONP(seq))
262 "As of 20.3, `%s' no longer works with compiled-function objects",
266 DEFUN("length", Flength, 1, 1, 0, /*
267 Return the length of vector, bit vector, list or string SEQUENCE.
272 /* that's whither we have to get */
273 if (LIKELY(!NILP(sequence))) {
274 return make_int(seq_length((seq_t)sequence));
280 if (LIKELY(STRINGP(sequence) ||
284 BIT_VECTORP(sequence))) {
285 return make_int(seq_length(sequence));
286 } else if (NILP(sequence)) {
289 check_losing_bytecode("length", sequence);
290 sequence = wrong_type_argument(Qsequencep, sequence);
295 if (STRINGP(sequence))
296 return make_int(XSTRING_CHAR_LENGTH(sequence));
297 else if (CONSP(sequence)) {
298 return make_int(seq_length(sequence));
299 } else if (VECTORP(sequence))
300 return make_int(seq_length(sequence));
301 else if (DLLISTP(sequence))
302 return make_int(XDLLIST_SIZE(sequence));
303 else if (NILP(sequence))
305 else if (BIT_VECTORP(sequence))
306 return make_int(bit_vector_length(XBIT_VECTOR(sequence)));
308 check_losing_bytecode("length", sequence);
309 sequence = wrong_type_argument(Qsequencep, sequence);
315 DEFUN("safe-length", Fsafe_length, 1, 1, 0, /*
316 Return the length of a list, but avoid error or infinite loop.
317 This function never gets an error. If LIST is not really a list,
318 it returns 0. If LIST is circular, it returns a finite value
319 which is at least the number of distinct elements.
323 Lisp_Object hare, tortoise;
326 for (hare = tortoise = list, len = 0;
327 CONSP(hare) && (!EQ(hare, tortoise) || len == 0);
328 hare = XCDR(hare), len++) {
330 tortoise = XCDR(tortoise);
333 return make_int(len);
336 /*** string functions. ***/
338 DEFUN("string-equal", Fstring_equal, 2, 2, 0, /*
339 Return t if two strings have identical contents.
340 Case is significant. Text properties are ignored.
341 \(Under SXEmacs, `equal' also ignores text properties and extents in
342 strings, but this is not the case under FSF Emacs 19. In FSF Emacs 20
343 `equal' is the same as in SXEmacs, in that respect.)
344 Symbols are also allowed; their print names are used instead.
349 Lisp_String *p1, *p2;
351 if (SYMBOLP(string1))
352 p1 = XSYMBOL(string1)->name;
354 CHECK_STRING(string1);
355 p1 = XSTRING(string1);
358 if (SYMBOLP(string2))
359 p2 = XSYMBOL(string2)->name;
361 CHECK_STRING(string2);
362 p2 = XSTRING(string2);
365 return (((len = string_length(p1)) == string_length(p2)) &&
366 !memcmp(string_data(p1), string_data(p2), len)) ? Qt : Qnil;
369 DEFUN("string-lessp", Fstring_lessp, 2, 2, 0, /*
370 Return t if first arg string is less than second in lexicographic order.
371 If I18N2 support (but not Mule support) was compiled in, ordering is
372 determined by the locale. (Case is significant for the default C locale.)
373 In all other cases, comparison is simply done on a character-by-
374 character basis using the numeric value of a character. (Note that
375 this may not produce particularly meaningful results under Mule if
376 characters from different charsets are being compared.)
378 Symbols are also allowed; their print names are used instead.
380 The reason that the I18N2 locale-specific collation is not used under
381 Mule is that the locale model of internationalization does not handle
382 multiple charsets and thus has no hope of working properly under Mule.
383 What we really should do is create a collation table over all built-in
384 charsets. This is extremely difficult to do from scratch, however.
386 Unicode is a good first step towards solving this problem. In fact,
387 it is quite likely that a collation table exists (or will exist) for
388 Unicode. When Unicode support is added to SXEmacs/Mule, this problem
393 Lisp_String *p1, *p2;
397 if (SYMBOLP(string1))
398 p1 = XSYMBOL(string1)->name;
400 CHECK_STRING(string1);
401 p1 = XSTRING(string1);
404 if (SYMBOLP(string2))
405 p2 = XSYMBOL(string2)->name;
407 CHECK_STRING(string2);
408 p2 = XSTRING(string2);
411 end = string_char_length(p1);
412 len2 = string_char_length(p2);
416 #if defined (I18N2) && !defined (MULE)
417 /* There is no hope of this working under Mule. Even if we converted
418 the data into an external format so that strcoll() processed it
419 properly, it would still not work because strcoll() does not
420 handle multiple locales. This is the fundamental flaw in the
423 Bytecount bcend = charcount_to_bytecount(string_data(p1), end);
424 /* Compare strings using collation order of locale. */
425 /* Need to be tricky to handle embedded nulls. */
427 for (i = 0; i < bcend;
428 i += strlen((char *)string_data(p1) + i) + 1) {
429 int val = strcoll((char *)string_data(p1) + i,
430 (char *)string_data(p2) + i);
437 #else /* not I18N2, or MULE */
439 Bufbyte *ptr1 = string_data(p1);
440 Bufbyte *ptr2 = string_data(p2);
442 /* #### It is not really necessary to do this: We could compare
443 byte-by-byte and still get a reasonable comparison, since this
444 would compare characters with a charset in the same way. With
445 a little rearrangement of the leading bytes, we could make most
446 inter-charset comparisons work out the same, too; even if some
447 don't, this is not a big deal because inter-charset comparisons
448 aren't really well-defined anyway. */
449 for (i = 0; i < end; i++) {
450 if (charptr_emchar(ptr1) != charptr_emchar(ptr2))
451 return charptr_emchar(ptr1) <
452 charptr_emchar(ptr2) ? Qt : Qnil;
457 #endif /* not I18N2, or MULE */
458 /* Can't do i < len2 because then comparison between "foo" and "foo^@"
459 won't work right in I18N2 case */
460 return end < len2 ? Qt : Qnil;
463 DEFUN("string-greaterp", Fstring_greaterp, 2, 2, 0, /*
464 Return t if first arg string is greater than second in lexicographic order.
465 If I18N2 support (but not Mule support) was compiled in, ordering is
466 determined by the locale. (Case is significant for the default C locale.)
467 In all other cases, comparison is simply done on a character-by-
468 character basis using the numeric value of a character. (Note that
469 this may not produce particularly meaningful results under Mule if
470 characters from different charsets are being compared.)
472 Symbols are also allowed; their print names are used instead.
474 The reason that the I18N2 locale-specific collation is not used under
475 Mule is that the locale model of internationalization does not handle
476 multiple charsets and thus has no hope of working properly under Mule.
477 What we really should do is create a collation table over all built-in
478 charsets. This is extremely difficult to do from scratch, however.
480 Unicode is a good first step towards solving this problem. In fact,
481 it is quite likely that a collation table exists (or will exist) for
482 Unicode. When Unicode support is added to SXEmacs/Mule, this problem
487 return Fstring_lessp(string2, string1);
490 DEFUN("string-modified-tick", Fstring_modified_tick, 1, 1, 0, /*
491 Return STRING's tick counter, incremented for each change to the string.
492 Each string has a tick counter which is incremented each time the contents
493 of the string are changed (e.g. with `aset'). It wraps around occasionally.
499 CHECK_STRING(string);
501 if (CONSP(s->plist) && INTP(XCAR(s->plist)))
502 return XCAR(s->plist);
507 void bump_string_modiff(Lisp_Object str)
509 Lisp_String *s = XSTRING(str);
510 Lisp_Object *ptr = &s->plist;
513 /* #### remove the `string-translatable' property from the string,
516 /* skip over extent info if it's there */
517 if (CONSP(*ptr) && EXTENT_INFOP(XCAR(*ptr)))
519 if (CONSP(*ptr) && INTP(XCAR(*ptr)))
520 XSETINT(XCAR(*ptr), 1 + XINT(XCAR(*ptr)));
522 *ptr = Fcons(make_int(1), *ptr);
525 enum concat_target_type { c_cons, c_string, c_vector, c_bit_vector, c_dllist };
526 static Lisp_Object concat(int nargs, Lisp_Object * args,
527 enum concat_target_type target_type,
530 Lisp_Object concat2(Lisp_Object string1, Lisp_Object string2)
535 return concat(2, args, c_string, 0);
539 concat3(Lisp_Object string1, Lisp_Object string2, Lisp_Object string3)
545 return concat(3, args, c_string, 0);
548 Lisp_Object vconcat2(Lisp_Object vec1, Lisp_Object vec2)
553 return concat(2, args, c_vector, 0);
556 Lisp_Object vconcat3(Lisp_Object vec1, Lisp_Object vec2, Lisp_Object vec3)
562 return concat(3, args, c_vector, 0);
565 DEFUN("append", Fappend, 0, MANY, 0, /*
566 Concatenate all the arguments and make the result a list.
567 The result is a list whose elements are the elements of all the arguments.
568 Each argument may be a list, vector, bit vector, or string.
569 The last argument is not copied, just used as the tail of the new list.
572 (int nargs, Lisp_Object * args))
574 return concat(nargs, args, c_cons, 1);
577 DEFUN("concat", Fconcat, 0, MANY, 0, /*
578 Concatenate all the arguments and make the result a string.
579 The result is a string whose elements are the elements of all the arguments.
580 Each argument may be a string or a list or vector of characters.
582 As of XEmacs 21.0, this function does NOT accept individual integers
583 as arguments. Old code that relies on, for example, (concat "foo" 50)
584 returning "foo50" will fail. To fix such code, either apply
585 `int-to-string' to the integer argument, or use `format'.
587 (int nargs, Lisp_Object * args))
589 return concat(nargs, args, c_string, 0);
592 DEFUN("vconcat", Fvconcat, 0, MANY, 0, /*
593 Concatenate all the arguments and make the result a vector.
594 The result is a vector whose elements are the elements of all the arguments.
595 Each argument may be a list, vector, bit vector, or string.
597 (int nargs, Lisp_Object * args))
599 return concat(nargs, args, c_vector, 0);
602 DEFUN("bvconcat", Fbvconcat, 0, MANY, 0, /*
603 Concatenate all the arguments and make the result a bit vector.
604 The result is a bit vector whose elements are the elements of all the
605 arguments. Each argument may be a list, vector, bit vector, or string.
607 (int nargs, Lisp_Object * args))
609 return concat(nargs, args, c_bit_vector, 0);
612 /* Copy a (possibly dotted) list. LIST must be a cons.
613 Can't use concat (1, &alist, c_cons, 0) - doesn't handle dotted lists. */
614 static Lisp_Object copy_list(Lisp_Object list)
616 Lisp_Object list_copy = Fcons(XCAR(list), XCDR(list));
617 Lisp_Object last = list_copy;
618 Lisp_Object hare, tortoise;
621 for (tortoise = hare = XCDR(list), len = 1;
622 CONSP(hare); hare = XCDR(hare), len++) {
623 XCDR(last) = Fcons(XCAR(hare), XCDR(hare));
626 if (len < CIRCULAR_LIST_SUSPICION_LENGTH)
629 tortoise = XCDR(tortoise);
630 if (EQ(tortoise, hare))
631 signal_circular_list_error(list);
637 DEFUN("copy-list", Fcopy_list, 1, 1, 0, /*
638 Return a copy of list LIST, which may be a dotted list.
639 The elements of LIST are not copied; they are shared
648 return copy_list(list);
650 list = wrong_type_argument(Qlistp, list);
654 DEFUN("copy-sequence", Fcopy_sequence, 1, 1, 0, /*
655 Return a copy of list, dllist, vector, bit vector or string SEQUENCE.
656 The elements of a list or vector are not copied; they are shared
657 with the original. SEQUENCE may be a dotted list.
665 return copy_list(sequence);
666 if (DLLISTP(sequence))
667 return Fcopy_dllist(sequence);
668 if (STRINGP(sequence))
669 return concat(1, &sequence, c_string, 0);
670 if (VECTORP(sequence))
671 return concat(1, &sequence, c_vector, 0);
672 if (BIT_VECTORP(sequence))
673 return concat(1, &sequence, c_bit_vector, 0);
675 check_losing_bytecode("copy-sequence", sequence);
676 sequence = wrong_type_argument(Qsequencep, sequence);
680 struct merge_string_extents_struct {
682 Bytecount entry_offset;
683 Bytecount entry_length;
687 concat(int nargs, Lisp_Object * args,
688 enum concat_target_type target_type, int last_special)
691 Lisp_Object tail = Qnil;
694 Lisp_Object last_tail;
696 struct merge_string_extents_struct *args_mse = 0;
697 Bufbyte *string_result = NULL;
698 Bufbyte *string_result_ptr = NULL;
700 int speccount = specpdl_depth();
701 Charcount total_length;
704 /* The modus operandi in Emacs is "caller gc-protects args".
705 However, concat is called many times in Emacs on freshly
706 created stuff. So we help those callers out by protecting
707 the args ourselves to save them a lot of temporary-variable
713 /* #### if the result is a string and any of the strings have a string
714 for the `string-translatable' property, then concat should also
715 concat the args but use the `string-translatable' strings, and store
716 the result in the returned string's `string-translatable' property. */
718 if (target_type == c_string)
719 XMALLOC_OR_ALLOCA(args_mse, nargs, struct merge_string_extents_struct);
721 /* In append, the last arg isn't treated like the others */
722 if (last_special && nargs > 0) {
724 last_tail = args[nargs];
728 /* Check and coerce the arguments. */
729 for (argnum = 0; argnum < nargs; argnum++) {
730 Lisp_Object seq = args[argnum];
731 if (LISTP(seq) || DLLISTP(seq)) ;
732 else if (VECTORP(seq) || STRINGP(seq) || BIT_VECTORP(seq)) ;
733 #ifdef LOSING_BYTECODE
734 else if (COMPILED_FUNCTIONP(seq))
735 /* Urk! We allow this, for "compatibility"... */
738 #if 0 /* removed for XEmacs 21 */
740 /* This is too revolting to think about but maintains
741 compatibility with FSF (and lots and lots of old code). */