Commit | Line | Data |
---|---|---|
212e58ed DH |
1 | /* Copyright (C) 1995,1996,1997,2000,2001,2003,2004 |
2 | * Free Software Foundation, Inc. | |
0f2d19dd | 3 | * |
73be1d9e MV |
4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser General Public | |
6 | * License as published by the Free Software Foundation; either | |
7 | * version 2.1 of the License, or (at your option) any later version. | |
0f2d19dd | 8 | * |
73be1d9e MV |
9 | * This library is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | * Lesser General Public License for more details. | |
0f2d19dd | 13 | * |
73be1d9e MV |
14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with this library; if not, write to the Free Software | |
92205699 | 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
73be1d9e | 17 | */ |
1bbd0b84 | 18 | |
1bbd0b84 | 19 | |
0f2d19dd | 20 | \f |
a0599745 MD |
21 | #include "libguile/_scm.h" |
22 | #include "libguile/eq.h" | |
c96d76b8 | 23 | #include "libguile/lang.h" |
20e6290e | 24 | |
a0599745 MD |
25 | #include "libguile/validate.h" |
26 | #include "libguile/list.h" | |
c614a00b | 27 | #include "libguile/eval.h" |
0f2d19dd | 28 | |
0f2d19dd | 29 | #include <stdarg.h> |
0f2d19dd JB |
30 | |
31 | \f | |
df13742c | 32 | /* creating lists */ |
0f2d19dd | 33 | |
34d19ef6 | 34 | #define SCM_I_CONS(cell, x, y) \ |
1afff620 | 35 | do { \ |
228a24ef | 36 | cell = scm_cell ((scm_t_bits)x, (scm_t_bits)y); \ |
1afff620 KN |
37 | } while (0) |
38 | ||
39 | SCM | |
40 | scm_list_1 (SCM e1) | |
41 | { | |
42 | SCM c1; | |
43 | SCM_I_CONS (c1, e1, SCM_EOL); | |
44 | return c1; | |
45 | } | |
46 | ||
47 | SCM | |
48 | scm_list_2 (SCM e1, SCM e2) | |
49 | { | |
50 | SCM c1, c2; | |
51 | SCM_I_CONS (c2, e2, SCM_EOL); | |
52 | SCM_I_CONS (c1, e1, c2); | |
53 | return c1; | |
54 | } | |
55 | ||
56 | SCM | |
57 | scm_list_3 (SCM e1, SCM e2, SCM e3) | |
58 | { | |
59 | SCM c1, c2, c3; | |
60 | SCM_I_CONS (c3, e3, SCM_EOL); | |
61 | SCM_I_CONS (c2, e2, c3); | |
62 | SCM_I_CONS (c1, e1, c2); | |
63 | return c1; | |
64 | } | |
65 | ||
66 | SCM | |
67 | scm_list_4 (SCM e1, SCM e2, SCM e3, SCM e4) | |
68 | { | |
69 | return scm_cons2 (e1, e2, scm_list_2 (e3, e4)); | |
70 | } | |
71 | ||
72 | SCM | |
73 | scm_list_5 (SCM e1, SCM e2, SCM e3, SCM e4, SCM e5) | |
74 | { | |
75 | return scm_cons2 (e1, e2, scm_list_3 (e3, e4, e5)); | |
76 | } | |
77 | ||
0f2d19dd | 78 | SCM |
1afff620 | 79 | scm_list_n (SCM elt, ...) |
0f2d19dd JB |
80 | { |
81 | va_list foo; | |
2de14ecd GB |
82 | SCM answer = SCM_EOL; |
83 | SCM *pos = &answer; | |
0f2d19dd | 84 | |
0dbfb25a | 85 | va_start (foo, elt); |
fbd485ba | 86 | while (! SCM_UNBNDP (elt)) |
0f2d19dd | 87 | { |
1e55d288 | 88 | #if (SCM_DEBUG_CELL_ACCESSES == 1) |
eb741d98 HWN |
89 | if (SCM_NIMP (elt)) |
90 | SCM_VALIDATE_CELL(elt, 0); | |
1e55d288 | 91 | #endif |
0f2d19dd | 92 | *pos = scm_cons (elt, SCM_EOL); |
25d8012c | 93 | pos = SCM_CDRLOC (*pos); |
0f2d19dd JB |
94 | elt = va_arg (foo, SCM); |
95 | } | |
de90ef0f | 96 | va_end (foo); |
0f2d19dd JB |
97 | return answer; |
98 | } | |
99 | ||
100 | ||
2ac6b60e KR |
101 | SCM_DEFINE (scm_make_list, "make-list", 1, 1, 0, |
102 | (SCM n, SCM init), | |
103 | "Create a list containing of @var{n} elements, where each\n" | |
104 | "element is initialized to @var{init}. @var{init} defaults to\n" | |
105 | "the empty list @code{()} if not given.") | |
106 | #define FUNC_NAME s_scm_srfi1_count | |
107 | { | |
108 | unsigned nn = scm_to_uint (n); | |
109 | unsigned i; | |
110 | SCM ret = SCM_EOL; | |
111 | ||
112 | if (SCM_UNBNDP (init)) | |
113 | init = SCM_EOL; | |
114 | ||
115 | for (i = 0; i < nn; i++) | |
116 | ret = scm_cons (init, ret); | |
117 | return ret; | |
118 | } | |
119 | #undef FUNC_NAME | |
120 | ||
121 | ||
b906b056 | 122 | SCM_DEFINE (scm_cons_star, "cons*", 1, 0, 1, |
1bbd0b84 | 123 | (SCM arg, SCM rest), |
5352393c MG |
124 | "Like @code{list}, but the last arg provides the tail of the\n" |
125 | "constructed list, returning @code{(cons @var{arg1} (cons\n" | |
a17bb5fd | 126 | "@var{arg2} (cons @dots{} @var{argn})))}. Requires at least one\n" |
5352393c MG |
127 | "argument. If given one argument, that argument is returned as\n" |
128 | "result. This function is called @code{list*} in some other\n" | |
129 | "Schemes and in Common LISP.") | |
26a379b2 | 130 | #define FUNC_NAME s_scm_cons_star |
a610b8d9 | 131 | { |
b906b056 KR |
132 | SCM ret = SCM_EOL; |
133 | SCM *p = &ret; | |
134 | ||
af45e3b0 | 135 | SCM_VALIDATE_REST_ARGUMENT (rest); |
b906b056 KR |
136 | |
137 | for ( ; scm_is_pair (rest); rest = SCM_CDR (rest)) | |
a610b8d9 | 138 | { |
b906b056 KR |
139 | *p = scm_cons (arg, SCM_EOL); |
140 | p = SCM_CDRLOC (*p); | |
141 | arg = SCM_CAR (rest); | |
a610b8d9 | 142 | } |
b906b056 KR |
143 | |
144 | *p = arg; | |
145 | return ret; | |
a610b8d9 | 146 | } |
1bbd0b84 | 147 | #undef FUNC_NAME |
a610b8d9 | 148 | |
0f2d19dd JB |
149 | |
150 | \f | |
df13742c | 151 | /* general questions about lists --- null?, list?, length, etc. */ |
0f2d19dd | 152 | |
3b3b36dd | 153 | SCM_DEFINE (scm_null_p, "null?", 1, 0, 0, |
1bbd0b84 | 154 | (SCM x), |
5352393c | 155 | "Return @code{#t} iff @var{x} is the empty list, else @code{#f}.") |
1bbd0b84 | 156 | #define FUNC_NAME s_scm_null_p |
0f2d19dd | 157 | { |
7888309b | 158 | return scm_from_bool (SCM_NULL_OR_NIL_P (x)); |
0f2d19dd | 159 | } |
1bbd0b84 | 160 | #undef FUNC_NAME |
0f2d19dd | 161 | |
2de14ecd | 162 | |
3b3b36dd | 163 | SCM_DEFINE (scm_list_p, "list?", 1, 0, 0, |
1bbd0b84 | 164 | (SCM x), |
5352393c | 165 | "Return @code{#t} iff @var{x} is a proper list, else @code{#f}.") |
1bbd0b84 | 166 | #define FUNC_NAME s_scm_list_p |
0f2d19dd | 167 | { |
7888309b | 168 | return scm_from_bool (scm_ilength (x) >= 0); |
0f2d19dd | 169 | } |
1bbd0b84 | 170 | #undef FUNC_NAME |
0f2d19dd JB |
171 | |
172 | ||
df13742c | 173 | /* Return the length of SX, or -1 if it's not a proper list. |
448a3bc2 | 174 | This uses the "tortoise and hare" algorithm to detect "infinitely |
df13742c JB |
175 | long" lists (i.e. lists with cycles in their cdrs), and returns -1 |
176 | if it does find one. */ | |
c014a02e ML |
177 | long |
178 | scm_ilength(SCM sx) | |
0f2d19dd | 179 | { |
c014a02e | 180 | long i = 0; |
e1385ffc GB |
181 | SCM tortoise = sx; |
182 | SCM hare = sx; | |
df13742c | 183 | |
0f2d19dd | 184 | do { |
c96d76b8 | 185 | if (SCM_NULL_OR_NIL_P(hare)) return i; |
d2e53ed6 | 186 | if (!scm_is_pair (hare)) return -1; |
df13742c | 187 | hare = SCM_CDR(hare); |
0f2d19dd | 188 | i++; |
c96d76b8 | 189 | if (SCM_NULL_OR_NIL_P(hare)) return i; |
d2e53ed6 | 190 | if (!scm_is_pair (hare)) return -1; |
df13742c | 191 | hare = SCM_CDR(hare); |
0f2d19dd | 192 | i++; |
448a3bc2 JB |
193 | /* For every two steps the hare takes, the tortoise takes one. */ |
194 | tortoise = SCM_CDR(tortoise); | |
0f2d19dd | 195 | } |
bc36d050 | 196 | while (!scm_is_eq (hare, tortoise)); |
df13742c | 197 | |
448a3bc2 | 198 | /* If the tortoise ever catches the hare, then the list must contain |
df13742c | 199 | a cycle. */ |
0f2d19dd JB |
200 | return -1; |
201 | } | |
202 | ||
2de14ecd | 203 | |
3b3b36dd | 204 | SCM_DEFINE (scm_length, "length", 1, 0, 0, |
1bbd0b84 | 205 | (SCM lst), |
5352393c | 206 | "Return the number of elements in list @var{lst}.") |
1bbd0b84 | 207 | #define FUNC_NAME s_scm_length |
0f2d19dd | 208 | { |
c014a02e | 209 | long i; |
34d19ef6 | 210 | SCM_VALIDATE_LIST_COPYLEN (1, lst, i); |
e11e83f3 | 211 | return scm_from_long (i); |
0f2d19dd | 212 | } |
1bbd0b84 | 213 | #undef FUNC_NAME |
0f2d19dd JB |
214 | |
215 | ||
216 | \f | |
df13742c | 217 | /* appending lists */ |
0f2d19dd | 218 | |
a1ec6916 | 219 | SCM_DEFINE (scm_append, "append", 0, 0, 1, |
1bbd0b84 | 220 | (SCM args), |
5352393c MG |
221 | "Return a list consisting of the elements the lists passed as\n" |
222 | "arguments.\n" | |
1e6808ea | 223 | "@lisp\n" |
5352393c MG |
224 | "(append '(x) '(y)) @result{} (x y)\n" |
225 | "(append '(a) '(b c d)) @result{} (a b c d)\n" | |
226 | "(append '(a (b)) '((c))) @result{} (a (b) (c))\n" | |
1e6808ea | 227 | "@end lisp\n" |
5352393c MG |
228 | "The resulting list is always newly allocated, except that it\n" |
229 | "shares structure with the last list argument. The last\n" | |
230 | "argument may actually be any object; an improper list results\n" | |
231 | "if the last argument is not a proper list.\n" | |
1e6808ea | 232 | "@lisp\n" |
5352393c MG |
233 | "(append '(a b) '(c . d)) @result{} (a b c . d)\n" |
234 | "(append '() 'a) @result{} a\n" | |
1e6808ea | 235 | "@end lisp") |
1bbd0b84 | 236 | #define FUNC_NAME s_scm_append |
0f2d19dd | 237 | { |
af45e3b0 | 238 | SCM_VALIDATE_REST_ARGUMENT (args); |
d2e53ed6 | 239 | if (scm_is_null (args)) { |
af45e3b0 DH |
240 | return SCM_EOL; |
241 | } else { | |
242 | SCM res = SCM_EOL; | |
243 | SCM *lloc = &res; | |
244 | SCM arg = SCM_CAR (args); | |
4c13270f | 245 | int argnum = 1; |
af45e3b0 | 246 | args = SCM_CDR (args); |
d2e53ed6 MV |
247 | while (!scm_is_null (args)) { |
248 | while (scm_is_pair (arg)) { | |
af45e3b0 DH |
249 | *lloc = scm_cons (SCM_CAR (arg), SCM_EOL); |
250 | lloc = SCM_CDRLOC (*lloc); | |
251 | arg = SCM_CDR (arg); | |
252 | } | |
4c13270f | 253 | SCM_VALIDATE_NULL_OR_NIL (argnum, arg); |
af45e3b0 DH |
254 | arg = SCM_CAR (args); |
255 | args = SCM_CDR (args); | |
4c13270f | 256 | argnum++; |
af45e3b0 DH |
257 | }; |
258 | *lloc = arg; | |
0f2d19dd JB |
259 | return res; |
260 | } | |
0f2d19dd | 261 | } |
1bbd0b84 | 262 | #undef FUNC_NAME |
0f2d19dd JB |
263 | |
264 | ||
a1ec6916 | 265 | SCM_DEFINE (scm_append_x, "append!", 0, 0, 1, |
1e6808ea MG |
266 | (SCM lists), |
267 | "A destructive version of @code{append} (@pxref{Pairs and\n" | |
7a095584 | 268 | "Lists,,,r5rs, The Revised^5 Report on Scheme}). The cdr field\n" |
1e6808ea | 269 | "of each list's final pair is changed to point to the head of\n" |
71a89639 | 270 | "the next list, so no consing is performed. Return\n" |
1e6808ea | 271 | "the mutated list.") |
1bbd0b84 | 272 | #define FUNC_NAME s_scm_append_x |
0f2d19dd | 273 | { |
d4641098 | 274 | SCM ret, *loc; |
1e6808ea | 275 | SCM_VALIDATE_REST_ARGUMENT (lists); |
d4641098 | 276 | |
d2e53ed6 | 277 | if (scm_is_null (lists)) |
d4641098 KR |
278 | return SCM_EOL; |
279 | ||
280 | loc = &ret; | |
281 | for (;;) | |
282 | { | |
1e6808ea | 283 | SCM arg = SCM_CAR (lists); |
d4641098 KR |
284 | *loc = arg; |
285 | ||
1e6808ea | 286 | lists = SCM_CDR (lists); |
d2e53ed6 | 287 | if (scm_is_null (lists)) |
d4641098 KR |
288 | return ret; |
289 | ||
290 | if (!SCM_NULL_OR_NIL_P (arg)) | |
291 | { | |
292 | SCM_VALIDATE_CONS (SCM_ARG1, arg); | |
293 | loc = SCM_CDRLOC (scm_last_pair (arg)); | |
294 | } | |
af45e3b0 | 295 | } |
0f2d19dd | 296 | } |
1bbd0b84 | 297 | #undef FUNC_NAME |
0f2d19dd JB |
298 | |
299 | ||
3b3b36dd | 300 | SCM_DEFINE (scm_last_pair, "last-pair", 1, 0, 0, |
e1385ffc | 301 | (SCM lst), |
71a89639 | 302 | "Return the last pair in @var{lst}, signalling an error if\n" |
b380b885 | 303 | "@var{lst} is circular.") |
1bbd0b84 | 304 | #define FUNC_NAME s_scm_last_pair |
df13742c | 305 | { |
e1385ffc GB |
306 | SCM tortoise = lst; |
307 | SCM hare = lst; | |
0f2d19dd | 308 | |
c96d76b8 NJ |
309 | if (SCM_NULL_OR_NIL_P (lst)) |
310 | return lst; | |
df13742c | 311 | |
e1385ffc GB |
312 | SCM_VALIDATE_CONS (SCM_ARG1, lst); |
313 | do { | |
314 | SCM ahead = SCM_CDR(hare); | |
d2e53ed6 | 315 | if (!scm_is_pair (ahead)) return hare; |
e1385ffc GB |
316 | hare = ahead; |
317 | ahead = SCM_CDR(hare); | |
d2e53ed6 | 318 | if (!scm_is_pair (ahead)) return hare; |
e1385ffc GB |
319 | hare = ahead; |
320 | tortoise = SCM_CDR(tortoise); | |
df13742c | 321 | } |
bc36d050 | 322 | while (!scm_is_eq (hare, tortoise)); |
1afff620 | 323 | SCM_MISC_ERROR ("Circular structure in position 1: ~S", scm_list_1 (lst)); |
df13742c | 324 | } |
1bbd0b84 | 325 | #undef FUNC_NAME |
df13742c JB |
326 | |
327 | \f | |
328 | /* reversing lists */ | |
0f2d19dd | 329 | |
a1ec6916 | 330 | SCM_DEFINE (scm_reverse, "reverse", 1, 0, 0, |
e1385ffc | 331 | (SCM lst), |
5352393c MG |
332 | "Return a new list that contains the elements of @var{lst} but\n" |
333 | "in reverse order.") | |
e1385ffc GB |
334 | #define FUNC_NAME s_scm_reverse |
335 | { | |
336 | SCM result = SCM_EOL; | |
337 | SCM tortoise = lst; | |
338 | SCM hare = lst; | |
339 | ||
340 | do { | |
c96d76b8 | 341 | if (SCM_NULL_OR_NIL_P(hare)) return result; |
d2e53ed6 | 342 | SCM_ASSERT(scm_is_pair(hare), lst, 1, FUNC_NAME); |
e1385ffc GB |
343 | result = scm_cons (SCM_CAR (hare), result); |
344 | hare = SCM_CDR (hare); | |
c96d76b8 | 345 | if (SCM_NULL_OR_NIL_P(hare)) return result; |
d2e53ed6 | 346 | SCM_ASSERT(scm_is_pair(hare), lst, 1, FUNC_NAME); |
e1385ffc GB |
347 | result = scm_cons (SCM_CAR (hare), result); |
348 | hare = SCM_CDR (hare); | |
349 | tortoise = SCM_CDR (tortoise); | |
350 | } | |
bc36d050 | 351 | while (!scm_is_eq (hare, tortoise)); |
1afff620 | 352 | SCM_MISC_ERROR ("Circular structure in position 1: ~S", scm_list_1 (lst)); |
e1385ffc GB |
353 | } |
354 | #undef FUNC_NAME | |
355 | ||
356 | SCM_DEFINE (scm_reverse_x, "reverse!", 1, 1, 0, | |
357 | (SCM lst, SCM new_tail), | |
7a095584 NJ |
358 | "A destructive version of @code{reverse} (@pxref{Pairs and Lists,,,r5rs,\n" |
359 | "The Revised^5 Report on Scheme}). The cdr of each cell in @var{lst} is\n" | |
71a89639 MV |
360 | "modified to point to the previous list element. Return the\n" |
361 | "reversed list.\n\n" | |
b380b885 MD |
362 | "Caveat: because the list is modified in place, the tail of the original\n" |
363 | "list now becomes its head, and the head of the original list now becomes\n" | |
364 | "the tail. Therefore, the @var{lst} symbol to which the head of the\n" | |
365 | "original list was bound now points to the tail. To ensure that the head\n" | |
366 | "of the modified list is not lost, it is wise to save the return value of\n" | |
367 | "@code{reverse!}") | |
1bbd0b84 | 368 | #define FUNC_NAME s_scm_reverse_x |
0f2d19dd | 369 | { |
e39c3de4 | 370 | SCM_VALIDATE_LIST (1, lst); |
3946f0de MD |
371 | if (SCM_UNBNDP (new_tail)) |
372 | new_tail = SCM_EOL; | |
373 | else | |
e39c3de4 | 374 | SCM_VALIDATE_LIST (2, new_tail); |
0f2d19dd | 375 | |
c96d76b8 | 376 | while (!SCM_NULL_OR_NIL_P (lst)) |
3946f0de | 377 | { |
e1385ffc GB |
378 | SCM old_tail = SCM_CDR (lst); |
379 | SCM_SETCDR (lst, new_tail); | |
380 | new_tail = lst; | |
381 | lst = old_tail; | |
3946f0de MD |
382 | } |
383 | return new_tail; | |
0f2d19dd | 384 | } |
1bbd0b84 | 385 | #undef FUNC_NAME |
0f2d19dd | 386 | |
0f2d19dd | 387 | \f |
685c0d71 | 388 | |
df13742c | 389 | /* indexing lists by element number */ |
0f2d19dd | 390 | |
3b3b36dd | 391 | SCM_DEFINE (scm_list_ref, "list-ref", 2, 0, 0, |
685c0d71 | 392 | (SCM list, SCM k), |
5352393c | 393 | "Return the @var{k}th element from @var{list}.") |
1bbd0b84 GB |
394 | #define FUNC_NAME s_scm_list_ref |
395 | { | |
685c0d71 | 396 | SCM lst = list; |
c014a02e | 397 | unsigned long int i; |
a55c2b68 | 398 | i = scm_to_ulong (k); |
d2e53ed6 | 399 | while (scm_is_pair (lst)) { |
685c0d71 DH |
400 | if (i == 0) |
401 | return SCM_CAR (lst); | |
402 | else { | |
403 | --i; | |
404 | lst = SCM_CDR (lst); | |
405 | } | |
406 | }; | |
c96d76b8 | 407 | if (SCM_NULL_OR_NIL_P (lst)) |
685c0d71 DH |
408 | SCM_OUT_OF_RANGE (2, k); |
409 | else | |
410 | SCM_WRONG_TYPE_ARG (1, list); | |
0f2d19dd | 411 | } |
1bbd0b84 | 412 | #undef FUNC_NAME |
0f2d19dd | 413 | |
685c0d71 | 414 | |
3b3b36dd | 415 | SCM_DEFINE (scm_list_set_x, "list-set!", 3, 0, 0, |
685c0d71 DH |
416 | (SCM list, SCM k, SCM val), |
417 | "Set the @var{k}th element of @var{list} to @var{val}.") | |
1bbd0b84 GB |
418 | #define FUNC_NAME s_scm_list_set_x |
419 | { | |
685c0d71 | 420 | SCM lst = list; |
a55c2b68 | 421 | unsigned long int i = scm_to_ulong (k); |
d2e53ed6 | 422 | while (scm_is_pair (lst)) { |
685c0d71 DH |
423 | if (i == 0) { |
424 | SCM_SETCAR (lst, val); | |
425 | return val; | |
426 | } else { | |
427 | --i; | |
428 | lst = SCM_CDR (lst); | |
429 | } | |
430 | }; | |
c96d76b8 | 431 | if (SCM_NULL_OR_NIL_P (lst)) |
685c0d71 DH |
432 | SCM_OUT_OF_RANGE (2, k); |
433 | else | |
434 | SCM_WRONG_TYPE_ARG (1, list); | |
0f2d19dd | 435 | } |
1bbd0b84 | 436 | #undef FUNC_NAME |
0f2d19dd JB |
437 | |
438 | ||
1bbd0b84 GB |
439 | SCM_REGISTER_PROC(s_list_cdr_ref, "list-cdr-ref", 2, 0, 0, scm_list_tail); |
440 | ||
3b3b36dd | 441 | SCM_DEFINE (scm_list_tail, "list-tail", 2, 0, 0, |
1bbd0b84 | 442 | (SCM lst, SCM k), |
8f85c0c6 | 443 | "@deffnx {Scheme Procedure} list-cdr-ref lst k\n" |
b380b885 MD |
444 | "Return the \"tail\" of @var{lst} beginning with its @var{k}th element.\n" |
445 | "The first element of the list is considered to be element 0.\n\n" | |
872e0c72 | 446 | "@code{list-tail} and @code{list-cdr-ref} are identical. It may help to\n" |
b380b885 MD |
447 | "think of @code{list-cdr-ref} as accessing the @var{k}th cdr of the list,\n" |
448 | "or returning the results of cdring @var{k} times down @var{lst}.") | |
1bbd0b84 | 449 | #define FUNC_NAME s_scm_list_tail |
df13742c | 450 | { |
a55c2b68 | 451 | size_t i = scm_to_size_t (k); |
df13742c | 452 | while (i-- > 0) { |
34d19ef6 | 453 | SCM_VALIDATE_CONS (1, lst); |
df13742c JB |
454 | lst = SCM_CDR(lst); |
455 | } | |
456 | return lst; | |
457 | } | |
1bbd0b84 | 458 | #undef FUNC_NAME |
df13742c | 459 | |
0f2d19dd | 460 | |
3b3b36dd | 461 | SCM_DEFINE (scm_list_cdr_set_x, "list-cdr-set!", 3, 0, 0, |
685c0d71 DH |
462 | (SCM list, SCM k, SCM val), |
463 | "Set the @var{k}th cdr of @var{list} to @var{val}.") | |
1bbd0b84 GB |
464 | #define FUNC_NAME s_scm_list_cdr_set_x |
465 | { | |
685c0d71 | 466 | SCM lst = list; |
a55c2b68 | 467 | size_t i = scm_to_size_t (k); |
d2e53ed6 | 468 | while (scm_is_pair (lst)) { |
685c0d71 DH |
469 | if (i == 0) { |
470 | SCM_SETCDR (lst, val); | |
471 | return val; | |
472 | } else { | |
473 | --i; | |
474 | lst = SCM_CDR (lst); | |
475 | } | |
476 | }; | |
c96d76b8 | 477 | if (SCM_NULL_OR_NIL_P (lst)) |
685c0d71 DH |
478 | SCM_OUT_OF_RANGE (2, k); |
479 | else | |
480 | SCM_WRONG_TYPE_ARG (1, list); | |
0f2d19dd | 481 | } |
1bbd0b84 | 482 | #undef FUNC_NAME |
0f2d19dd JB |
483 | |
484 | ||
485 | \f | |
df13742c | 486 | /* copying lists, perhaps partially */ |
0f2d19dd | 487 | |
3b3b36dd | 488 | SCM_DEFINE (scm_list_head, "list-head", 2, 0, 0, |
1bbd0b84 | 489 | (SCM lst, SCM k), |
b380b885 MD |
490 | "Copy the first @var{k} elements from @var{lst} into a new list, and\n" |
491 | "return it.") | |
1bbd0b84 | 492 | #define FUNC_NAME s_scm_list_head |
0f2d19dd JB |
493 | { |
494 | SCM answer; | |
495 | SCM * pos; | |
a55c2b68 | 496 | size_t i = scm_to_size_t (k); |
0f2d19dd | 497 | |
0f2d19dd JB |
498 | answer = SCM_EOL; |
499 | pos = &answer; | |
0f2d19dd JB |
500 | while (i-- > 0) |
501 | { | |
34d19ef6 | 502 | SCM_VALIDATE_CONS (1, lst); |
0f2d19dd | 503 | *pos = scm_cons (SCM_CAR (lst), SCM_EOL); |
25d8012c | 504 | pos = SCM_CDRLOC (*pos); |
0f2d19dd JB |
505 | lst = SCM_CDR(lst); |
506 | } | |
507 | return answer; | |
508 | } | |
1bbd0b84 | 509 | #undef FUNC_NAME |
0f2d19dd JB |
510 | |
511 | ||
212e58ed DH |
512 | /* Copy a list which is known to be finite. The last pair may or may not have |
513 | * a '() in its cdr. That is, improper lists are accepted. */ | |
514 | SCM | |
515 | scm_i_finite_list_copy (SCM list) | |
516 | { | |
d2e53ed6 | 517 | if (!scm_is_pair (list)) |
212e58ed DH |
518 | { |
519 | return list; | |
520 | } | |
521 | else | |
522 | { | |
523 | SCM tail; | |
524 | const SCM result = tail = scm_list_1 (SCM_CAR (list)); | |
525 | list = SCM_CDR (list); | |
d2e53ed6 | 526 | while (scm_is_pair (list)) |
212e58ed DH |
527 | { |
528 | const SCM new_tail = scm_list_1 (SCM_CAR (list)); | |
529 | SCM_SETCDR (tail, new_tail); | |
530 | tail = new_tail; | |
531 | list = SCM_CDR (list); | |
532 | } | |
533 | SCM_SETCDR (tail, list); | |
534 | ||
535 | return result; | |
536 | } | |
537 | } | |
538 | ||
539 | ||
a1ec6916 | 540 | SCM_DEFINE (scm_list_copy, "list-copy", 1, 0, 0, |
1bbd0b84 | 541 | (SCM lst), |
b380b885 | 542 | "Return a (newly-created) copy of @var{lst}.") |
1bbd0b84 | 543 | #define FUNC_NAME s_scm_list_copy |
df13742c JB |
544 | { |
545 | SCM newlst; | |
546 | SCM * fill_here; | |
547 | SCM from_here; | |
548 | ||
5d6bb349 KN |
549 | SCM_VALIDATE_LIST (1, lst); |
550 | ||
df13742c JB |
551 | newlst = SCM_EOL; |
552 | fill_here = &newlst; | |
553 | from_here = lst; | |
554 | ||
d2e53ed6 | 555 | while (scm_is_pair (from_here)) |
df13742c JB |
556 | { |
557 | SCM c; | |
558 | c = scm_cons (SCM_CAR (from_here), SCM_CDR (from_here)); | |
559 | *fill_here = c; | |
25d8012c | 560 | fill_here = SCM_CDRLOC (c); |
df13742c JB |
561 | from_here = SCM_CDR (from_here); |
562 | } | |
563 | return newlst; | |
564 | } | |
1bbd0b84 | 565 | #undef FUNC_NAME |
df13742c | 566 | |
fad3aaf1 KR |
567 | |
568 | SCM_PROC (s_list, "list", 0, 0, 1, scm_list_copy); | |
569 | SCM_SNARF_DOCS (register, scm_list_copy, "list", (SCM objs), 0, 0, 1, | |
570 | "Return a list containing @var{objs}, the arguments to\n" | |
571 | "@code{list}.") | |
572 | ||
573 | ||
0f2d19dd | 574 | \f |
df13742c JB |
575 | /* membership tests (memq, memv, etc.) */ |
576 | ||
79a3dafe DH |
577 | /* The function scm_c_memq returns the first sublist of list whose car is |
578 | * 'eq?' obj, where the sublists of list are the non-empty lists returned by | |
579 | * (list-tail list k) for k less than the length of list. If obj does not | |
1e6808ea | 580 | * occur in list, then #f (not the empty list) is returned. |
79a3dafe DH |
581 | * List must be a proper list, otherwise scm_c_memq may crash or loop |
582 | * endlessly. | |
583 | */ | |
584 | SCM | |
585 | scm_c_memq (SCM obj, SCM list) | |
586 | { | |
c96d76b8 | 587 | for (; !SCM_NULL_OR_NIL_P (list); list = SCM_CDR (list)) |
79a3dafe | 588 | { |
bc36d050 | 589 | if (scm_is_eq (SCM_CAR (list), obj)) |
79a3dafe DH |
590 | return list; |
591 | } | |
592 | return SCM_BOOL_F; | |
593 | } | |
594 | ||
595 | ||
3b3b36dd | 596 | SCM_DEFINE (scm_memq, "memq", 2, 0, 0, |
1bbd0b84 | 597 | (SCM x, SCM lst), |
5352393c MG |
598 | "Return the first sublist of @var{lst} whose car is @code{eq?}\n" |
599 | "to @var{x} where the sublists of @var{lst} are the non-empty\n" | |
600 | "lists returned by @code{(list-tail @var{lst} @var{k})} for\n" | |
601 | "@var{k} less than the length of @var{lst}. If @var{x} does not\n" | |
602 | "occur in @var{lst}, then @code{#f} (not the empty list) is\n" | |
603 | "returned.") | |
1bbd0b84 | 604 | #define FUNC_NAME s_scm_memq |
0f2d19dd | 605 | { |
daa6ba18 | 606 | SCM_VALIDATE_LIST (2, lst); |
79a3dafe | 607 | return scm_c_memq (x, lst); |
0f2d19dd | 608 | } |
1bbd0b84 | 609 | #undef FUNC_NAME |
0f2d19dd JB |
610 | |
611 | ||
3b3b36dd | 612 | SCM_DEFINE (scm_memv, "memv", 2, 0, 0, |
1bbd0b84 | 613 | (SCM x, SCM lst), |
5352393c MG |
614 | "Return the first sublist of @var{lst} whose car is @code{eqv?}\n" |
615 | "to @var{x} where the sublists of @var{lst} are the non-empty\n" | |
616 | "lists returned by @code{(list-tail @var{lst} @var{k})} for\n" | |
617 | "@var{k} less than the length of @var{lst}. If @var{x} does not\n" | |
618 | "occur in @var{lst}, then @code{#f} (not the empty list) is\n" | |
619 | "returned.") | |
1bbd0b84 | 620 | #define FUNC_NAME s_scm_memv |
0f2d19dd | 621 | { |
daa6ba18 | 622 | SCM_VALIDATE_LIST (2, lst); |
c96d76b8 | 623 | for (; !SCM_NULL_OR_NIL_P (lst); lst = SCM_CDR (lst)) |
daa6ba18 | 624 | { |
7888309b | 625 | if (! scm_is_false (scm_eqv_p (SCM_CAR (lst), x))) |
daa6ba18 DH |
626 | return lst; |
627 | } | |
628 | return SCM_BOOL_F; | |
0f2d19dd | 629 | } |
1bbd0b84 | 630 | #undef FUNC_NAME |
0f2d19dd JB |
631 | |
632 | ||
3b3b36dd | 633 | SCM_DEFINE (scm_member, "member", 2, 0, 0, |
1bbd0b84 | 634 | (SCM x, SCM lst), |
5352393c MG |
635 | "Return the first sublist of @var{lst} whose car is\n" |
636 | "@code{equal?} to @var{x} where the sublists of @var{lst} are\n" | |
637 | "the non-empty lists returned by @code{(list-tail @var{lst}\n" | |
638 | "@var{k})} for @var{k} less than the length of @var{lst}. If\n" | |
639 | "@var{x} does not occur in @var{lst}, then @code{#f} (not the\n" | |
640 | "empty list) is returned.") | |
1bbd0b84 | 641 | #define FUNC_NAME s_scm_member |
0f2d19dd | 642 | { |
daa6ba18 | 643 | SCM_VALIDATE_LIST (2, lst); |
c96d76b8 | 644 | for (; !SCM_NULL_OR_NIL_P (lst); lst = SCM_CDR (lst)) |
daa6ba18 | 645 | { |
7888309b | 646 | if (! scm_is_false (scm_equal_p (SCM_CAR (lst), x))) |
daa6ba18 DH |
647 | return lst; |
648 | } | |
649 | return SCM_BOOL_F; | |
0f2d19dd | 650 | } |
1bbd0b84 | 651 | #undef FUNC_NAME |
0f2d19dd | 652 | |
0f2d19dd | 653 | \f |
df13742c | 654 | /* deleting elements from a list (delq, etc.) */ |
0f2d19dd | 655 | |
3b3b36dd | 656 | SCM_DEFINE (scm_delq_x, "delq!", 2, 0, 0, |
1bbd0b84 | 657 | (SCM item, SCM lst), |
8f85c0c6 NJ |
658 | "@deffnx {Scheme Procedure} delv! item lst\n" |
659 | "@deffnx {Scheme Procedure} delete! item lst\n" | |
b380b885 | 660 | "These procedures are destructive versions of @code{delq}, @code{delv}\n" |
bfefbf18 | 661 | "and @code{delete}: they modify the existing @var{lst}\n" |
b380b885 MD |
662 | "rather than creating a new list. Caveat evaluator: Like other\n" |
663 | "destructive list functions, these functions cannot modify the binding of\n" | |
664 | "@var{lst}, and so cannot be used to delete the first element of\n" | |
665 | "@var{lst} destructively.") | |
1bbd0b84 | 666 | #define FUNC_NAME s_scm_delq_x |
0f2d19dd | 667 | { |
164271a1 JB |
668 | SCM walk; |
669 | SCM *prev; | |
0f2d19dd | 670 | |
164271a1 | 671 | for (prev = &lst, walk = lst; |
d2e53ed6 | 672 | scm_is_pair (walk); |
164271a1 | 673 | walk = SCM_CDR (walk)) |
0f2d19dd | 674 | { |
bc36d050 | 675 | if (scm_is_eq (SCM_CAR (walk), item)) |
164271a1 JB |
676 | *prev = SCM_CDR (walk); |
677 | else | |
678 | prev = SCM_CDRLOC (walk); | |
0f2d19dd | 679 | } |
164271a1 JB |
680 | |
681 | return lst; | |
0f2d19dd | 682 | } |
1bbd0b84 | 683 | #undef FUNC_NAME |
0f2d19dd JB |
684 | |
685 | ||
3b3b36dd | 686 | SCM_DEFINE (scm_delv_x, "delv!", 2, 0, 0, |
5352393c MG |
687 | (SCM item, SCM lst), |
688 | "Destructively remove all elements from @var{lst} that are\n" | |
689 | "@code{eqv?} to @var{item}.") | |
1bbd0b84 | 690 | #define FUNC_NAME s_scm_delv_x |
0f2d19dd | 691 | { |
164271a1 JB |
692 | SCM walk; |
693 | SCM *prev; | |
0f2d19dd | 694 | |
164271a1 | 695 | for (prev = &lst, walk = lst; |
d2e53ed6 | 696 | scm_is_pair (walk); |
164271a1 | 697 | walk = SCM_CDR (walk)) |
0f2d19dd | 698 | { |
7888309b | 699 | if (! scm_is_false (scm_eqv_p (SCM_CAR (walk), item))) |
164271a1 JB |
700 | *prev = SCM_CDR (walk); |
701 | else | |
702 | prev = SCM_CDRLOC (walk); | |
0f2d19dd | 703 | } |
164271a1 JB |
704 | |
705 | return lst; | |
0f2d19dd | 706 | } |
1bbd0b84 | 707 | #undef FUNC_NAME |
0f2d19dd JB |
708 | |
709 | ||
710 | ||
3b3b36dd | 711 | SCM_DEFINE (scm_delete_x, "delete!", 2, 0, 0, |
5352393c MG |
712 | (SCM item, SCM lst), |
713 | "Destructively remove all elements from @var{lst} that are\n" | |
714 | "@code{equal?} to @var{item}.") | |
1bbd0b84 | 715 | #define FUNC_NAME s_scm_delete_x |
0f2d19dd | 716 | { |
164271a1 JB |
717 | SCM walk; |
718 | SCM *prev; | |
0f2d19dd | 719 | |
164271a1 | 720 | for (prev = &lst, walk = lst; |
d2e53ed6 | 721 | scm_is_pair (walk); |
164271a1 | 722 | walk = SCM_CDR (walk)) |
0f2d19dd | 723 | { |
7888309b | 724 | if (! scm_is_false (scm_equal_p (SCM_CAR (walk), item))) |
164271a1 JB |
725 | *prev = SCM_CDR (walk); |
726 | else | |
727 | prev = SCM_CDRLOC (walk); | |
0f2d19dd | 728 | } |
164271a1 JB |
729 | |
730 | return lst; | |
0f2d19dd | 731 | } |
1bbd0b84 | 732 | #undef FUNC_NAME |
0f2d19dd JB |
733 | |
734 | ||
735 | \f | |
736 | ||
0f2d19dd | 737 | |
a1ec6916 | 738 | SCM_DEFINE (scm_delq, "delq", 2, 0, 0, |
1bbd0b84 | 739 | (SCM item, SCM lst), |
5352393c MG |
740 | "Return a newly-created copy of @var{lst} with elements\n" |
741 | "@code{eq?} to @var{item} removed. This procedure mirrors\n" | |
742 | "@code{memq}: @code{delq} compares elements of @var{lst} against\n" | |
743 | "@var{item} with @code{eq?}.") | |
1bbd0b84 | 744 | #define FUNC_NAME s_scm_delq |
0f2d19dd | 745 | { |
1bbd0b84 | 746 | SCM copy = scm_list_copy (lst); |
0f2d19dd JB |
747 | return scm_delq_x (item, copy); |
748 | } | |
1bbd0b84 | 749 | #undef FUNC_NAME |
0f2d19dd | 750 | |
a1ec6916 | 751 | SCM_DEFINE (scm_delv, "delv", 2, 0, 0, |
1bbd0b84 | 752 | (SCM item, SCM lst), |
5352393c MG |
753 | "Return a newly-created copy of @var{lst} with elements\n" |
754 | "@code{eqv?} to @var{item} removed. This procedure mirrors\n" | |
755 | "@code{memv}: @code{delv} compares elements of @var{lst} against\n" | |
756 | "@var{item} with @code{eqv?}.") | |
1bbd0b84 | 757 | #define FUNC_NAME s_scm_delv |
0f2d19dd | 758 | { |
1bbd0b84 | 759 | SCM copy = scm_list_copy (lst); |
0f2d19dd JB |
760 | return scm_delv_x (item, copy); |
761 | } | |
1bbd0b84 | 762 | #undef FUNC_NAME |
0f2d19dd | 763 | |
a1ec6916 | 764 | SCM_DEFINE (scm_delete, "delete", 2, 0, 0, |
1bbd0b84 | 765 | (SCM item, SCM lst), |
5352393c MG |
766 | "Return a newly-created copy of @var{lst} with elements\n" |
767 | "@code{equal?} to @var{item} removed. This procedure mirrors\n" | |
768 | "@code{member}: @code{delete} compares elements of @var{lst}\n" | |
769 | "against @var{item} with @code{equal?}.") | |
1bbd0b84 | 770 | #define FUNC_NAME s_scm_delete |
0f2d19dd | 771 | { |
1bbd0b84 | 772 | SCM copy = scm_list_copy (lst); |
0f2d19dd JB |
773 | return scm_delete_x (item, copy); |
774 | } | |
1bbd0b84 | 775 | #undef FUNC_NAME |
0f2d19dd JB |
776 | |
777 | ||
3b3b36dd | 778 | SCM_DEFINE (scm_delq1_x, "delq1!", 2, 0, 0, |
1bbd0b84 | 779 | (SCM item, SCM lst), |
5352393c MG |
780 | "Like @code{delq!}, but only deletes the first occurrence of\n" |
781 | "@var{item} from @var{lst}. Tests for equality using\n" | |
782 | "@code{eq?}. See also @code{delv1!} and @code{delete1!}.") | |
1bbd0b84 | 783 | #define FUNC_NAME s_scm_delq1_x |
82dc9f57 MD |
784 | { |
785 | SCM walk; | |
786 | SCM *prev; | |
787 | ||
788 | for (prev = &lst, walk = lst; | |
d2e53ed6 | 789 | scm_is_pair (walk); |
82dc9f57 MD |
790 | walk = SCM_CDR (walk)) |
791 | { | |
bc36d050 | 792 | if (scm_is_eq (SCM_CAR (walk), item)) |
82dc9f57 MD |
793 | { |
794 | *prev = SCM_CDR (walk); | |
795 | break; | |
796 | } | |
797 | else | |
798 | prev = SCM_CDRLOC (walk); | |
799 | } | |
800 | ||
801 | return lst; | |
802 | } | |
1bbd0b84 | 803 | #undef FUNC_NAME |
82dc9f57 MD |
804 | |
805 | ||
3b3b36dd | 806 | SCM_DEFINE (scm_delv1_x, "delv1!", 2, 0, 0, |
8507b88c | 807 | (SCM item, SCM lst), |
5352393c MG |
808 | "Like @code{delv!}, but only deletes the first occurrence of\n" |
809 | "@var{item} from @var{lst}. Tests for equality using\n" | |
810 | "@code{eqv?}. See also @code{delq1!} and @code{delete1!}.") | |
1bbd0b84 | 811 | #define FUNC_NAME s_scm_delv1_x |
82dc9f57 MD |
812 | { |
813 | SCM walk; | |
814 | SCM *prev; | |
815 | ||
816 | for (prev = &lst, walk = lst; | |
d2e53ed6 | 817 | scm_is_pair (walk); |
82dc9f57 MD |
818 | walk = SCM_CDR (walk)) |
819 | { | |
7888309b | 820 | if (! scm_is_false (scm_eqv_p (SCM_CAR (walk), item))) |
82dc9f57 MD |
821 | { |
822 | *prev = SCM_CDR (walk); | |
823 | break; | |
824 | } | |
825 | else | |
826 | prev = SCM_CDRLOC (walk); | |
827 | } | |
828 | ||
829 | return lst; | |
830 | } | |
1bbd0b84 | 831 | #undef FUNC_NAME |
82dc9f57 MD |
832 | |
833 | ||
3b3b36dd | 834 | SCM_DEFINE (scm_delete1_x, "delete1!", 2, 0, 0, |
8507b88c | 835 | (SCM item, SCM lst), |
5352393c MG |
836 | "Like @code{delete!}, but only deletes the first occurrence of\n" |
837 | "@var{item} from @var{lst}. Tests for equality using\n" | |
838 | "@code{equal?}. See also @code{delq1!} and @code{delv1!}.") | |
1bbd0b84 | 839 | #define FUNC_NAME s_scm_delete1_x |
82dc9f57 MD |
840 | { |
841 | SCM walk; | |
842 | SCM *prev; | |
843 | ||
844 | for (prev = &lst, walk = lst; | |
d2e53ed6 | 845 | scm_is_pair (walk); |
82dc9f57 MD |
846 | walk = SCM_CDR (walk)) |
847 | { | |
7888309b | 848 | if (! scm_is_false (scm_equal_p (SCM_CAR (walk), item))) |
82dc9f57 MD |
849 | { |
850 | *prev = SCM_CDR (walk); | |
851 | break; | |
852 | } | |
853 | else | |
854 | prev = SCM_CDRLOC (walk); | |
855 | } | |
856 | ||
857 | return lst; | |
858 | } | |
1bbd0b84 | 859 | #undef FUNC_NAME |
82dc9f57 | 860 | |
c614a00b MD |
861 | SCM_DEFINE (scm_filter, "filter", 2, 0, 0, |
862 | (SCM pred, SCM list), | |
863 | "Return all the elements of 2nd arg @var{list} that satisfy predicate @var{pred}.\n" | |
864 | "The list is not disordered -- elements that appear in the result list occur\n" | |
865 | "in the same order as they occur in the argument list. The returned list may\n" | |
866 | "share a common tail with the argument list. The dynamic order in which the\n" | |
867 | "various applications of pred are made is not specified.\n\n" | |
868 | "@lisp\n" | |
869 | "(filter even? '(0 7 8 8 43 -4)) => (0 8 8 -4)\n" | |
870 | "@end lisp") | |
871 | #define FUNC_NAME s_scm_filter | |
872 | { | |
873 | scm_t_trampoline_1 call = scm_trampoline_1 (pred); | |
874 | SCM walk; | |
875 | SCM *prev; | |
876 | SCM res = SCM_EOL; | |
877 | SCM_ASSERT (call, pred, 1, FUNC_NAME); | |
878 | SCM_VALIDATE_LIST (2, list); | |
879 | ||
880 | for (prev = &res, walk = list; | |
d2e53ed6 | 881 | scm_is_pair (walk); |
c614a00b MD |
882 | walk = SCM_CDR (walk)) |
883 | { | |
7888309b | 884 | if (scm_is_true (call (pred, SCM_CAR (walk)))) |
c614a00b MD |
885 | { |
886 | *prev = scm_cons (SCM_CAR (walk), SCM_EOL); | |
887 | prev = SCM_CDRLOC (*prev); | |
888 | } | |
889 | } | |
890 | ||
891 | return res; | |
892 | } | |
893 | #undef FUNC_NAME | |
894 | ||
895 | SCM_DEFINE (scm_filter_x, "filter!", 2, 0, 0, | |
896 | (SCM pred, SCM list), | |
897 | "Linear-update variant of @code{filter}.") | |
898 | #define FUNC_NAME s_scm_filter_x | |
899 | { | |
900 | scm_t_trampoline_1 call = scm_trampoline_1 (pred); | |
901 | SCM walk; | |
902 | SCM *prev; | |
903 | SCM_ASSERT (call, pred, 1, FUNC_NAME); | |
904 | SCM_VALIDATE_LIST (2, list); | |
905 | ||
906 | for (prev = &list, walk = list; | |
d2e53ed6 | 907 | scm_is_pair (walk); |
c614a00b MD |
908 | walk = SCM_CDR (walk)) |
909 | { | |
7888309b | 910 | if (scm_is_true (call (pred, SCM_CAR (walk)))) |
c614a00b MD |
911 | prev = SCM_CDRLOC (walk); |
912 | else | |
913 | *prev = SCM_CDR (walk); | |
914 | } | |
915 | ||
916 | return list; | |
917 | } | |
918 | #undef FUNC_NAME | |
82dc9f57 | 919 | |
0f2d19dd | 920 | \f |
0f2d19dd JB |
921 | void |
922 | scm_init_list () | |
0f2d19dd | 923 | { |
a0599745 | 924 | #include "libguile/list.x" |
0f2d19dd | 925 | } |
89e00824 ML |
926 | |
927 | /* | |
928 | Local Variables: | |
929 | c-file-style: "gnu" | |
930 | End: | |
931 | */ |