Allegro 6.2 reports source position of definitions by file-position, which does not properly account for line-ending encoding. This means that a file with carriage returns will cause all reported positions to appear to be offset from the actual definition in the emacs buffer. This is assuming that your emacs is properly understanding the line-ending encoding and is not displaying a bunch of ^Ms at the end of every line.
This quick hack counts the number of carriage returns that need to be subtracted from the file-position. It runs quickly enough on large (15msec to count CRs for 4481 lines in a file I am testing) files that I think it should be acceptable, unless someone has a better idea. I don't know if 7.0 has this problem as well; if not then this could be conditionalized.
diff -u -r1.61 swank-allegro.lisp --- swank-allegro.lisp 25 Oct 2004 16:17:11 -0000 1.61 +++ swank-allegro.lisp 18 Nov 2004 22:12:25 -0000 @@ -274,10 +274,22 @@ (symbol (string fspec)) (list (string (second fspec)))))
+(defun count-cr (file pos) + (let* ((bufsize 256) + (buf (make-array bufsize :element-type '(unsigned-byte 8))) + (cr-count 0)) + (with-open-file (stream file :direction :input) + (loop for bytes-read = (read-sequence buf stream) do + (incf cr-count (count (char-code #\return) buf + :end (min pos bytes-read))) + (decf pos bytes-read) + (when (<= pos 0) + (return cr-count)))))) + (defun find-definition-in-file (fspec type file) (let* ((start (scm:find-definition-in-file fspec type file)) (pos (if start - (list :position (1+ start)) + (list :position (1+ (- start (count-cr file start)))) (list :function-name (fspec-primary-name fspec))))) (make-location (list :file (namestring (truename file))) pos)))
Matthew Danish mrd+nospam@cmu.edu writes:
This quick hack counts the number of carriage returns that need to be subtracted from the file-position. It runs quickly enough on large (15msec to count CRs for 4481 lines in a file I am testing) files that I think it should be acceptable, unless someone has a better idea. I don't know if 7.0 has this problem as well; if not then this could be conditionalized.
The problem is the same with 7.0 if I open a file with DOS-style eol-conversion. At least on Linux. The Allegro manual says something about #\newline#\linefeed -> #newline conversion under Windows, but I didn't understand when exactly it is used. Let's use your patch until somebody encounters a real problem.
Helmut.
Helmut Eller e9626484@stud3.tuwien.ac.at writes:
Matthew Danish mrd+nospam@cmu.edu writes:
This quick hack counts the number of carriage returns that need to be subtracted from the file-position. It runs quickly enough on large (15msec to count CRs for 4481 lines in a file I am testing) files that I think it should be acceptable, unless someone has a better idea. I don't know if 7.0 has this problem as well; if not then this could be conditionalized.
The problem is the same with 7.0 if I open a file with DOS-style eol-conversion. At least on Linux. The Allegro manual says something about #\newline#\linefeed -> #newline conversion under Windows, but I didn't understand when exactly it is used. Let's use your patch until somebody encounters a real problem.
Well I'm pretty sure that what is happening is that READ-CHAR is doing the necessary transformation on the input stream to convert #\return#\linefeed to #\newline, but the source file recording mechanism is using FILE-POSITION to record the location of the form. If you run a simple test like this:
(defun test (file) (with-open-file (stream file :direction :input) (loop for char = (read-char stream nil nil) while char do (format t "~S ~S~%" char (file-position stream)))))
Then you will see that the file-position advances twice everytime #\Newline is encountered. The entry for FILE-POSITION in the Allegro documentation seems to indicate this as well.