Raymond Toy pushed to branch issue-240-set-diff-with-hash-table at cmucl / cmucl
Commits:
-
1fcdbdb2
by Raymond Toy at 2023-06-19T14:17:30-07:00
-
4e433b83
by Raymond Toy at 2023-07-05T06:40:08-07:00
-
da69492b
by Raymond Toy at 2023-07-17T15:07:01+00:00
-
635d07ca
by Raymond Toy at 2023-07-17T15:07:04+00:00
-
0a35575a
by Raymond Toy at 2023-07-17T15:07:47+00:00
-
5d4b0622
by Raymond Toy at 2023-07-17T15:07:49+00:00
-
bdd7294f
by Raymond Toy at 2023-07-21T19:15:10+00:00
-
4bce99fc
by Raymond Toy at 2023-07-21T19:15:11+00:00
-
d37a3150
by Raymond Toy at 2023-07-22T00:19:38+00:00
-
95dfdcf3
by Raymond Toy at 2023-07-22T00:19:39+00:00
-
8c6e050a
by Raymond Toy at 2023-07-21T18:06:08-07:00
-
a85ad7cf
by Raymond Toy at 2023-07-23T12:18:48-07:00
-
d5c23293
by Raymond Toy at 2023-07-23T15:07:27-07:00
-
1b54eed9
by Raymond Toy at 2023-07-23T17:18:18-07:00
-
f44c4b81
by Raymond Toy at 2023-07-24T14:51:30-07:00
15 changed files:
- bin/build.sh
- bin/run-tests.sh
- src/code/alieneval.lisp
- src/code/extfmts.lisp
- src/code/fd-stream-comp.lisp
- src/code/list.lisp
- src/code/pathname.lisp
- src/code/pred.lisp
- src/compiler/x86/c-call.lisp
- src/compiler/x86/insts.lisp
- src/general-info/release-21f.md
- src/i18n/locale/cmucl.pot
- tests/issues.lisp
- tests/pathname.lisp
- + tests/test-return.c
Changes:
... | ... | @@ -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
|
... | ... | @@ -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)'
|
... | ... | @@ -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))
|
... | ... | @@ -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)))) |
... | ... | @@ -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+) |
... | ... | @@ -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))
|
... | ... | @@ -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)
|
... | ... | @@ -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)
|
... | ... | @@ -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
|
... | ... | @@ -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.
|
... | ... | @@ -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:
|
... | ... | @@ -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"
|
... | ... | @@ -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)))) |
... | ... | @@ -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)))))) |
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 | + |