/* character.d -- Character routines. */ /* Copyright (c) 1984, Taiichi Yuasa and Masami Hagiya. Copyright (c) 1990, Giuseppe Attardi. ECL is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See file '../Copyright' for full details. */ #include "ecl.h" #include /******************************* LOCALS *******************************/ static cl_object STreturn; static cl_object STspace; static cl_object STrubout; static cl_object STpage; static cl_object STtab; static cl_object STbackspace; static cl_object STlinefeed; static cl_object STnewline; static cl_object STnull; /******************************* ------- ******************************/ cl_fixnum char_code(cl_object c) { if (CHARACTERP(c)) return CHAR_CODE(c); FEtype_error_character(c); } cl_object cl_standard_char_p(cl_object c) { /* INV: char_code() checks the type */ cl_fixnum i = char_code(c); if ((' ' <= i && i < '\177') || i == '\n') return1(Ct); return1(Cnil); } cl_object cl_graphic_char_p(cl_object c) { /* INV: char_code() checks the type */ cl_fixnum i = char_code(c); if (' ' <= i && i < '\177') /* ' ' < '\177' ??? Beppe*/ return1(Ct); return1(Cnil); } cl_object cl_alpha_char_p(cl_object c) { /* INV: char_code() checks the type */ cl_fixnum i = char_code(c); if (isalpha(i)) return1(Ct); else return1(Cnil); } cl_object cl_upper_case_p(cl_object c) { /* INV: char_code() checks the type */ if (isupper(char_code(c))) return1(Ct); return1(Cnil); } cl_object cl_lower_case_p(cl_object c) { /* INV: char_code() checks the type */ if (islower(char_code(c))) return1(Ct); return1(Cnil); } cl_object cl_both_case_p(cl_object c) { /* INV: char_code() checks the type */ cl_fixnum code = char_code(c); return1((isupper(code) || islower(code)) ? Ct : Cnil); } #define basep(d) (d <= 36) @(defun digit_char_p (c &optional (r MAKE_FIXNUM(10))) cl_fixnum d; @ /* INV: char_code() checks `c' and fixnnint() checks `r' */ if (type_of(r) == t_bignum) @(return Cnil) d = fixnnint(r); if (!basep(d) || (d = digitp(char_code(c), d)) < 0) @(return Cnil) @(return MAKE_FIXNUM(d)) @) /* Digitp(i, r) returns the weight of code i as a digit of radix r, which must be 1 < r <= 36. If i is not a digit, -1 is returned. */ int digitp(int i, int r) { if (('0' <= i) && (i <= '9') && (i < '0' + r)) return(i - '0'); if (('A' <= i) && (10 < r) && (i < 'A' + (r - 10))) return(i - 'A' + 10); if (('a' <= i) && (10 < r) && (i < 'a' + (r - 10))) return(i - 'a' + 10); return(-1); } cl_object cl_alphanumericp(cl_object c) { /* INV: char_code() checks type of `c' */ cl_fixnum i = char_code(c); return1(isalnum(i)? Ct : Cnil); } @(defun char= (c &rest cs) @ /* INV: char_eq() checks types of `c' and `cs' */ while (--narg) if (!char_eq(c, cl_va_arg(cs))) @(return Cnil) @(return Ct) @) bool char_eq(cl_object x, cl_object y) { return char_code(x) == char_code(y); } @(defun char/= (&rest cs) int i, j; cl_object c; @ /* INV: char_eq() checks types of its arguments */ if (narg == 0) @(return Ct) c = cl_va_arg(cs); for (i = 2; i<=narg; i++) { cl_va_list ds; cl_va_start(ds, narg, narg, 0); c = cl_va_arg(cs); for (j = 1; j (&rest args) @ @(return Lchar_cmp(narg,-1, 1, args)) @) @(defun char<= (&rest args) @ @(return Lchar_cmp(narg, 1, 0, args)) @) @(defun char>= (&rest args) @ @(return Lchar_cmp(narg,-1, 0, args)) @) @(defun char_equal (c &rest cs) int i; @ /* INV: char_equal() checks the type of its arguments */ for (narg--, i = 0; i < narg; i++) { if (!char_equal(c, cl_va_arg(cs))) @(return Cnil) } @(return Ct) @) bool char_equal(cl_object x, cl_object y) { cl_fixnum i = char_code(x); cl_fixnum j = char_code(y); if (islower(i)) i = toupper(i); if (islower(j)) j = toupper(j); return(i == j); } @(defun char-not-equal (&rest cs) int i, j; cl_object c; @ if (narg == 0) @(return Ct) /* INV: char_equal() checks the type of its arguments */ c = cl_va_arg(cs); for (i = 2; i<=narg; i++) { cl_va_list ds; cl_va_start(ds, narg, narg, 0); c = cl_va_arg(cs); for (j=1; jsymbol.name; case t_string: if (x->string.fillp == 1) x = CODE_CHAR(x->string.self[0]); break; default: FEtype_error_character(x); } @(return x) } cl_object cl_char_code(cl_object c) { /* INV: char_code() checks the type of `c' */ @(return MAKE_FIXNUM(char_code(c))) } cl_object cl_code_char(cl_object c) { cl_fixnum fc; switch (type_of(c)) { case t_fixnum: fc = fix(c); if (fc < CHAR_CODE_LIMIT && fc >= 0) { c = CODE_CHAR(fc); break; } case t_bignum: c = Cnil; break; default: FEtype_error_integer(c); } @(return c) } cl_object cl_char_upcase(cl_object c) { /* INV: char_code() checks the type of `c' */ cl_fixnum code = char_code(c); return1(islower(char_code(c)) ? CODE_CHAR(toupper(char_code(c))) : c); } cl_object cl_char_downcase(cl_object c) { /* INV: char_code() checks the type of `c' */ cl_fixnum code = char_code(c); return1(isupper(char_code(c)) ? CODE_CHAR(tolower(char_code(c))) : c); } @(defun digit_char (w &optional (r MAKE_FIXNUM(10))) int dw; @ /* INV: fixnnint() checks the types of `w' and `r' */ if (type_of(w) == t_bignum || type_of(r) == t_bignum) @(return Cnil) dw = digit_weight(fixnnint(w), fixnnint(r)); if (dw < 0) @(return Cnil) @(return CODE_CHAR(dw)) @) short digit_weight(int w, int r) { if (r < 2 || r > 36 || w < 0 || w >= r) return(-1); if (w < 10) return(w + '0'); else return(w - 10 + 'A'); } cl_object cl_char_int(cl_object c) { /* INV: char_code() checks the type of `c' */ return1(MAKE_FIXNUM(char_code(c))); } cl_object cl_int_char(cl_object x) { /* INV: fixnnint(x) checks the type of `c' */ if (type_of(x) == t_bignum) return1(Cnil); return1(CODE_CHAR(fixnnint(x))); } cl_object cl_char_name(cl_object c) { /* INV: char_code() checks the type of `c' */ switch (char_code(c)) { case '0': return1(STnull); case '\r': return1(STreturn); case ' ': return1(STspace); case '\177': return1(STrubout); case '\f': return1(STpage); case '\t': return1(STtab); case '\b': return1(STbackspace); case '\n': return1(STnewline); } return1(Cnil); } cl_object cl_name_char(cl_object s) { char c; s = cl_string(s); if (string_equal(s, STreturn)) c = '\r'; else if (string_equal(s, STspace)) c = ' '; else if (string_equal(s, STrubout)) c = '\177'; else if (string_equal(s, STpage)) c = '\f'; else if (string_equal(s, STtab)) c = '\t'; else if (string_equal(s, STbackspace)) c = '\b'; else if (string_equal(s, STlinefeed) || string_equal(s, STnewline)) c = '\n'; else if (string_equal(s, STnull)) c = '\000'; else return1(Cnil); return1(CODE_CHAR(c)); } void init_character(void) { SYM_VAL(@'char-code-limit') = MAKE_FIXNUM(CHAR_CODE_LIMIT); STreturn = make_simple_string("RETURN"); ecl_register_static_root(&STreturn); STspace = make_simple_string("SPACE"); ecl_register_static_root(&STspace); STrubout = make_simple_string("RUBOUT"); ecl_register_static_root(&STrubout); STpage = make_simple_string("PAGE"); ecl_register_static_root(&STpage); STtab = make_simple_string("TAB"); ecl_register_static_root(&STtab); STbackspace = make_simple_string("BACKSPACE"); ecl_register_static_root(&STbackspace); STlinefeed = make_simple_string("LINEFEED"); ecl_register_static_root(&STlinefeed); STnull = make_simple_string("NULL"); ecl_register_static_root(&STnull); STnewline = make_simple_string("NEWLINE"); ecl_register_static_root(&STnewline); }