* convert.c: include <string.h> for convert_i.c.
[bpt/guile.git] / srfi / srfi-14.c
CommitLineData
ca003b26
MG
1/* srfi-14.c --- SRFI-14 procedures for Guile
2 *
e81d98ec 3 * Copyright (C) 2001 Free Software Foundation, Inc.
ca003b26
MG
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2, or (at
8 * your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this software; see the file COPYING. If not, write to
17 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307 USA
19 *
20 * As a special exception, the Free Software Foundation gives
21 * permission for additional uses of the text contained in its release
22 * of GUILE.
23 *
24 * The exception is that, if you link the GUILE library with other
25 * files to produce an executable, this does not by itself cause the
26 * resulting executable to be covered by the GNU General Public
27 * License. Your use of that executable is in no way restricted on
28 * account of linking the GUILE library code into it.
29 *
30 * This exception does not however invalidate any other reasons why
31 * the executable file might be covered by the GNU General Public
32 * License.
33 *
34 * This exception applies only to the code released by the Free
35 * Software Foundation under the name GUILE. If you copy code from
36 * other Free Software Foundation releases into a copy of GUILE, as
37 * the General Public License permits, the exception does not apply to
38 * the code that you add in this way. To avoid misleading anyone as
39 * to the status of such modified files, you must delete this
40 * exception notice from them.
41 *
42 * If you write modifications of your own for GUILE, it is your choice
43 * whether to permit this exception to apply to your modifications.
44 * If you do not wish that, delete this exception notice. */
45
46
47#include <string.h>
48
49#include <libguile.h>
50
51#include "srfi-14.h"
52
ca003b26 53
cc0ce1e7
RB
54#define SCM_CHARSET_SET(cs, idx) \
55 (((long *) SCM_SMOB_DATA (cs))[(idx) / SCM_BITS_PER_LONG] |= \
56 (1L << ((idx) % SCM_BITS_PER_LONG)))
ca003b26 57
4c4185ee
MG
58#define BYTES_PER_CHARSET (SCM_CHARSET_SIZE / 8)
59#define LONGS_PER_CHARSET (SCM_CHARSET_SIZE / SCM_BITS_PER_LONG)
60
61
ca003b26
MG
62/* Smob type code for character sets. */
63int scm_tc16_charset = 0;
64
65
66/* Smob print hook for character sets. */
67static int
e81d98ec 68charset_print (SCM charset, SCM port, scm_print_state *pstate SCM_UNUSED)
ca003b26
MG
69{
70 int i;
71 int first = 1;
72
73 scm_puts ("#<charset {", port);
74 for (i = 0; i < SCM_CHARSET_SIZE; i++)
75 if (SCM_CHARSET_GET (charset, i))
76 {
77 if (first)
78 first = 0;
79 else
80 scm_puts (" ", port);
81 scm_write (SCM_MAKE_CHAR (i), port);
82 }
83 scm_puts ("}>", port);
84 return 1;
85}
86
87
88/* Smob free hook for character sets. */
1be6b49c 89static size_t
ca003b26
MG
90charset_free (SCM charset)
91{
92 return scm_smob_free (charset);
93}
94
95
96/* Create a new, empty character set. */
97static SCM
98make_char_set (const char * func_name)
99{
100 long * p;
101
6c70aef1 102 p = scm_gc_malloc (BYTES_PER_CHARSET, "character-set");
4c4185ee 103 memset (p, 0, BYTES_PER_CHARSET);
ca003b26
MG
104 SCM_RETURN_NEWSMOB (scm_tc16_charset, p);
105}
106
107
108SCM_DEFINE (scm_char_set_p, "char-set?", 1, 0, 0,
109 (SCM obj),
110 "Return @code{#t} if @var{obj} is a character set, @code{#f}\n"
111 "otherwise.")
112#define FUNC_NAME s_scm_char_set_p
113{
114 return SCM_BOOL (SCM_SMOB_PREDICATE (scm_tc16_charset, obj));
115}
116#undef FUNC_NAME
117
118
dd84cd4d
GH
119SCM_DEFINE (scm_char_set_eq, "char-set=", 0, 0, 1,
120 (SCM char_sets),
ca003b26
MG
121 "Return @code{#t} if all given character sets are equal.")
122#define FUNC_NAME s_scm_char_set_eq
123{
dd84cd4d
GH
124 int argnum = 1;
125 long *cs1_data = NULL;
ca003b26 126
dd84cd4d 127 SCM_VALIDATE_REST_ARGUMENT (char_sets);
ca003b26 128
dd84cd4d 129 while (!SCM_NULLP (char_sets))
ca003b26 130 {
be390de2
GH
131 SCM csi = SCM_CAR (char_sets);
132 long *csi_data;
dd84cd4d 133
b87f5a83
GH
134 SCM_VALIDATE_SMOB (argnum, csi, charset);
135 argnum++;
be390de2 136 csi_data = (long *) SCM_SMOB_DATA (csi);
dd84cd4d 137 if (cs1_data == NULL)
be390de2 138 cs1_data = csi_data;
4c4185ee 139 else if (memcmp (cs1_data, csi_data, BYTES_PER_CHARSET) != 0)
dd84cd4d
GH
140 return SCM_BOOL_F;
141 char_sets = SCM_CDR (char_sets);
ca003b26
MG
142 }
143 return SCM_BOOL_T;
144}
145#undef FUNC_NAME
146
147
be390de2
GH
148SCM_DEFINE (scm_char_set_leq, "char-set<=", 0, 0, 1,
149 (SCM char_sets),
ca003b26
MG
150 "Return @code{#t} if every character set @var{cs}i is a subset\n"
151 "of character set @var{cs}i+1.")
152#define FUNC_NAME s_scm_char_set_leq
153{
be390de2
GH
154 int argnum = 1;
155 long *prev_data = NULL;
ca003b26 156
be390de2 157 SCM_VALIDATE_REST_ARGUMENT (char_sets);
ca003b26 158
be390de2 159 while (!SCM_NULLP (char_sets))
ca003b26 160 {
be390de2
GH
161 SCM csi = SCM_CAR (char_sets);
162 long *csi_data;
163
b87f5a83
GH
164 SCM_VALIDATE_SMOB (argnum, csi, charset);
165 argnum++;
be390de2
GH
166 csi_data = (long *) SCM_SMOB_DATA (csi);
167 if (prev_data)
ca003b26 168 {
be390de2
GH
169 int k;
170
4c4185ee 171 for (k = 0; k < LONGS_PER_CHARSET; k++)
be390de2
GH
172 {
173 if ((prev_data[k] & csi_data[k]) != prev_data[k])
174 return SCM_BOOL_F;
175 }
ca003b26 176 }
be390de2
GH
177 prev_data = csi_data;
178 char_sets = SCM_CDR (char_sets);
ca003b26
MG
179 }
180 return SCM_BOOL_T;
181}
182#undef FUNC_NAME
183
184
185SCM_DEFINE (scm_char_set_hash, "char-set-hash", 1, 1, 0,
186 (SCM cs, SCM bound),
187 "Compute a hash value for the character set @var{cs}. If\n"
396f36cd 188 "@var{bound} is given and non-zero, it restricts the\n"
ca003b26
MG
189 "returned value to the range 0 @dots{} @var{bound - 1}.")
190#define FUNC_NAME s_scm_char_set_hash
191{
396f36cd 192 const int default_bnd = 871;
ca003b26
MG
193 int bnd;
194 long * p;
cc0ce1e7 195 unsigned long val = 0;
ca003b26
MG
196 int k;
197
198 SCM_VALIDATE_SMOB (1, cs, charset);
396f36cd
GH
199
200 if (SCM_UNBNDP (bound))
201 bnd = default_bnd;
ca003b26 202 else
396f36cd
GH
203 {
204 SCM_VALIDATE_INUM_MIN_COPY (2, bound, 0, bnd);
205 if (bnd == 0)
206 bnd = default_bnd;
207 }
ca003b26
MG
208
209 p = (long *) SCM_SMOB_DATA (cs);
4c4185ee 210 for (k = 0; k < LONGS_PER_CHARSET; k++)
ca003b26 211 {
cebf3d62
MG
212 if (p[k] != 0)
213 val = p[k] + (val << 1);
ca003b26
MG
214 }
215 return SCM_MAKINUM (val % bnd);
216}
217#undef FUNC_NAME
218
219
220SCM_DEFINE (scm_char_set_cursor, "char-set-cursor", 1, 0, 0,
221 (SCM cs),
222 "Return a cursor into the character set @var{cs}.")
223#define FUNC_NAME s_scm_char_set_cursor
224{
225 int idx;
226
227 SCM_VALIDATE_SMOB (1, cs, charset);
228 for (idx = 0; idx < SCM_CHARSET_SIZE; idx++)
229 {
230 if (SCM_CHARSET_GET (cs, idx))
231 break;
232 }
233 return SCM_MAKINUM (idx);
234}
235#undef FUNC_NAME
236
237
238SCM_DEFINE (scm_char_set_ref, "char-set-ref", 2, 0, 0,
239 (SCM cs, SCM cursor),
240 "Return the character at the current cursor position\n"
241 "@var{cursor} in the character set @var{cs}. It is an error to\n"
242 "pass a cursor for which @code{end-of-char-set?} returns true.")
243#define FUNC_NAME s_scm_char_set_ref
244{
245 int ccursor;
246
247 SCM_VALIDATE_SMOB (1, cs, charset);
8b19021c 248 SCM_VALIDATE_INUM_MIN_COPY (2, cursor, 0, ccursor);
ca003b26
MG
249
250 if (ccursor >= SCM_CHARSET_SIZE || !SCM_CHARSET_GET (cs, ccursor))
2c4df451 251 SCM_MISC_ERROR ("invalid character set cursor: ~A", scm_list_1 (cursor));
ca003b26
MG
252 return SCM_MAKE_CHAR (ccursor);
253}
254#undef FUNC_NAME
255
256
257SCM_DEFINE (scm_char_set_cursor_next, "char-set-cursor-next", 2, 0, 0,
258 (SCM cs, SCM cursor),
259 "Advance the character set cursor @var{cursor} to the next\n"
260 "character in the character set @var{cs}. It is an error if the\n"
261 "cursor given satisfies @code{end-of-char-set?}.")
262#define FUNC_NAME s_scm_char_set_cursor_next
263{
264 int ccursor;
265
266 SCM_VALIDATE_SMOB (1, cs, charset);
8b19021c 267 SCM_VALIDATE_INUM_MIN_COPY (2, cursor, 0, ccursor);
ca003b26
MG
268
269 if (ccursor >= SCM_CHARSET_SIZE || !SCM_CHARSET_GET (cs, ccursor))
2c4df451 270 SCM_MISC_ERROR ("invalid character set cursor: ~A", scm_list_1 (cursor));
ca003b26
MG
271 for (ccursor++; ccursor < SCM_CHARSET_SIZE; ccursor++)
272 {
273 if (SCM_CHARSET_GET (cs, ccursor))
274 break;
275 }
276 return SCM_MAKINUM (ccursor);
277}
278#undef FUNC_NAME
279
280
281SCM_DEFINE (scm_end_of_char_set_p, "end-of-char-set?", 1, 0, 0,
282 (SCM cursor),
283 "Return @code{#t} if @var{cursor} has reached the end of a\n"
284 "character set, @code{#f} otherwise.")
285#define FUNC_NAME s_scm_end_of_char_set_p
286{
287 int ccursor;
288
8b19021c 289 SCM_VALIDATE_INUM_MIN_COPY (1, cursor, 0, ccursor);
ca003b26
MG
290 return SCM_BOOL (ccursor >= SCM_CHARSET_SIZE);
291}
292#undef FUNC_NAME
293
294
295SCM_DEFINE (scm_char_set_fold, "char-set-fold", 3, 0, 0,
296 (SCM kons, SCM knil, SCM cs),
297 "Fold the procedure @var{kons} over the character set @var{cs},\n"
298 "initializing it with @var{knil}.")
299#define FUNC_NAME s_scm_char_set_fold
300{
301 int k;
302
303 SCM_VALIDATE_PROC (1, kons);
304 SCM_VALIDATE_SMOB (3, cs, charset);
305
306 for (k = 0; k < SCM_CHARSET_SIZE; k++)
307 if (SCM_CHARSET_GET (cs, k))
308 {
2c4df451 309 knil = scm_call_2 (kons, SCM_MAKE_CHAR (k), knil);
ca003b26
MG
310 }
311 return knil;
312}
313#undef FUNC_NAME
314
2c4df451 315
ca003b26
MG
316SCM_DEFINE (scm_char_set_unfold, "char-set-unfold", 4, 1, 0,
317 (SCM p, SCM f, SCM g, SCM seed, SCM base_cs),
318 "This is a fundamental constructor for character sets.\n"
2d953700 319 "@itemize @bullet\n"
9401323e 320 "@item @var{g} is used to generate a series of ``seed'' values\n"
ca003b26
MG
321 "from the initial seed: @var{seed}, (@var{g} @var{seed}),\n"
322 "(@var{g}^2 @var{seed}), (@var{g}^3 @var{seed}), @dots{}\n"
323 "@item @var{p} tells us when to stop -- when it returns true\n"
9401323e 324 "when applied to one of the seed values.\n"
ca003b26
MG
325 "@item @var{f} maps each seed value to a character. These\n"
326 "characters are added to the base character set @var{base_cs} to\n"
327 "form the result; @var{base_cs} defaults to the empty set.\n"
328 "@end itemize")
329#define FUNC_NAME s_scm_char_set_unfold
330{
331 SCM result, tmp;
332
333 SCM_VALIDATE_PROC (1, p);
334 SCM_VALIDATE_PROC (2, f);
335 SCM_VALIDATE_PROC (3, g);
336 if (!SCM_UNBNDP (base_cs))
337 {
338 SCM_VALIDATE_SMOB (5, base_cs, charset);
339 result = scm_char_set_copy (base_cs);
340 }
341 else
342 result = make_char_set (FUNC_NAME);
343
2c4df451 344 tmp = scm_call_1 (p, seed);
ca003b26
MG
345 while (SCM_FALSEP (tmp))
346 {
2c4df451 347 SCM ch = scm_call_1 (f, seed);
ca003b26 348 if (!SCM_CHARP (ch))
2c4df451 349 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (f));
ca003b26
MG
350 SCM_CHARSET_SET (result, SCM_CHAR (ch));
351
2c4df451
MG
352 seed = scm_call_1 (g, seed);
353 tmp = scm_call_1 (p, seed);
ca003b26
MG
354 }
355 return result;
356}
357#undef FUNC_NAME
358
359
360SCM_DEFINE (scm_char_set_unfold_x, "char-set-unfold!", 5, 0, 0,
361 (SCM p, SCM f, SCM g, SCM seed, SCM base_cs),
362 "This is a fundamental constructor for character sets.\n"
2d953700 363 "@itemize @bullet\n"
ca003b26 364 "@item @var{g} is used to generate a series of ``seed'' values\n"
9401323e 365 "from the initial seed: @var{seed}, (@var{g} @var{seed}),\n"
ca003b26
MG
366 "(@var{g}^2 @var{seed}), (@var{g}^3 @var{seed}), @dots{}\n"
367 "@item @var{p} tells us when to stop -- when it returns true\n"
9401323e 368 "when applied to one of the seed values.\n"
ca003b26
MG
369 "@item @var{f} maps each seed value to a character. These\n"
370 "characters are added to the base character set @var{base_cs} to\n"
371 "form the result; @var{base_cs} defaults to the empty set.\n"
372 "@end itemize")
373#define FUNC_NAME s_scm_char_set_unfold_x
374{
375 SCM tmp;
376
377 SCM_VALIDATE_PROC (1, p);
378 SCM_VALIDATE_PROC (2, f);
379 SCM_VALIDATE_PROC (3, g);
380 SCM_VALIDATE_SMOB (5, base_cs, charset);
381
2c4df451 382 tmp = scm_call_1 (p, seed);
ca003b26
MG
383 while (SCM_FALSEP (tmp))
384 {
2c4df451 385 SCM ch = scm_call_1 (f, seed);
ca003b26 386 if (!SCM_CHARP (ch))
2c4df451 387 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (f));
ca003b26
MG
388 SCM_CHARSET_SET (base_cs, SCM_CHAR (ch));
389
2c4df451
MG
390 seed = scm_call_1 (g, seed);
391 tmp = scm_call_1 (p, seed);
ca003b26
MG
392 }
393 return base_cs;
394}
395#undef FUNC_NAME
396
397
398SCM_DEFINE (scm_char_set_for_each, "char-set-for-each", 2, 0, 0,
399 (SCM proc, SCM cs),
400 "Apply @var{proc} to every character in the character set\n"
401 "@var{cs}. The return value is not specified.")
402#define FUNC_NAME s_scm_char_set_for_each
403{
404 int k;
405
406 SCM_VALIDATE_PROC (1, proc);
407 SCM_VALIDATE_SMOB (2, cs, charset);
408
409 for (k = 0; k < SCM_CHARSET_SIZE; k++)
410 if (SCM_CHARSET_GET (cs, k))
2c4df451 411 scm_call_1 (proc, SCM_MAKE_CHAR (k));
ca003b26
MG
412 return SCM_UNSPECIFIED;
413}
414#undef FUNC_NAME
415
416
417SCM_DEFINE (scm_char_set_map, "char-set-map", 2, 0, 0,
418 (SCM proc, SCM cs),
419 "Map the procedure @var{proc} over every character in @var{cs}.\n"
420 "@var{proc} must be a character -> character procedure.")
421#define FUNC_NAME s_scm_char_set_map
422{
423 SCM result;
424 int k;
425
426 SCM_VALIDATE_PROC (1, proc);
427 SCM_VALIDATE_SMOB (2, cs, charset);
428
429 result = make_char_set (FUNC_NAME);
430 for (k = 0; k < SCM_CHARSET_SIZE; k++)
431 if (SCM_CHARSET_GET (cs, k))
432 {
2c4df451 433 SCM ch = scm_call_1 (proc, SCM_MAKE_CHAR (k));
ca003b26 434 if (!SCM_CHARP (ch))
2c4df451 435 SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (proc));
139777e5 436 SCM_CHARSET_SET (result, SCM_CHAR (ch));
ca003b26
MG
437 }
438 return result;
439}
440#undef FUNC_NAME
441
442
443SCM_DEFINE (scm_char_set_copy, "char-set-copy", 1, 0, 0,
444 (SCM cs),
445 "Return a newly allocated character set containing all\n"
446 "characters in @var{cs}.")
447#define FUNC_NAME s_scm_char_set_copy
448{
449 SCM ret;
450 long * p1, * p2;
451 int k;
452
453 SCM_VALIDATE_SMOB (1, cs, charset);
454 ret = make_char_set (FUNC_NAME);
455 p1 = (long *) SCM_SMOB_DATA (cs);
456 p2 = (long *) SCM_SMOB_DATA (ret);
4c4185ee 457 for (k = 0; k < LONGS_PER_CHARSET; k++)
ca003b26
MG
458 p2[k] = p1[k];
459 return ret;
460}
461#undef FUNC_NAME
462
463
464SCM_DEFINE (scm_char_set, "char-set", 0, 0, 1,
465 (SCM rest),
466 "Return a character set containing all given characters.")
467#define FUNC_NAME s_scm_char_set
468{
b87f5a83 469 SCM cs;
ca003b26 470 long * p;
b87f5a83 471 int argnum = 1;
ca003b26
MG
472
473 SCM_VALIDATE_REST_ARGUMENT (rest);
ca003b26
MG
474 cs = make_char_set (FUNC_NAME);
475 p = (long *) SCM_SMOB_DATA (cs);
b87f5a83 476 while (!SCM_NULLP (rest))
ca003b26 477 {
ca003b26
MG
478 int c;
479
b87f5a83
GH
480 SCM_VALIDATE_CHAR_COPY (argnum, SCM_CAR (rest), c);
481 argnum++;
482 rest = SCM_CDR (rest);
cc0ce1e7 483 p[c / SCM_BITS_PER_LONG] |= 1L << (c % SCM_BITS_PER_LONG);
ca003b26
MG
484 }
485 return cs;
486}
487#undef FUNC_NAME
488
489
490SCM_DEFINE (scm_list_to_char_set, "list->char-set", 1, 1, 0,
491 (SCM list, SCM base_cs),
492 "Convert the character list @var{list} to a character set. If\n"
493 "the character set @var{base_cs} is given, the character in this\n"
494 "set are also included in the result.")
495#define FUNC_NAME s_scm_list_to_char_set
496{
497 SCM cs;
498 long * p;
499
500 SCM_VALIDATE_LIST (1, list);
501 if (SCM_UNBNDP (base_cs))
502 cs = make_char_set (FUNC_NAME);
503 else
504 {
505 SCM_VALIDATE_SMOB (2, base_cs, charset);
506 cs = scm_char_set_copy (base_cs);
507 }
508 p = (long *) SCM_SMOB_DATA (cs);
509 while (!SCM_NULLP (list))
510 {
511 SCM chr = SCM_CAR (list);
512 int c;
513
8b19021c 514 SCM_VALIDATE_CHAR_COPY (0, chr, c);
ca003b26
MG
515 list = SCM_CDR (list);
516
cc0ce1e7 517 p[c / SCM_BITS_PER_LONG] |= 1L << (c % SCM_BITS_PER_LONG);
ca003b26
MG
518 }
519 return cs;
520}
521#undef FUNC_NAME
522
523
524SCM_DEFINE (scm_list_to_char_set_x, "list->char-set!", 2, 0, 0,
525 (SCM list, SCM base_cs),
526 "Convert the character list @var{list} to a character set. The\n"
527 "characters are added to @var{base_cs} and @var{base_cs} is\n"
528 "returned.")
cc0ce1e7 529#define FUNC_NAME s_scm_list_to_char_set_x
ca003b26
MG
530{
531 long * p;
532
533 SCM_VALIDATE_LIST (1, list);
534 SCM_VALIDATE_SMOB (2, base_cs, charset);
535 p = (long *) SCM_SMOB_DATA (base_cs);
536 while (!SCM_NULLP (list))
537 {
538 SCM chr = SCM_CAR (list);
539 int c;
540
8b19021c 541 SCM_VALIDATE_CHAR_COPY (0, chr, c);
ca003b26
MG
542 list = SCM_CDR (list);
543
cc0ce1e7 544 p[c / SCM_BITS_PER_LONG] |= 1L << (c % SCM_BITS_PER_LONG);
ca003b26
MG
545 }
546 return base_cs;
547}
548#undef FUNC_NAME
549
550
551SCM_DEFINE (scm_string_to_char_set, "string->char-set", 1, 1, 0,
552 (SCM str, SCM base_cs),
553 "Convert the string @var{str} to a character set. If the\n"
554 "character set @var{base_cs} is given, the characters in this\n"
555 "set are also included in the result.")
556#define FUNC_NAME s_scm_string_to_char_set
557{
558 SCM cs;
559 long * p;
560 char * s;
cc0ce1e7 561 size_t k = 0;
ca003b26
MG
562
563 SCM_VALIDATE_STRING (1, str);
564 if (SCM_UNBNDP (base_cs))
565 cs = make_char_set (FUNC_NAME);
566 else
567 {
568 SCM_VALIDATE_SMOB (2, base_cs, charset);
569 cs = scm_char_set_copy (base_cs);
570 }
571 p = (long *) SCM_SMOB_DATA (cs);
572 s = SCM_STRING_CHARS (str);
573 while (k < SCM_STRING_LENGTH (str))
574 {
575 int c = s[k++];
cc0ce1e7 576 p[c / SCM_BITS_PER_LONG] |= 1L << (c % SCM_BITS_PER_LONG);
ca003b26
MG
577 }
578 return cs;
579}
580#undef FUNC_NAME
581
582
583SCM_DEFINE (scm_string_to_char_set_x, "string->char-set!", 2, 0, 0,
584 (SCM str, SCM base_cs),
585 "Convert the string @var{str} to a character set. The\n"
586 "characters from the string are added to @var{base_cs}, and\n"
587 "@var{base_cs} is returned.")
588#define FUNC_NAME s_scm_string_to_char_set_x
589{
590 long * p;
591 char * s;
cc0ce1e7 592 size_t k = 0;
ca003b26
MG
593
594 SCM_VALIDATE_STRING (1, str);
595 SCM_VALIDATE_SMOB (2, base_cs, charset);
596 p = (long *) SCM_SMOB_DATA (base_cs);
597 s = SCM_STRING_CHARS (str);
598 while (k < SCM_STRING_LENGTH (str))
599 {
600 int c = s[k++];
cc0ce1e7 601 p[c / SCM_BITS_PER_LONG] |= 1L << (c % SCM_BITS_PER_LONG);
ca003b26
MG
602 }
603 return base_cs;
604}
605#undef FUNC_NAME
606
607
608SCM_DEFINE (scm_char_set_filter, "char-set-filter", 2, 1, 0,
609 (SCM pred, SCM cs, SCM base_cs),
610 "Return a character set containing every character from @var{cs}\n"
611 "so that it satisfies @var{pred}. If provided, the characters\n"
612 "from @var{base_cs} are added to the result.")
613#define FUNC_NAME s_scm_char_set_filter
614{
615 SCM ret;
616 int k;
617 long * p;
618
619 SCM_VALIDATE_PROC (1, pred);
620 SCM_VALIDATE_SMOB (2, cs, charset);
621 if (!SCM_UNBNDP (base_cs))
622 {
623 SCM_VALIDATE_SMOB (3, base_cs, charset);
624 ret = scm_char_set_copy (base_cs);
625 }
626 else
627 ret = make_char_set (FUNC_NAME);
628 p = (long *) SCM_SMOB_DATA (ret);
629 for (k = 0; k < SCM_CHARSET_SIZE; k++)
630 {
631 if (SCM_CHARSET_GET (cs, k))
632 {
2c4df451 633 SCM res = scm_call_1 (pred, SCM_MAKE_CHAR (k));
ca003b26
MG
634
635 if (!SCM_FALSEP (res))
cc0ce1e7 636 p[k / SCM_BITS_PER_LONG] |= 1L << (k % SCM_BITS_PER_LONG);
ca003b26
MG
637 }
638 }
639 return ret;
640}
641#undef FUNC_NAME
642
643
644SCM_DEFINE (scm_char_set_filter_x, "char-set-filter!", 3, 0, 0,
645 (SCM pred, SCM cs, SCM base_cs),
646 "Return a character set containing every character from @var{cs}\n"
647 "so that it satisfies @var{pred}. The characters are added to\n"
648 "@var{base_cs} and @var{base_cs} is returned.")
649#define FUNC_NAME s_scm_char_set_filter_x
650{
651 int k;
652 long * p;
653
654 SCM_VALIDATE_PROC (1, pred);
655 SCM_VALIDATE_SMOB (2, cs, charset);
656 SCM_VALIDATE_SMOB (3, base_cs, charset);
657 p = (long *) SCM_SMOB_DATA (base_cs);
658 for (k = 0; k < SCM_CHARSET_SIZE; k++)
659 {
660 if (SCM_CHARSET_GET (cs, k))
661 {
2c4df451 662 SCM res = scm_call_1 (pred, SCM_MAKE_CHAR (k));
ca003b26
MG
663
664 if (!SCM_FALSEP (res))
cc0ce1e7 665 p[k / SCM_BITS_PER_LONG] |= 1L << (k % SCM_BITS_PER_LONG);
ca003b26
MG
666 }
667 }
668 return base_cs;
669}
670#undef FUNC_NAME
671
672
673SCM_DEFINE (scm_ucs_range_to_char_set, "ucs-range->char-set", 2, 2, 0,
674 (SCM lower, SCM upper, SCM error, SCM base_cs),
675 "Return a character set containing all characters whose\n"
676 "character codes lie in the half-open range\n"
677 "[@var{lower},@var{upper}).\n"
678 "\n"
679 "If @var{error} is a true value, an error is signalled if the\n"
680 "specified range contains characters which are not contained in\n"
681 "the implemented character range. If @var{error} is @code{#f},\n"
682 "these characters are silently left out of the resultung\n"
683 "character set.\n"
684 "\n"
685 "The characters in @var{base_cs} are added to the result, if\n"
686 "given.")
687#define FUNC_NAME s_scm_ucs_range_to_char_set
688{
689 SCM cs;
690 int clower, cupper;
691 long * p;
692
693 SCM_VALIDATE_INUM_COPY (1, lower, clower);
694 SCM_VALIDATE_INUM_COPY (2, upper, cupper);
695 SCM_ASSERT_RANGE (1, lower, clower >= 0);
696 SCM_ASSERT_RANGE (2, upper, cupper >= 0 && cupper >= clower);
697 if (!SCM_UNBNDP (error))
698 {
699 if (!SCM_FALSEP (error))
700 {
701 SCM_ASSERT_RANGE (1, lower, clower <= SCM_CHARSET_SIZE);
702 SCM_ASSERT_RANGE (2, upper, cupper <= SCM_CHARSET_SIZE);
703 }
704 }
705 if (clower > SCM_CHARSET_SIZE)
706 clower = SCM_CHARSET_SIZE;
707 if (cupper > SCM_CHARSET_SIZE)
708 cupper = SCM_CHARSET_SIZE;
709 if (SCM_UNBNDP (base_cs))
710 cs = make_char_set (FUNC_NAME);
711 else
712 {
713 SCM_VALIDATE_SMOB (2, base_cs, charset);
714 cs = scm_char_set_copy (base_cs);
715 }
716 p = (long *) SCM_SMOB_DATA (cs);
717 while (clower < cupper)
718 {
cc0ce1e7 719 p[clower / SCM_BITS_PER_LONG] |= 1L << (clower % SCM_BITS_PER_LONG);
ca003b26
MG
720 clower++;
721 }
722 return cs;
723}
724#undef FUNC_NAME
725
726
727SCM_DEFINE (scm_ucs_range_to_char_set_x, "ucs-range->char-set!", 4, 0, 0,
728 (SCM lower, SCM upper, SCM error, SCM base_cs),
729 "Return a character set containing all characters whose\n"
730 "character codes lie in the half-open range\n"
731 "[@var{lower},@var{upper}).\n"
732 "\n"
733 "If @var{error} is a true value, an error is signalled if the\n"
734 "specified range contains characters which are not contained in\n"
735 "the implemented character range. If @var{error} is @code{#f},\n"
736 "these characters are silently left out of the resultung\n"
737 "character set.\n"
738 "\n"
739 "The characters are added to @var{base_cs} and @var{base_cs} is\n"
740 "returned.")
741#define FUNC_NAME s_scm_ucs_range_to_char_set_x
742{
743 int clower, cupper;
744 long * p;
745
746 SCM_VALIDATE_INUM_COPY (1, lower, clower);
747 SCM_VALIDATE_INUM_COPY (2, upper, cupper);
748 SCM_ASSERT_RANGE (1, lower, clower >= 0);
749 SCM_ASSERT_RANGE (2, upper, cupper >= 0 && cupper >= clower);
750 if (!SCM_FALSEP (error))
751 {
752 SCM_ASSERT_RANGE (1, lower, clower <= SCM_CHARSET_SIZE);
753 SCM_ASSERT_RANGE (2, upper, cupper <= SCM_CHARSET_SIZE);
754 }
755 if (clower > SCM_CHARSET_SIZE)
756 clower = SCM_CHARSET_SIZE;
757 if (cupper > SCM_CHARSET_SIZE)
758 cupper = SCM_CHARSET_SIZE;
759 p = (long *) SCM_SMOB_DATA (base_cs);
760 while (clower < cupper)
761 {
cc0ce1e7 762 p[clower / SCM_BITS_PER_LONG] |= 1L << (clower % SCM_BITS_PER_LONG);
ca003b26
MG
763 clower++;
764 }
765 return base_cs;
766}
767#undef FUNC_NAME
768
769
770SCM_DEFINE (scm_char_set_size, "char-set-size", 1, 0, 0,
771 (SCM cs),
772 "Return the number of elements in character set @var{cs}.")
773#define FUNC_NAME s_scm_char_set_size
774{
775 int k, count = 0;
776
777 SCM_VALIDATE_SMOB (1, cs, charset);
778 for (k = 0; k < SCM_CHARSET_SIZE; k++)
779 if (SCM_CHARSET_GET (cs, k))
780 count++;
781 return SCM_MAKINUM (count);
782}
783#undef FUNC_NAME
784
785
786SCM_DEFINE (scm_char_set_count, "char-set-count", 2, 0, 0,
787 (SCM pred, SCM cs),
788 "Return the number of the elements int the character set\n"
789 "@var{cs} which satisfy the predicate @var{pred}.")
790#define FUNC_NAME s_scm_char_set_count
791{
792 int k, count = 0;
793
794 SCM_VALIDATE_PROC (1, pred);
795 SCM_VALIDATE_SMOB (2, cs, charset);
796
797 for (k = 0; k < SCM_CHARSET_SIZE; k++)
798 if (SCM_CHARSET_GET (cs, k))
799 {
2c4df451 800 SCM res = scm_call_1 (pred, SCM_MAKE_CHAR (k));
ca003b26
MG
801 if (!SCM_FALSEP (res))
802 count++;
803 }
804 return SCM_MAKINUM (count);
805}
806#undef FUNC_NAME
807
808
809SCM_DEFINE (scm_char_set_to_list, "char-set->list", 1, 0, 0,
810 (SCM cs),
811 "Return a list containing the elements of the character set\n"
812 "@var{cs}.")
813#define FUNC_NAME s_scm_char_set_to_list
814{
815 int k;
816 SCM result = SCM_EOL;
817
818 SCM_VALIDATE_SMOB (1, cs, charset);
819 for (k = SCM_CHARSET_SIZE; k > 0; k--)
820 if (SCM_CHARSET_GET (cs, k - 1))
821 result = scm_cons (SCM_MAKE_CHAR (k - 1), result);
822 return result;
823}
824#undef FUNC_NAME
825
826
827SCM_DEFINE (scm_char_set_to_string, "char-set->string", 1, 0, 0,
828 (SCM cs),
829 "Return a string containing the elements of the character set\n"
830 "@var{cs}. The order in which the characters are placed in the\n"
831 "string is not defined.")
832#define FUNC_NAME s_scm_char_set_to_string
833{
834 int k;
835 int count = 0;
836 int idx = 0;
837 SCM result;
838 char * p;
839
840 SCM_VALIDATE_SMOB (1, cs, charset);
841 for (k = 0; k < SCM_CHARSET_SIZE; k++)
842 if (SCM_CHARSET_GET (cs, k))
843 count++;
844 result = scm_allocate_string (count);
845 p = SCM_STRING_CHARS (result);
846 for (k = 0; k < SCM_CHARSET_SIZE; k++)
847 if (SCM_CHARSET_GET (cs, k))
848 p[idx++] = k;
849 return result;
850}
851#undef FUNC_NAME
852
853
854SCM_DEFINE (scm_char_set_contains_p, "char-set-contains?", 2, 0, 0,
855 (SCM cs, SCM ch),
856 "Return @code{#t} iff the character @var{ch} is contained in the\n"
857 "character set @var{cs}.")
858#define FUNC_NAME s_scm_char_set_contains_p
859{
860 SCM_VALIDATE_SMOB (1, cs, charset);
861 SCM_VALIDATE_CHAR (2, ch);
862 return SCM_BOOL (SCM_CHARSET_GET (cs, SCM_CHAR (ch)));
863}
864#undef FUNC_NAME
865
866
867SCM_DEFINE (scm_char_set_every, "char-set-every", 2, 0, 0,
868 (SCM pred, SCM cs),
869 "Return a true value if every character in the character set\n"
870 "@var{cs} satisfies the predicate @var{pred}.")
871#define FUNC_NAME s_scm_char_set_every
872{
873 int k;
874 SCM res = SCM_BOOL_T;
875
876 SCM_VALIDATE_PROC (1, pred);
877 SCM_VALIDATE_SMOB (2, cs, charset);
878
879 for (k = 0; k < SCM_CHARSET_SIZE; k++)
880 if (SCM_CHARSET_GET (cs, k))
881 {
2c4df451 882 res = scm_call_1 (pred, SCM_MAKE_CHAR (k));
ca003b26
MG
883 if (SCM_FALSEP (res))
884 return res;
885 }
886 return res;
887}
888#undef FUNC_NAME
889
890
891SCM_DEFINE (scm_char_set_any, "char-set-any", 2, 0, 0,
892 (SCM pred, SCM cs),
893 "Return a true value if any character in the character set\n"
894 "@var{cs} satisfies the predicate @var{pred}.")
895#define FUNC_NAME s_scm_char_set_any
896{
897 int k;
898
899 SCM_VALIDATE_PROC (1, pred);
900 SCM_VALIDATE_SMOB (2, cs, charset);
901
902 for (k = 0; k < SCM_CHARSET_SIZE; k++)
903 if (SCM_CHARSET_GET (cs, k))
904 {
2c4df451 905 SCM res = scm_call_1 (pred, SCM_MAKE_CHAR (k));
ca003b26
MG
906 if (!SCM_FALSEP (res))
907 return res;
908 }
909 return SCM_BOOL_F;
910}
911#undef FUNC_NAME
912
913
914SCM_DEFINE (scm_char_set_adjoin, "char-set-adjoin", 1, 0, 1,
915 (SCM cs, SCM rest),
916 "Add all character arguments to the first argument, which must\n"
917 "be a character set.")
918#define FUNC_NAME s_scm_char_set_adjoin
919{
920 long * p;
921
922 SCM_VALIDATE_SMOB (1, cs, charset);
923 SCM_VALIDATE_REST_ARGUMENT (rest);
924 cs = scm_char_set_copy (cs);
925
926 p = (long *) SCM_SMOB_DATA (cs);
927 while (!SCM_NULLP (rest))
928 {
929 SCM chr = SCM_CAR (rest);
930 int c;
931
932 SCM_VALIDATE_CHAR_COPY (1, chr, c);
933 rest = SCM_CDR (rest);
934
cc0ce1e7 935 p[c / SCM_BITS_PER_LONG] |= 1L << (c % SCM_BITS_PER_LONG);
ca003b26
MG
936 }
937 return cs;
938}
939#undef FUNC_NAME
940
2c4df451 941
ca003b26
MG
942SCM_DEFINE (scm_char_set_delete, "char-set-delete", 1, 0, 1,
943 (SCM cs, SCM rest),
944 "Delete all character arguments from the first argument, which\n"
945 "must be a character set.")
946#define FUNC_NAME s_scm_char_set_delete
947{
948 long * p;
949
950 SCM_VALIDATE_SMOB (1, cs, charset);
951 SCM_VALIDATE_REST_ARGUMENT (rest);
952 cs = scm_char_set_copy (cs);
953
954 p = (long *) SCM_SMOB_DATA (cs);
955 while (!SCM_NULLP (rest))
956 {
957 SCM chr = SCM_CAR (rest);
958 int c;
959
960 SCM_VALIDATE_CHAR_COPY (1, chr, c);
961 rest = SCM_CDR (rest);
962
cc0ce1e7 963 p[c / SCM_BITS_PER_LONG] &= ~(1L << (c % SCM_BITS_PER_LONG));
ca003b26
MG
964 }
965 return cs;
966}
967#undef FUNC_NAME
968
2c4df451 969
ca003b26
MG
970SCM_DEFINE (scm_char_set_adjoin_x, "char-set-adjoin!", 1, 0, 1,
971 (SCM cs, SCM rest),
972 "Add all character arguments to the first argument, which must\n"
973 "be a character set.")
974#define FUNC_NAME s_scm_char_set_adjoin_x
975{
976 long * p;
977
978 SCM_VALIDATE_SMOB (1, cs, charset);
979 SCM_VALIDATE_REST_ARGUMENT (rest);
980
981 p = (long *) SCM_SMOB_DATA (cs);
982 while (!SCM_NULLP (rest))
983 {
984 SCM chr = SCM_CAR (rest);
985 int c;
986
987 SCM_VALIDATE_CHAR_COPY (1, chr, c);
988 rest = SCM_CDR (rest);
989
cc0ce1e7 990 p[c / SCM_BITS_PER_LONG] |= 1L << (c % SCM_BITS_PER_LONG);
ca003b26
MG
991 }
992 return cs;
993}
994#undef FUNC_NAME
995
2c4df451 996
ca003b26
MG
997SCM_DEFINE (scm_char_set_delete_x, "char-set-delete!", 1, 0, 1,
998 (SCM cs, SCM rest),
999 "Delete all character arguments from the first argument, which\n"
1000 "must be a character set.")
1001#define FUNC_NAME s_scm_char_set_delete_x
1002{
1003 long * p;
1004
1005 SCM_VALIDATE_SMOB (1, cs, charset);
1006 SCM_VALIDATE_REST_ARGUMENT (rest);
1007
1008 p = (long *) SCM_SMOB_DATA (cs);
1009 while (!SCM_NULLP (rest))
1010 {
1011 SCM chr = SCM_CAR (rest);
1012 int c;
1013
1014 SCM_VALIDATE_CHAR_COPY (1, chr, c);
1015 rest = SCM_CDR (rest);
1016
cc0ce1e7 1017 p[c / SCM_BITS_PER_LONG] &= ~(1L << (c % SCM_BITS_PER_LONG));
ca003b26
MG
1018 }
1019 return cs;
1020}
1021#undef FUNC_NAME
1022
1023
1024SCM_DEFINE (scm_char_set_complement, "char-set-complement", 1, 0, 0,
1025 (SCM cs),
1026 "Return the complement of the character set @var{cs}.")
1027#define FUNC_NAME s_scm_char_set_complement
1028{
1029 int k;
1030 SCM res;
1031 long * p, * q;
1032
1033 SCM_VALIDATE_SMOB (1, cs, charset);
1034
1035 res = make_char_set (FUNC_NAME);
1036 p = (long *) SCM_SMOB_DATA (res);
1037 q = (long *) SCM_SMOB_DATA (cs);
4c4185ee 1038 for (k = 0; k < LONGS_PER_CHARSET; k++)
ca003b26
MG
1039 p[k] = ~q[k];
1040 return res;
1041}
1042#undef FUNC_NAME
1043
1044
1045SCM_DEFINE (scm_char_set_union, "char-set-union", 0, 0, 1,
1046 (SCM rest),
1047 "Return the union of all argument character sets.")
1048#define FUNC_NAME s_scm_char_set_union
1049{
1050 int c = 1;
1051 SCM res;
1052 long * p;
1053
1054 SCM_VALIDATE_REST_ARGUMENT (rest);
1055
1056 res = make_char_set (FUNC_NAME);
1057 p = (long *) SCM_SMOB_DATA (res);
1058 while (!SCM_NULLP (rest))
1059 {
1060 int k;
1061 SCM cs = SCM_CAR (rest);
1062 SCM_VALIDATE_SMOB (c, cs, charset);
1063 c++;
1064 rest = SCM_CDR (rest);
1065
4c4185ee 1066 for (k = 0; k < LONGS_PER_CHARSET; k++)
ca003b26
MG
1067 p[k] |= ((long *) SCM_SMOB_DATA (cs))[k];
1068 }
1069 return res;
1070}
1071#undef FUNC_NAME
1072
1073
d1bc6602
GH
1074SCM_DEFINE (scm_char_set_intersection, "char-set-intersection", 0, 0, 1,
1075 (SCM rest),
ca003b26
MG
1076 "Return the intersection of all argument character sets.")
1077#define FUNC_NAME s_scm_char_set_intersection
1078{
ca003b26 1079 SCM res;
ca003b26 1080
ca003b26
MG
1081 SCM_VALIDATE_REST_ARGUMENT (rest);
1082
d1bc6602
GH
1083 if (SCM_NULLP (rest))
1084 res = make_char_set (FUNC_NAME);
1085 else
ca003b26 1086 {
d1bc6602
GH
1087 long *p;
1088 int argnum = 2;
1089
1090 res = scm_char_set_copy (SCM_CAR (rest));
1091 p = (long *) SCM_SMOB_DATA (res);
ca003b26
MG
1092 rest = SCM_CDR (rest);
1093
d1bc6602
GH
1094 while (SCM_CONSP (rest))
1095 {
1096 int k;
1097 SCM cs = SCM_CAR (rest);
1098 long *cs_data;
1099
1100 SCM_VALIDATE_SMOB (argnum, cs, charset);
1101 argnum++;
1102 cs_data = (long *) SCM_SMOB_DATA (cs);
1103 rest = SCM_CDR (rest);
1104 for (k = 0; k < LONGS_PER_CHARSET; k++)
1105 p[k] &= cs_data[k];
1106 }
ca003b26 1107 }
d1bc6602 1108
ca003b26
MG
1109 return res;
1110}
1111#undef FUNC_NAME
1112
1113
1114SCM_DEFINE (scm_char_set_difference, "char-set-difference", 1, 0, 1,
1115 (SCM cs1, SCM rest),
1116 "Return the difference of all argument character sets.")
1117#define FUNC_NAME s_scm_char_set_difference
1118{
1119 int c = 2;
1120 SCM res;
1121 long * p;
1122
1123 SCM_VALIDATE_SMOB (1, cs1, charset);
1124 SCM_VALIDATE_REST_ARGUMENT (rest);
1125
1126 res = scm_char_set_copy (cs1);
1127 p = (long *) SCM_SMOB_DATA (res);
1128 while (!SCM_NULLP (rest))
1129 {
1130 int k;
1131 SCM cs = SCM_CAR (rest);
1132 SCM_VALIDATE_SMOB (c, cs, charset);
1133 c++;
1134 rest = SCM_CDR (rest);
1135
4c4185ee 1136 for (k = 0; k < LONGS_PER_CHARSET; k++)
ca003b26
MG
1137 p[k] &= ~((long *) SCM_SMOB_DATA (cs))[k];
1138 }
1139 return res;
1140}
1141#undef FUNC_NAME
1142
1143
d1bc6602
GH
1144SCM_DEFINE (scm_char_set_xor, "char-set-xor", 0, 0, 1,
1145 (SCM rest),
2671725a 1146 "Return the exclusive-or of all argument character sets.")
ca003b26
MG
1147#define FUNC_NAME s_scm_char_set_xor
1148{
ca003b26 1149 SCM res;
ca003b26 1150
ca003b26
MG
1151 SCM_VALIDATE_REST_ARGUMENT (rest);
1152
d1bc6602
GH
1153 if (SCM_NULLP (rest))
1154 res = make_char_set (FUNC_NAME);
1155 else
ca003b26 1156 {
d1bc6602 1157 int argnum = 2;
d95744e9 1158 long * p;
d1bc6602
GH
1159
1160 res = scm_char_set_copy (SCM_CAR (rest));
1161 p = (long *) SCM_SMOB_DATA (res);
ca003b26
MG
1162 rest = SCM_CDR (rest);
1163
d1bc6602
GH
1164 while (SCM_CONSP (rest))
1165 {
d1bc6602 1166 SCM cs = SCM_CAR (rest);
42b54c05 1167 long *cs_data;
d95744e9 1168 int k;
d1bc6602
GH
1169
1170 SCM_VALIDATE_SMOB (argnum, cs, charset);
1171 argnum++;
1172 cs_data = (long *) SCM_SMOB_DATA (cs);
1173 rest = SCM_CDR (rest);
1174
1175 for (k = 0; k < LONGS_PER_CHARSET; k++)
d95744e9 1176 p[k] ^= cs_data[k];
d1bc6602 1177 }
ca003b26
MG
1178 }
1179 return res;
1180}
1181#undef FUNC_NAME
1182
1183
1184SCM_DEFINE (scm_char_set_diff_plus_intersection, "char-set-diff+intersection", 1, 0, 1,
1185 (SCM cs1, SCM rest),
1186 "Return the difference and the intersection of all argument\n"
1187 "character sets.")
1188#define FUNC_NAME s_scm_char_set_diff_plus_intersection
1189{
1190 int c = 2;
1191 SCM res1, res2;
1192 long * p, * q;
1193
1194 SCM_VALIDATE_SMOB (1, cs1, charset);
1195 SCM_VALIDATE_REST_ARGUMENT (rest);
1196
1197 res1 = scm_char_set_copy (cs1);
9be74503 1198 res2 = make_char_set (FUNC_NAME);
ca003b26
MG
1199 p = (long *) SCM_SMOB_DATA (res1);
1200 q = (long *) SCM_SMOB_DATA (res2);
1201 while (!SCM_NULLP (rest))
1202 {
1203 int k;
1204 SCM cs = SCM_CAR (rest);
9be74503
GH
1205 long *r;
1206
ca003b26
MG
1207 SCM_VALIDATE_SMOB (c, cs, charset);
1208 c++;
9be74503 1209 r = (long *) SCM_SMOB_DATA (cs);
ca003b26 1210
4c4185ee 1211 for (k = 0; k < LONGS_PER_CHARSET; k++)
ca003b26 1212 {
9be74503
GH
1213 q[k] |= p[k] & r[k];
1214 p[k] &= ~r[k];
ca003b26 1215 }
9be74503 1216 rest = SCM_CDR (rest);
ca003b26 1217 }
2c4df451 1218 return scm_values (scm_list_2 (res1, res2));
ca003b26
MG
1219}
1220#undef FUNC_NAME
1221
1222
1223SCM_DEFINE (scm_char_set_complement_x, "char-set-complement!", 1, 0, 0,
1224 (SCM cs),
1225 "Return the complement of the character set @var{cs}.")
1226#define FUNC_NAME s_scm_char_set_complement_x
1227{
1228 int k;
1229 long * p;
1230
1231 SCM_VALIDATE_SMOB (1, cs, charset);
1232 p = (long *) SCM_SMOB_DATA (cs);
4c4185ee 1233 for (k = 0; k < LONGS_PER_CHARSET; k++)
ca003b26
MG
1234 p[k] = ~p[k];
1235 return cs;
1236}
1237#undef FUNC_NAME
1238
1239
1240SCM_DEFINE (scm_char_set_union_x, "char-set-union!", 1, 0, 1,
1241 (SCM cs1, SCM rest),
1242 "Return the union of all argument character sets.")
1243#define FUNC_NAME s_scm_char_set_union_x
1244{
1245 int c = 2;
1246 long * p;
1247
1248 SCM_VALIDATE_SMOB (1, cs1, charset);
1249 SCM_VALIDATE_REST_ARGUMENT (rest);
1250
1251 p = (long *) SCM_SMOB_DATA (cs1);
1252 while (!SCM_NULLP (rest))
1253 {
1254 int k;
1255 SCM cs = SCM_CAR (rest);
1256 SCM_VALIDATE_SMOB (c, cs, charset);
1257 c++;
1258 rest = SCM_CDR (rest);
1259
4c4185ee 1260 for (k = 0; k < LONGS_PER_CHARSET; k++)
ca003b26
MG
1261 p[k] |= ((long *) SCM_SMOB_DATA (cs))[k];
1262 }
1263 return cs1;
1264}
1265#undef FUNC_NAME
1266
1267
1268SCM_DEFINE (scm_char_set_intersection_x, "char-set-intersection!", 1, 0, 1,
1269 (SCM cs1, SCM rest),
1270 "Return the intersection of all argument character sets.")
1271#define FUNC_NAME s_scm_char_set_intersection_x
1272{
1273 int c = 2;
1274 long * p;
1275
1276 SCM_VALIDATE_SMOB (1, cs1, charset);
1277 SCM_VALIDATE_REST_ARGUMENT (rest);
1278
1279 p = (long *) SCM_SMOB_DATA (cs1);
1280 while (!SCM_NULLP (rest))
1281 {
1282 int k;
1283 SCM cs = SCM_CAR (rest);
1284 SCM_VALIDATE_SMOB (c, cs, charset);
1285 c++;
1286 rest = SCM_CDR (rest);
1287
4c4185ee 1288 for (k = 0; k < LONGS_PER_CHARSET; k++)
ca003b26
MG
1289 p[k] &= ((long *) SCM_SMOB_DATA (cs))[k];
1290 }
1291 return cs1;
1292}
1293#undef FUNC_NAME
1294
1295
1296SCM_DEFINE (scm_char_set_difference_x, "char-set-difference!", 1, 0, 1,
1297 (SCM cs1, SCM rest),
1298 "Return the difference of all argument character sets.")
1299#define FUNC_NAME s_scm_char_set_difference_x
1300{
1301 int c = 2;
1302 long * p;
1303
1304 SCM_VALIDATE_SMOB (1, cs1, charset);
1305 SCM_VALIDATE_REST_ARGUMENT (rest);
1306
1307 p = (long *) SCM_SMOB_DATA (cs1);
1308 while (!SCM_NULLP (rest))
1309 {
1310 int k;
1311 SCM cs = SCM_CAR (rest);
1312 SCM_VALIDATE_SMOB (c, cs, charset);
1313 c++;
1314 rest = SCM_CDR (rest);
1315
4c4185ee 1316 for (k = 0; k < LONGS_PER_CHARSET; k++)
ca003b26
MG
1317 p[k] &= ~((long *) SCM_SMOB_DATA (cs))[k];
1318 }
1319 return cs1;
1320}
1321#undef FUNC_NAME
1322
1323
1324SCM_DEFINE (scm_char_set_xor_x, "char-set-xor!", 1, 0, 1,
1325 (SCM cs1, SCM rest),
2671725a 1326 "Return the exclusive-or of all argument character sets.")
ca003b26
MG
1327#define FUNC_NAME s_scm_char_set_xor_x
1328{
9be74503
GH
1329 /* a side-effecting variant should presumably give consistent results:
1330 (define a (char-set #\a))
1331 (char-set-xor a a a) -> char set #\a
1332 (char-set-xor! a a a) -> char set #\a
1333 */
1334 return scm_char_set_xor (scm_cons (cs1, rest));
1335
1336#if 0
1337 /* this would give (char-set-xor! a a a) -> empty char set. */
ca003b26
MG
1338 int c = 2;
1339 long * p;
1340
1341 SCM_VALIDATE_SMOB (1, cs1, charset);
1342 SCM_VALIDATE_REST_ARGUMENT (rest);
1343
1344 p = (long *) SCM_SMOB_DATA (cs1);
1345 while (!SCM_NULLP (rest))
1346 {
1347 int k;
1348 SCM cs = SCM_CAR (rest);
1349 SCM_VALIDATE_SMOB (c, cs, charset);
1350 c++;
1351 rest = SCM_CDR (rest);
1352
4c4185ee 1353 for (k = 0; k < LONGS_PER_CHARSET; k++)
ca003b26
MG
1354 p[k] ^= ((long *) SCM_SMOB_DATA (cs))[k];
1355 }
1356 return cs1;
9be74503 1357#endif
ca003b26
MG
1358}
1359#undef FUNC_NAME
1360
1361
9be74503
GH
1362SCM_DEFINE (scm_char_set_diff_plus_intersection_x, "char-set-diff+intersection!", 2, 0, 1,
1363 (SCM cs1, SCM cs2, SCM rest),
2c4df451
MG
1364 "Return the difference and the intersection of all argument\n"
1365 "character sets.")
ca003b26
MG
1366#define FUNC_NAME s_scm_char_set_diff_plus_intersection_x
1367{
9be74503 1368 int c = 3;
ca003b26 1369 long * p, * q;
9be74503 1370 int k;
ca003b26
MG
1371
1372 SCM_VALIDATE_SMOB (1, cs1, charset);
9be74503 1373 SCM_VALIDATE_SMOB (2, cs2, charset);
ca003b26
MG
1374 SCM_VALIDATE_REST_ARGUMENT (rest);
1375
ca003b26 1376 p = (long *) SCM_SMOB_DATA (cs1);
9be74503
GH
1377 q = (long *) SCM_SMOB_DATA (cs2);
1378 if (p == q)
1379 {
1380 /* (char-set-diff+intersection! a a ...): can't share storage,
1381 but we know the answer without checking for further
1382 arguments. */
1383 return scm_values (scm_list_2 (make_char_set (FUNC_NAME), cs1));
1384 }
1385 for (k = 0; k < LONGS_PER_CHARSET; k++)
1386 {
1387 long t = p[k];
1388
1389 p[k] &= ~q[k];
1390 q[k] = t & q[k];
1391 }
ca003b26
MG
1392 while (!SCM_NULLP (rest))
1393 {
ca003b26 1394 SCM cs = SCM_CAR (rest);
9be74503
GH
1395 long *r;
1396
ca003b26
MG
1397 SCM_VALIDATE_SMOB (c, cs, charset);
1398 c++;
9be74503 1399 r = (long *) SCM_SMOB_DATA (cs);
ca003b26 1400
4c4185ee 1401 for (k = 0; k < LONGS_PER_CHARSET; k++)
ca003b26 1402 {
9be74503
GH
1403 q[k] |= p[k] & r[k];
1404 p[k] &= ~r[k];
ca003b26 1405 }
9be74503 1406 rest = SCM_CDR (rest);
ca003b26 1407 }
9be74503 1408 return scm_values (scm_list_2 (cs1, cs2));
ca003b26
MG
1409}
1410#undef FUNC_NAME
1411
1412
2c4df451 1413/* Create the charset smob type. */
ca003b26 1414void
94451729 1415scm_c_init_srfi_14 (void)
ca003b26 1416{
2c4df451
MG
1417 /* Charset smob creation is protected by this variable because this
1418 function can be both called from the SRFI-13 and SRFI-14
1419 initialization functions. This is because the SRFI-13 procedures
1420 access the charset smob type code. */
5d980558 1421 static int initialized = 0;
94451729
MV
1422
1423 if (!initialized)
1424 {
2671725a 1425 scm_tc16_charset = scm_make_smob_type ("character-set",
4c4185ee 1426 BYTES_PER_CHARSET);
94451729
MV
1427 scm_set_smob_free (scm_tc16_charset, charset_free);
1428 scm_set_smob_print (scm_tc16_charset, charset_print);
1429 initialized = 1;
1430 }
1431}
ca003b26 1432
2c4df451
MG
1433
1434/* Initialize the SRFI-14 module. This function will be called by the
1435 loading Scheme module. */
94451729
MV
1436void
1437scm_init_srfi_14 (void)
1438{
4c4185ee
MG
1439#if 0
1440 fprintf(stderr, "bytes-per-charset: %d\n", BYTES_PER_CHARSET);
1441 fprintf(stderr, "bits-per-long: %d\n", SCM_BITS_PER_LONG);
1442 fprintf(stderr, "longs-per-charset: %d\n", LONGS_PER_CHARSET);
1443 fflush (stderr);
1444#endif /* 0 */
1445
2c4df451 1446 /* Do the smob type initialization. */
94451729 1447 scm_c_init_srfi_14 ();
2c4df451
MG
1448
1449 /* Install the charset primitives. */
ca003b26 1450#ifndef SCM_MAGIC_SNARFER
485efc12 1451#include "srfi/srfi-14.x"
ca003b26
MG
1452#endif
1453}
2c4df451
MG
1454
1455/* End of srfi-14.c. */