Mercurial > hg > xemacs-beta
diff src/fns.c @ 70:131b0175ea99 r20-0b30
Import from CVS: tag r20-0b30
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:02:59 +0200 |
parents | ee648375d8d6 |
children | c0c698873ce1 |
line wrap: on
line diff
--- a/src/fns.c Mon Aug 13 09:00:04 2007 +0200 +++ b/src/fns.c Mon Aug 13 09:02:59 2007 +0200 @@ -123,9 +123,9 @@ DEFUN ("random", Frandom, 0, 1, 0, /* Return a pseudo-random number. -All integers representable in Lisp are equally likely. - On most systems, this is 28 bits' worth. -With positive integer argument N, return random number in interval [0,N). +All integers representable in Lisp are equally likely.\n\ + On most systems, this is 28 bits' worth.\n\ +With positive integer argument N, return random number in interval [0,N).\n\ With argument t, set the random number seed from the current time and pid. */ (limit)) @@ -272,7 +272,7 @@ strings, but this is not the case under FSF Emacs.) Symbols are also allowed; their print names are used instead. */ - (s1, s2)) + (s1, s2)) { int len; @@ -293,9 +293,25 @@ DEFUN ("string-lessp", Fstring_lessp, 2, 2, 0, /* T if first arg string is less than second in lexicographic order. -If I18N2 support was compiled in, ordering is determined by the locale. -Case is significant for the default C locale. +If I18N2 support (but not Mule support) was compiled in, ordering is +determined by the locale. (Case is significant for the default C locale.) +In all other cases, comparison is simply done on a character-by- +character basis using the numeric value of a character. (Note that +this may not produce particularly meaningful results under Mule if +characters from different charsets are being compared.) + Symbols are also allowed; their print names are used instead. + +The reason that the I18N2 locale-specific collation is not used under +Mule is that the locale model of internationalization does not handle +multiple charsets and thus has no hope of working properly under Mule. +What we really should do is create a collation table over all built-in +charsets. This is extremely difficult to do from scratch, however. + +Unicode is a good first step towards solving this problem. In fact, +it is quite likely that a collation table exists (or will exist) for +Unicode. When Unicode support is added to XEmacs/Mule, this problem +may be solved. */ (s1, s2)) { @@ -319,7 +335,12 @@ { int i; -#ifdef I18N2 +#if defined (I18N2) && !defined (MULE) + /* There is no hope of this working under Mule. Even if we converted + the data into an external format so that strcoll() processed it + properly, it would still not work because strcoll() does not + handle multiple locales. This is the fundamental flaw in the + locale model. */ Bytecount bcend = charcount_to_bytecount (string_data (p1), end); /* Compare strings using collation order of locale. */ /* Need to be tricky to handle embedded nulls. */ @@ -333,13 +354,20 @@ if (val > 0) return Qnil; } -#else /* not I18N2 */ +#else /* not I18N2, or MULE */ + /* #### It is not really necessary to do this: We could compare + byte-by-byte and still get a reasonable comparison, since this + would compare characters with a charset in the same way. + With a little rearrangement of the leading bytes, we could + make most inter-charset comparisons work out the same, too; + even if some don't, this is not a big deal because inter-charset + comparisons aren't really well-defined anyway. */ for (i = 0; i < end; i++) { if (string_char (p1, i) != string_char (p2, i)) return string_char (p1, i) < string_char (p2, i) ? Qt : Qnil; } -#endif /* not I18N2 */ +#endif /* not I18N2, or MULE */ /* Can't do i < len2 because then comparison between "foo" and "foo^@" won't work right in I18N2 case */ return ((end < len2) ? Qt : Qnil); @@ -1059,6 +1087,25 @@ return Qnil; } +DEFUN ("old-member", Fold_member, 2, 2, 0, /* +Return non-nil if ELT is an element of LIST. Comparison done with `old-equal'. +The value is actually the tail of LIST whose car is ELT. +This function is provided only for byte-code compatibility with v19. +Do not use it. +*/ + (elt, list)) +{ + REGISTER Lisp_Object tail, tem; + for (tail = list; !NILP (tail); tail = Fcdr (tail)) + { + tem = Fcar (tail); + if (! NILP (Fold_equal (elt, tem))) + return tail; + QUIT; + } + return Qnil; +} + DEFUN ("memq", Fmemq, 2, 2, 0, /* Return non-nil if ELT is an element of LIST. Comparison done with `eq'. The value is actually the tail of LIST whose car is ELT. @@ -1069,6 +1116,24 @@ for (tail = list; !NILP (tail); tail = Fcdr (tail)) { tem = Fcar (tail); + if (EQ_WITH_EBOLA_NOTICE (elt, tem)) return tail; + QUIT; + } + return Qnil; +} + +DEFUN ("old-memq", Fold_memq, 2, 2, 0, /* +Return non-nil if ELT is an element of LIST. Comparison done with `old-eq'. +The value is actually the tail of LIST whose car is ELT. +This function is provided only for byte-code compatibility with v19. +Do not use it. +*/ + (elt, list)) +{ + REGISTER Lisp_Object tail, tem; + for (tail = list; !NILP (tail); tail = Fcdr (tail)) + { + tem = Fcar (tail); if (HACKEQ_UNSAFE (elt, tem)) return tail; QUIT; } @@ -1082,7 +1147,7 @@ for (tail = list; CONSP (tail); tail = XCDR (tail)) { tem = XCAR (tail); - if (HACKEQ_UNSAFE (elt, tem)) return tail; + if (EQ_WITH_EBOLA_NOTICE (elt, tem)) return tail; } return Qnil; } @@ -1106,6 +1171,25 @@ return Qnil; } +DEFUN ("old-assoc", Fold_assoc, 2, 2, 0, /* +Return non-nil if KEY is `old-equal' to the car of an element of LIST. +The value is actually the element of LIST whose car equals KEY. +*/ + (key, list)) +{ + /* This function can GC. */ + REGISTER Lisp_Object tail, elt, tem; + for (tail = list; !NILP (tail); tail = Fcdr (tail)) + { + elt = Fcar (tail); + if (!CONSP (elt)) continue; + tem = Fold_equal (Fcar (elt), key); + if (!NILP (tem)) return elt; + QUIT; + } + return Qnil; +} + Lisp_Object assoc_no_quit (Lisp_Object key, Lisp_Object list) { @@ -1127,6 +1211,27 @@ elt = Fcar (tail); if (!CONSP (elt)) continue; tem = Fcar (elt); + if (EQ_WITH_EBOLA_NOTICE (key, tem)) return elt; + QUIT; + } + return Qnil; +} + +DEFUN ("old-assq", Fold_assq, 2, 2, 0, /* +Return non-nil if KEY is `old-eq' to the car of an element of LIST. +The value is actually the element of LIST whose car is KEY. +Elements of LIST that are not conses are ignored. +This function is provided only for byte-code compatibility with v19. +Do not use it. +*/ + (key, list)) +{ + REGISTER Lisp_Object tail, elt, tem; + for (tail = list; !NILP (tail); tail = Fcdr (tail)) + { + elt = Fcar (tail); + if (!CONSP (elt)) continue; + tem = Fcar (elt); if (HACKEQ_UNSAFE (key, tem)) return elt; QUIT; } @@ -1146,7 +1251,7 @@ elt = XCAR (tail); if (!CONSP (elt)) continue; tem = XCAR (elt); - if (HACKEQ_UNSAFE (key, tem)) return elt; + if (EQ_WITH_EBOLA_NOTICE (key, tem)) return elt; } return Qnil; } @@ -1170,6 +1275,25 @@ return Qnil; } +DEFUN ("old-rassoc", Fold_rassoc, 2, 2, 0, /* +Return non-nil if KEY is `old-equal' to the cdr of an element of LIST. +The value is actually the element of LIST whose cdr equals KEY. +*/ + (key, list)) +{ + REGISTER Lisp_Object tail; + for (tail = list; !NILP (tail); tail = Fcdr (tail)) + { + REGISTER Lisp_Object elt, tem; + elt = Fcar (tail); + if (!CONSP (elt)) continue; + tem = Fold_equal (Fcdr (elt), key); + if (!NILP (tem)) return elt; + QUIT; + } + return Qnil; +} + DEFUN ("rassq", Frassq, 2, 2, 0, /* Return non-nil if KEY is `eq' to the cdr of an element of LIST. The value is actually the element of LIST whose cdr is KEY. @@ -1182,6 +1306,24 @@ elt = Fcar (tail); if (!CONSP (elt)) continue; tem = Fcdr (elt); + if (EQ_WITH_EBOLA_NOTICE (key, tem)) return elt; + QUIT; + } + return Qnil; +} + +DEFUN ("old-rassq", Fold_rassq, 2, 2, 0, /* +Return non-nil if KEY is `old-eq' to the cdr of an element of LIST. +The value is actually the element of LIST whose cdr is KEY. +*/ + (key, list)) +{ + REGISTER Lisp_Object tail, elt, tem; + for (tail = list; !NILP (tail); tail = Fcdr (tail)) + { + elt = Fcar (tail); + if (!CONSP (elt)) continue; + tem = Fcdr (elt); if (HACKEQ_UNSAFE (key, tem)) return elt; QUIT; } @@ -1197,7 +1339,7 @@ elt = XCAR (tail); if (!CONSP (elt)) continue; tem = XCDR (elt); - if (HACKEQ_UNSAFE (key, tem)) return elt; + if (EQ_WITH_EBOLA_NOTICE (key, tem)) return elt; } return Qnil; } @@ -1233,6 +1375,36 @@ return list; } +DEFUN ("old-delete", Fold_delete, 2, 2, 0, /* +Delete by side effect any occurrences of ELT as a member of LIST. +The modified LIST is returned. Comparison is done with `old-equal'. +If the first member of LIST is ELT, there is no way to remove it by side +effect; therefore, write `(setq foo (delete element foo))' to be sure +of changing the value of `foo'. +*/ + (elt, list)) +{ + REGISTER Lisp_Object tail, prev; + + tail = list; + prev = Qnil; + while (!NILP (tail)) + { + if (!NILP (Fold_equal (elt, Fcar (tail)))) + { + if (NILP (prev)) + list = Fcdr (tail); + else + Fsetcdr (prev, Fcdr (tail)); + } + else + prev = tail; + tail = Fcdr (tail); + QUIT; + } + return list; +} + DEFUN ("delq", Fdelq, 2, 2, 0, /* Delete by side effect any occurrences of ELT as a member of LIST. The modified LIST is returned. Comparison is done with `eq'. @@ -1250,6 +1422,38 @@ while (!NILP (tail)) { tem = Fcar (tail); + if (EQ_WITH_EBOLA_NOTICE (elt, tem)) + { + if (NILP (prev)) + list = Fcdr (tail); + else + Fsetcdr (prev, Fcdr (tail)); + } + else + prev = tail; + tail = Fcdr (tail); + QUIT; + } + return list; +} + +DEFUN ("old-delq", Fold_delq, 2, 2, 0, /* +Delete by side effect any occurrences of ELT as a member of LIST. +The modified LIST is returned. Comparison is done with `old-eq'. +If the first member of LIST is ELT, there is no way to remove it by side +effect; therefore, write `(setq foo (delq element foo))' to be sure of +changing the value of `foo'. +*/ + (elt, list)) +{ + REGISTER Lisp_Object tail, prev; + REGISTER Lisp_Object tem; + + tail = list; + prev = Qnil; + while (!NILP (tail)) + { + tem = Fcar (tail); if (HACKEQ_UNSAFE (elt, tem)) { if (NILP (prev)) @@ -1278,7 +1482,7 @@ while (CONSP (tail)) { tem = XCAR (tail); - if (HACKEQ_UNSAFE (elt, tem)) + if (EQ_WITH_EBOLA_NOTICE (elt, tem)) { if (NILP (prev)) list = XCDR (tail); @@ -1311,7 +1515,7 @@ { Lisp_Object cons_to_free = Qnil; tem = XCAR (tail); - if (HACKEQ_UNSAFE (elt, tem)) + if (EQ_WITH_EBOLA_NOTICE (elt, tem)) { if (NILP (prev)) list = XCDR (tail); @@ -1383,7 +1587,7 @@ while (!NILP (tail)) { Lisp_Object elt = Fcar (tail); - if (CONSP (elt) && HACKEQ_UNSAFE (key, Fcar (elt))) + if (CONSP (elt) && EQ_WITH_EBOLA_NOTICE (key, Fcar (elt))) { if (NILP (prev)) list = Fcdr (tail); @@ -1411,7 +1615,7 @@ while (CONSP (tail)) { tem = XCAR (tail); - if (CONSP (tem) && HACKEQ_UNSAFE (key, XCAR (tem))) + if (CONSP (tem) && EQ_WITH_EBOLA_NOTICE (key, XCAR (tem))) { if (NILP (prev)) list = XCDR (tail); @@ -1472,7 +1676,7 @@ while (!NILP (tail)) { Lisp_Object elt = Fcar (tail); - if (CONSP (elt) && HACKEQ_UNSAFE (value, Fcdr (elt))) + if (CONSP (elt) && EQ_WITH_EBOLA_NOTICE (value, Fcdr (elt))) { if (NILP (prev)) list = Fcdr (tail); @@ -1500,7 +1704,7 @@ while (CONSP (tail)) { tem = XCAR (tail); - if (CONSP (tem) && HACKEQ_UNSAFE (value, XCDR (tem))) + if (CONSP (tem) && EQ_WITH_EBOLA_NOTICE (value, XCDR (tem))) { if (NILP (prev)) list = XCDR (tail); @@ -1757,8 +1961,8 @@ if (!laxp ? EQ (k, keys [i]) : internal_equal (k, keys [i], depth)) { if ((eqp - /* Ebolified here too, sigh ... */ - ? !HACKEQ_UNSAFE (v, vals [i]) + /* We narrowly escaped being Ebolified here. */ + ? !EQ_WITH_EBOLA_NOTICE (v, vals [i]) : !internal_equal (v, vals [i], depth))) /* a property in B has a different value than in A */ goto MISMATCH; @@ -2518,7 +2722,7 @@ (which defaults to `nil'). OBJECT can be a symbol, face, extent, or string. See also `put', `remprop', and `object-plist'. */ - (object, propname, defalt)) /* Cant spel in C */ +(object, propname, defalt)) /* Cant spel in C */ { Lisp_Object val; @@ -2677,7 +2881,7 @@ error ("Stack overflow in equal"); do_cdr: QUIT; - if (HACKEQ_UNSAFE (o1, o2)) + if (EQ_WITH_EBOLA_NOTICE (o1, o2)) return (1); /* Note that (equal 20 20.0) should be nil */ else if (XTYPE (o1) != XTYPE (o2)) @@ -2735,6 +2939,76 @@ return (0); } +/* Note that we may be calling sub-objects that will use + internal_equal() (instead of internal_old_equal()). Oh well. + We will get an Ebola note if there's any possibility of confusion, + but that seems unlikely. */ + +static int +internal_old_equal (Lisp_Object o1, Lisp_Object o2, int depth) +{ + if (depth > 200) + error ("Stack overflow in equal"); + do_cdr: + QUIT; + if (HACKEQ_UNSAFE (o1, o2)) + return (1); + /* Note that (equal 20 20.0) should be nil */ + else if (XTYPE (o1) != XTYPE (o2)) + return (0); + else if (CONSP (o1)) + { + if (!internal_old_equal (Fcar (o1), Fcar (o2), depth + 1)) + return (0); + o1 = Fcdr (o1); + o2 = Fcdr (o2); + goto do_cdr; + } + +#ifndef LRECORD_VECTOR + else if (VECTORP (o1)) + { + int indecks; + int len = vector_length (XVECTOR (o1)); + if (len != vector_length (XVECTOR (o2))) + return (0); + for (indecks = 0; indecks < len; indecks++) + { + Lisp_Object v1, v2; + v1 = vector_data (XVECTOR (o1)) [indecks]; + v2 = vector_data (XVECTOR (o2)) [indecks]; + if (!internal_old_equal (v1, v2, depth + 1)) + return (0); + } + return (1); + } +#endif /* !LRECORD_VECTOR */ + else if (STRINGP (o1)) + { + Bytecount len = XSTRING_LENGTH (o1); + if (len != XSTRING_LENGTH (o2)) + return (0); + if (memcmp (XSTRING_DATA (o1), XSTRING_DATA (o2), len)) + return (0); + return (1); + } + else if (LRECORDP (o1)) + { + CONST struct lrecord_implementation + *imp1 = XRECORD_LHEADER (o1)->implementation, + *imp2 = XRECORD_LHEADER (o2)->implementation; + if (imp1 != imp2) + return (0); + else if (imp1->equal == 0) + /* EQ-ness of the objects was noticed above */ + return (0); + else + return ((imp1->equal) (o1, o2, depth)); + } + + return (0); +} + DEFUN ("equal", Fequal, 2, 2, 0, /* T if two Lisp objects have similar structure and contents. They must have the same data type. @@ -2747,6 +3021,20 @@ return ((internal_equal (o1, o2, 0)) ? Qt : Qnil); } +DEFUN ("old-equal", Fold_equal, 2, 2, 0, /* +T if two Lisp objects have similar structure and contents. +They must have the same data type. +\(Note, however, that an exception is made for characters and integers; +this is known as the \"char-int confoundance disease.\" See `eq' and +`old-eq'.) +This function is provided only for byte-code compatibility with v19. +Do not use it. +*/ + (o1, o2)) +{ + return (internal_old_equal (o1, o2, 0) ? Qt : Qnil); +} + DEFUN ("fillarray", Ffillarray, 2, 2, 0, /* Store each element of ARRAY with ITEM. @@ -2755,43 +3043,42 @@ (array, item)) { retry: - if (STRINGP (array)) + if (VECTORP (array)) { - Charcount size; - Charcount i; - Emchar charval; - struct Lisp_String *s; - CHECK_CHAR_COERCE_INT (item); + Lisp_Object *p; + int size; + int indecks; CHECK_IMPURE (array); - charval = XCHAR (item); - s = XSTRING (array); - size = string_char_length (s); - for (i = 0; i < size; i++) - set_string_char (s, i, charval); - bump_string_modiff (array); + size = vector_length (XVECTOR (array)); + p = vector_data (XVECTOR (array)); + for (indecks = 0; indecks < size; indecks++) + p[indecks] = item; } else if (VECTORP (array)) { - Lisp_Object *p; - int size; - int i; - CHECK_IMPURE (array); - size = vector_length (XVECTOR (array)); - p = vector_data (XVECTOR (array)); - for (i = 0; i < size; i++) - p[i] = item; - } - else if (BIT_VECTORP (array)) - { struct Lisp_Bit_Vector *v; int size; - int i; + int indecks; + CHECK_BIT (item); CHECK_IMPURE (array); v = XBIT_VECTOR (array); size = bit_vector_length (v); - for (i = 0; i < size; i++) - set_bit_vector_bit (v, i, XINT (item)); + for (indecks = 0; indecks < size; indecks++) + set_bit_vector_bit (v, indecks, XINT (item)); + } + else if (STRINGP (array)) + { + Charcount size; + Charcount indecks; + Emchar charval; + CHECK_CHAR_COERCE_INT (item); + CHECK_IMPURE (array); + charval = XCHAR (item); + size = string_char_length (XSTRING (array)); + for (indecks = 0; indecks < size; indecks++) + set_string_char (XSTRING (array), indecks, charval); + bump_string_modiff (array); } else { @@ -3008,8 +3295,8 @@ If the 5-minute or 15-minute load averages are not available, return a shortened list, containing only those averages which are available. -On some systems, this won't work due to permissions on /dev/kmem in -which case you can't use this. +On most systems, this won't work unless the emacs executable is installed +as setgid kmem (assuming that /dev/kmem is in the group kmem). */ ()) { @@ -3031,77 +3318,18 @@ Lisp_Object Vfeatures; -extern Lisp_Object Vemacs_major_version, Vemacs_minor_version; DEFUN ("featurep", Ffeaturep, 1, 1, 0, /* -Return non-nil if feature expression FEXP is true. +Return t if FEATURE is present in this Emacs. +Use this to conditionalize execution of lisp code based on the +presence or absence of emacs or environment extensions. +Use `provide' to declare that a feature is available. +This function looks at the value of the variable `features'. */ - (fexp)) + (feature)) { - static double featurep_emacs_version; - - /* Brute force translation from Erik Naggum's lisp function. */ - if (SYMBOLP(fexp)) - { - /* Original definition */ - return NILP (Fmemq (fexp, Vfeatures)) ? Qnil : Qt; - } - else if (INTP(fexp) || FLOATP(fexp)) - { - double d = extract_float(fexp); - - if (featurep_emacs_version == 0.0) - { - featurep_emacs_version = XINT (Vemacs_major_version) + - (XINT (Vemacs_minor_version) / 100.0); - } - return featurep_emacs_version >= d ? Qt : Qnil; - } - else if (CONSP(fexp)) - { - Lisp_Object tem; - - tem = XCAR(fexp); - if (EQ(tem, Qnot)) - { - Lisp_Object negate = XCDR(fexp); - - if (!NILP(XCDR(fexp))) - { - return Fsignal(Qinvalid_read_syntax, list1(XCDR(fexp))); - } - else - { - return NILP(Ffeaturep(negate)) ? Qt : Qnil; - } - } - else if (EQ(tem, Qand)) - { - tem = XCDR(fexp); - while (!NILP(tem) && !NILP(Ffeaturep(XCAR(tem)))) - { - tem = XCDR(tem); - } - return NILP(tem) ? Qt : Qnil; - } - else if (EQ(tem, Qor)) - { - tem = XCDR(fexp); - while (!NILP(tem) && NILP(Ffeaturep(XCAR(tem)))) - { - tem = XCDR(tem); - } - return NILP(tem) ? Qnil : Qt; - } - else - { - return Fsignal(Qinvalid_read_syntax, list1(XCDR(fexp))); - } - } - else - { - return Fsignal(Qinvalid_read_syntax, list1 (fexp)); - } + CHECK_SYMBOL (feature); + return NILP (Fmemq (feature, Vfeatures)) ? Qnil : Qt; } DEFUN ("provide", Fprovide, 1, 1, 0, /* @@ -3187,13 +3415,21 @@ DEFSUBR (Fnth); DEFSUBR (Felt); DEFSUBR (Fmember); + DEFSUBR (Fold_member); DEFSUBR (Fmemq); + DEFSUBR (Fold_memq); DEFSUBR (Fassoc); + DEFSUBR (Fold_assoc); DEFSUBR (Fassq); + DEFSUBR (Fold_assq); DEFSUBR (Frassoc); + DEFSUBR (Fold_rassoc); DEFSUBR (Frassq); + DEFSUBR (Fold_rassq); DEFSUBR (Fdelete); + DEFSUBR (Fold_delete); DEFSUBR (Fdelq); + DEFSUBR (Fold_delq); DEFSUBR (Fremassoc); DEFSUBR (Fremassq); DEFSUBR (Fremrassoc); @@ -3223,6 +3459,7 @@ DEFSUBR (Fremprop); DEFSUBR (Fobject_plist); DEFSUBR (Fequal); + DEFSUBR (Fold_equal); DEFSUBR (Ffillarray); DEFSUBR (Fnconc); DEFSUBR (Fmapcar);