* eval.c (RETURN): Wrap in do{}while(0) in order to make it
[bpt/guile.git] / libguile / chars.c
... / ...
CommitLineData
1/* Copyright (C) 1995,1996,1998, 2000, 2001 Free Software Foundation, Inc.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
41
42
43\f
44
45#include <ctype.h>
46#include "libguile/_scm.h"
47#include "libguile/validate.h"
48
49#include "libguile/chars.h"
50\f
51
52SCM_DEFINE (scm_char_p, "char?", 1, 0, 0,
53 (SCM x),
54 "Return @code{#t} iff @var{x} is a character, else @code{#f}.")
55#define FUNC_NAME s_scm_char_p
56{
57 return SCM_BOOL(SCM_CHARP(x));
58}
59#undef FUNC_NAME
60
61SCM_DEFINE1 (scm_char_eq_p, "char=?", scm_tc7_rpsubr,
62 (SCM x, SCM y),
63 "Return @code{#t} iff @var{x} is the same character as @var{y}, else @code{#f}.")
64#define FUNC_NAME s_scm_char_eq_p
65{
66 SCM_VALIDATE_CHAR (1, x);
67 SCM_VALIDATE_CHAR (2, y);
68 return SCM_BOOL (SCM_EQ_P (x, y));
69}
70#undef FUNC_NAME
71
72
73SCM_DEFINE1 (scm_char_less_p, "char<?", scm_tc7_rpsubr,
74 (SCM x, SCM y),
75 "Return @code{#t} iff @var{x} is less than @var{y} in the ASCII sequence,\n"
76 "else @code{#f}.")
77#define FUNC_NAME s_scm_char_less_p
78{
79 SCM_VALIDATE_CHAR (1,x);
80 SCM_VALIDATE_CHAR (2,y);
81 return SCM_BOOL(SCM_CHAR(x) < SCM_CHAR(y));
82}
83#undef FUNC_NAME
84
85SCM_DEFINE1 (scm_char_leq_p, "char<=?", scm_tc7_rpsubr,
86 (SCM x, SCM y),
87 "Return @code{#t} iff @var{x} is less than or equal to @var{y} in the\n"
88 "ASCII sequence, else @code{#f}.")
89#define FUNC_NAME s_scm_char_leq_p
90{
91 SCM_VALIDATE_CHAR (1,x);
92 SCM_VALIDATE_CHAR (2,y);
93 return SCM_BOOL(SCM_CHAR(x) <= SCM_CHAR(y));
94}
95#undef FUNC_NAME
96
97SCM_DEFINE1 (scm_char_gr_p, "char>?", scm_tc7_rpsubr,
98 (SCM x, SCM y),
99 "Return @code{#t} iff @var{x} is greater than @var{y} in the ASCII\n"
100 "sequence, else @code{#f}.")
101#define FUNC_NAME s_scm_char_gr_p
102{
103 SCM_VALIDATE_CHAR (1,x);
104 SCM_VALIDATE_CHAR (2,y);
105 return SCM_BOOL(SCM_CHAR(x) > SCM_CHAR(y));
106}
107#undef FUNC_NAME
108
109SCM_DEFINE1 (scm_char_geq_p, "char>=?", scm_tc7_rpsubr,
110 (SCM x, SCM y),
111 "Return @code{#t} iff @var{x} is greater than or equal to @var{y} in the\n"
112 "ASCII sequence, else @code{#f}.")
113#define FUNC_NAME s_scm_char_geq_p
114{
115 SCM_VALIDATE_CHAR (1,x);
116 SCM_VALIDATE_CHAR (2,y);
117 return SCM_BOOL(SCM_CHAR(x) >= SCM_CHAR(y));
118}
119#undef FUNC_NAME
120
121SCM_DEFINE1 (scm_char_ci_eq_p, "char-ci=?", scm_tc7_rpsubr,
122 (SCM x, SCM y),
123 "Return @code{#t} iff @var{x} is the same character as @var{y} ignoring\n"
124 "case, else @code{#f}.")
125#define FUNC_NAME s_scm_char_ci_eq_p
126{
127 SCM_VALIDATE_CHAR (1,x);
128 SCM_VALIDATE_CHAR (2,y);
129 return SCM_BOOL(scm_upcase(SCM_CHAR(x))==scm_upcase(SCM_CHAR(y)));
130}
131#undef FUNC_NAME
132
133SCM_DEFINE1 (scm_char_ci_less_p, "char-ci<?", scm_tc7_rpsubr,
134 (SCM x, SCM y),
135 "Return @code{#t} iff @var{x} is less than @var{y} in the ASCII sequence\n"
136 "ignoring case, else @code{#f}.")
137#define FUNC_NAME s_scm_char_ci_less_p
138{
139 SCM_VALIDATE_CHAR (1,x);
140 SCM_VALIDATE_CHAR (2,y);
141 return SCM_BOOL((scm_upcase(SCM_CHAR(x))) < scm_upcase(SCM_CHAR(y)));
142}
143#undef FUNC_NAME
144
145SCM_DEFINE1 (scm_char_ci_leq_p, "char-ci<=?", scm_tc7_rpsubr,
146 (SCM x, SCM y),
147 "Return @code{#t} iff @var{x} is less than or equal to @var{y} in the\n"
148 "ASCII sequence ignoring case, else @code{#f}.")
149#define FUNC_NAME s_scm_char_ci_leq_p
150{
151 SCM_VALIDATE_CHAR (1,x);
152 SCM_VALIDATE_CHAR (2,y);
153 return SCM_BOOL(scm_upcase(SCM_CHAR(x)) <= scm_upcase(SCM_CHAR(y)));
154}
155#undef FUNC_NAME
156
157SCM_DEFINE1 (scm_char_ci_gr_p, "char-ci>?", scm_tc7_rpsubr,
158 (SCM x, SCM y),
159 "Return @code{#t} iff @var{x} is greater than @var{y} in the ASCII\n"
160 "sequence ignoring case, else @code{#f}.")
161#define FUNC_NAME s_scm_char_ci_gr_p
162{
163 SCM_VALIDATE_CHAR (1,x);
164 SCM_VALIDATE_CHAR (2,y);
165 return SCM_BOOL(scm_upcase(SCM_CHAR(x)) > scm_upcase(SCM_CHAR(y)));
166}
167#undef FUNC_NAME
168
169SCM_DEFINE1 (scm_char_ci_geq_p, "char-ci>=?", scm_tc7_rpsubr,
170 (SCM x, SCM y),
171 "Return @code{#t} iff @var{x} is greater than or equal to @var{y} in the\n"
172 "ASCII sequence ignoring case, else @code{#f}.")
173#define FUNC_NAME s_scm_char_ci_geq_p
174{
175 SCM_VALIDATE_CHAR (1,x);
176 SCM_VALIDATE_CHAR (2,y);
177 return SCM_BOOL(scm_upcase(SCM_CHAR(x)) >= scm_upcase(SCM_CHAR(y)));
178}
179#undef FUNC_NAME
180
181
182SCM_DEFINE (scm_char_alphabetic_p, "char-alphabetic?", 1, 0, 0,
183 (SCM chr),
184 "Return @code{#t} iff @var{chr} is alphabetic, else @code{#f}.\n"
185 "Alphabetic means the same thing as the isalpha C library function.")
186#define FUNC_NAME s_scm_char_alphabetic_p
187{
188 SCM_VALIDATE_CHAR (1,chr);
189 return SCM_BOOL(isalpha(SCM_CHAR(chr)));
190}
191#undef FUNC_NAME
192
193SCM_DEFINE (scm_char_numeric_p, "char-numeric?", 1, 0, 0,
194 (SCM chr),
195 "Return @code{#t} iff @var{chr} is numeric, else @code{#f}.\n"
196 "Numeric means the same thing as the isdigit C library function.")
197#define FUNC_NAME s_scm_char_numeric_p
198{
199 SCM_VALIDATE_CHAR (1,chr);
200 return SCM_BOOL(isdigit(SCM_CHAR(chr)));
201}
202#undef FUNC_NAME
203
204SCM_DEFINE (scm_char_whitespace_p, "char-whitespace?", 1, 0, 0,
205 (SCM chr),
206 "Return @code{#t} iff @var{chr} is whitespace, else @code{#f}.\n"
207 "Whitespace means the same thing as the isspace C library function.")
208#define FUNC_NAME s_scm_char_whitespace_p
209{
210 SCM_VALIDATE_CHAR (1,chr);
211 return SCM_BOOL(isspace(SCM_CHAR(chr)));
212}
213#undef FUNC_NAME
214
215
216
217SCM_DEFINE (scm_char_upper_case_p, "char-upper-case?", 1, 0, 0,
218 (SCM chr),
219 "Return @code{#t} iff @var{chr} is uppercase, else @code{#f}.\n"
220 "Uppercase means the same thing as the isupper C library function.")
221#define FUNC_NAME s_scm_char_upper_case_p
222{
223 SCM_VALIDATE_CHAR (1,chr);
224 return SCM_BOOL(isupper(SCM_CHAR(chr)));
225}
226#undef FUNC_NAME
227
228
229SCM_DEFINE (scm_char_lower_case_p, "char-lower-case?", 1, 0, 0,
230 (SCM chr),
231 "Return @code{#t} iff @var{chr} is lowercase, else @code{#f}.\n"
232 "Lowercase means the same thing as the islower C library function.")
233#define FUNC_NAME s_scm_char_lower_case_p
234{
235 SCM_VALIDATE_CHAR (1,chr);
236 return SCM_BOOL(islower(SCM_CHAR(chr)));
237}
238#undef FUNC_NAME
239
240
241
242SCM_DEFINE (scm_char_is_both_p, "char-is-both?", 1, 0, 0,
243 (SCM chr),
244 "Return @code{#t} iff @var{chr} is either uppercase or lowercase, else @code{#f}.\n"
245 "Uppercase and lowercase are as defined by the isupper and islower\n"
246 "C library functions.")
247#define FUNC_NAME s_scm_char_is_both_p
248{
249 SCM_VALIDATE_CHAR (1,chr);
250 return SCM_BOOL((isupper(SCM_CHAR(chr)) || islower(SCM_CHAR(chr))));
251}
252#undef FUNC_NAME
253
254
255
256
257SCM_DEFINE (scm_char_to_integer, "char->integer", 1, 0, 0,
258 (SCM chr),
259 "Return the number corresponding to ordinal position of @var{chr} in the\n"
260 "ASCII sequence.")
261#define FUNC_NAME s_scm_char_to_integer
262{
263 SCM_VALIDATE_CHAR (1,chr);
264 return scm_ulong2num((unsigned long)SCM_CHAR(chr));
265}
266#undef FUNC_NAME
267
268
269
270SCM_DEFINE (scm_integer_to_char, "integer->char", 1, 0, 0,
271 (SCM n),
272 "Return the character at position @var{n} in the ASCII sequence.")
273#define FUNC_NAME s_scm_integer_to_char
274{
275 SCM_VALIDATE_INUM_RANGE (1, n, 0, 256);
276 return SCM_MAKE_CHAR (SCM_INUM (n));
277}
278#undef FUNC_NAME
279
280
281SCM_DEFINE (scm_char_upcase, "char-upcase", 1, 0, 0,
282 (SCM chr),
283 "Return the uppercase character version of @var{chr}.")
284#define FUNC_NAME s_scm_char_upcase
285{
286 SCM_VALIDATE_CHAR (1,chr);
287 return SCM_MAKE_CHAR(scm_upcase(SCM_CHAR(chr)));
288}
289#undef FUNC_NAME
290
291
292SCM_DEFINE (scm_char_downcase, "char-downcase", 1, 0, 0,
293 (SCM chr),
294 "Return the lowercase character version of @var{chr}.")
295#define FUNC_NAME s_scm_char_downcase
296{
297 SCM_VALIDATE_CHAR (1,chr);
298 return SCM_MAKE_CHAR(scm_downcase(SCM_CHAR(chr)));
299}
300#undef FUNC_NAME
301
302\f
303
304
305
306static unsigned char scm_upcase_table[SCM_CHAR_CODE_LIMIT];
307static unsigned char scm_downcase_table[SCM_CHAR_CODE_LIMIT];
308static const unsigned char scm_lowers[] = "abcdefghijklmnopqrstuvwxyz";
309static const unsigned char scm_uppers[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
310
311
312void
313scm_tables_prehistory ()
314{
315 int i;
316 for (i = 0; i < SCM_CHAR_CODE_LIMIT; i++)
317 scm_upcase_table[i] = scm_downcase_table[i] = i;
318 for (i = 0; i < (int) (sizeof scm_lowers / sizeof (scm_lowers[0])); i++)
319 {
320 scm_upcase_table[scm_lowers[i]] = scm_uppers[i];
321 scm_downcase_table[scm_uppers[i]] = scm_lowers[i];
322 }
323}
324
325
326int
327scm_upcase (unsigned int c)
328{
329 if (c < sizeof (scm_upcase_table))
330 return scm_upcase_table[c];
331 else
332 return c;
333}
334
335
336int
337scm_downcase (unsigned int c)
338{
339 if (c < sizeof (scm_downcase_table))
340 return scm_downcase_table[c];
341 else
342 return c;
343}
344
345
346#ifdef _DCC
347# define ASCII
348#else
349# if (('\n'=='\025') && (' '=='\100') && ('a'=='\201') && ('A'=='\301'))
350# define EBCDIC
351# endif /* (('\n'=='\025') && (' '=='\100') && ('a'=='\201') && ('A'=='\301')) */
352# if (('\n'=='\012') && (' '=='\040') && ('a'=='\141') && ('A'=='\101'))
353# define ASCII
354# endif /* (('\n'=='\012') && (' '=='\040') && ('a'=='\141') && ('A'=='\101')) */
355#endif /* def _DCC */
356
357
358#ifdef EBCDIC
359char *const scm_charnames[] =
360{
361 "nul","soh","stx","etx", "pf", "ht", "lc","del",
362 0 , 0 ,"smm", "vt", "ff", "cr", "so", "si",
363 "dle","dc1","dc2","dc3","res", "nl", "bs", "il",
364 "can", "em", "cc", 0 ,"ifs","igs","irs","ius",
365 "ds","sos", "fs", 0 ,"byp", "lf","eob","pre",
366 0 , 0 , "sm", 0 , 0 ,"enq","ack","bel",
367 0 , 0 ,"syn", 0 , "pn", "rs", "uc","eot",
368 0 , 0 , 0 , 0 ,"dc4","nak", 0 ,"sub",
369 "space", scm_s_newline, "tab", "backspace", "return", "page", "null"};
370
371const char scm_charnums[] =
372"\000\001\002\003\004\005\006\007\
373\010\011\012\013\014\015\016\017\
374\020\021\022\023\024\025\026\027\
375\030\031\032\033\034\035\036\037\
376\040\041\042\043\044\045\046\047\
377\050\051\052\053\054\055\056\057\
378\060\061\062\063\064\065\066\067\
379\070\071\072\073\074\075\076\077\
380 \n\t\b\r\f\0";
381#endif /* def EBCDIC */
382#ifdef ASCII
383char *const scm_charnames[] =
384{
385 "nul","soh","stx","etx","eot","enq","ack","bel",
386 "bs", "ht", "newline", "vt", "np", "cr", "so", "si",
387 "dle","dc1","dc2","dc3","dc4","nak","syn","etb",
388 "can", "em","sub","esc", "fs", "gs", "rs", "us",
389 "space", "nl", "tab", "backspace", "return", "page", "null", "del"};
390const char scm_charnums[] =
391"\000\001\002\003\004\005\006\007\
392\010\011\012\013\014\015\016\017\
393\020\021\022\023\024\025\026\027\
394\030\031\032\033\034\035\036\037\
395 \n\t\b\r\f\0\177";
396#endif /* def ASCII */
397
398int scm_n_charnames = sizeof (scm_charnames) / sizeof (char *);
399
400
401\f
402
403
404void
405scm_init_chars ()
406{
407#ifndef SCM_MAGIC_SNARFER
408#include "libguile/chars.x"
409#endif
410}
411
412
413/*
414 Local Variables:
415 c-file-style: "gnu"
416 End:
417*/