comparison src/fns.c @ 5182:2e528066e2fc

Move #'sort*, #'fill, #'merge to C from cl-seq.el. lisp/ChangeLog addition: 2010-04-01 Aidan Kehoe <kehoea@parhasard.net> * cl-seq.el (fill, sort*, merge): Move these functions to fns.c. (stable-sort): Make this docstring reflect the argument names used in the #'sort* docstring. * cl-macs.el (stable-sort): Make #'stable-sort exactly equivalent to #'sort* in compiled code. * bytecomp.el (byte-compile-maybe-add-*): New macro, for functions like #'sort and #'mapcar that, to be strictly compatible, should only take two args, but in our implementation can take more, because they're aliases of #'sort* and #'mapcar*. (byte-compile-mapcar, byte-compile-sort, byte-compile-fillarray): Use this new macro. (map-into): Add a byte-compile method for #'map-into in passing. * apropos.el (apropos-print): Use #'sort* with a :key argument, now it's in C. * compat.el (extent-at): Ditto. * register.el (list-registers): Ditto. * package-ui.el (pui-list-packages): Ditto. * help.el (sorted-key-descriptions): Ditto. src/ChangeLog addition: 2010-03-31 Aidan Kehoe <kehoea@parhasard.net> * fns.c (STRING_DATA_TO_OBJECT_ARRAY) (BIT_VECTOR_TO_OBJECT_ARRAY, c_merge_predicate_key) (c_merge_predicate_nokey, list_merge, array_merge) (list_array_merge_into_list, list_list_merge_into_array) (list_array_merge_into_array, CHECK_KEY_ARGUMENT, Fmerge) (list_sort, array_sort, FsortX): Move #'sort*, #'fill, #'merge from cl-seq.el to C, extending the implementations of Fsort, Ffillarray, and merge() to do so. * keymap.c (keymap_submaps, map_keymap_sort_predicate) (describe_map_sort_predicate): Change the calling semantics of the C sort predicates to return a non-nil Lisp object if the first argument is less than the second, rather than C integers. * fontcolor-msw.c (sort_font_list_function): * fileio.c (build_annotations): * dired.c (Fdirectory_files): * abbrev.c (Finsert_abbrev_table_description): Call list_sort instead of Fsort, list_merge instead of merge() in these functions. man/ChangeLog addition: 2010-04-01 Aidan Kehoe <kehoea@parhasard.net> * lispref/lists.texi (Rearrangement): Update the documentation of #'sort here, now that it accepts any type of sequence and the KEY keyword argument. (Though this is probably now the wrong place for this function, given that.)
author Aidan Kehoe <kehoea@parhasard.net>
date Thu, 01 Apr 2010 20:22:50 +0100
parents 7be849cb8828
children 039d9a7f2e6d
comparison
equal deleted inserted replaced
5181:a00bfbd64e0a 5182:2e528066e2fc
52 #include "opaque.h" 52 #include "opaque.h"
53 53
54 /* NOTE: This symbol is also used in lread.c */ 54 /* NOTE: This symbol is also used in lread.c */
55 #define FEATUREP_SYNTAX 55 #define FEATUREP_SYNTAX
56 56
57 Lisp_Object Qstring_lessp; 57 Lisp_Object Qstring_lessp, Qsort, Qmerge, Qfill;
58 Lisp_Object Qidentity; 58 Lisp_Object Qidentity;
59 Lisp_Object Qvector, Qarray, Qbit_vector; 59 Lisp_Object Qvector, Qarray, Qbit_vector, QsortX;
60 60
61 Lisp_Object Qbase64_conversion_error; 61 Lisp_Object Qbase64_conversion_error;
62 62
63 Lisp_Object Vpath_separator; 63 Lisp_Object Vpath_separator;
64 64
1934 reversed_list = Fcons (elt, reversed_list); 1934 reversed_list = Fcons (elt, reversed_list);
1935 } 1935 }
1936 return reversed_list; 1936 return reversed_list;
1937 } 1937 }
1938 1938
1939 static Lisp_Object list_merge (Lisp_Object org_l1, Lisp_Object org_l2, 1939 static Lisp_Object
1940 Lisp_Object lisp_arg, 1940 c_merge_predicate_key (Lisp_Object obj1, Lisp_Object obj2,
1941 int (*pred_fn) (Lisp_Object, Lisp_Object, 1941 Lisp_Object pred, Lisp_Object key_func)
1942 Lisp_Object lisp_arg)); 1942 {
1943 1943 struct gcpro gcpro1;
1944 /* The sort function should return > 0 if OBJ1 < OBJ2, < 0 otherwise. 1944 Lisp_Object args[3];
1945 NOTE: This is backwards from the way qsort() works. */ 1945
1946 /* We could use call2() and call3() here, but we're called O(nlogn) times
1947 for a sequence of length n, it make some sense to inline them. */
1948 args[0] = key_func;
1949 args[1] = obj1;
1950 args[2] = Qnil;
1951
1952 GCPRO1 (args[0]);
1953 gcpro1.nvars = countof (args);
1954
1955 obj1 = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
1956
1957 args[1] = obj2;
1958 obj2 = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
1959
1960 args[0] = pred;
1961 args[1] = obj1;
1962 args[2] = obj2;
1963
1964 RETURN_UNGCPRO (IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)));
1965 }
1966
1967 static Lisp_Object
1968 c_merge_predicate_nokey (Lisp_Object obj1, Lisp_Object obj2,
1969 Lisp_Object pred, Lisp_Object UNUSED (key_func))
1970 {
1971 struct gcpro gcpro1;
1972 Lisp_Object args[3];
1973
1974 /* This is (almost) the implementation of call2, it makes some sense to
1975 inline it here. */
1976 args[0] = pred;
1977 args[1] = obj1;
1978 args[2] = obj2;
1979
1980 GCPRO1 (args[0]);
1981 gcpro1.nvars = countof (args);
1982
1983 RETURN_UNGCPRO (IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)));
1984 }
1946 1985
1947 Lisp_Object 1986 Lisp_Object
1948 list_sort (Lisp_Object list,
1949 Lisp_Object lisp_arg,
1950 int (*pred_fn) (Lisp_Object obj1, Lisp_Object obj2,
1951 Lisp_Object lisp_arg))
1952 {
1953 struct gcpro gcpro1, gcpro2, gcpro3;
1954 Lisp_Object back, tem;
1955 Lisp_Object front = list;
1956 Lisp_Object len = Flength (list);
1957
1958 if (XINT (len) < 2)
1959 return list;
1960
1961 len = make_int (XINT (len) / 2 - 1);
1962 tem = Fnthcdr (len, list);
1963 back = Fcdr (tem);
1964 Fsetcdr (tem, Qnil);
1965
1966 GCPRO3 (front, back, lisp_arg);
1967 front = list_sort (front, lisp_arg, pred_fn);
1968 back = list_sort (back, lisp_arg, pred_fn);
1969 UNGCPRO;
1970 return list_merge (front, back, lisp_arg, pred_fn);
1971 }
1972
1973
1974 static int
1975 merge_pred_function (Lisp_Object obj1, Lisp_Object obj2,
1976 Lisp_Object pred)
1977 {
1978 Lisp_Object tmp;
1979
1980 /* prevents the GC from happening in call2 */
1981 /* Emacs' GC doesn't actually relocate pointers, so this probably
1982 isn't strictly necessary */
1983 int speccount = begin_gc_forbidden ();
1984 tmp = call2 (pred, obj1, obj2);
1985 unbind_to (speccount);
1986
1987 if (NILP (tmp))
1988 return -1;
1989 else
1990 return 1;
1991 }
1992
1993 DEFUN ("sort", Fsort, 2, 2, 0, /*
1994 Sort LIST, stably, comparing elements using PREDICATE.
1995 Returns the sorted list. LIST is modified by side effects.
1996 PREDICATE is called with two elements of LIST, and should return T
1997 if the first element is "less" than the second.
1998 */
1999 (list, predicate))
2000 {
2001 return list_sort (list, predicate, merge_pred_function);
2002 }
2003
2004 Lisp_Object
2005 merge (Lisp_Object org_l1, Lisp_Object org_l2,
2006 Lisp_Object pred)
2007 {
2008 return list_merge (org_l1, org_l2, pred, merge_pred_function);
2009 }
2010
2011
2012 static Lisp_Object
2013 list_merge (Lisp_Object org_l1, Lisp_Object org_l2, 1987 list_merge (Lisp_Object org_l1, Lisp_Object org_l2,
2014 Lisp_Object lisp_arg, 1988 Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object,
2015 int (*pred_fn) (Lisp_Object, Lisp_Object, Lisp_Object lisp_arg)) 1989 Lisp_Object, Lisp_Object),
1990 Lisp_Object predicate, Lisp_Object key_func)
2016 { 1991 {
2017 Lisp_Object value; 1992 Lisp_Object value;
2018 Lisp_Object tail; 1993 Lisp_Object tail;
2019 Lisp_Object tem; 1994 Lisp_Object tem;
2020 Lisp_Object l1, l2; 1995 Lisp_Object l1, l2;
2021 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; 1996 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1997 int looped = 0;
2022 1998
2023 l1 = org_l1; 1999 l1 = org_l1;
2024 l2 = org_l2; 2000 l2 = org_l2;
2025 tail = Qnil; 2001 tail = Qnil;
2026 value = Qnil; 2002 value = Qnil;
2027 2003
2004 if (NULL == c_predicate)
2005 {
2006 c_predicate = EQ (key_func, Qidentity) ?
2007 c_merge_predicate_nokey : c_merge_predicate_key;
2008 }
2009
2028 /* It is sufficient to protect org_l1 and org_l2. 2010 /* It is sufficient to protect org_l1 and org_l2.
2029 When l1 and l2 are updated, we copy the new values 2011 When l1 and l2 are updated, we copy the new values
2030 back into the org_ vars. */ 2012 back into the org_ vars. */
2031 2013
2032 GCPRO4 (org_l1, org_l2, lisp_arg, value); 2014 GCPRO4 (org_l1, org_l2, predicate, value);
2033 2015
2034 while (1) 2016 while (1)
2035 { 2017 {
2036 if (NILP (l1)) 2018 if (NILP (l1))
2037 { 2019 {
2048 return l1; 2030 return l1;
2049 Fsetcdr (tail, l1); 2031 Fsetcdr (tail, l1);
2050 return value; 2032 return value;
2051 } 2033 }
2052 2034
2053 if (((*pred_fn) (Fcar (l2), Fcar (l1), lisp_arg)) < 0) 2035 if (NILP (c_predicate (Fcar (l2), Fcar (l1), predicate, key_func)))
2054 { 2036 {
2055 tem = l1; 2037 tem = l1;
2056 l1 = Fcdr (l1); 2038 l1 = Fcdr (l1);
2057 org_l1 = l1; 2039 org_l1 = l1;
2058 } 2040 }
2065 if (NILP (tail)) 2047 if (NILP (tail))
2066 value = tem; 2048 value = tem;
2067 else 2049 else
2068 Fsetcdr (tail, tem); 2050 Fsetcdr (tail, tem);
2069 tail = tem; 2051 tail = tem;
2070 } 2052
2071 } 2053 if (++looped % CIRCULAR_LIST_SUSPICION_LENGTH) continue;
2072 2054
2055 /* Just check the lists aren't circular:*/
2056 {
2057 EXTERNAL_LIST_LOOP_1 (l1)
2058 {
2059 }
2060 }
2061 {
2062 EXTERNAL_LIST_LOOP_1 (l2)
2063 {
2064 }
2065 }
2066 }
2067 }
2068
2069 static void
2070 array_merge (Lisp_Object *dest, Elemcount dest_len,
2071 Lisp_Object *front, Elemcount front_len,
2072 Lisp_Object *back, Elemcount back_len,
2073 Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object,
2074 Lisp_Object, Lisp_Object),
2075 Lisp_Object predicate, Lisp_Object key_func)
2076 {
2077 Elemcount ii, fronting, backing;
2078 Lisp_Object *front_staging = front;
2079 Lisp_Object *back_staging = back;
2080 struct gcpro gcpro1, gcpro2;
2081
2082 assert (dest_len == (back_len + front_len));
2083
2084 if (0 == dest_len)
2085 {
2086 return;
2087 }
2088
2089 if (front >= dest && front < (dest + dest_len))
2090 {
2091 front_staging = alloca_array (Lisp_Object, front_len);
2092
2093 for (ii = 0; ii < front_len; ++ii)
2094 {
2095 front_staging[ii] = front[ii];
2096 }
2097 }
2098
2099 if (back >= dest && back < (dest + dest_len))
2100 {
2101 back_staging = alloca_array (Lisp_Object, back_len);
2102
2103 for (ii = 0; ii < back_len; ++ii)
2104 {
2105 back_staging[ii] = back[ii];
2106 }
2107 }
2108
2109 GCPRO2 (front_staging[0], back_staging[0]);
2110 gcpro1.nvars = front_len;
2111 gcpro2.nvars = back_len;
2112
2113 for (ii = fronting = backing = 0; ii < dest_len; ++ii)
2114 {
2115 if (fronting >= front_len)
2116 {
2117 while (ii < dest_len)
2118 {
2119 dest[ii] = back_staging[backing];
2120 ++ii, ++backing;
2121 }
2122 UNGCPRO;
2123 return;
2124 }
2125
2126 if (backing >= back_len)
2127 {
2128 while (ii < dest_len)
2129 {
2130 dest[ii] = front_staging[fronting];
2131 ++ii, ++fronting;
2132 }
2133 UNGCPRO;
2134 return;
2135 }
2136
2137 if (NILP (c_predicate (back_staging[backing], front_staging[fronting],
2138 predicate, key_func)))
2139 {
2140 dest[ii] = front_staging[fronting];
2141 ++fronting;
2142 }
2143 else
2144 {
2145 dest[ii] = back_staging[backing];
2146 ++backing;
2147 }
2148 }
2149
2150 UNGCPRO;
2151 }
2152
2153 static Lisp_Object
2154 list_array_merge_into_list (Lisp_Object list,
2155 Lisp_Object *array, Elemcount array_len,
2156 Lisp_Object (*c_predicate) (Lisp_Object,
2157 Lisp_Object,
2158 Lisp_Object,
2159 Lisp_Object),
2160 Lisp_Object predicate, Lisp_Object key_func,
2161 Boolint reverse_order)
2162 {
2163 Lisp_Object tail = Qnil, value = Qnil;
2164 struct gcpro gcpro1, gcpro2, gcpro3;
2165 Elemcount array_index = 0;
2166 int looped = 0;
2167
2168 GCPRO3 (list, tail, value);
2169
2170 while (1)
2171 {
2172 if (NILP (list))
2173 {
2174 UNGCPRO;
2175
2176 if (NILP (tail))
2177 {
2178 return Flist (array_len, array);
2179 }
2180
2181 Fsetcdr (tail, Flist (array_len - array_index, array + array_index));
2182 return value;
2183 }
2184
2185 if (array_index >= array_len)
2186 {
2187 UNGCPRO;
2188 if (NILP (tail))
2189 {
2190 return list;
2191 }
2192
2193 Fsetcdr (tail, list);
2194 return value;
2195 }
2196
2197
2198 if (reverse_order ?
2199 !NILP (c_predicate (Fcar (list), array [array_index], predicate,
2200 key_func)) :
2201 NILP (c_predicate (array [array_index], Fcar (list), predicate,
2202 key_func)))
2203 {
2204 if (NILP (tail))
2205 {
2206 value = tail = list;
2207 }
2208 else
2209 {
2210 Fsetcdr (tail, list);
2211 tail = XCDR (tail);
2212 }
2213
2214 list = Fcdr (list);
2215 }
2216 else
2217 {
2218 if (NILP (tail))
2219 {
2220 value = tail = Fcons (array [array_index], Qnil);
2221 }
2222 else
2223 {
2224 Fsetcdr (tail, Fcons (array [array_index], tail));
2225 tail = XCDR (tail);
2226 }
2227 ++array_index;
2228 }
2229
2230 if (++looped % CIRCULAR_LIST_SUSPICION_LENGTH) continue;
2231
2232 {
2233 EXTERNAL_LIST_LOOP_1 (list)
2234 {
2235 }
2236 }
2237 }
2238 }
2239
2240 static void
2241 list_list_merge_into_array (Lisp_Object *output, Elemcount output_len,
2242 Lisp_Object list_one, Lisp_Object list_two,
2243 Lisp_Object (*c_predicate) (Lisp_Object,
2244 Lisp_Object,
2245 Lisp_Object,
2246 Lisp_Object),
2247 Lisp_Object predicate, Lisp_Object key_func)
2248 {
2249 Elemcount output_index = 0;
2250
2251 while (output_index < output_len)
2252 {
2253 if (NILP (list_one))
2254 {
2255 while (output_index < output_len)
2256 {
2257 output [output_index] = Fcar (list_two);
2258 list_two = Fcdr (list_two), ++output_index;
2259 }
2260 return;
2261 }
2262
2263 if (NILP (list_two))
2264 {
2265 while (output_index < output_len)
2266 {
2267 output [output_index] = Fcar (list_one);
2268 list_one = Fcdr (list_one), ++output_index;
2269 }
2270 return;
2271 }
2272
2273 if (NILP (c_predicate (Fcar (list_two), Fcar (list_one), predicate,
2274 key_func)))
2275 {
2276 output [output_index] = XCAR (list_one);
2277 list_one = XCDR (list_one);
2278 }
2279 else
2280 {
2281 output [output_index] = XCAR (list_two);
2282 list_two = XCDR (list_two);
2283 }
2284
2285 ++output_index;
2286
2287 /* No need to check for circularity. */
2288 }
2289 }
2290
2291 static void
2292 list_array_merge_into_array (Lisp_Object *output, Elemcount output_len,
2293 Lisp_Object list,
2294 Lisp_Object *array, Elemcount array_len,
2295 Lisp_Object (*c_predicate) (Lisp_Object,
2296 Lisp_Object,
2297 Lisp_Object,
2298 Lisp_Object),
2299 Lisp_Object predicate, Lisp_Object key_func,
2300 Boolint reverse_order)
2301 {
2302 Elemcount output_index = 0, array_index = 0;
2303
2304 while (output_index < output_len)
2305 {
2306 if (NILP (list))
2307 {
2308 if (array_len - array_index != output_len - output_index)
2309 {
2310 invalid_state ("List length modified during merge", Qunbound);
2311 }
2312
2313 while (array_index < array_len)
2314 {
2315 output [output_index++] = array [array_index++];
2316 }
2317
2318 return;
2319 }
2320
2321 if (array_index >= array_len)
2322 {
2323 while (output_index < output_len)
2324 {
2325 output [output_index++] = Fcar (list);
2326 list = Fcdr (list);
2327 }
2328
2329 return;
2330 }
2331
2332 if (reverse_order ?
2333 !NILP (c_predicate (Fcar (list), array [array_index], predicate,
2334 key_func)) :
2335 NILP (c_predicate (array [array_index], Fcar (list), predicate,
2336 key_func)))
2337 {
2338 output [output_index] = XCAR (list);
2339 list = XCDR (list);
2340 }
2341 else
2342 {
2343 output [output_index] = array [array_index];
2344 ++array_index;
2345 }
2346
2347 ++output_index;
2348 }
2349 }
2350
2351 #define STRING_DATA_TO_OBJECT_ARRAY(strdata, c_array, counter, len) \
2352 do { \
2353 c_array = alloca_array (Lisp_Object, len); \
2354 for (counter = 0; counter < len; ++counter) \
2355 { \
2356 c_array[counter] = make_char (itext_ichar (strdata)); \
2357 INC_IBYTEPTR (strdata); \
2358 } \
2359 } while (0)
2360
2361 #define BIT_VECTOR_TO_OBJECT_ARRAY(v, c_array, counter, len) do { \
2362 c_array = alloca_array (Lisp_Object, len); \
2363 for (counter = 0; counter < len; ++counter) \
2364 { \
2365 c_array[counter] = make_int (bit_vector_bit (v, counter)); \
2366 } \
2367 } while (0)
2368
2369 /* This macro might eventually find a better home than here. */
2370
2371 #define CHECK_KEY_ARGUMENT(key, c_predicate) \
2372 do { \
2373 if (NILP (key)) \
2374 { \
2375 key = Qidentity; \
2376 } \
2377 \
2378 if (EQ (key, Qidentity)) \
2379 { \
2380 c_predicate = c_merge_predicate_nokey; \
2381 } \
2382 else \
2383 { \
2384 key = indirect_function (key, 1); \
2385 c_predicate = c_merge_predicate_key; \
2386 } \
2387 } while (0)
2388
2389 DEFUN ("merge", Fmerge, 4, MANY, 0, /*
2390 Destructively merge SEQUENCE-ONE and SEQUENCE-TWO, producing a new sequence.
2391
2392 TYPE is the type of sequence to return. PREDICATE is a `less-than'
2393 predicate on the elements.
2394
2395 Optional keyword argument KEY is a function used to extract an object to be
2396 used for comparison from each element of SEQUENCE-ONE and SEQUENCE-TWO.
2397
2398 arguments: (TYPE SEQUENCE-ONE SEQUENCE-TWO PREDICATE &key (KEY #'IDENTITY))
2399 */
2400 (int nargs, Lisp_Object *args))
2401 {
2402 Lisp_Object type = args[0], sequence_one = args[1], sequence_two = args[2],
2403 predicate = args[3], result = Qnil;
2404 Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, Lisp_Object,
2405 Lisp_Object);
2406
2407 PARSE_KEYWORDS (Qmerge, nargs, args, 4, 1, (key), NULL, 0);
2408
2409 CHECK_SEQUENCE (sequence_one);
2410 CHECK_SEQUENCE (sequence_two);
2411
2412 CHECK_KEY_ARGUMENT (key, c_predicate);
2413
2414 if (EQ (type, Qlist) && (LISTP (sequence_one) || LISTP (sequence_two)))
2415 {
2416 if (NILP (sequence_two))
2417 {
2418 result = Fappend (2, args + 1);
2419 }
2420 else if (NILP (sequence_one))
2421 {
2422 args[3] = Qnil; /* Overwriting PREDICATE, and losing its GC
2423 protection, but that doesn't matter. */
2424 result = Fappend (2, args + 2);
2425 }
2426 else if (CONSP (sequence_one) && CONSP (sequence_two))
2427 {
2428 result = list_merge (sequence_one, sequence_two, c_predicate,
2429 predicate, key);
2430 }
2431 else
2432 {
2433 Lisp_Object *array_storage, swap;
2434 Elemcount array_length, i;
2435 Boolint reverse_order = 0;
2436
2437 if (!CONSP (sequence_one))
2438 {
2439 /* Make sequence_one the cons, sequence_two the array: */
2440 swap = sequence_one;
2441 sequence_one = sequence_two;
2442 sequence_two = swap;
2443 reverse_order = 1;
2444 }
2445
2446 if (VECTORP (sequence_two))
2447 {
2448 array_storage = XVECTOR_DATA (sequence_two);
2449 array_length = XVECTOR_LENGTH (sequence_two);
2450 }
2451 else if (STRINGP (sequence_two))
2452 {
2453 Ibyte *strdata = XSTRING_DATA (sequence_two);
2454 array_length = string_char_length (sequence_two);
2455 /* No need to GCPRO, characters are immediate. */
2456 STRING_DATA_TO_OBJECT_ARRAY (strdata, array_storage, i,
2457 array_length);
2458
2459 }
2460 else
2461 {
2462 Lisp_Bit_Vector *v = XBIT_VECTOR (sequence_two);
2463 array_length = bit_vector_length (v);
2464 /* No need to GCPRO, fixnums are immediate. */
2465 BIT_VECTOR_TO_OBJECT_ARRAY (v, array_storage, i, array_length);
2466 }
2467
2468 result = list_array_merge_into_list (sequence_one,
2469 array_storage, array_length,
2470 c_predicate,
2471 predicate, key,
2472 reverse_order);
2473 }
2474 }
2475 else
2476 {
2477 Elemcount sequence_one_len = XINT (Flength (sequence_one)),
2478 sequence_two_len = XINT (Flength (sequence_two)), i;
2479 Elemcount output_len = 1 + sequence_one_len + sequence_two_len;
2480 Lisp_Object *output = alloca_array (Lisp_Object, output_len),
2481 *sequence_one_storage = NULL, *sequence_two_storage = NULL;
2482 Boolint do_coerce = !(EQ (type, Qvector) || EQ (type, Qstring)
2483 || EQ (type, Qbit_vector) || EQ (type, Qlist));
2484 Ibyte *strdata = NULL;
2485 Lisp_Bit_Vector *v = NULL;
2486 struct gcpro gcpro1;
2487
2488 output[0] = do_coerce ? Qlist : type;
2489 for (i = 1; i < output_len; ++i)
2490 {
2491 output[i] = Qnil;
2492 }
2493
2494 GCPRO1 (output[0]);
2495 gcpro1.nvars = output_len;
2496
2497 if (VECTORP (sequence_one))
2498 {
2499 sequence_one_storage = XVECTOR_DATA (sequence_one);
2500 }
2501 else if (STRINGP (sequence_one))
2502 {
2503 strdata = XSTRING_DATA (sequence_one);
2504 STRING_DATA_TO_OBJECT_ARRAY (strdata, sequence_one_storage,
2505 i, sequence_one_len);
2506 }
2507 else if (BIT_VECTORP (sequence_one))
2508 {
2509 v = XBIT_VECTOR (sequence_one);
2510 BIT_VECTOR_TO_OBJECT_ARRAY (v, sequence_one_storage,
2511 i, sequence_one_len);
2512 }
2513
2514 if (VECTORP (sequence_two))
2515 {
2516 sequence_two_storage = XVECTOR_DATA (sequence_two);
2517 }
2518 else if (STRINGP (sequence_two))
2519 {
2520 strdata = XSTRING_DATA (sequence_two);
2521 STRING_DATA_TO_OBJECT_ARRAY (strdata, sequence_two_storage,
2522 i, sequence_two_len);
2523 }
2524 else if (BIT_VECTORP (sequence_two))
2525 {
2526 v = XBIT_VECTOR (sequence_two);
2527 BIT_VECTOR_TO_OBJECT_ARRAY (v, sequence_two_storage,
2528 i, sequence_two_len);
2529 }
2530
2531 if (LISTP (sequence_one) && LISTP (sequence_two))
2532 {
2533 list_list_merge_into_array (output + 1, output_len - 1,
2534 sequence_one, sequence_two,
2535 c_predicate, predicate,
2536 key);
2537 }
2538 else if (LISTP (sequence_one))
2539 {
2540 list_array_merge_into_array (output + 1, output_len - 1,
2541 sequence_one,
2542 sequence_two_storage,
2543 sequence_two_len,
2544 c_predicate, predicate,
2545 key, 0);
2546 }
2547 else if (LISTP (sequence_two))
2548 {
2549 list_array_merge_into_array (output + 1, output_len - 1,
2550 sequence_two,
2551 sequence_one_storage,
2552 sequence_one_len,
2553 c_predicate, predicate,
2554 key, 1);
2555 }
2556 else
2557 {
2558 array_merge (output + 1, output_len - 1,
2559 sequence_one_storage, sequence_one_len,
2560 sequence_two_storage, sequence_two_len,
2561 c_predicate, predicate,
2562 key);
2563 }
2564
2565 result = Ffuncall (output_len, output);
2566
2567 if (do_coerce)
2568 {
2569 result = call2 (Qcoerce, result, type);
2570 }
2571
2572 UNGCPRO;
2573 }
2574
2575 return result;
2576 }
2577
2578 /* The sort function should return non-nil if OBJ1 < OBJ2, nil otherwise.
2579 NOTE: This is backwards from the way qsort() works. */
2580 Lisp_Object
2581 list_sort (Lisp_Object list,
2582 Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object,
2583 Lisp_Object, Lisp_Object),
2584 Lisp_Object predicate, Lisp_Object key_func)
2585 {
2586 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2587 Lisp_Object back, tem;
2588 Lisp_Object front = list;
2589 Lisp_Object len = Flength (list);
2590
2591 if (XINT (len) < 2)
2592 return list;
2593
2594 if (NULL == c_predicate)
2595 {
2596 c_predicate = EQ (key_func, Qidentity) ? c_merge_predicate_nokey :
2597 c_merge_predicate_key;
2598 }
2599
2600 len = make_int (XINT (len) / 2 - 1);
2601 tem = Fnthcdr (len, list);
2602 back = Fcdr (tem);
2603 Fsetcdr (tem, Qnil);
2604
2605 GCPRO4 (front, back, predicate, key_func);
2606 front = list_sort (front, c_predicate, predicate, key_func);
2607 back = list_sort (back, c_predicate, predicate, key_func);
2608
2609 RETURN_UNGCPRO (list_merge (front, back, c_predicate, predicate, key_func));
2610 }
2611
2612 static void
2613 array_sort (Lisp_Object *array, Elemcount array_len,
2614 Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object,
2615 Lisp_Object, Lisp_Object),
2616 Lisp_Object predicate, Lisp_Object key_func)
2617 {
2618 Elemcount split;
2619
2620 if (array_len < 2)
2621 return;
2622
2623 split = array_len / 2;
2624
2625 array_sort (array, split, c_predicate, predicate, key_func);
2626 array_sort (array + split, array_len - split, c_predicate, predicate,
2627 key_func);
2628 array_merge (array, array_len, array, split, array + split,
2629 array_len - split, c_predicate, predicate, key_func);
2630 }
2631
2632 DEFUN ("sort*", FsortX, 2, MANY, 0, /*
2633 Sort SEQUENCE, comparing elements using PREDICATE.
2634 Returns the sorted sequence. SEQUENCE is modified by side effect.
2635
2636 PREDICATE is called with two elements of SEQUENCE, and should return t if
2637 the first element is `less' than the second.
2638
2639 Optional keyword argument KEY is a function used to extract an object to be
2640 used for comparison from each element of SEQUENCE.
2641
2642 In this implementation, sorting is always stable; but call `stable-sort' if
2643 this stability is important to you, other implementations may not make the
2644 same guarantees.
2645
2646 arguments: (SEQUENCE PREDICATE &key (KEY #'IDENTITY))
2647 */
2648 (int nargs, Lisp_Object *args))
2649 {
2650 Lisp_Object sequence = args[0], predicate = args[1];
2651 Lisp_Object *sequence_carray;
2652 Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, Lisp_Object,
2653 Lisp_Object);
2654 Elemcount sequence_len, i;
2655
2656 PARSE_KEYWORDS (QsortX, nargs, args, 2, 1, (key), NULL, 0);
2657
2658 CHECK_SEQUENCE (sequence);
2659
2660 CHECK_KEY_ARGUMENT (key, c_predicate);
2661
2662 if (LISTP (sequence))
2663 {
2664 sequence = list_sort (sequence, c_predicate, predicate, key);
2665 }
2666 else if (VECTORP (sequence))
2667 {
2668 array_sort (XVECTOR_DATA (sequence), XVECTOR_LENGTH (sequence),
2669 c_predicate, predicate, key);
2670 }
2671 else if (STRINGP (sequence))
2672 {
2673 Ibyte *strdata = XSTRING_DATA (sequence);
2674 Elemcount string_ascii_begin = 0;
2675 Ichar ch;
2676
2677 sequence_len = string_char_length (sequence);
2678
2679 STRING_DATA_TO_OBJECT_ARRAY (strdata, sequence_carray, i, sequence_len);
2680
2681 /* No GCPRO necessary, characters are immediate. */
2682 array_sort (sequence_carray, sequence_len, c_predicate, predicate, key);
2683
2684 strdata = XSTRING_DATA (sequence);
2685
2686 CHECK_LISP_WRITEABLE (sequence);
2687 for (i = 0; i < sequence_len; ++i)
2688 {
2689 ch = XCHAR (sequence_carray[i]);
2690 strdata += set_itext_ichar (strdata, ch);
2691
2692 if (string_ascii_begin <= i)
2693 {
2694 if (byte_ascii_p (ch))
2695 {
2696 string_ascii_begin = i;
2697 }
2698 else
2699 {
2700 string_ascii_begin = MAX_STRING_ASCII_BEGIN;
2701 }
2702 }
2703 }
2704
2705 XSET_STRING_ASCII_BEGIN (sequence, min (string_ascii_begin,
2706 MAX_STRING_ASCII_BEGIN));
2707 bump_string_modiff (sequence);
2708 sledgehammer_check_ascii_begin (sequence);
2709 }
2710 else if (BIT_VECTORP (sequence))
2711 {
2712 Lisp_Bit_Vector *v = XBIT_VECTOR (sequence);
2713 sequence_len = bit_vector_length (v);
2714
2715 BIT_VECTOR_TO_OBJECT_ARRAY (v, sequence_carray, i, sequence_len);
2716
2717 /* No GCPRO necessary, bits are immediate. */
2718 array_sort (sequence_carray, sequence_len, c_predicate, predicate, key);
2719
2720 for (i = 0; i < sequence_len; ++i)
2721 {
2722 set_bit_vector_bit (v, i, XINT (sequence_carray [i]));
2723 }
2724 }
2725
2726 return sequence;
2727 }
2073 2728
2074 /************************************************************************/ 2729 /************************************************************************/
2075 /* property-list functions */ 2730 /* property-list functions */
2076 /************************************************************************/ 2731 /************************************************************************/
2077 2732
3122 { 3777 {
3123 return internal_old_equal (object1, object2, 0) ? Qt : Qnil; 3778 return internal_old_equal (object1, object2, 0) ? Qt : Qnil;
3124 } 3779 }
3125 3780
3126 3781
3127 DEFUN ("fillarray", Ffillarray, 2, 2, 0, /* 3782 DEFUN ("fill", Ffill, 2, MANY, 0, /*
3128 Destructively modify ARRAY by replacing each element with ITEM. 3783 Destructively modify SEQUENCE by replacing each element with ITEM.
3129 ARRAY is a vector, bit vector, or string. 3784 SEQUENCE is a list, vector, bit vector, or string.
3130 */ 3785
3131 (array, item)) 3786 Optional keyword START is the index of the first element of SEQUENCE
3132 { 3787 to be modified, and defaults to zero. Optional keyword END is the
3788 exclusive upper bound on the elements of SEQUENCE to be modified, and
3789 defaults to the length of SEQUENCE.
3790
3791 arguments: (SEQUENCE ITEM &key (START 0) END)
3792 */
3793 (int nargs, Lisp_Object *args))
3794 {
3795 Lisp_Object sequence = args[0];
3796 Lisp_Object item = args[1];
3797 Elemcount starting = 0, ending = EMACS_INT_MAX, ii;
3798
3799 PARSE_KEYWORDS (Qfill, nargs, args, 2, 2, (start, end),
3800 (start = Qzero, end = Qunbound), 0);
3801
3802 CHECK_NATNUM (start);
3803 starting = XINT (start);
3804
3805 if (!UNBOUNDP (end))
3806 {
3807 CHECK_NATNUM (end);
3808 ending = XINT (end);
3809 }
3810
3133 retry: 3811 retry:
3134 if (STRINGP (array)) 3812 if (STRINGP (sequence))
3135 { 3813 {
3136 Bytecount old_bytecount = XSTRING_LENGTH (array); 3814 Bytecount old_bytecount, new_bytecount, item_bytecount;
3137 Bytecount new_bytecount;
3138 Bytecount item_bytecount;
3139 Ibyte item_buf[MAX_ICHAR_LEN]; 3815 Ibyte item_buf[MAX_ICHAR_LEN];
3140 Ibyte *p; 3816 Ibyte *p;
3141 Ibyte *end; 3817 Ibyte *pend;
3142 3818
3143 CHECK_CHAR_COERCE_INT (item); 3819 CHECK_CHAR_COERCE_INT (item);
3144 3820
3145 CHECK_LISP_WRITEABLE (array); 3821 CHECK_LISP_WRITEABLE (sequence);
3146 sledgehammer_check_ascii_begin (array); 3822 sledgehammer_check_ascii_begin (sequence);
3147 item_bytecount = set_itext_ichar (item_buf, XCHAR (item)); 3823 item_bytecount = set_itext_ichar (item_buf, XCHAR (item));
3148 new_bytecount = item_bytecount * (Bytecount) string_char_length (array); 3824
3149 3825 p = XSTRING_DATA (sequence);
3150 resize_string (array, -1, new_bytecount - old_bytecount); 3826 p = (Ibyte *) itext_n_addr (p, starting);
3151 3827 old_bytecount = p - XSTRING_DATA (sequence);
3152 for (p = XSTRING_DATA (array), end = p + new_bytecount; 3828
3153 p < end; 3829 ending = min (ending, string_char_length (sequence));
3154 p += item_bytecount) 3830 pend = (Ibyte *) itext_n_addr (p, ending - starting);
3831
3832 new_bytecount = old_bytecount + (item_bytecount * (ending - starting));
3833 resize_string (sequence, -1, new_bytecount - old_bytecount);
3834
3835 for (; p < pend; p += item_bytecount)
3155 memcpy (p, item_buf, item_bytecount); 3836 memcpy (p, item_buf, item_bytecount);
3156 *p = '\0'; 3837 *p = '\0';
3157 3838
3158 XSET_STRING_ASCII_BEGIN (array, 3839 XSET_STRING_ASCII_BEGIN (sequence,
3159 item_bytecount == 1 ? 3840 item_bytecount == 1 ?
3160 min (new_bytecount, MAX_STRING_ASCII_BEGIN) : 3841 min (new_bytecount, MAX_STRING_ASCII_BEGIN) :
3161 0); 3842 0);
3162 bump_string_modiff (array); 3843 bump_string_modiff (sequence);
3163 sledgehammer_check_ascii_begin (array); 3844 sledgehammer_check_ascii_begin (sequence);
3164 } 3845 }
3165 else if (VECTORP (array)) 3846 else if (VECTORP (sequence))
3166 { 3847 {
3167 Lisp_Object *p = XVECTOR_DATA (array); 3848 Lisp_Object *p = XVECTOR_DATA (sequence);
3168 Elemcount len = XVECTOR_LENGTH (array); 3849 CHECK_LISP_WRITEABLE (sequence);
3169 CHECK_LISP_WRITEABLE (array); 3850
3170 while (len--) 3851 ending = min (ending, XVECTOR_LENGTH (sequence));
3171 *p++ = item; 3852 for (ii = starting; ii < ending; ++ii)
3172 } 3853 {
3173 else if (BIT_VECTORP (array)) 3854 p[ii] = item;
3174 { 3855 }
3175 Lisp_Bit_Vector *v = XBIT_VECTOR (array); 3856 }
3176 Elemcount len = bit_vector_length (v); 3857 else if (BIT_VECTORP (sequence))
3858 {
3859 Lisp_Bit_Vector *v = XBIT_VECTOR (sequence);
3177 int bit; 3860 int bit;
3178 CHECK_BIT (item); 3861 CHECK_BIT (item);
3179 bit = XINT (item); 3862 bit = XINT (item);
3180 CHECK_LISP_WRITEABLE (array); 3863 CHECK_LISP_WRITEABLE (sequence);
3181 while (len--) 3864
3182 set_bit_vector_bit (v, len, bit); 3865 ending = min (ending, bit_vector_length (v));
3866 for (ii = starting; ii < ending; ++ii)
3867 {
3868 set_bit_vector_bit (v, ii, bit);
3869 }
3870 }
3871 else if (LISTP (sequence))
3872 {
3873 Elemcount counting = 0;
3874
3875 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
3876 {
3877 if (counting >= starting)
3878 {
3879 if (counting < ending)
3880 {
3881 XSETCAR (tail, item);
3882 }
3883 else if (counting == ending)
3884 {
3885 break;
3886 }
3887 }
3888 ++counting;
3889 }
3183 } 3890 }
3184 else 3891 else
3185 { 3892 {
3186 array = wrong_type_argument (Qarrayp, array); 3893 sequence = wrong_type_argument (Qsequencep, sequence);
3187 goto retry; 3894 goto retry;
3188 } 3895 }
3189 return array; 3896 return sequence;
3190 } 3897 }
3191 3898
3192 Lisp_Object 3899 Lisp_Object
3193 nconc2 (Lisp_Object arg1, Lisp_Object arg2) 3900 nconc2 (Lisp_Object arg1, Lisp_Object arg2)
3194 { 3901 {
4756 syms_of_fns (void) 5463 syms_of_fns (void)
4757 { 5464 {
4758 INIT_LISP_OBJECT (bit_vector); 5465 INIT_LISP_OBJECT (bit_vector);
4759 5466
4760 DEFSYMBOL (Qstring_lessp); 5467 DEFSYMBOL (Qstring_lessp);
5468 DEFSYMBOL (Qsort);
5469 DEFSYMBOL (Qmerge);
5470 DEFSYMBOL (Qfill);
4761 DEFSYMBOL (Qidentity); 5471 DEFSYMBOL (Qidentity);
4762 DEFSYMBOL (Qvector); 5472 DEFSYMBOL (Qvector);
4763 DEFSYMBOL (Qarray); 5473 DEFSYMBOL (Qarray);
4764 DEFSYMBOL (Qstring); 5474 DEFSYMBOL (Qstring);
4765 DEFSYMBOL (Qlist); 5475 DEFSYMBOL (Qlist);
4766 DEFSYMBOL (Qbit_vector); 5476 DEFSYMBOL (Qbit_vector);
5477 defsymbol (&QsortX, "sort*");
4767 5478
4768 DEFSYMBOL (Qyes_or_no_p); 5479 DEFSYMBOL (Qyes_or_no_p);
4769 5480
4770 DEFERROR_STANDARD (Qbase64_conversion_error, Qconversion_error); 5481 DEFERROR_STANDARD (Qbase64_conversion_error, Qconversion_error);
4771 5482
4812 DEFSUBR (Fremassq); 5523 DEFSUBR (Fremassq);
4813 DEFSUBR (Fremrassoc); 5524 DEFSUBR (Fremrassoc);
4814 DEFSUBR (Fremrassq); 5525 DEFSUBR (Fremrassq);
4815 DEFSUBR (Fnreverse); 5526 DEFSUBR (Fnreverse);
4816 DEFSUBR (Freverse); 5527 DEFSUBR (Freverse);
4817 DEFSUBR (Fsort); 5528 DEFSUBR (FsortX);
5529 Ffset (intern ("sort"), QsortX);
5530 DEFSUBR (Fmerge);
4818 DEFSUBR (Fplists_eq); 5531 DEFSUBR (Fplists_eq);
4819 DEFSUBR (Fplists_equal); 5532 DEFSUBR (Fplists_equal);
4820 DEFSUBR (Flax_plists_eq); 5533 DEFSUBR (Flax_plists_eq);
4821 DEFSUBR (Flax_plists_equal); 5534 DEFSUBR (Flax_plists_equal);
4822 DEFSUBR (Fplist_get); 5535 DEFSUBR (Fplist_get);
4837 DEFSUBR (Fremprop); 5550 DEFSUBR (Fremprop);
4838 DEFSUBR (Fobject_plist); 5551 DEFSUBR (Fobject_plist);
4839 DEFSUBR (Fequal); 5552 DEFSUBR (Fequal);
4840 DEFSUBR (Fequalp); 5553 DEFSUBR (Fequalp);
4841 DEFSUBR (Fold_equal); 5554 DEFSUBR (Fold_equal);
4842 DEFSUBR (Ffillarray); 5555 DEFSUBR (Ffill);
5556 Ffset (intern ("fillarray"), Qfill);
5557
4843 DEFSUBR (Fnconc); 5558 DEFSUBR (Fnconc);
4844 DEFSUBR (FmapcarX); 5559 DEFSUBR (FmapcarX);
4845 DEFSUBR (Fmapvector); 5560 DEFSUBR (Fmapvector);
4846 DEFSUBR (Fmapcan); 5561 DEFSUBR (Fmapcan);
4847 DEFSUBR (Fmapc); 5562 DEFSUBR (Fmapc);