home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcl / src-16f.lha / code / char.lisp < prev    next >
Encoding:
Text File  |  1992-05-30  |  12.0 KB  |  376 lines

  1. ;;; -*- Log: code.log; Package: Lisp -*-
  2. ;;;
  3. ;;; **********************************************************************
  4. ;;; This code was written as part of the CMU Common Lisp project at
  5. ;;; Carnegie Mellon University, and has been placed in the public domain.
  6. ;;; If you want to use this code or any part of CMU Common Lisp, please contact
  7. ;;; Scott Fahlman or slisp-group@cs.cmu.edu.
  8. ;;;
  9. (ext:file-comment
  10.   "$Header: char.lisp,v 1.6 91/11/09 02:47:07 wlott Exp $")
  11. ;;;
  12. ;;; **********************************************************************
  13. ;;;
  14. ;;; Character functions for Spice Lisp.  Part of the standard Spice Lisp
  15. ;;; environment.
  16. ;;;
  17. ;;; This file assumes the use of ASCII codes and the specific character formats
  18. ;;; used in Spice Lisp and Vax Common Lisp.  It is optimized for performance
  19. ;;; rather than for portability and elegance, and may have to be rewritten if
  20. ;;; the character representation is changed.
  21. ;;;
  22. ;;; Written by Guy Steele.
  23. ;;; Rewritten by David Dill.
  24. ;;; Hacked up for speed by Scott Fahlman.
  25. ;;; Font support flushed and type hackery rewritten by Rob MacLachlan.
  26. ;;;
  27. (in-package 'lisp)
  28.  
  29. (export '(char-code-limit standard-char-p graphic-char-p 
  30.       alpha-char-p upper-case-p lower-case-p both-case-p digit-char-p
  31.       alphanumericp char= char/= char< char> char<= char>= char-equal
  32.       char-not-equal char-lessp char-greaterp char-not-greaterp
  33.       char-not-lessp character char-code code-char char-upcase
  34.       char-downcase digit-char char-int char-name name-char))
  35.  
  36.  
  37. ;;; Compile some trivial character operations via inline expansion:
  38. ;;;
  39. (proclaim '(inline standard-char-p graphic-char-p alpha-char-p
  40.            upper-case-p lower-case-p both-case-p alphanumericp
  41.            char-int))
  42.  
  43.  
  44. (defconstant char-code-limit 256
  45.   "The upper exclusive bound on values produced by CHAR-CODE.")
  46.  
  47. (deftype char-code ()
  48.   `(integer 0 (,char-code-limit)))
  49.  
  50.  
  51. (defparameter char-name-alist
  52.     `(("NULL" . ,(code-char 0))
  53.       ("BELL" . ,(code-char 7))
  54.       ("BACKSPACE" . ,(code-char 8)) ("BS" . ,(code-char 8))
  55.       ("TAB" . ,(code-char 9))
  56.       ("NEWLINE" . ,(code-char 10)) ("NL" . ,(code-char 10))  
  57.       ("LINEFEED" . ,(code-char 10)) ("LF" . ,(code-char 10))
  58.       ("VT" . ,(code-char 11))
  59.       ("PAGE" . ,(code-char 12)) ("FORM" . ,(code-char 12))
  60.       ("FORMFEED" . ,(code-char 12)) ("FF" . ,(code-char 12))
  61.       ("RETURN" . ,(code-char 13)) ("CR" . ,(code-char 13))
  62.       ("ESCAPE" . ,(code-char 27)) ("ESC" . ,(code-char 27))
  63.       ("ALTMODE" . ,(code-char 27)) ("ALT" . ,(code-char 27))
  64.       ("SPACE" . ,(code-char 32)) ("SP" . ,(code-char 32))
  65.       ("DELETE" . ,(code-char 127)) ("RUBOUT" . ,(code-char 127)))
  66.   "This is the alist of (character-name . character) for characters
  67.   with long names.  The first name in this list for a given character
  68.   is used on typeout and is the preferred form for input.")
  69.  
  70.  
  71. ;;;; Accessor functions:
  72.  
  73. (defun char-code (char)
  74.   "Returns the integer code of CHAR."
  75.   (etypecase char
  76.     (base-char (char-code (truly-the base-char char)))))
  77.  
  78.  
  79. (defun char-int (char)
  80.   "Returns the integer code of CHAR.  This is the same as char-code, as
  81.    CMU Common Lisp does not implement character bits or fonts."
  82.   (char-code char))
  83.  
  84.  
  85. (defun code-char (code)
  86.   "Returns the character with the code CODE."
  87.   (declare (type char-code code))
  88.   (code-char code))
  89.  
  90.  
  91. (defun character (object)
  92.   "Coerces its argument into a character object if possible.  Accepts
  93.   characters, strings and symbols of length 1, and integers."
  94.   (typecase object
  95.     (character object)
  96.     (char-code (code-char object))
  97.     (string (if (= 1 (length (the string object)))
  98.         (char object 0)
  99.         (error "String is not of length one: ~S" object)))
  100.     (symbol (if (= 1 (length (symbol-name object)))
  101.         (schar (symbol-name object) 0)
  102.         (error "Symbol name is not of length one: ~S" object)))
  103.     (t
  104.      (error "~S cannot be coerced to a character."))))
  105.  
  106.  
  107.  
  108. (defun char-name (char)
  109.   "Given a character object, char-name returns the name for that
  110.   object (a symbol)."
  111.   (car (rassoc char char-name-alist)))
  112.  
  113.  
  114. (defun name-char (name)
  115.   "Given an argument acceptable to string, name-char returns a character
  116.   object whose name is that symbol, if one exists.  Otherwise, () is returned."
  117.   (cdr (assoc (string name) char-name-alist :test #'string-equal)))
  118.  
  119.  
  120.  
  121.  
  122. ;;;; Predicates:
  123.  
  124. (defun standard-char-p (char)
  125.   "The argument must be a character object.  Standard-char-p returns T if the
  126.    argument is a standard character -- one of the 95 ASCII printing characters
  127.    or <return>."
  128.   (declare (character char))
  129.   (and (typep char 'base-char)
  130.        (let ((n (char-code (the base-char char))))
  131.      (or (< 31 n 127)
  132.          (= n 10)))))
  133.  
  134. (defun %standard-char-p (thing)
  135.   "Return T if and only if THING is a standard-char.  Differs from
  136.   standard-char-p in that THING doesn't have to be a character."
  137.   (and (characterp thing) (standard-char-p thing)))
  138.  
  139. (defun graphic-char-p (char)
  140.   "The argument must be a character object.  Graphic-char-p returns T if the
  141.   argument is a printing character (space through ~ in ASCII), otherwise
  142.   returns ()."
  143.   (declare (character char))
  144.   (and (typep char 'base-char)
  145.        (< 31
  146.       (char-code (the base-char char))
  147.       127)))
  148.  
  149.  
  150. (defun alpha-char-p (char)
  151.   "The argument must be a character object.  Alpha-char-p returns T if the
  152.    argument is an alphabetic character, A-Z or a-z; otherwise ()."
  153.   (declare (character char))
  154.   (let ((m (char-code char)))
  155.     (or (< 64 m 91) (< 96 m 123))))
  156.  
  157.  
  158. (defun upper-case-p (char)
  159.   "The argument must be a character object; upper-case-p returns T if the
  160.    argument is an upper-case character, () otherwise."
  161.   (declare (character char))
  162.   (< 64
  163.      (char-code char)
  164.      91))
  165.  
  166.  
  167. (defun lower-case-p (char)
  168.   "The argument must be a character object; lower-case-p returns T if the 
  169.    argument is a lower-case character, () otherwise."
  170.   (declare (character char))
  171.   (< 96
  172.      (char-code char)
  173.      123))
  174.  
  175.  
  176. (defun both-case-p (char)
  177.   "The argument must be a character object.  Both-case-p returns T if the
  178.   argument is an alphabetic character and if the character exists in
  179.   both upper and lower case.  For ASCII, this is the same as Alpha-char-p."
  180.   (declare (character char))
  181.   (let ((m (char-code char)))
  182.     (or (< 64 m 91) (< 96 m 123))))
  183.  
  184.  
  185. (defun digit-char-p (char &optional (radix 10.))
  186.   "If char is a digit in the specified radix, returns the fixnum for
  187.   which that digit stands, else returns NIL.  Radix defaults to 10
  188.   (decimal)."
  189.   (declare (character char))
  190.   (let ((m (- (char-code char) 48)))
  191.     (cond ((<= radix 10.)
  192.        ;; Special-case decimal and smaller radices.
  193.        (if (and (>= m 0) (< m radix))  m  nil))
  194.       ;; Cannot handle radix past Z.
  195.       ((> radix 36)
  196.        (error "~S too large to be an input radix."  radix))
  197.       ;; Digits 0 - 9 are used as is, since radix is larger.
  198.       ((and (>= m 0) (< m 10)) m)
  199.       ;; Check for upper case A - Z.
  200.       ((and (>= (setq m (- m 7)) 10) (< m radix)) m)
  201.       ;; Also check lower case a - z.
  202.       ((and (>= (setq m (- m 32)) 10) (< m radix)) m)
  203.       ;; Else, fail.
  204.       (t nil))))
  205.  
  206.  
  207. (defun alphanumericp (char)
  208.   "Given a character-object argument, alphanumericp returns T if the
  209.    argument is either numeric or alphabetic."
  210.   (declare (character char))
  211.   (let ((m (char-code char)))
  212.     (or (< 47 m 58) (< 64 m 91) (< 96 m 123))))
  213.  
  214.  
  215. (defun char= (character &rest more-characters)
  216.   "Returns T if all of its arguments are the same character."
  217.   (do ((clist more-characters (cdr clist)))
  218.       ((atom clist) T)
  219.     (unless (eq (car clist) character) (return nil))))
  220.  
  221.  
  222. (defun char/= (character &rest more-characters)
  223.   "Returns T if no two of its arguments are the same character."
  224.   (do* ((head character (car list))
  225.     (list more-characters (cdr list)))
  226.        ((atom list) T)
  227.     (unless (do* ((l list (cdr l)))                  ;inner loop returns T 
  228.          ((atom l) T)                 ; iff head /= rest.
  229.           (if (eq head (car l)) (return nil)))
  230.       (return nil))))
  231.  
  232.  
  233. (defun char< (character &rest more-characters)
  234.   "Returns T if its arguments are in strictly increasing alphabetic order."
  235.   (do* ((c character (car list))
  236.     (list more-characters (cdr list)))
  237.        ((atom list) T)
  238.     (unless (< (char-int c)
  239.            (char-int (car list)))
  240.       (return nil))))
  241.  
  242.  
  243. (defun char> (character &rest more-characters)
  244.   "Returns T if its arguments are in strictly decreasing alphabetic order."
  245.   (do* ((c character (car list))
  246.     (list more-characters (cdr list)))
  247.        ((atom list) T)
  248.     (unless (> (char-int c)
  249.            (char-int (car list)))
  250.       (return nil))))
  251.  
  252.  
  253. (defun char<= (character &rest more-characters)
  254.   "Returns T if its arguments are in strictly non-decreasing alphabetic order."
  255.   (do* ((c character (car list))
  256.     (list more-characters (cdr list)))
  257.        ((atom list) T)
  258.     (unless (<= (char-int c)
  259.         (char-int (car list)))
  260.       (return nil))))
  261.  
  262.  
  263. (defun char>= (character &rest more-characters)
  264.   "Returns T if its arguments are in strictly non-increasing alphabetic order."
  265.   (do* ((c character (car list))
  266.     (list more-characters (cdr list)))
  267.        ((atom list) T)
  268.     (unless (>= (char-int c)
  269.         (char-int (car list)))
  270.       (return nil))))
  271.  
  272.  
  273.  
  274. ;;; Equal-Char-Code is used by the following functions as a version of char-int
  275. ;;;  which loses font, bits, and case info.
  276.  
  277. (defmacro equal-char-code (character)
  278.   `(let ((ch (char-code ,character)))
  279.      (if (< 96 ch 123) (- ch 32) ch)))
  280.  
  281.  
  282.  
  283. (defun char-equal (character &rest more-characters)
  284.   "Returns T if all of its arguments are the same character.
  285.   Font, bits, and case are ignored."
  286.   (do ((clist more-characters (cdr clist)))
  287.       ((atom clist) T)
  288.     (unless (= (equal-char-code (car clist))
  289.            (equal-char-code character))
  290.       (return nil))))
  291.  
  292.  
  293. (defun char-not-equal (character &rest more-characters)
  294.   "Returns T if no two of its arguments are the same character.
  295.    Font, bits, and case are ignored."
  296.   (do* ((head character (car list))
  297.     (list more-characters (cdr list)))
  298.        ((atom list) T)
  299.     (unless (do* ((l list (cdr l)))
  300.          ((atom l) T)
  301.           (if (= (equal-char-code head)
  302.              (equal-char-code (car l)))
  303.           (return nil)))
  304.       (return nil))))
  305.  
  306.  
  307. (defun char-lessp (character &rest more-characters)
  308.   "Returns T if its arguments are in strictly increasing alphabetic order.
  309.    Font, bits, and case are ignored."
  310.   (do* ((c character (car list))
  311.     (list more-characters (cdr list)))
  312.        ((atom list) T)
  313.     (unless (< (equal-char-code c)
  314.            (equal-char-code (car list)))
  315.       (return nil))))
  316.  
  317.  
  318. (defun char-greaterp (character &rest more-characters)
  319.   "Returns T if its arguments are in strictly decreasing alphabetic order.
  320.    Font, bits, and case are ignored."
  321.   (do* ((c character (car list))
  322.     (list more-characters (cdr list)))
  323.        ((atom list) T)
  324.     (unless (> (equal-char-code c)
  325.            (equal-char-code (car list)))
  326.       (return nil))))
  327.  
  328.  
  329. (defun char-not-greaterp (character &rest more-characters)
  330.   "Returns T if its arguments are in strictly non-decreasing alphabetic order.
  331.    Font, bits, and case are ignored."
  332.   (do* ((c character (car list))
  333.     (list more-characters (cdr list)))
  334.        ((atom list) T)
  335.     (unless (<= (equal-char-code c)
  336.         (equal-char-code (car list)))
  337.       (return nil))))
  338.  
  339.  
  340. (defun char-not-lessp (character &rest more-characters)
  341.   "Returns T if its arguments are in strictly non-increasing alphabetic order.
  342.    Font, bits, and case are ignored."
  343.   (do* ((c character (car list))
  344.     (list more-characters (cdr list)))
  345.        ((atom list) T)
  346.     (unless (>= (equal-char-code c)
  347.         (equal-char-code (car list)))
  348.       (return nil))))
  349.  
  350.  
  351.  
  352.  
  353. ;;;; Miscellaneous functions:
  354.  
  355. (defun char-upcase (char)
  356.   "Returns CHAR converted to upper-case if that is possible."
  357.   (declare (character char))
  358.   (if (lower-case-p char)
  359.       (code-char (- (char-code char) 32))
  360.       char))
  361.  
  362. (defun char-downcase (char)
  363.   "Returns CHAR converted to lower-case if that is possible."
  364.   (declare (character char))
  365.   (if (upper-case-p char)
  366.       (code-char (+ (char-code char) 32))
  367.       char))
  368.  
  369. (defun digit-char (weight &optional (radix 10))
  370.   "All arguments must be integers.  Returns a character object that
  371.   represents a digit of the given weight in the specified radix.  Returns
  372.   NIL if no such character exists.  The character will have the specified
  373.   font attributes."
  374.   (and (>= weight 0) (< weight radix) (< weight 36)
  375.        (code-char (if (< weight 10) (+ 48 weight) (+ 55 weight)))))
  376.