Re: Some bug reports

JP Massar <[email protected]>
Newsgroups gmane.lisp.corman
Message-ID <[email protected]>
At 10:38 PM 2/21/03 +0100, Edi Weitz wrote:
>Here's a summary of some bug reports I just sent to Roger. I'll repeat
>them here FYI and to avoid duplicate submissions.
>
>1. Bug report: PARSE-INTEGER hangs
>
>   ;; Corman Lisp 2.0  Copyright © 2002 Roger Corman. All rights reserved.
>   ;; Licensed to Edmund Weitz.
>   (parse-integer "" :junk-allowed t)
>   ;;; An error occurred in function ELT:
>   ;;; Error: Index out of range: 0
>   ;;; Entering Corman Lisp debug loop.
>   ;;; Use :C followed by an option to exit. Type :HELP for help.
>   ;;; Restart options:
>   ;;; 1   Abort to top level.
>   :c 1
>
>
>   ;;; Returning to top level loop.
>   (parse-integer "" :junk-allowed t :radix 16 :start 0)
>
>At this point Corman Lisp hangs and has to be killed. I've looked at
>the source code of PARSE-INTEGER but have no idea what might be the
>cause for this. I guess this must have something to do with how
>keyword arguments are processed.

Yeah, that is mind-boggling.  It doesn't get into the body of the function
at all.

Here is a (crudely) revised PARSE-INTEGER that seems to fix
the problems you mentioned along with a few others I found in
playing with it.

For some reason it also seems to fix the hang, at least on my machine.
I experimented with making a dummy function with the same lambda
list and no body, but it doesn't hang when given equivalent arguments.

------------------------------------

;;; Patch for PARSE-INTEGER
;;; Author:  JP Massar

(in-package :lisp)

(defun parse-integer (string
                       &key (start 0)
                            (end nil) ;; (length string))
                            (radix 10)
                            (junk-allowed nil)
                       &aux (result 0)
                            (state :initial)
                            (sign 1)
                            c)

   (let ((len (length string))
         (whitespace '(#\Space #\Tab #\Newline)))
     (flet ((whitespace? (x) (member x whitespace)))

       ;; First canonicalize the string so that we are always dealing
       ;; with a non-null string which begins and ends with non-whitespace.

       (when (null end) (setq end len))
       (cond
        ;; A substring was specifier
        ((or (not (zerop start)) (not (= end len)))
         (multiple-value-bind (val bound)
             (parse-integer (subseq string start end)
                            :radix radix :junk-allowed junk-allowed)
           (values val (+ bound start))
           ))
        ;; null or blank string
        ((or (zerop len) (not (find-if-not #'whitespace? string)))
         (if junk-allowed
             (values nil len)
           (error "Cannot parse null or blank string as an integer")))
        ;; Initial characters are whitespace
        ((whitespace? (char string 0))
         (let ((start-pos (position-if-not #'whitespace? string)))
           (multiple-value-bind (val bound)
               (parse-integer (string-trim whitespace string)
                              :radix radix :junk-allowed junk-allowed)
             (values val (+ bound start-pos))
             )))
        ;; Ending characters are whitespace
        ((whitespace? (char string (1- len)))
         (parse-integer (string-trim whitespace string)
                        :radix radix :junk-allowed junk-allowed))

        ;; Implement the original algorithm.

        (t

         ;; check for leading sign
         (setf c (char string start))
         (if (char= c #\-)
             (progn (setf sign -1) (incf start))
           (if (char= c #\+)
               (incf start)))

         (do* ((i start (+ i 1))
               (n 0))
             ((>= i end))
           (setq c (char string i))
           (setq n (digit-char-p c radix))
           (cond
            (n (progn
                 (cond
                  ((eq state :finished)
                   (if (not junk-allowed)
                       (error "Invalid integer parsed: ~A" string)
                     (progn (setq end i) (return)))))
                 (setq result (+ (* result radix) n))
                 (setq state :collecting)))

            ;; '(#\Newline #\Space #\Tab)
            ((member c (list (int-char 13) (int-char 32) (int-char 9)))
             (cond
              ((eq state :collecting) (setq state :finished))
              ((eq state :initial) nil)  ; don't do anything
              ((eq state :finished) nil)))
            (t
             (if (not junk-allowed)
                 (error "Invalid integer parsed: ~A" string)  ;; string
               (progn (setq end i) (return))))))

         (if (eq state :initial)
             (setq result nil)
           (setq result (* result sign)))
         (values result end))

        ))))


------------------------ Yahoo! Groups Sponsor ---------------------~-->
Get 128 Bit SSL Encryption!
http://us.click.yahoo.com/FpY02D/vN2EAA/xGHJAA/SyjtlB/TM
---------------------------------------------------------------------~->

To unsubscribe from this group, send an email to:
[email protected]

 

Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.