Raymond Toy pushed to branch issue-240-set-diff-with-hash-table at cmucl / cmucl

Commits:

15 changed files:

Changes:

  • bin/build.sh
    ... ... @@ -110,6 +110,8 @@ case `uname -s` in
    110 110
           esac ;;
    
    111 111
     esac
    
    112 112
     
    
    113
    +export LANG=en_US.UTF-8
    
    114
    +
    
    113 115
     buildit ()
    
    114 116
     {
    
    115 117
         if echo $INTERACTIVE_BUILD | grep $BUILD > /dev/null; then
    

  • bin/run-tests.sh
    ... ... @@ -47,6 +47,11 @@ function cleanup {
    47 47
     
    
    48 48
     trap cleanup EXIT
    
    49 49
     
    
    50
    +# Compile up the C file that is used for testing alien funcalls to
    
    51
    +# functions that return integer types of different lengths.  We use
    
    52
    +# gcc since clang isn't always available.
    
    53
    +(cd tests; gcc -m32 -O3 -c test-return.c)
    
    54
    +
    
    50 55
     if [ $# -eq 0 ]; then
    
    51 56
         # No args so run all the tests
    
    52 57
         $LISP -noinit -load tests/run-tests.lisp -eval '(cmucl-test-runner:run-all-tests)'
    

  • src/code/alieneval.lisp
    ... ... @@ -170,6 +170,9 @@
    170 170
       (alien-rep nil :type (or null function))
    
    171 171
       (extract-gen nil :type (or null function))
    
    172 172
       (deposit-gen nil :type (or null function))
    
    173
    +  ;;
    
    174
    +  ;; Method that accepts the alien type and the alien value.  The
    
    175
    +  ;; method converts the alien value into an appropriate lisp value.
    
    173 176
       (naturalize-gen nil :type (or null function))
    
    174 177
       (deport-gen nil :type (or null function))
    
    175 178
       ;; Cast?
    
    ... ... @@ -646,8 +649,26 @@
    646 649
     
    
    647 650
     #-amd64
    
    648 651
     (def-alien-type-method (integer :naturalize-gen) (type alien)
    
    649
    -  (declare (ignore type))
    
    650
    -  alien)
    
    652
    +  ;; Mask out any unwanted bits.  Important if the C code returns
    
    653
    +  ;; values in %al, or %ax
    
    654
    +  (if (alien-integer-type-signed type)
    
    655
    +      (let ((val (gensym "VAL-")))
    
    656
    +	(case (alien-integer-type-bits type)
    
    657
    +	  ;; First, get just the low part of the alien and then
    
    658
    +	  ;; sign-extend it appropriately.
    
    659
    +	  (8 `(let ((,val (ldb (byte 8 0) ,alien)))
    
    660
    +		(if (> ,val #x7f)
    
    661
    +		    (- ,val #x100)
    
    662
    +		    ,val)))
    
    663
    +	  (16 `(let ((,val (ldb (byte 16 0) ,alien)))
    
    664
    +		 (if (> ,val #x7fff)
    
    665
    +		     (- ,val #x10000)
    
    666
    +		     ,val)))
    
    667
    +	  (t alien)))
    
    668
    +      (case (alien-integer-type-bits type)
    
    669
    +	(8 `(ldb (byte 8 0) (truly-the (unsigned-byte 32) ,alien)))
    
    670
    +	(16 `(ldb (byte 16 0) (truly-the (unsigned-byte 32) ,alien)))
    
    671
    +	(t alien))))
    
    651 672
     
    
    652 673
     ;; signed numbers <= 32 bits need to be sign extended.
    
    653 674
     ;; I really should use the movsxd instruction, but I don't
    
    ... ... @@ -694,8 +715,8 @@
    694 715
     
    
    695 716
     (def-alien-type-class (boolean :include integer :include-args (signed)))
    
    696 717
     
    
    697
    -(def-alien-type-translator boolean (&optional (bits vm:word-bits))
    
    698
    -  (make-alien-boolean-type :bits bits :signed nil))
    
    718
    +(def-alien-type-translator boolean (&optional (bits 8))
    
    719
    +  (make-alien-boolean-type :bits bits :signed t))
    
    699 720
     
    
    700 721
     (def-alien-type-method (boolean :unparse) (type)
    
    701 722
       `(boolean ,(alien-boolean-type-bits type)))
    
    ... ... @@ -705,8 +726,10 @@
    705 726
       `(member t nil))
    
    706 727
     
    
    707 728
     (def-alien-type-method (boolean :naturalize-gen) (type alien)
    
    708
    -  (declare (ignore type))
    
    709
    -  `(not (zerop ,alien)))
    
    729
    +  ;; Mask out any unwanted bits.  Important if the C code returns
    
    730
    +  ;; values in %al, or %ax
    
    731
    +  `(not (zerop (ldb (byte ,(alien-boolean-type-bits type) 0)
    
    732
    +		    ,alien))))
    
    710 733
     
    
    711 734
     (def-alien-type-method (boolean :deport-gen) (type value)
    
    712 735
       (declare (ignore type))
    

  • src/code/extfmts.lisp
    ... ... @@ -461,15 +461,18 @@
    461 461
     	       (format t "~&~A~%"
    
    462 462
     		       (intl:gettext (or (ef-documentation ef) "")))))))))
    
    463 463
     
    
    464
    +(defconstant +builtin-external-formats+ '(:utf-8 :iso8859-1 :ascii)
    
    465
    +  "List of external formats that are builtin so that they don't need to
    
    466
    +  be loaded on first use.")
    
    467
    +
    
    464 468
     (defun %find-external-format (name)
    
    465 469
       ;; avoid loading files, etc., early in the boot sequence
    
    466
    -  (when (or (eq name :iso8859-1)
    
    467
    -	    (and (eq name :default) (eq *default-external-format* :iso8859-1)))
    
    468
    -    (return-from %find-external-format
    
    469
    -      (gethash :iso8859-1 *external-formats*)))
    
    470
    -  (when (eq name :utf-8)
    
    470
    +  (when (and (eq name :default)
    
    471
    +	     (eq *default-external-format* :iso8859-1))
    
    472
    +    (setf name :iso8859-1))
    
    473
    +  (when (member name +builtin-external-formats+ :test 'eq)
    
    471 474
         (return-from %find-external-format
    
    472
    -      (gethash :utf-8 *external-formats*)))
    
    475
    +      (gethash name *external-formats*)))
    
    473 476
     
    
    474 477
       (when (zerop (hash-table-count *external-format-aliases*))
    
    475 478
         (setf (gethash :latin1 *external-format-aliases*) :iso8859-1)
    
    ... ... @@ -1188,6 +1191,8 @@ character and illegal outputs are replaced by a question mark.")
    1188 1191
     	 ,(subst (ef-name ef) ef
    
    1189 1192
     		 (function-lambda-expression (aref (ef-cache ef) slot))))))
    
    1190 1193
     
    
    1194
    +;;; Builtin external formats.
    
    1195
    +
    
    1191 1196
     ;; A safe UTF-8 external format.  Any illegal UTF-8 sequences on input
    
    1192 1197
     ;; are replaced with the Unicode REPLACEMENT CHARACTER (U+FFFD), or
    
    1193 1198
     ;; signals an error as appropriate.
    
    ... ... @@ -1303,3 +1308,29 @@ replacement character.")
    1303 1308
              ((< ,code #x10000) (utf8 ,code 2))
    
    1304 1309
              ((< ,code #x110000) (utf8 ,code 3))
    
    1305 1310
              (t (error "How did this happen?  Codepoint U+~X is illegal" ,code))))))
    
    1311
    +
    
    1312
    +(define-external-format :ascii (:size 1 :documentation
    
    1313
    +"US ASCII 7-bit encoding.  Illegal input sequences are replaced with
    
    1314
    +the Unicode replacment character.  Illegal output characters are
    
    1315
    +replaced with a question mark.")
    
    1316
    +  ()
    
    1317
    +  (octets-to-code (state input unput error c)
    
    1318
    +    `(let ((,c ,input))
    
    1319
    +       (values (if (< ,c #x80)
    
    1320
    +		   ,c
    
    1321
    +		   (if ,error
    
    1322
    +		       (locally
    
    1323
    +			   ;; No warnings about fdefinition
    
    1324
    +			   (declare (optimize (ext:inhibit-warnings 3)))
    
    1325
    +			 (funcall ,error "Invalid octet #x~4,'0X for ASCII" ,c 1))
    
    1326
    +		       +replacement-character-code+))
    
    1327
    +	       1)))
    
    1328
    +  (code-to-octets (code state output error)
    
    1329
    +    `(,output (if (> ,code #x7F)
    
    1330
    +		  (if ,error
    
    1331
    +		      (locally
    
    1332
    +			  ;; No warnings about fdefinition
    
    1333
    +			  (declare (optimize (ext:inhibit-warnings 3)))
    
    1334
    +			(funcall ,error "Cannot output codepoint #x~X to ASCII stream" ,code))
    
    1335
    +		      #x3F)
    
    1336
    +		  ,code))))

  • src/code/fd-stream-comp.lisp
    ... ... @@ -28,6 +28,7 @@
    28 28
     (stream::precompile-ef-slot :iso8859-1 #.stream::+ef-de+)
    
    29 29
     (stream::precompile-ef-slot :iso8859-1 #.stream::+ef-osc+)
    
    30 30
     
    
    31
    +;; :utf-8 is builtin.  Important since it's the default now.
    
    31 32
     (stream::precompile-ef-slot :utf-8 #.stream::+ef-cin+)
    
    32 33
     (stream::precompile-ef-slot :utf-8 #.stream::+ef-cout+)
    
    33 34
     (stream::precompile-ef-slot :utf-8 #.stream::+ef-sout+)
    
    ... ... @@ -36,3 +37,13 @@
    36 37
     (stream::precompile-ef-slot :utf-8 #.stream::+ef-en+)
    
    37 38
     (stream::precompile-ef-slot :utf-8 #.stream::+ef-de+)
    
    38 39
     (stream::precompile-ef-slot :utf-8 #.stream::+ef-osc+)
    
    40
    +
    
    41
    +;; :ascii is builtin.
    
    42
    +(stream::precompile-ef-slot :ascii #.stream::+ef-cin+)
    
    43
    +(stream::precompile-ef-slot :ascii #.stream::+ef-cout+)
    
    44
    +(stream::precompile-ef-slot :ascii #.stream::+ef-sout+)
    
    45
    +(stream::precompile-ef-slot :ascii #.stream::+ef-os+)
    
    46
    +(stream::precompile-ef-slot :ascii #.stream::+ef-so+)
    
    47
    +(stream::precompile-ef-slot :ascii #.stream::+ef-en+)
    
    48
    +(stream::precompile-ef-slot :ascii #.stream::+ef-de+)
    
    49
    +(stream::precompile-ef-slot :ascii #.stream::+ef-osc+)

  • src/code/list.lisp
    ... ... @@ -748,64 +748,30 @@
    748 748
     (defparameter *min-list-length-for-hashtable*
    
    749 749
       15)
    
    750 750
     
    
    751
    -(defun init-hashtable-list1 (list1 len &key key test)
    
    752
    -  (let ((hashtable (make-hash-table :test test :size len)))
    
    753
    -    (dolist (item list1)
    
    754
    -      (push item (gethash (apply-key key item) hashtable)))
    
    755
    -    (values hashtable list1)))
    
    756
    -
    
    757
    -(defun init-hashtable-list2 (list2 len &key key test)
    
    758
    -  (let ((hashtable (make-hash-table :test test :size len)))
    
    759
    -    (dolist (item list2)
    
    760
    -      (setf (gethash (apply-key key item) hashtable) item))
    
    761
    -    (values hashtable list2)))
    
    762
    -
    
    763
    -;; Convert a list to a hashtable.  Given 2 lists, find the shorter of
    
    764
    -;; the two lists and add the shorter list to a hashtable.  Returns the
    
    765
    -;; hashtable and the shorter list.
    
    766
    -(defun list-to-hashtable (list1 list2 &key test test-not key)
    
    751
    +;; Convert a list to a hashtable.  The hashtable does not handle
    
    752
    +;; duplicated values in the list.  Returns the hashtable.
    
    753
    +(defun list-to-hashtable (list &key test test-not key)
    
    767 754
       ;; Don't currently support test-not when converting a list to a hashtable
    
    768 755
       (unless test-not
    
    769 756
         (let ((hash-test (let ((test-fn (if (and (symbolp test)
    
    770 757
     					     (fboundp test))
    
    771 758
     					(fdefinition test)
    
    772 759
     					test)))
    
    773
    -		       (cond ((eql test-fn #'eq) 'eq)
    
    774
    -			     ((eql test-fn #'eql) 'eql)
    
    775
    -			     ((eql test-fn #'equal) 'equal)
    
    776
    -			     ((eql test-fn #'equalp) 'equalp)))))
    
    760
    +		       (case test-fn
    
    761
    +			 (#'eq 'eq)
    
    762
    +			 (#'eql 'eql)
    
    763
    +			 (#'equal 'equal)
    
    764
    +			 (#'equalp 'equalp)))))
    
    777 765
           (unless hash-test
    
    778
    -	(return-from list-to-hashtable (values nil nil)))
    
    779
    -      (multiple-value-bind (len shorter-list)
    
    780
    -	  ;; Find the list with the shorter length.  If they're they
    
    781
    -	  ;; same, we prefer the second list to the first list since
    
    782
    -	  ;; the hashtable implementation is slightly simplier.
    
    783
    -          (do ((length 0 (1+ length))
    
    784
    -               (l1 list1 (cdr l1))
    
    785
    -               (l2 list2 (cdr l2)))
    
    786
    -              ((cond ((endp l2)
    
    787
    -                      (return (values length list2)))
    
    788
    -		     #+nil
    
    789
    -		     ((endp l1)
    
    790
    -                      (return (values length list1))))))
    
    791
    -	;; If the list is too short, the hashtable makes things
    
    792
    -	;; slower.  We also need to balance memory usage.
    
    793
    -        (when (< len *min-list-length-for-hashtable*)
    
    794
    -          (return-from list-to-hashtable (values nil nil)))
    
    795
    -        (cond ((eq shorter-list list2)
    
    796
    -	       #+nil
    
    797
    -	       (let ((hashtable (make-hash-table :test test :size len)))
    
    798
    -                 (dolist (item list2)
    
    799
    -                   (setf (gethash (apply-key key item) hashtable) item))
    
    800
    -                 (values hashtable list2))
    
    801
    -	       (init-hashtable-list2 list2 len :key key :test test))
    
    802
    -              ((eq shorter-list list1)
    
    803
    -	       #+nil
    
    804
    -	       (let ((hashtable (make-hash-table :test test :size len)))
    
    805
    -		 (dolist (item list1)
    
    806
    -     		   (push item (gethash (apply-key key item) hashtable)))
    
    807
    -		 (values hashtable list1))
    
    808
    -	       (init-hashtable-list1 list1 len :key key :test test)))))))
    
    766
    +	(return-from list-to-hashtable nil))
    
    767
    +      ;; If the list is too short, the hashtable makes things
    
    768
    +      ;; slower.  We also need to balance memory usage.
    
    769
    +      (when (< (length list) *min-list-length-for-hashtable*)
    
    770
    +        (return-from list-to-hashtable nil))
    
    771
    +      (let ((hashtable (make-hash-table :test test :size len)))
    
    772
    +	(dolist (item list)
    
    773
    +	  (setf (gethash (apply-key key item) hashtable) item))
    
    774
    +	hashtable))))
    
    809 775
     
    
    810 776
     ;;; UNION -- Public.
    
    811 777
     ;;;
    
    ... ... @@ -874,24 +840,6 @@
    874 840
     	  (setq list1 (Cdr list1))))
    
    875 841
         res))
    
    876 842
     
    
    877
    -(defun set-diff-hash2 (list1 hashtable &key key)
    
    878
    -  (let (diff)
    
    879
    -    (dolist (item list1)
    
    880
    -      (unless (nth-value 1 (gethash (apply-key key item) hashtable))
    
    881
    -        (push item diff)))
    
    882
    -    diff))
    
    883
    -
    
    884
    -(defun set-diff-hash1 (list2 hashtable &key key)
    
    885
    -  (dolist (item list2)
    
    886
    -    (unless (eq hashtable (gethash (apply-key key item) hashtable hashtable))
    
    887
    -      (remhash item hashtable)))
    
    888
    -  (let ((result '()))
    
    889
    -    (maphash #'(lambda (key value)
    
    890
    -		 (declare (ignore key))
    
    891
    -		 (setq result (nconc result value)))
    
    892
    -	     hashtable)
    
    893
    -    result))  
    
    894
    -
    
    895 843
     (defun set-difference (list1 list2 &key key (test #'eql testp) (test-not nil notp))
    
    896 844
       "Returns the elements of list1 which are not in list2."
    
    897 845
       (declare (inline member))
    
    ... ... @@ -901,40 +849,23 @@
    901 849
       (when (null list2)
    
    902 850
         (return-from set-difference list1))
    
    903 851
     
    
    904
    -  (multiple-value-bind (hashtable shorter-list)
    
    905
    -      (list-to-hashtable list1 list2 :key key :test test :test-not test-not)
    
    906
    -    (cond ((null hashtable)
    
    852
    +  (let ((hashtable 
    
    853
    +	  (list-to-hashtable list2 :key key :test test :test-not test-not)))
    
    854
    +    (cond (hashtable
    
    855
    +	   ;; list2 was placed in hash table.
    
    856
    +	   (let (diff)
    
    857
    +	     (dolist (item list1)
    
    858
    +	       (unless (nth-value 1 (gethash (apply-key key item) hashtable))
    
    859
    +		 (push item diff)))
    
    860
    +	     diff))
    
    861
    +	  ((null hashtable)
    
    907 862
     	   ;; Default implementation because we didn't create the hash
    
    908 863
     	   ;; table.
    
    909 864
                (let ((res nil))
    
    910 865
     	     (dolist (elt list1)
    
    911 866
                    (if (not (with-set-keys (member (apply-key key elt) list2)))
    
    912 867
                        (push elt res)))
    
    913
    -	     res))
    
    914
    -	  ((eq shorter-list list2)
    
    915
    -	   ;; list2 was placed in hash table.
    
    916
    -	   #+nil
    
    917
    -	   (let (diff)
    
    918
    -             (dolist (item list1)
    
    919
    -	       (unless (nth-value 1 (gethash (apply-key key item) hashtable))
    
    920
    -                 (push item diff)))
    
    921
    -             diff)
    
    922
    -	   (set-diff-hash2 list1 hashtable :key key))
    
    923
    -          ((eq shorter-list list1)
    
    924
    -	   ;; list1 was placed in the hash table.
    
    925
    -	   #+nil
    
    926
    -           (dolist (item list2)
    
    927
    -	     (unless (eq hashtable (gethash (apply-key key item) hashtable hashtable))
    
    928
    -               (remhash item hashtable)))
    
    929
    -	   #+nil
    
    930
    -	   (let ((result '()))
    
    931
    -	     (maphash #'(lambda (key value)
    
    932
    -			  (declare (ignore key))
    
    933
    -			  (setq result (nconc result value)))
    
    934
    -		      hashtable)
    
    935
    -	     result)
    
    936
    -	   (set-diff-hash1 list2 hashtable :key key)))))
    
    937
    -
    
    868
    +	     res)))))
    
    938 869
     
    
    939 870
     (defun nset-difference (list1 list2 &key key
    
    940 871
     			      (test #'eql testp) (test-not nil notp))
    

  • src/code/pathname.lisp
    ... ... @@ -121,58 +121,73 @@
    121 121
     (defun %print-pathname (pathname stream depth)
    
    122 122
       (declare (ignore depth))
    
    123 123
       (let* ((host (%pathname-host pathname))
    
    124
    +	 (device (%pathname-device pathname))
    
    125
    +	 (directory (%pathname-directory pathname))
    
    126
    +	 (name (%pathname-name pathname))
    
    127
    +	 (type (%pathname-type pathname))
    
    128
    +	 (version (%pathname-version pathname))
    
    129
    +	 (unspecific-p (or (eq device :unspecific)
    
    130
    +			   (eq name :unspecific)
    
    131
    +			   (eq type :unspecific)
    
    132
    +			   (eq version :unspecific)))
    
    124 133
     	 (namestring (if host
    
    125 134
     			 (handler-case (namestring pathname)
    
    126 135
     			   (error nil))
    
    127 136
     			 nil)))
    
    128
    -    (cond (namestring
    
    137
    +    ;; A pathname with :UNSPECIFIC components has a namestring that
    
    138
    +    ;; ignores :UNSPECIFIC (and NIL).  Thus the namestring exists, but
    
    139
    +    ;; we want to use our special syntax to print the pathname
    
    140
    +    ;; readably when :UNSPECIFIC occurs.
    
    141
    +    (cond ((and namestring (not unspecific-p))
    
    129 142
     	   (if (or *print-escape* *print-readably*)
    
    130 143
     	       (format stream "#P~S" namestring)
    
    131 144
     	       (format stream "~A" namestring)))
    
    132 145
     	  (t
    
    133
    -	   (let ((device (%pathname-device pathname))
    
    134
    -		 (directory (%pathname-directory pathname))
    
    135
    -		 (name (%pathname-name pathname))
    
    136
    -		 (type (%pathname-type pathname))
    
    137
    -		 (version (%pathname-version pathname)))
    
    138
    -	     (cond ((every #'(lambda (d)
    
    139
    -			       (or (stringp d)
    
    140
    -				   (symbolp d)))
    
    141
    -			   (cdr directory))
    
    142
    -		    ;; A CMUCL extension.  If we have an unprintable
    
    143
    -		    ;; pathname, convert it to a form that would be
    
    144
    -		    ;; suitable as args to MAKE-PATHNAME to recreate
    
    145
    -		    ;; the pathname.
    
    146
    -		    ;;
    
    147
    -		    ;; We don't handle search-lists because we don't
    
    148
    -		    ;; currently have a readable syntax for
    
    149
    -		    ;; search-lists.
    
    150
    -		    (collect ((result))
    
    151
    -		      (unless (eq host *unix-host*)
    
    152
    -			(result :host)
    
    153
    -			(result (if host
    
    154
    -				    (pathname-host pathname)
    
    155
    -				    nil)))
    
    156
    -		      (when device
    
    157
    -			(result :device)
    
    158
    -			(result device))
    
    159
    -		      (when directory
    
    160
    -			(result :directory)
    
    161
    -			(result directory))
    
    162
    -		      (when name
    
    163
    -			(result :name)
    
    164
    -			(result name))
    
    165
    -		      (when type
    
    166
    -			(result :type)
    
    167
    -			(result type))
    
    168
    -		      (when version
    
    169
    -			(result :version)
    
    170
    -			(result version))
    
    171
    -		      (format stream "#P~S" (result))))
    
    172
    -		   (*print-readably*
    
    173
    -		    (error 'print-not-readable :object pathname))
    
    174
    -		   (t
    
    175
    -		    (funcall (formatter "#<Unprintable pathname,~:_ Host=~S,~:_ Device=~S,~:_ ~
    
    146
    +	   (cond ((and
    
    147
    +		   ;; We only use the extension if the pathname does
    
    148
    +		   ;; not contain a pattern object which doesn't print
    
    149
    +		   ;; readably.  Search-lists, which are part of the
    
    150
    +		   ;; directory component, are excluded too.
    
    151
    +		   (not (typep name 'pattern))
    
    152
    +		   (not (typep type 'pattern))
    
    153
    +		   (every #'(lambda (d)
    
    154
    +			      (or (stringp d)
    
    155
    +				  (symbolp d)))
    
    156
    +			  (cdr directory)))
    
    157
    +		  ;; A CMUCL extension.  If we have an unprintable
    
    158
    +		  ;; pathname, convert it to a form that would be
    
    159
    +		  ;; suitable as args to MAKE-PATHNAME to recreate
    
    160
    +		  ;; the pathname.
    
    161
    +		  ;;
    
    162
    +		  ;; We don't handle search-lists because we don't
    
    163
    +		  ;; currently have a readable syntax for
    
    164
    +		  ;; search-lists.
    
    165
    +		  (collect ((result))
    
    166
    +		    (unless (eq host *unix-host*)
    
    167
    +		      (result :host)
    
    168
    +		      (result (if host
    
    169
    +				  (pathname-host pathname)
    
    170
    +				  nil)))
    
    171
    +		    (when device
    
    172
    +		      (result :device)
    
    173
    +		      (result device))
    
    174
    +		    (when directory
    
    175
    +		      (result :directory)
    
    176
    +		      (result directory))
    
    177
    +		    (when name
    
    178
    +		      (result :name)
    
    179
    +		      (result name))
    
    180
    +		    (when type
    
    181
    +		      (result :type)
    
    182
    +		      (result type))
    
    183
    +		    (when version
    
    184
    +		      (result :version)
    
    185
    +		      (result version))
    
    186
    +		    (format stream "#P~S" (result))))
    
    187
    +		 (*print-readably*
    
    188
    +		  (error 'print-not-readable :object pathname))
    
    189
    +		 (t
    
    190
    +		  (funcall (formatter "#<Unprintable pathname,~:_ Host=~S,~:_ Device=~S,~:_ ~
    
    176 191
     				Directory=~S,~:_ Name=~S,~:_ Type=~S,~:_ Version=~S>")
    
    177 192
     			     stream
    
    178 193
     			     (%pathname-host pathname)
    

  • src/code/pred.lisp
    ... ... @@ -387,8 +387,8 @@
    387 387
     (defun equal (x y)
    
    388 388
       "Returns T if X and Y are EQL or if they are structured components
    
    389 389
       whose elements are EQUAL.  Strings and bit-vectors are EQUAL if they
    
    390
    -  are the same length and have indentical components.  Other arrays must be
    
    391
    -  EQ to be EQUAL."
    
    390
    +  are the same length and have identical components.  Other arrays
    
    391
    +  must be EQ to be EQUAL."
    
    392 392
       (cond ((eql x y) t)
    
    393 393
     	((consp x)
    
    394 394
     	 (and (consp y)
    

  • src/compiler/x86/c-call.lisp
    ... ... @@ -141,59 +141,77 @@
    141 141
     					(alien-function-type-result-type type)
    
    142 142
     					(make-result-state))))))
    
    143 143
     
    
    144
    -(deftransform %alien-funcall ((function type &rest args))
    
    145
    -  (assert (c::constant-continuation-p type))
    
    144
    +(defun %alien-funcall-aux (function type &rest args)
    
    145
    +  (declare (ignorable function type args))
    
    146 146
       (let* ((type (c::continuation-value type))
    
    147 147
     	 (arg-types (alien-function-type-arg-types type))
    
    148 148
     	 (result-type (alien-function-type-result-type type)))
    
    149 149
         (assert (= (length arg-types) (length args)))
    
    150
    -    (if (or (some #'(lambda (type)
    
    151
    -		      (and (alien-integer-type-p type)
    
    152
    -			   (> (alien::alien-integer-type-bits type) 32)))
    
    153
    -		  arg-types)
    
    154
    -	    (and (alien-integer-type-p result-type)
    
    155
    -		 (> (alien::alien-integer-type-bits result-type) 32)))
    
    156
    -	(collect ((new-args) (lambda-vars) (new-arg-types))
    
    157
    -	  (dolist (type arg-types)
    
    158
    -	    (let ((arg (gensym)))
    
    159
    -	      (lambda-vars arg)
    
    160
    -	      (cond ((and (alien-integer-type-p type)
    
    161
    -			  (> (alien::alien-integer-type-bits type) 32))
    
    162
    -		     (new-args `(logand ,arg #xffffffff))
    
    163
    -		     (new-args `(ash ,arg -32))
    
    164
    -		     (new-arg-types (parse-alien-type '(unsigned 32)))
    
    165
    -		     (if (alien-integer-type-signed type)
    
    166
    -			 (new-arg-types (parse-alien-type '(signed 32)))
    
    167
    -			 (new-arg-types (parse-alien-type '(unsigned 32)))))
    
    168
    -		    (t
    
    169
    -		     (new-args arg)
    
    170
    -		     (new-arg-types type)))))
    
    171
    -	  (cond ((and (alien-integer-type-p result-type)
    
    172
    -		      (> (alien::alien-integer-type-bits result-type) 32))
    
    173
    -		 (let ((new-result-type
    
    174
    -			(let ((alien::*values-type-okay* t))
    
    175
    -			  (parse-alien-type
    
    176
    -			   (if (alien-integer-type-signed result-type)
    
    177
    -			       '(values (unsigned 32) (signed 32))
    
    178
    -			       '(values (unsigned 32) (unsigned 32)))))))
    
    179
    -		   `(lambda (function type ,@(lambda-vars))
    
    180
    -		      (declare (ignore type))
    
    181
    -		      (multiple-value-bind (low high)
    
    182
    -			  (%alien-funcall function
    
    183
    -					  ',(make-alien-function-type
    
    184
    -					     :arg-types (new-arg-types)
    
    185
    -					     :result-type new-result-type)
    
    186
    -					  ,@(new-args))
    
    187
    -			(logior low (ash high 32))))))
    
    150
    +    (unless (or (some #'(lambda (type)
    
    151
    +			  (and (alien-integer-type-p type)
    
    152
    +			       (> (alien::alien-integer-type-bits type) 32)))
    
    153
    +		      arg-types)
    
    154
    +		(and (alien-integer-type-p result-type)
    
    155
    +		     (/= (alien::alien-integer-type-bits result-type) 32)))
    
    156
    +      (c::give-up))
    
    157
    +    (collect ((new-args) (lambda-vars) (new-arg-types))
    
    158
    +      (dolist (type arg-types)
    
    159
    +	(let ((arg (gensym)))
    
    160
    +	  (lambda-vars arg)
    
    161
    +	  (cond ((and (alien-integer-type-p type)
    
    162
    +		      (> (alien::alien-integer-type-bits type) 32))
    
    163
    +		 (new-args `(logand ,arg #xffffffff))
    
    164
    +		 (new-args `(ash ,arg -32))
    
    165
    +		 (new-arg-types (parse-alien-type '(unsigned 32)))
    
    166
    +		 (if (alien-integer-type-signed type)
    
    167
    +		     (new-arg-types (parse-alien-type '(signed 32)))
    
    168
    +		     (new-arg-types (parse-alien-type '(unsigned 32)))))
    
    188 169
     		(t
    
    189
    -		 `(lambda (function type ,@(lambda-vars))
    
    190
    -		    (declare (ignore type))
    
    191
    -		    (%alien-funcall function
    
    192
    -				    ',(make-alien-function-type
    
    193
    -				       :arg-types (new-arg-types)
    
    194
    -				       :result-type result-type)
    
    195
    -				    ,@(new-args))))))
    
    196
    -	(c::give-up))))
    
    170
    +		 (new-args arg)
    
    171
    +		 (new-arg-types type)))))
    
    172
    +      (cond ((and (alien-integer-type-p result-type)
    
    173
    +		  (< (alien::alien-integer-type-bits result-type) 32))
    
    174
    +	     (let ((new-result-type
    
    175
    +		     (parse-alien-type
    
    176
    +		      (if (alien-integer-type-signed result-type)
    
    177
    +			  '(signed 32)
    
    178
    +			  '(unsigned 32)))))
    
    179
    +	       `(lambda (function type ,@(lambda-vars))
    
    180
    +		  (declare (ignore type))
    
    181
    +		  (%alien-funcall function
    
    182
    +				  ',(make-alien-function-type
    
    183
    +				     :arg-types (new-arg-types)
    
    184
    +				     :result-type new-result-type)
    
    185
    +				  ,@(new-args)))))
    
    186
    +	    ((and (alien-integer-type-p result-type)
    
    187
    +		  (> (alien::alien-integer-type-bits result-type) 32))
    
    188
    +	     (let ((new-result-type
    
    189
    +		     (let ((alien::*values-type-okay* t))
    
    190
    +		       (parse-alien-type
    
    191
    +			(if (alien-integer-type-signed result-type)
    
    192
    +			    '(values (unsigned 32) (signed 32))
    
    193
    +			    '(values (unsigned 32) (unsigned 32)))))))
    
    194
    +	       `(lambda (function type ,@(lambda-vars))
    
    195
    +		  (declare (ignore type))
    
    196
    +		  (multiple-value-bind (low high)
    
    197
    +		      (%alien-funcall function
    
    198
    +				      ',(make-alien-function-type
    
    199
    +					 :arg-types (new-arg-types)
    
    200
    +					 :result-type new-result-type)
    
    201
    +				      ,@(new-args))
    
    202
    +		    (logior low (ash high 32))))))
    
    203
    +	    (t
    
    204
    +	     `(lambda (function type ,@(lambda-vars))
    
    205
    +		(declare (ignore type))
    
    206
    +		(%alien-funcall function
    
    207
    +				',(make-alien-function-type
    
    208
    +				   :arg-types (new-arg-types)
    
    209
    +				   :result-type result-type)
    
    210
    +				,@(new-args))))))))
    
    211
    +
    
    212
    +(deftransform %alien-funcall ((function type &rest args))
    
    213
    +  (assert (c::constant-continuation-p type))
    
    214
    +  (apply #'%alien-funcall-aux function type args))
    
    197 215
     
    
    198 216
     (define-vop (foreign-symbol-code-address)
    
    199 217
       (:translate #+linkage-table foreign-symbol-code-address
    

  • src/compiler/x86/insts.lisp
    ... ... @@ -744,7 +744,12 @@
    744 744
     			  ;; set by a prefix instruction
    
    745 745
     			  (or (disassem:dstate-get-prop dstate 'word-width)
    
    746 746
     			      *default-operand-size*)))
    
    747
    -		     (princ (schar (symbol-name word-width) 0) stream)))))
    
    747
    +		     ;; Make sure the print case is honored when
    
    748
    +		     ;; printing out the width.
    
    749
    +		     (princ (ecase word-width
    
    750
    +			      (:word 'w)
    
    751
    +			      (:dword 'd))
    
    752
    +			    stream)))))
    
    748 753
     
    
    749 754
     
    
    750 755
     ;;;; Disassembler instruction formats.
    

  • src/general-info/release-21f.md
    ... ... @@ -23,6 +23,9 @@ public domain.
    23 23
       * Bug fixes:
    
    24 24
       * Gitlab tickets:
    
    25 25
         * ~~#154~~ piglatin translation does not work anymore
    
    26
    +	* ~~#171~~ Readably print `(make-pathname :name :unspecfic)`
    
    27
    +	* ~~#242~~ Fix bug in `alien-funcall` with `c-call:char` as result type
    
    28
    +    * ~~#248~~ Print MOVS instruction with correct case
    
    26 29
       * Other changes:
    
    27 30
       * Improvements to the PCL implementation of CLOS:
    
    28 31
       * Changes to building procedure:
    

  • src/i18n/locale/cmucl.pot
    ... ... @@ -1593,8 +1593,8 @@ msgstr ""
    1593 1593
     msgid ""
    
    1594 1594
     "Returns T if X and Y are EQL or if they are structured components\n"
    
    1595 1595
     "  whose elements are EQUAL.  Strings and bit-vectors are EQUAL if they\n"
    
    1596
    -"  are the same length and have indentical components.  Other arrays must be\n"
    
    1597
    -"  EQ to be EQUAL."
    
    1596
    +"  are the same length and have identical components.  Other arrays\n"
    
    1597
    +"  must be EQ to be EQUAL."
    
    1598 1598
     msgstr ""
    
    1599 1599
     
    
    1600 1600
     #: src/code/pred.lisp
    
    ... ... @@ -9148,6 +9148,12 @@ msgstr ""
    9148 9148
     msgid "~&Could not find external format ~S~%"
    
    9149 9149
     msgstr ""
    
    9150 9150
     
    
    9151
    +#: src/code/extfmts.lisp
    
    9152
    +msgid ""
    
    9153
    +"List of external formats that are builtin so that they don't need to\n"
    
    9154
    +"  be loaded on first use."
    
    9155
    +msgstr ""
    
    9156
    +
    
    9151 9157
     #: src/code/extfmts.lisp
    
    9152 9158
     msgid "External-format aliasing depth exceeded."
    
    9153 9159
     msgstr ""
    
    ... ... @@ -9288,6 +9294,13 @@ msgid ""
    9288 9294
     "replacement character."
    
    9289 9295
     msgstr ""
    
    9290 9296
     
    
    9297
    +#: src/code/extfmts.lisp
    
    9298
    +msgid ""
    
    9299
    +"US ASCII 7-bit encoding.  Illegal input sequences are replaced with\n"
    
    9300
    +"the Unicode replacment character.  Illegal output characters are\n"
    
    9301
    +"replaced with a question mark."
    
    9302
    +msgstr ""
    
    9303
    +
    
    9291 9304
     #: src/code/fd-stream.lisp
    
    9292 9305
     msgid ""
    
    9293 9306
     "List of available buffers.  Each buffer is an sap pointing to\n"
    
    ... ... @@ -21325,12 +21338,6 @@ msgstr ""
    21325 21338
     msgid "    Gray Streams Protocol Support"
    
    21326 21339
     msgstr ""
    
    21327 21340
     
    
    21328
    -msgid ""
    
    21329
    -"US ASCII 7-bit encoding.  Illegal input sequences are replaced with\n"
    
    21330
    -"the Unicode replacment character.  Illegal output characters are\n"
    
    21331
    -"replaced with a question mark."
    
    21332
    -msgstr ""
    
    21333
    -
    
    21334 21341
     msgid ""
    
    21335 21342
     "MAC-ROMAN is an 8-bit character encoding for Western European\n"
    
    21336 21343
     "languages including English.\n"
    

  • tests/issues.lisp
    ... ... @@ -997,3 +997,111 @@
    997 997
           ;; This is the condition from the CLHS entry for enough-namestring
    
    998 998
           (assert-equal (merge-pathnames enough defaults)
    
    999 999
     		    (merge-pathnames (parse-namestring pathname nil defaults) defaults))))))
    
    1000
    +
    
    1001
    +(define-test issue.242-load-foreign
    
    1002
    +  ;; load-foreign apparently returns NIL if it succeeds.
    
    1003
    +  (assert-true (eql nil (ext:load-foreign (merge-pathnames "test-return.o" *test-path*)))))
    
    1004
    +
    
    1005
    +(alien:def-alien-variable "test_arg" c-call:int)
    
    1006
    +
    
    1007
    +(define-test issue.242.test-alien-return-signed-char
    
    1008
    +  (:tag :issues)
    
    1009
    +  (flet ((fun (n)
    
    1010
    +	   (setf test-arg n)
    
    1011
    +	   (alien:alien-funcall
    
    1012
    +	    (alien:extern-alien "int_to_signed_char"
    
    1013
    +				(function c-call:char))))
    
    1014
    +	 (sign-extend (n)
    
    1015
    +	   (let ((n (ldb (byte 8 0) n)))
    
    1016
    +	     (if (> n #x7f)
    
    1017
    +		 (- n #x100)
    
    1018
    +		 n))))
    
    1019
    +    (dolist (x '(99 -99 1023 -1023))
    
    1020
    +      (assert-equal (sign-extend x) (fun x) x))))
    
    1021
    +
    
    1022
    +(define-test issue.242.test-alien-return-signed-short
    
    1023
    +  (:tag :issues)
    
    1024
    +  (flet ((fun (n)
    
    1025
    +	   (setf test-arg n)
    
    1026
    +	   (alien:alien-funcall
    
    1027
    +	    (alien:extern-alien "int_to_short"
    
    1028
    +				(function c-call:short))))
    
    1029
    +	 (sign-extend (n)
    
    1030
    +	   (let ((n (ldb (byte 16 0) n)))
    
    1031
    +	     (if (> n #x7fff)
    
    1032
    +		 (- n #x10000)
    
    1033
    +		 n))))
    
    1034
    +    (dolist (x '(1023 -1023 100000 -100000))
    
    1035
    +      (assert-equal (sign-extend x) (fun x) x))))
    
    1036
    +
    
    1037
    +(define-test issue.242.test-alien-return-signed-int
    
    1038
    +  (:tag :issues)
    
    1039
    +  (flet ((fun (n)
    
    1040
    +	   (setf test-arg n)
    
    1041
    +	   (alien:alien-funcall
    
    1042
    +	    (alien:extern-alien "int_to_int"
    
    1043
    +				(function c-call:int)))))
    
    1044
    +    (dolist (x '(1023 -1023 #x7fffffff #x-80000000))
    
    1045
    +      (assert-equal x (fun x) x))))
    
    1046
    +
    
    1047
    +(define-test issue.242.test-alien-return-unsigned-char
    
    1048
    +  (:tag :issues)
    
    1049
    +  (flet ((fun (n)
    
    1050
    +	   (setf test-arg n)
    
    1051
    +	   (alien:alien-funcall
    
    1052
    +	    (alien:extern-alien "int_to_unsigned_char"
    
    1053
    +				(function c-call:unsigned-char))))
    
    1054
    +	 (expected (n)
    
    1055
    +	   (ldb (byte 8 0) n)))
    
    1056
    +    (dolist (x '(99 -99 1023 -1023))
    
    1057
    +      (assert-equal (expected x) (fun x) x))))
    
    1058
    +
    
    1059
    +(define-test issue.242.test-alien-return-unsigned-short
    
    1060
    +  (:tag :issues)
    
    1061
    +  (flet ((fun (n)
    
    1062
    +	   (setf test-arg n)
    
    1063
    +	   (alien:alien-funcall
    
    1064
    +	    (alien:extern-alien "int_to_unsigned_short"
    
    1065
    +				(function c-call:unsigned-short))))
    
    1066
    +	 (expected (n)
    
    1067
    +	   (ldb (byte 16 0) n)))
    
    1068
    +    (dolist (x '(1023 -1023 100000 -100000))
    
    1069
    +      (assert-equal (expected x) (fun x) x))))
    
    1070
    +
    
    1071
    +(define-test issue.242.test-alien-return-unsigned-int
    
    1072
    +  (:tag :issues)
    
    1073
    +  (flet ((fun (n)
    
    1074
    +	   (setf test-arg n)
    
    1075
    +	   (alien:alien-funcall
    
    1076
    +	    (alien:extern-alien "int_to_unsigned_int"
    
    1077
    +				(function c-call:unsigned-int))))
    
    1078
    +	 (expected (n)
    
    1079
    +	   (ldb (byte 32 0) n)))
    
    1080
    +    (dolist (x '(1023 -1023 #x7fffffff #x-80000000))
    
    1081
    +      (assert-equal (expected x) (fun x) x))))
    
    1082
    +
    
    1083
    +(define-test issue.242.test-alien-return-bool
    
    1084
    +  (:tag :issues)
    
    1085
    +  (flet ((fun (n)
    
    1086
    +	   (setf test-arg n)
    
    1087
    +	   (alien:alien-funcall
    
    1088
    +	    (alien:extern-alien "int_to_bool"
    
    1089
    +				(function c-call:char))))
    
    1090
    +	 (expected (n)
    
    1091
    +	   (if (zerop n)
    
    1092
    +	       0
    
    1093
    +	       1)))
    
    1094
    +    (dolist (x '(0 1 1000))
    
    1095
    +      (assert-equal (expected x) (fun x) x))))
    
    1096
    +
    
    1097
    +(define-test issue.242.test-alien-return-bool.2
    
    1098
    +  (:tag :issues)
    
    1099
    +  (flet ((fun (n)
    
    1100
    +	   (setf test-arg n)
    
    1101
    +	   (alien:alien-funcall
    
    1102
    +	    (alien:extern-alien "int_to_bool"
    
    1103
    +				(function alien:boolean))))
    
    1104
    +	 (expected (n)
    
    1105
    +	   (not (zerop n))))
    
    1106
    +    (dolist (x '(0 1 1000))
    
    1107
    +      (assert-equal (expected x) (fun x) x))))

  • tests/pathname.lisp
    ... ... @@ -83,3 +83,31 @@
    83 83
     	  and type = (pathname-type f)
    
    84 84
     	  do
    
    85 85
     	     (assert-true (and (null name) (null type)) f))))
    
    86
    +
    
    87
    +
    
    88
    +
    
    89
    +;; Test that pathnames with :unspecific components are printed using
    
    90
    +;; our extension to make :unspecific explicit. 
    
    91
    +(define-test issue.171.unspecific
    
    92
    +  (:tag :issues)
    
    93
    +  (flet ((output (path)
    
    94
    +	   (with-output-to-string (s)
    
    95
    +	     (write path :stream s))))
    
    96
    +    (dolist (test
    
    97
    +	     (list
    
    98
    +	      (list (make-pathname :name "foo" :type :unspecific)
    
    99
    +		    "#P(:NAME \"foo\" :TYPE :UNSPECIFIC)"
    
    100
    +		    "foo")
    
    101
    +	      (list (make-pathname :name :unspecific :type "foo")
    
    102
    +		    "#P(:NAME :UNSPECIFIC :TYPE \"foo\")"
    
    103
    +		    ".foo")
    
    104
    +	      (list (make-pathname :name "foo" :type "txt" :version :unspecific)
    
    105
    +		    "#P(:NAME \"foo\" :TYPE \"txt\" :VERSION :UNSPECIFIC)"
    
    106
    +		    "foo.txt")
    
    107
    +	      (list (make-pathname :device :unspecific)
    
    108
    +		    "#P(:DEVICE :UNSPECIFIC)"
    
    109
    +		    "")))
    
    110
    +      (destructuring-bind (pathname printed-value namestring)
    
    111
    +	  test
    
    112
    +	(assert-equal printed-value (output pathname))
    
    113
    +	(assert-equal namestring (namestring pathname))))))

  • tests/test-return.c
    1
    +#include <stdbool.h>
    
    2
    +
    
    3
    +int test_arg;
    
    4
    +
    
    5
    +signed char
    
    6
    +int_to_signed_char()
    
    7
    +{
    
    8
    +  return (signed char) test_arg;
    
    9
    +}
    
    10
    +
    
    11
    +short
    
    12
    +int_to_short()
    
    13
    +{
    
    14
    +  return (short) test_arg;
    
    15
    +}
    
    16
    +
    
    17
    +int
    
    18
    +int_to_int()
    
    19
    +{
    
    20
    +  return (int) test_arg;
    
    21
    +}
    
    22
    +
    
    23
    +unsigned char
    
    24
    +int_to_unsigned_char()
    
    25
    +{
    
    26
    +  return (unsigned char) test_arg;
    
    27
    +}
    
    28
    +
    
    29
    +unsigned short
    
    30
    +int_to_unsigned_short()
    
    31
    +{
    
    32
    +  return (unsigned short) test_arg;
    
    33
    +}
    
    34
    +
    
    35
    +unsigned int
    
    36
    +int_to_unsigned_int()
    
    37
    +{
    
    38
    +  return (unsigned int) test_arg;
    
    39
    +}
    
    40
    +
    
    41
    +_Bool int_to_bool()
    
    42
    +{
    
    43
    +  return (_Bool) test_arg;
    
    44
    +}
    
    45
    +