(FILECREATED "29-Jul-86 01:54:16" {ERIS}<LISPCORE>LIBRARY>CMLSTRING.;14 36210  

      changes to:  (VARS CMLSTRINGCOMS)
                   (FNS STRING)

      previous date: "17-Jul-86 04:58:25" {ERIS}<LISPCORE>LIBRARY>CMLSTRING.;13)


(* Copyright (c) 1985, 1986 by Xerox Corporation. All rights reserved.)

(PRETTYCOMPRINT CMLSTRINGCOMS)

(RPAQQ CMLSTRINGCOMS 
       [(FUNCTIONS FOR-SUBSTRING \STRING WITH-ONE-STRING WITH-STRING WITH-TWO-STRINGS STRING<>=*-BODY
               )
        (FNS STRING STRING-EQUAL \SP-STRING-COMPARE STRING=* STRING/=* STRING<* STRING>* STRING<=* 
             STRING>=* STRING< STRING> STRING<= STRING>= STRING= STRING/= STRING-LESSP 
             STRING-GREATERP STRING-NOT-GREATERP STRING-NOT-LESSP STRING-NOT-EQUAL MAKE-STRING 
             STRING-UPCASE STRING-DOWNCASE STRING-CAPITALIZE NSTRING-UPCASE NSTRING-DOWNCASE 
             NSTRING-CAPITALIZE STRING-LEFT-TRIM STRING-RIGHT-TRIM STRING-TRIM)
        (PROP FILETYPE CMLSTRING)
        (DECLARE: DONTEVAL@LOAD DOEVAL@COMPILE DONTCOPY COMPILERVARS
               (ADDVARS (NLAMA)
                      (NLAML)
                      (LAMA STRING-TRIM STRING-RIGHT-TRIM STRING-LEFT-TRIM NSTRING-CAPITALIZE 
                            NSTRING-DOWNCASE NSTRING-UPCASE STRING-CAPITALIZE STRING-DOWNCASE 
                            STRING-UPCASE MAKE-STRING STRING-NOT-EQUAL STRING-NOT-LESSP 
                            STRING-NOT-GREATERP STRING-GREATERP STRING-LESSP STRING/= STRING= 
                            STRING>= STRING<= STRING> STRING< STRING>=* STRING<=* STRING>* STRING<* 
                            STRING/=* STRING=* STRING-EQUAL STRING])
(DEFMACRO FOR-SUBSTRING (STRING START END NEW INDEX &REST FORMS) 
          
          (* * Creates a new string to hold the old string and iterates the body over the 
          positions START to END with INDEX * *)
 (BQUOTE (LET* ((SLEN (CL:LENGTH (\, STRING)))
                ((\, NEW)
                 (MAKE-STRING SLEN)))
               (for INDEX from 0 to (1- (\, START)) do (SETF (CHAR (\, NEW)
                                                                   INDEX)
                                                             (CHAR (\, STRING)
                                                                   INDEX)))
               (for (\, INDEX) from (\, START) to (1- (\, END)) do (\,@ FORMS))
               (for INDEX from (\, END) to (1- SLEN) do (SETF (CHAR (\, NEW)
                                                                    INDEX)
                                                              (CHAR (\, STRING)
                                                                    INDEX)))
               (\, NEW))))

(DEFMACRO \STRING (THING)                                    (* \String returns its arg if it is a 
                                                             string, otherwise calls String.
                                                             *) (BQUOTE (COND
                                                                           ((STRINGP (\, THING))
                                                                            (\, THING))
                                                                           (T (STRING (\, THING))))))

(DEFMACRO WITH-ONE-STRING (STRING START END &REST FORMS)     (* WITH-ONE-STRING is used to set up 
                                                             some string hacking things.
                                                             The keywords are parsed, and the 
                                                             string is hacked into a simple-string.
                                                             *)
   (BQUOTE (PROGN (COND
                     ((SYMBOLP (\, STRING))
                      (SETQ (\, STRING)
                       (SYMBOL-NAME (\, STRING)))))
                  (COND
                     ((NULL (\, END))
                      (SETQ (\, END)
                       (CL:LENGTH (\, STRING)))))
                  (\,@ FORMS))))

(DEFMACRO WITH-STRING (STRING &REST FORMS)                   (* WITH-STRING is like 
                                                             WITH-ONE-STRING, but doesn't parse 
                                                             keywords. *)
   (BQUOTE (LET ((START 0)
                 END)
                (COND
                   ((SYMBOLP (\, STRING))
                    (SETQ (\, STRING)
                     (SYMBOL-NAME (\, STRING)))))
                (SETQ END (CL:LENGTH (\, STRING)))
                (\,@ FORMS))))

(DEFMACRO WITH-TWO-STRINGS (STRING1 STRING2 START1 END1 START2 END2 &REST FORMS) 
                                                             (* WITH-TWO-STRINGS is used to set up 
                                                             string comparison operations.
                                                             The keywords are parsed, and symbols 
                                                             are hacked into strings *)
   (BQUOTE (PROGN (COND
                     ((SYMBOLP (\, STRING1))
                      (SETQ (\, STRING1)
                       (SYMBOL-NAME (\, STRING1)))))
                  (COND
                     ((NULL (\, END1))
                      (SETQ (\, END1)
                       (CL:LENGTH (\, STRING1)))))
                  (COND
                     ((SYMBOLP (\, STRING2))
                      (SETQ (\, STRING2)
                       (SYMBOL-NAME (\, STRING2)))))
                  (COND
                     ((NULL (\, END2))
                      (SETQ (\, END2)
                       (CL:LENGTH (\, STRING2)))))
                  (\,@ FORMS))))

(DEFMACRO STRING<>=*-BODY (LESSP EQUALP)
   (BQUOTE (WITH-TWO-STRINGS STRING1 STRING2 START1 END1 START2 END2
                  (LET ((INDEX (\SP-STRING-COMPARE STRING1 START1 END1 STRING2 START2 END2)))
                       (COND
                          (INDEX (COND
                                    ((= INDEX (\, (COND
                                                     (LESSP (QUOTE END1))
                                                     (T (QUOTE END2)))))
                                     INDEX)
                                    ((= INDEX (\, (COND
                                                     (LESSP (QUOTE END2))
                                                     (T (QUOTE END1)))))
                                     NIL)
                                    (((\, (COND
                                             (LESSP (QUOTE CHAR<))
                                             (T (QUOTE CHAR>))))
                                      (CHAR STRING1 INDEX)
                                      (CHAR STRING2 (+ INDEX (- START2 START1))))
                                     INDEX)
                                    (T NIL)))
                          (T (\, (COND
                                    (EQUALP (QUOTE (- END1 START1)))
                                    (T (QUOTE NIL))))))))))

(DEFINEQ

(STRING
  [CL:LAMBDA (X)                                             (* lmm "29-Jul-86 01:03")
          
          (* Coerces X into a string. If X is a string, X is returned.
          If X is a symbol, X's pname is returned.
          If X is a character then a one element string containing that character is 
          returned. If X cannot be coerced into a string, an error occurs.)

         (ETYPECASE X (STRING X)
                (SYMBOL (SYMBOL-NAME X))
                (CHARACTER (LET ((RES (MAKE-STRING 1)))
                                (SETF (SCHAR RES 0)
                                      X)
                                RES])

(STRING-EQUAL
  [CL:LAMBDA (STRING1 STRING2 &KEY (START1 0)
                    END1
                    (START2 0)
                    END2)                                    (* lmm "17-Jul-86 04:24")
          
          (* Given two strings (string1 and string2)%, and optional integers start1, 
          start2, end1 and end2, compares characters in string1 to characters in string2
          (using CHAR-EQUAL) . *)

         (WITH-TWO-STRINGS STRING1 STRING2 START1 END1 START2 END2
                (AND (= (- END2 START2)
                        (- END1 START1))
                     (NOT (for I1 from START1 to (1- END1) as I2 from START2
                             when [NOT (EQL (CHAR-UPCASE (CHAR STRING1 I1))
                                            (CHAR-UPCASE (CHAR STRING2 I2] do (RETURN T])

(\SP-STRING-COMPARE
  [LAMBDA (STRING1 START1 END1 STRING2 START2 END2)          (* raf " 5-Dec-85 03:14")
                                                             (* First INDEX at which compared portions of STRING1 
							     and STRING2 differ. *)
    (for I1 from START1 to (1- (OR END1 (CL:LENGTH STRING1))) as I2 from START2
       to (1- (OR END2 (CL:LENGTH STRING2))) as I from 0
       when (NOT (EQ (CHAR STRING1 I1)
			   (CHAR STRING2 I2)))
       do (RETURN I])

(STRING=*
  [CL:LAMBDA (STRING1 STRING2 START1 END1 START2 END2)       (* lmm "17-Jul-86 04:23")
         (WITH-TWO-STRINGS STRING1 STRING2 START1 END1 START2 END2
                (AND (= (- END2 START2)
                        (- END1 START1))
                     (NOT (\SP-STRING-COMPARE STRING1 START1 END1 STRING2 START2 END2])

(STRING/=*
  (CL:LAMBDA (STRING1 STRING2 START1 END1 START2 END2)
    (WITH-TWO-STRINGS STRING1 STRING2 START1 END1 START2 END2 (\SP-STRING-COMPARE STRING1 START1 
										    END1 STRING2 
										    START2 END2))))

(STRING<*
  [CL:LAMBDA (STRING1 STRING2 START1 END1 START2 END2)       (* raf " 4-Dec-85 23:19")
    (WITH-TWO-STRINGS STRING1 STRING2 START1 END1 START2 END2
		      (LET ((INDEX (\SP-STRING-COMPARE STRING1 START1 END1 STRING2 START2 END2)))
		           (COND
			     (INDEX (COND
				      ((= INDEX END1)
					INDEX)
				      ((= INDEX END2)
					NIL)
				      ([CHAR< (CHAR STRING1 INDEX)
						(CHAR STRING2 (+ INDEX (- START2 START1]
					INDEX)
				      (T NIL)))
			     (T NIL])

(STRING>*
  [CL:LAMBDA (STRING1 STRING2 START1 END1 START2 END2)       (* raf " 4-Dec-85 23:20")
    (WITH-TWO-STRINGS STRING1 STRING2 START1 END1 START2 END2
		      (LET ((INDEX (\SP-STRING-COMPARE STRING1 START1 END1 STRING2 START2 END2)))
		           (COND
			     (INDEX (COND
				      ((= INDEX END2)
					INDEX)
				      ((= INDEX END1)
					NIL)
				      ([CHAR> (CHAR STRING1 INDEX)
						(CHAR STRING2 (+ INDEX (- START2 START1]
					INDEX)
				      (T NIL)))
			     (T NIL])

(STRING<=*
  [CL:LAMBDA (STRING1 STRING2 START1 END1 START2 END2)       (* raf " 4-Dec-85 23:20")
    (WITH-TWO-STRINGS STRING1 STRING2 START1 END1 START2 END2
		      (LET ((INDEX (\SP-STRING-COMPARE STRING1 START1 END1 STRING2 START2 END2)))
		           (COND
			     (INDEX (COND
				      ((= INDEX END1)
					INDEX)
				      ((= INDEX END2)
					NIL)
				      ([CHAR< (CHAR STRING1 INDEX)
						(CHAR STRING2 (+ INDEX (- START2 START1]
					INDEX)
				      (T NIL)))
			     (T (- END1 START1])

(STRING>=*
  [CL:LAMBDA (STRING1 STRING2 START1 END1 START2 END2)       (* raf " 4-Dec-85 23:21")
    (WITH-TWO-STRINGS STRING1 STRING2 START1 END1 START2 END2
		      (LET ((INDEX (\SP-STRING-COMPARE STRING1 START1 END1 STRING2 START2 END2)))
		           (COND
			     (INDEX (COND
				      ((= INDEX END2)
					INDEX)
				      ((= INDEX END1)
					NIL)
				      ([CHAR> (CHAR STRING1 INDEX)
						(CHAR STRING2 (+ INDEX (- START2 START1]
					INDEX)
				      (T NIL)))
			     (T (- END1 START1])

(STRING<
  [CL:LAMBDA (STRING1 STRING2 &KEY (START1 0)
                    END1
                    (START2 0)
                    END2)                                    (* lmm "17-Jul-86 04:46")
         "A string A is less than a string B if in the first position in which they differ the character of A is less than the corresponding character of B according to char< or if string A is a proper prefix of string B (of shorter length and matching in all the characters of A)."
         (WITH-TWO-STRINGS STRING1 STRING2 START1 END1 START2 END2
                (LET ((SLEN1 (- END1 START1))
                      (SLEN2 (- END2 START2)))
                     (COND
                        ((OR (MINUSP SLEN1)
                             (MINUSP SLEN2))
                         (CL:ERROR "Improper bounds for string comparison."))
                        (T NIL))
                     (CL:DO ((INDEX1 START1 (1+ INDEX1))
                             (INDEX2 START2 (1+ INDEX2))
                             (CHAR1)
                             (CHAR2))
                            ((OR (= INDEX1 END1)
                                 (= INDEX2 END2))            (* return index if string1 shorter, 
                                                             NIL if they're the same *)
                             (COND
                                ((= INDEX1 END1)
                                 INDEX1)
                                (T NIL)))
                            (SETQ CHAR1 (CHAR STRING1 INDEX1))
                            (SETQ CHAR2 (CHAR STRING2 INDEX2))
                            (COND
                               [(NOT (EQL CHAR1 CHAR2))
                                (COND
                                   ((CHAR< CHAR1 CHAR2)
                                    (RETURN INDEX1))
                                   (T (RETURN NIL]
                               (T NIL])

(STRING>
  [CL:LAMBDA (STRING1 STRING2 &KEY (START1 0)
                    END1
                    (START2 0)
                    END2)                                    (* lmm "17-Jul-86 04:35")
         "A string A is less than a string B if in the first position in which they differ the character of A is less than the corresponding character of B according to char< or if string A is a proper prefix of string B (of shorter length and matching in all the characters of A)."
         (WITH-TWO-STRINGS STRING1 STRING2 START1 END1 START2 END2
                (LET ((SLEN1 (- END1 START1))
                      (SLEN2 (- END2 START2)))
                     (COND
                        ((OR (MINUSP SLEN1)
                             (MINUSP SLEN2))
                         (CL:ERROR "Improper bounds for string comparison."))
                        (T NIL))
                     (CL:DO ((INDEX1 START1 (1+ INDEX1))
                             (INDEX2 START2 (1+ INDEX2))
                             (CHAR1)
                             (CHAR2))
                            ((OR (= INDEX1 END1)
                                 (= INDEX2 END2))            (* return index if string1 shorter, 
                                                             NIL if they're the same *)
                             (COND
                                ((NOT (= SLEN1 SLEN2))
                                 INDEX1)
                                (T NIL)))
                            (SETQ CHAR1 (CHAR STRING1 INDEX1))
                            (SETQ CHAR2 (CHAR STRING2 INDEX2))
                            (COND
                               [(NOT (EQL CHAR1 CHAR2))
                                (COND
                                   ((CHAR> CHAR1 CHAR2)
                                    (RETURN INDEX1))
                                   (T (RETURN NIL]
                               (T NIL])

(STRING<=
  [CL:LAMBDA (STRING1 STRING2 &KEY (START1 0)
                    END1
                    (START2 0)
                    END2)                                    (* lmm "17-Jul-86 04:42")
         (WITH-TWO-STRINGS STRING1 STRING2 START1 END1 START2 END2
                (LET ((SLEN1 (- END1 START1))
                      (SLEN2 (- END2 START2)))
                     (COND
                        ((OR (MINUSP SLEN1)
                             (MINUSP SLEN2))
                         (CL:ERROR "Improper bounds for string comparison."))
                        (T NIL))
                     (CL:DO ((INDEX1 START1 (1+ INDEX1))
                             (INDEX2 START2 (1+ INDEX2))
                             (CHAR1)
                             (CHAR2))
                            ((OR (= INDEX1 END1)
                                 (= INDEX2 END2))
                             (CL:IF (= INDEX1 END1)
                                    INDEX1 NIL))
                            (SETQ CHAR1 (CHAR STRING1 INDEX1))
                            (SETQ CHAR2 (CHAR STRING2 INDEX2))
                            (COND
                               [(NOT (EQL CHAR1 CHAR2))
                                (COND
                                   ((CHAR<= CHAR1 CHAR2)
                                    (RETURN INDEX1))
                                   (T (RETURN NIL]
                               (T NIL])

(STRING>=
  (CL:LAMBDA (STRING1 STRING2 &KEY (START1 0)
		      END1
		      (START2 0)
		      END2)                                  (* kbr: " 4-Oct-85 11:31")

          (* Given two strings, if the first string is lexicographically greater than or equal to the second string, returns 
	  the longest common prefix (using char=) of the two strings. Otherwise, returns NIL . *)


    (STRING>=* STRING1 STRING2 START1 END1 START2 END2)))

(STRING=
  [CL:LAMBDA (STRING1 STRING2 &KEY (START1 0)
                    END1
                    (START2 0)
                    END2)                                    (* lmm "17-Jul-86 04:57")
         (WITH-TWO-STRINGS STRING1 STRING2 START1 END1 START2 END2
                (AND (= (- END2 START2)
                        (- END1 START1))
                     (for I1 from START1 to (1- END1) as I2 from START2 to (1- END2)
                        when (NOT (EQL (CHAR STRING1 I1)
                                       (CHAR STRING2 I2))) do (RETURN NIL) finally (RETURN I1])

(STRING/=
  [CL:LAMBDA (STRING1 STRING2 &KEY (START1 0)
                    END1
                    (START2 0)
                    END2)                                    (* lmm "17-Jul-86 04:53")
         (WITH-TWO-STRINGS STRING1 STRING2 START1 END1 START2 END2
                (for I1 from START1 to (1- END1) as I2 from START2 to (1- END2)
                   when (NOT (EQ (CHAR STRING1 I1)
                                 (CHAR STRING2 I2))) do (RETURN I1)
                   finally (RETURN (CL:IF (= I1 END1)
                                          (CL:IF (= I2 END2)
                                                 NIL I2)
                                          I2])

(STRING-LESSP
  [CL:LAMBDA (STRING1 STRING2 &KEY (START1 0)
                    END1
                    (START2 0)
                    END2)                                    (* lmm "17-Jul-86 04:28")
          
          (* Given two strings, if the first string is lexicographically less than the 
          second string, returns the longest common prefix
          (using char-equal) of the two strings. Otherwise, returns NIL . *)

         (WITH-TWO-STRINGS STRING1 STRING2 START1 END1 START2 END2
                (LET ((SLEN1 (- END1 START1))
                      (SLEN2 (- END2 START2)))
                     (COND
                        ((OR (MINUSP SLEN1)
                             (MINUSP SLEN2))
                         (CL:ERROR "Improper bounds for string comparison."))
                        (T NIL))
                     (CL:DO ((INDEX1 START1 (1+ INDEX1))
                             (INDEX2 START2 (1+ INDEX2))
                             (CHAR1)
                             (CHAR2))
                            ((OR (= INDEX1 END1)
                                 (= INDEX2 END2))            (* return index if string1 shorter, 
                                                             NIL if they're the same *)
                             (COND
                                ((NOT (= SLEN1 SLEN2))
                                 INDEX1)
                                (T NIL)))
                            (SETQ CHAR1 (CHAR STRING1 INDEX1))
                            (SETQ CHAR2 (CHAR STRING2 INDEX2))
                            (COND
                               [(NOT (CHAR-EQUAL CHAR1 CHAR2))
                                (COND
                                   ((CHAR-LESSP CHAR1 CHAR2)
                                    (RETURN INDEX1))
                                   (T (RETURN NIL]
                               (T NIL])

(STRING-GREATERP
  [CL:LAMBDA (STRING1 STRING2 &KEY (START1 0)
		      END1
		      (START2 0)
		      END2)                                  (* raf " 5-Dec-85 04:11")

          (* Given two strings, if the first string is lexicographically greater than the second string, returns the longest 
	  common prefix (using char-equal) of the two strings. Otherwise, returns NIL . *)


    (WITH-TWO-STRINGS STRING1 STRING2 START1 END1 START2 END2
		      (LET ((SLEN1 (- END1 START1))
			    (SLEN2 (- END2 START2)))
		           (DECLARE (TYPE FIXNUM SLEN1 SLEN2))
                                                             (* prevent endless looping later.
							     *)
		           (COND
			     ((OR (MINUSP SLEN1)
				    (MINUSP SLEN2))
			       (CL:ERROR "Improper bounds for string comparison."))
			     (T NIL))
		           (CL:DO ((INDEX1 START1 (1+ INDEX1))
				   (INDEX2 START2 (1+ INDEX2))
				   (CHAR1)
				   (CHAR2))
				  ((OR (= INDEX1 END1)
					 (= INDEX2 END2))
                                                             (* return index if string1 shorter, NIL if they're the
							     same *)
				   (COND
				     ((NOT (= SLEN1 SLEN2))
				       INDEX1)
				     (T NIL)))
				  (DECLARE (TYPE FIXNUM INDEX1 INDEX2))
				  (SETQ CHAR1 (CHAR STRING1 INDEX1))
				  (SETQ CHAR2 (CHAR STRING2 INDEX2))
				  (COND
				    [(NOT (CHAR-EQUAL CHAR1 CHAR2))
				      (COND
					((CHAR-GREATERP CHAR1 CHAR2)
					  (RETURN INDEX1))
					(T (RETURN NIL]
				    (T NIL])

(STRING-NOT-GREATERP
  [CL:LAMBDA (STRING1 STRING2 &KEY (START1 0)
		      END1
		      (START2 0)
		      END2)                                  (* raf " 5-Dec-85 04:12")

          (* Given two strings, if the first string is lexicographically less than or equal to the second string, returns the
	  longest common prefix (using char-equal) of the two strings. Otherwise, returns NIL . *)


    (WITH-TWO-STRINGS STRING1 STRING2 START1 END1 START2 END2
		      (LET ((SLEN1 (- END1 START1))
			    (SLEN2 (- END2 START2)))
		           (DECLARE (TYPE FIXNUM SLEN1 SLEN2))
                                                             (* prevent endless looping later.
							     *)
		           (COND
			     ((OR (MINUSP SLEN1)
				    (MINUSP SLEN2))
			       (CL:ERROR "Improper bounds for string comparison."))
			     (T NIL))
		           (CL:DO ((INDEX1 START1 (1+ INDEX1))
				   (INDEX2 START2 (1+ INDEX2))
				   (CHAR1)
				   (CHAR2))
				  ((OR (= INDEX1 END1)
					 (= INDEX2 END2))
                                                             (* return index if string1 shorter, NIL if they're the
							     same *)
				   INDEX1)
				  (DECLARE (TYPE FIXNUM INDEX1 INDEX2))
				  (SETQ CHAR1 (CHAR STRING1 INDEX1))
				  (SETQ CHAR2 (CHAR STRING2 INDEX2))
				  (COND
				    [(NOT (CHAR-EQUAL CHAR1 CHAR2))
				      (COND
					((NOT (CHAR-GREATERP CHAR1 CHAR2))
					  (RETURN INDEX1))
					(T (RETURN NIL]
				    (T NIL])

(STRING-NOT-LESSP
  [CL:LAMBDA (STRING1 STRING2 &KEY (START1 0)
		      END1
		      (START2 0)
		      END2)                                  (* raf " 5-Dec-85 04:12")

          (* Given two strings, if the first string is lexicographically greater than or equal to the second string, returns 
	  the longest common prefix (using char-equal) of the two strings. Otherwise, returns NIL . *)


    (WITH-TWO-STRINGS STRING1 STRING2 START1 END1 START2 END2
		      (LET ((SLEN1 (- END1 START1))
			    (SLEN2 (- END2 START2)))
		           (DECLARE (TYPE FIXNUM SLEN1 SLEN2))
                                                             (* prevent endless looping later.
							     *)
		           (COND
			     ((OR (MINUSP SLEN1)
				    (MINUSP SLEN2))
			       (CL:ERROR "Improper bounds for string comparison."))
			     (T NIL))
		           (CL:DO ((INDEX1 START1 (1+ INDEX1))
				   (INDEX2 START2 (1+ INDEX2))
				   (CHAR1)
				   (CHAR2))
				  ((OR (= INDEX1 END1)
					 (= INDEX2 END2))
                                                             (* return index if string1 shorter, NIL if they're the
							     same *)
				   INDEX1)
				  (DECLARE (TYPE FIXNUM INDEX1 INDEX2))
				  (SETQ CHAR1 (CHAR STRING1 INDEX1))
				  (SETQ CHAR2 (CHAR STRING2 INDEX2))
				  (COND
				    [(NOT (CHAR-EQUAL CHAR1 CHAR2))
				      (COND
					((NOT (CHAR-LESSP CHAR1 CHAR2))
					  (RETURN INDEX1))
					(T (RETURN NIL]
				    (T NIL])

(STRING-NOT-EQUAL
  [CL:LAMBDA (STRING1 STRING2 &KEY (START1 0)
		      END1
		      (START2 0)
		      END2)                                  (* raf " 5-Dec-85 04:13")

          (* Given two strings, if the first string is not lexicographically equal to the second string, returns the longest 
	  common prefix (using char-equal) of the two strings. Otherwise, returns NIL . *)


    (WITH-TWO-STRINGS STRING1 STRING2 START1 END1 START2 END2
		      (LET ((SLEN1 (- END1 START1))
			    (SLEN2 (- END2 START2)))
		           (DECLARE (TYPE FIXNUM SLEN1 SLEN2))
                                                             (* prevent endless looping later.
							     *)
		           (COND
			     ((OR (MINUSP SLEN1)
				    (MINUSP SLEN2))
			       (CL:ERROR "Improper bounds for string comparison."))
			     (T NIL))
		           (COND
			     ((OR (MINUSP SLEN1)
				    (OR (MINUSP SLEN2)))
			       (CL:ERROR "Improper substring for comparison."))
			     [(= SLEN1 SLEN2)
			       (CL:DO ((INDEX1 START1 (1+ INDEX1))
				       (INDEX2 START2 (1+ INDEX2)))
				      ((= INDEX1 END1)
				       NIL)
				      (DECLARE (TYPE FIXNUM INDEX1 INDEX2))
				      (COND
					((NOT (CHAR-EQUAL (CHAR STRING1 INDEX1)
							      (CHAR STRING2 INDEX2)))
					  (RETURN INDEX1))
					(T NIL]
			     [(< SLEN1 SLEN2)
			       (CL:DO ((INDEX1 START1 (1+ INDEX1))
				       (INDEX2 START2 (1+ INDEX2)))
				      ([OR (= INDEX1 END1)
					     (NOT (CHAR-EQUAL (CHAR STRING1 INDEX1)
								  (CHAR STRING2 INDEX2]
				       INDEX1)
				      (DECLARE (TYPE FIXNUM INDEX1 INDEX2]
			     (T (CL:DO ((INDEX1 START1 (1+ INDEX1))
					(INDEX2 START2 (1+ INDEX2)))
				       ([OR (= INDEX2 END2)
					      (NOT (CHAR-EQUAL (CHAR STRING1 INDEX1)
								   (CHAR STRING2 INDEX2]
					INDEX1)
				       (DECLARE (TYPE FIXNUM INDEX1 INDEX2])

(MAKE-STRING
  [CL:LAMBDA (SIZE &KEY INITIAL-ELEMENT)                     (* lmm " 5-Sep-85 02:36")
    (ALLOCSTRING SIZE (AND INITIAL-ELEMENT (CHAR-INT INITIAL-ELEMENT])

(STRING-UPCASE
  [CL:LAMBDA (STRING &KEY (START 0)
		       END)                                  (* raf " 4-Dec-85 23:59")
                                                             (* Given a string, returns a new string that is a copy
							     of it with all lower case alphabetic characters 
							     converted to uppercase. *)
    (WITH-ONE-STRING STRING START END (FOR-SUBSTRING STRING START END NEWSTRING INDEX
						     (SETF (CHAR NEWSTRING INDEX)
							   (CHAR-UPCASE (CHAR STRING INDEX])

(STRING-DOWNCASE
  [CL:LAMBDA (STRING &KEY (START 0)
		       END)                                  (* raf " 4-Dec-85 23:59")
                                                             (* Given a string, returns a new string that is a copy
							     of it with all upper case alphabetic characters 
							     converted to lowercase. *)
    (WITH-ONE-STRING STRING START END (FOR-SUBSTRING STRING START END NEWSTRING INDEX
						     (SETF (CHAR NEWSTRING INDEX)
							   (CHAR-DOWNCASE (CHAR STRING INDEX])

(STRING-CAPITALIZE
  [CL:LAMBDA (STRING &KEY (START 0)
		       END)                                  (* raf " 4-Dec-85 23:59")

          (* Given a string, returns a copy of the string with the first character of each ``word'' converted to upper-case, 
	  and remaining chars in the word converted to lower case. A ``word'' is defined to be a string of case-modifiable 
	  characters delimited by non-case-modifiable chars. *)


    (WITH-ONE-STRING STRING START END (LET ((NEWWORD T)
					    CHAR)
				           (FOR-SUBSTRING STRING START END NEWSTRING INDEX
							  (SETQ CHAR (CHAR STRING INDEX))
							  [COND
							    ((NOT (ALPHANUMERICP CHAR))
							      (SETQ NEWWORD T))
							    (NEWWORD 
                                                             (* char is first case-modifiable after 
							     non-case-modifiable *)
								     (SETQ CHAR (CHAR-UPCASE
									 CHAR))
								     (SETQ NEWWORD NIL))
							    (T 
                                                             (* char is case-modifiable, but not first *)
							       (SETQ CHAR (CHAR-DOWNCASE CHAR]
							  (SETF (CHAR NEWSTRING INDEX)
								CHAR])

(NSTRING-UPCASE
  (CL:LAMBDA (STRING &KEY (START 0)
		       END)                                  (* raf " 5-Dec-85 03:21")
                                                             (* Given a string, returns that string with all lower 
							     case alphabetic characters converted to uppercase.
							     *)
    (WITH-ONE-STRING STRING START END [for INDEX from START to (1- END)
					 do (SETF (CHAR STRING INDEX)
						    (CHAR-UPCASE (CHAR STRING INDEX]
		     STRING)))

(NSTRING-DOWNCASE
  (CL:LAMBDA (STRING &KEY (START 0)
		       END)                                  (* raf " 5-Dec-85 03:21")
                                                             (* Given a string, returns that string with all upper 
							     case alphabetic characters converted to lowercase.
							     *)
    (WITH-ONE-STRING STRING START END [for INDEX from START to (1- END)
					 do (SETF (CHAR STRING INDEX)
						    (CHAR-DOWNCASE (CHAR STRING INDEX]
		     STRING)))

(NSTRING-CAPITALIZE
  (CL:LAMBDA (STRING &KEY (START 0)
		       END)                                  (* raf " 5-Dec-85 03:22")

          (* Given a string, returns that string with the first character of each ``word'' converted to upper-case, and 
	  remaining chars in the word converted to lower case. A ``word'' is defined to be a string of case-modifiable 
	  characters delimited by non-case-modifiable chars. *)


    (WITH-ONE-STRING STRING START END (LET (CHAR (NEWWORD T))
				           (for INDEX from START to (1- END)
					      do (SETQ CHAR (CHAR STRING INDEX))
						   [COND
						     ((NOT (ALPHANUMERICP CHAR))
						       (SETQ NEWWORD T))
						     (NEWWORD 
                                                             (* char is first case-modifiable after 
							     non-case-modifiable *)
							      (SETQ CHAR (CHAR-UPCASE CHAR))
							      (SETQ NEWWORD NIL))
						     (T      (* char is case-modifiable, but not first *)
							(SETQ CHAR (CHAR-DOWNCASE CHAR]
						   (SETF (CHAR STRING INDEX)
							 CHAR))
				       STRING))))

(STRING-LEFT-TRIM
  [CL:LAMBDA (CHAR-BAG STRING)                               (* raf " 5-Dec-85 04:13")

          (* Given a set of characters (a list or string) and a string, returns a copy of the string with the characters in 
	  the set removed from the left end. *)


    (WITH-STRING STRING (CL:DO ((INDEX START (1+ INDEX)))
			       ((OR (= INDEX END)
				      (NOT (CL:FIND (CHAR STRING INDEX)
							CHAR-BAG)))
				(SUBSEQ (THE STRING STRING)
					  INDEX END))
			       (DECLARE (TYPE FIXNUM INDEX])

(STRING-RIGHT-TRIM
  [CL:LAMBDA (CHAR-BAG STRING)                               (* raf " 5-Dec-85 04:13")

          (* Given a set of characters (a list or string) and a string, returns a copy of the string with the characters in 
	  the set removed from the right end. *)


    (WITH-STRING STRING (CL:DO ((INDEX (1- END)
				       (1- INDEX)))
			       ((OR (< INDEX START)
				      (NOT (CL:FIND (CHAR STRING INDEX)
							CHAR-BAG)))
				(SUBSEQ (THE STRING STRING)
					  START
					  (1+ INDEX)))
			       (DECLARE (TYPE FIXNUM INDEX])

(STRING-TRIM
  [CL:LAMBDA (CHAR-BAG STRING)                               (* lmm "17-Jul-86 02:29")
          
          (* Given a set of characters (a list or string) and a string, returns a copy of 
          the string with the characters in the set removed from both ends.
          *)

         (WITH-STRING STRING (LET ((LEFT-END)
                                   (RIGHT-END))
                                  (CL:DO ((INDEX START (1+ INDEX)))
                                         ((OR (= INDEX END)
                                              (NOT (CL:FIND (CHAR STRING INDEX)
                                                          CHAR-BAG)))
                                          (SETQ LEFT-END INDEX))
                                         (DECLARE (TYPE FIXNUM INDEX)))
                                  (CL:DO ((INDEX (1- END)
                                                 (1- INDEX)))
                                         ((OR (< INDEX LEFT-END)
                                              (NOT (CL:FIND (CHAR STRING INDEX)
                                                          CHAR-BAG)))
                                          (SETQ RIGHT-END INDEX))
                                         (DECLARE (TYPE FIXNUM INDEX)))
                                  (SUBSEQ (THE STRING STRING)
                                         LEFT-END
                                         (1+ RIGHT-END])
)

(PUTPROPS CMLSTRING FILETYPE COMPILE-FILE)
(DECLARE: DONTEVAL@LOAD DOEVAL@COMPILE DONTCOPY COMPILERVARS 

(ADDTOVAR NLAMA )

(ADDTOVAR NLAML )

(ADDTOVAR LAMA 
          STRING-TRIM STRING-RIGHT-TRIM STRING-LEFT-TRIM NSTRING-CAPITALIZE NSTRING-DOWNCASE 
                NSTRING-UPCASE STRING-CAPITALIZE STRING-DOWNCASE STRING-UPCASE MAKE-STRING 
                STRING-NOT-EQUAL STRING-NOT-LESSP STRING-NOT-GREATERP STRING-GREATERP STRING-LESSP 
                STRING/= STRING= STRING>= STRING<= STRING> STRING< STRING>=* STRING<=* STRING>* 
                STRING<* STRING/=* STRING=* STRING-EQUAL STRING)
)
(PUTPROPS CMLSTRING COPYRIGHT ("Xerox Corporation" 1985 1986))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (7207 35498 (STRING 7217 . 7904) (STRING-EQUAL 7906 . 8772) (\SP-STRING-COMPARE 8774 . 
9354) (STRING=* 9356 . 9704) (STRING/=* 9706 . 9935) (STRING<* 9937 . 10476) (STRING>* 10478 . 11017) 
(STRING<=* 11019 . 11574) (STRING>=* 11576 . 12131) (STRING< 12133 . 14065) (STRING> 14067 . 16005) (
STRING<= 16007 . 17448) (STRING>= 17450 . 17909) (STRING= 17911 . 18542) (STRING/= 18544 . 19275) (
STRING-LESSP 19277 . 21197) (STRING-GREATERP 21199 . 22839) (STRING-NOT-GREATERP 22841 . 24423) (
STRING-NOT-LESSP 24425 . 26005) (STRING-NOT-EQUAL 26007 . 28049) (MAKE-STRING 28051 . 28241) (
STRING-UPCASE 28243 . 28788) (STRING-DOWNCASE 28790 . 29339) (STRING-CAPITALIZE 29341 . 30579) (
NSTRING-UPCASE 30581 . 31122) (NSTRING-DOWNCASE 31124 . 31669) (NSTRING-CAPITALIZE 31671 . 32852) (
STRING-LEFT-TRIM 32854 . 33416) (STRING-RIGHT-TRIM 33418 . 34020) (STRING-TRIM 34022 . 35496)))))
STOP