don't close runtime dlhandle on Darwin
[sbcl.git] / src / code / early-extensions.lisp
index 8b657cc..9ed8d28 100644 (file)
           (let* ((name (first spec))
                  (exp-temp (gensym "ONCE-ONLY")))
             `(let ((,exp-temp ,(second spec))
-                   (,name (gensym ,(symbol-name name))))
+                   (,name (sb!xc:gensym ,(symbol-name name))))
                `(let ((,,name ,,exp-temp))
                   ,,(frob (rest specs) body))))))))
 \f
 
 (defmacro define-deprecated-function (state since name replacements lambda-list &body body)
   (let* ((replacements (normalize-deprecation-replacements replacements))
-         (doc (let ((*package* (find-package :keyword)))
-                (apply #'format nil
-                       "~@<~S has been deprecated as of SBCL ~A.~
-                        ~#[~; Use ~S instead.~; ~
-                              Use ~S or ~S instead.~:; ~
-                              Use~@{~#[~; or~] ~S~^,~} instead.~]~@:>"
-                       name since replacements))))
+         (doc
+          (let ((*package* (find-package :keyword))
+                (*print-pretty* nil))
+            (apply #'format nil
+                   "~S has been deprecated as of SBCL ~A.~
+                    ~#[~;~2%Use ~S instead.~;~2%~
+                            Use ~S or ~S instead.~:;~2%~
+                            Use~@{~#[~; or~] ~S~^,~} instead.~]"
+                    name since replacements))))
     `(progn
        ,(ecase state
           ((:early :late)
-           `(defun ,name ,lambda-list
-              ,doc
-              ,@body))
+           `(progn
+              (defun ,name ,lambda-list
+                ,doc
+                ,@body)))
           ((:final)
            `(progn
               (declaim (ftype (function * nil) ,name))
@@ -1355,29 +1358,43 @@ to :INTERPRET, an interpreter will be used.")
          (make-unportable-float :long-float-negative-zero)
          0.0l0))))
 
-;;; Like DEFUN, but replaces &REST with &MORE while hiding that from the
-;;; lambda-list.
-(defmacro define-more-fun (name lambda-list &body body)
-  (let* ((p (position '&rest lambda-list))
-         (head (subseq lambda-list 0 p))
-         (tail (subseq lambda-list p))
-         (more-context (gensym "MORE-CONTEXT"))
-         (more-count (gensym "MORE-COUNT")))
-    (aver (= 2 (length tail)))
-    `(progn
-       (macrolet ((more-count ()
-                    `(truly-the index ,',more-count))
-                  (more-p ()
-                    `(not (eql 0 ,',more-count)))
-                  (more-arg (n)
-                    `(sb!c:%more-arg ,',more-context ,n))
-                  (do-more ((arg &optional (start 0)) &body body)
-                    (let ((i (gensym "I")))
-                      `(do ((,i (the index ,start) (truly-the index (1+ ,i))))
-                           ((>= ,i (more-count)))
-                         (declare (index ,i))
-                         (let ((,arg (sb!c:%more-arg ,',more-context ,i)))
-                           ,@body)))))
-         (defun ,name (,@head &more ,more-context ,more-count)
-           ,@body))
-       (setf (%simple-fun-arglist #',name) ',lambda-list))))
+;;; Signalling an error when trying to print an error condition is
+;;; generally a PITA, so whatever the failure encountered when
+;;; wondering about FILE-POSITION within a condition printer, 'tis
+;;; better silently to give up than to try to complain.
+(defun file-position-or-nil-for-error (stream &optional (pos nil posp))
+  ;; Arguably FILE-POSITION shouldn't be signalling errors at all; but
+  ;; "NIL if this cannot be determined" in the ANSI spec doesn't seem
+  ;; absolutely unambiguously to prohibit errors when, e.g., STREAM
+  ;; has been closed so that FILE-POSITION is a nonsense question. So
+  ;; my (WHN) impression is that the conservative approach is to
+  ;; IGNORE-ERRORS. (I encountered this failure from within a homebrew
+  ;; defsystemish operation where the ERROR-STREAM had been CL:CLOSEd,
+  ;; I think by nonlocally exiting through a WITH-OPEN-FILE, by the
+  ;; time an error was reported.)
+  (if posp
+      (ignore-errors (file-position stream pos))
+      (ignore-errors (file-position stream))))
+
+(defun stream-error-position-info (stream &optional position)
+  (unless (interactive-stream-p stream)
+    (let ((now (file-position-or-nil-for-error stream))
+          (pos position))
+      (when (and (not pos) now (plusp now))
+        ;; FILE-POSITION is the next character -- error is at the previous one.
+        (setf pos (1- now)))
+      (let (lineno colno)
+        (when (and pos
+                   (< pos sb!xc:array-dimension-limit)
+                   (file-position stream :start))
+          (let ((string
+                  (make-string pos :element-type (stream-element-type stream))))
+            (when (= pos (read-sequence string stream))
+              ;; Lines count from 1, columns from 0. It's stupid and traditional.
+              (setq lineno (1+ (count #\Newline string))
+                    colno (- pos (or (position #\Newline string :from-end t) 0)))))
+          (file-position-or-nil-for-error stream now))
+        (remove-if-not #'second
+                       (list (list :line lineno)
+                             (list :column colno)
+                             (list :file-position pos)))))))