Ticket #568: 0001-Implement-fix-for-568-by-making-sys-scan-buffer-line.patch

File 0001-Implement-fix-for-568-by-making-sys-scan-buffer-line.patch, 9.8 KB (added by sjamaan, 11 years ago)

Fix

  • NEWS

    From 77afc0fcdd79dc08f8bea3b1ae4a30d97e0be721 Mon Sep 17 00:00:00 2001
    From: Peter Bex <peter.bex@xs4all.nl>
    Date: Sun, 3 Feb 2013 18:51:26 +0100
    Subject: [PATCH] Implement fix for #568 by making ##sys#scan-buffer-line aware
     of the edge case. Invert data fetching logic to prevent having to put all
     this complicated stuff in the read-line handler of each port type.
    
    The hacky workaround for chicken-install introduced by 2a2656cacadd3791c11d24b57742c1b37370a24c is reverted.
    ---
     NEWS               |  2 ++
     library.scm        | 71 ++++++++++++++++++++++++++++++++++++------------------
     posixunix.scm      | 59 +++++++++++++++++++--------------------------
     setup-download.scm |  5 +---
     tcp.scm            | 52 ++++++++++++++++++---------------------
     5 files changed, 100 insertions(+), 89 deletions(-)
    
    diff --git a/NEWS b/NEWS
    index ad77c58..8fbaefd 100644
    a b  
    44  - csc: added "-oi"/"-ot" options as alternatives to "-emit-inline-file"
    55    and "-emit-type-file", respectively; "-n" has been deprecated.
    66
     7- Core libraries
     8  - read-line no longer returns trailing CRs in rare cases on TCP ports (#568)
    79
    8104.8.1
    911
  • library.scm

    diff --git a/library.scm b/library.scm
    index 3cabd3d..c53c884 100644
    a b EOF 
    35453545              (end (if limit (fx+ pos limit) size)))
    35463546         (if (fx>= pos size)
    35473547             #!eof
    3548              (##sys#scan-buffer-line
    3549               buf
    3550               (if (fx> end size) size end)
    3551               pos
    3552               (lambda (pos2 next)
    3553                 (when (not (eq? pos2 next))
    3554                   (##sys#setislot p 4 (fx+ (##sys#slot p 4) 1)) )
    3555                 (let ((dest (##sys#make-string (fx- pos2 pos))))
    3556                   (##core#inline "C_substring_copy" buf dest pos pos2 0)
    3557                   (##sys#setislot p 10 next)
    3558                   dest) ) ) ) ) )
     3548             (receive (next line)
     3549                 (##sys#scan-buffer-line
     3550                  buf (if (fx> end size) size end) pos
     3551                  (lambda (pos) (values #f pos #f) ) )
     3552               (##sys#setislot p 4 (fx+ (##sys#slot p 4) 1)) ; lineno
     3553               (##sys#setislot p 10 next)
     3554               line) ) ) )
    35593555     (lambda (p)                        ; read-buffered
    35603556       (let ((pos (##sys#slot p 10))
    35613557             (string (##sys#slot p 12))
    EOF 
    35673563               buffered))))
    35683564     )))
    35693565
    3570 ; Invokes the eol handler when EOL or EOS is reached.
    3571 (define (##sys#scan-buffer-line buf limit pos k)
    3572   (let loop ((pos2 pos))
    3573     (if (fx>= pos2 limit)
    3574         (k pos2 pos2)
    3575         (let ((c (##core#inline "C_subchar" buf pos2)))
    3576           (cond ((eq? c #\newline) (k pos2 (fx+ pos2 1)))
    3577                 ((and (eq? c #\return)
    3578                       (fx> limit (fx+ pos2 1))
    3579                       (eq? (##core#inline "C_subchar" buf (fx+ pos2 1)) #\newline) )
    3580                  (k pos2 (fx+ pos2 2)) )
    3581                 (else (loop (fx+ pos2 1))) ) ) ) ) )
     3566;; Invokes the eos handler when EOS is reached to get more data.
     3567;; The eos-handler is responsible for stopping, either when EOF is hit or
     3568;; a user-supplied limit is reached (ie, it's indistinguishable from EOF)
     3569(define (##sys#scan-buffer-line buf limit start-pos eos-handler)
     3570  (define (copy&append buf offset pos old-line)
     3571    (let* ((old-line-len (##sys#size old-line))
     3572           (new-line (##sys#make-string (fx+ old-line-len (fx- pos offset)))))
     3573      (##core#inline "C_substring_copy" old-line new-line 0 old-line-len 0)
     3574      (##core#inline "C_substring_copy" buf new-line offset pos old-line-len)
     3575      new-line))
     3576  (let loop ((buf buf)
     3577             (offset start-pos)
     3578             (pos start-pos)
     3579             (limit limit)
     3580             (line ""))
     3581    (if (fx= pos limit)
     3582        (let ((line (copy&append buf offset pos line)))
     3583          (receive (buf offset limit) (eos-handler pos)
     3584            (if buf
     3585                (loop buf offset offset limit line)
     3586                (values offset line))))
     3587        (let ((c (##core#inline "C_subchar" buf pos)))
     3588          (cond ((eq? c #\newline)
     3589                 (values (fx+ pos 1) (copy&append buf offset pos line)))
     3590                ((and (eq? c #\return)  ; \r\n -> drop \r from string
     3591                      (fx> limit (fx+ pos 1))
     3592                      (eq? (##core#inline "C_subchar" buf (fx+ pos 1)) #\newline))
     3593                 (values (fx+ pos 2) (copy&append buf offset pos line)))
     3594                ((and (eq? c #\return)  ; Edge case (#568): \r{read}[\n|xyz]
     3595                      (fx= limit (fx+ pos 1)))
     3596                 (let ((line (copy&append buf offset pos line)))
     3597                   (receive (buf offset limit) (eos-handler pos)
     3598                     (if buf
     3599                         (if (eq? (##core#inline "C_subchar" buf offset) #\newline)
     3600                             (values (fx+ offset 1) line)
     3601                             ;; "Restore" \r we didn't copy, loop w/ new string
     3602                             (loop buf offset offset limit
     3603                                   (##sys#string-append line "\r")))
     3604                         ;; Restore \r here, too (when we reached EOF)
     3605                         (values offset (##sys#string-append line "\r"))))))
     3606                (else (loop buf offset (fx+ pos 1) limit line)) ) ) ) ) )
    35823607
    35833608(define (open-input-string string)
    35843609  (##sys#check-string string 'open-input-string)
  • posixunix.scm

    diff --git a/posixunix.scm b/posixunix.scm
    index 9de549f..251c400 100644
    a b EOF 
    13841384                                  m
    13851385                                  (loop n m start) ) ] ) ) )
    13861386                   (lambda (port limit) ; read-line
    1387                      (let loop ([str #f])
    1388                        (let ([bumper
    1389                               (lambda (cur ptr)
    1390                                 (let* ([cnt (fx- cur bufpos)]
    1391                                        [dest
    1392                                         (if (eq? 0 cnt)
    1393                                             (or str "")
    1394                                             (let ([dest (##sys#make-string cnt)])
    1395                                               (##core#inline "C_substring_copy"
    1396                                                              buf dest bufpos cur 0)
    1397                                               (##sys#setislot port 5
    1398                                                               (fx+ (##sys#slot port 5) cnt))
    1399                                               (if str
    1400                                                   (##sys#string-append str dest)
    1401                                                   dest ) ) ) ] )
    1402                                   (set! bufpos ptr)
    1403                                   (cond [(eq? cur ptr) ; no EOL encountered
    1404                                          (fetch)
    1405                                          (values dest (fx< bufpos buflen)) ]
    1406                                         [else ; at EOL
    1407                                          (##sys#setislot port 4 (fx+ (##sys#slot port 4) 1))
    1408                                          (##sys#setislot port 5 0)
    1409                                          (values dest #f) ] ) ) ) ] )
    1410                          (cond [(fx< bufpos buflen)
    1411                                 (let-values ([(dest cont?)
    1412                                               (##sys#scan-buffer-line buf buflen bufpos bumper)])
    1413                                   (if cont?
    1414                                       (loop dest)
    1415                                       dest ) ) ]
    1416                                [else
    1417                                 (fetch)
    1418                                 (if (fx< bufpos buflen)
    1419                                     (loop str)
    1420                                     #!eof) ] ) ) ) )
     1387                     (when (fx>= bufpos buflen)
     1388                       (fetch))
     1389                     (if (fx>= bufpos buflen)
     1390                         #!eof
     1391                         (let ((limit (or limit (##sys#fudge 21))))
     1392                           (receive (next line)
     1393                               (##sys#scan-buffer-line
     1394                                buf
     1395                                (fxmin buflen (fx+ bufpos limit))
     1396                                bufpos
     1397                                (lambda (pos)
     1398                                  (let ((nbytes (fx- pos bufpos)))
     1399                                    (cond ((fx>= nbytes limit)
     1400                                           (values #f pos #f))
     1401                                          (else
     1402                                           (set! limit (fx- limit nbytes))
     1403                                           (fetch)
     1404                                           (if (fx< bufpos buflen)
     1405                                               (values buf bufpos
     1406                                                       (fxmin buflen
     1407                                                              (fx+ bufpos limit)))
     1408                                               (values #f bufpos #f)))))))
     1409                             (##sys#setislot port 4 (fx+ (##sys#slot port 4) 1))
     1410                             (set! bufpos next)
     1411                             line)) ) )
    14211412                   (lambda (port)               ; read-buffered
    14221413                     (if (fx>= bufpos buflen)
    14231414                         ""
  • setup-download.scm

    diff --git a/setup-download.scm b/setup-download.scm
    index 449de81..5267b22 100644
    a b  
    402402
    403403  (define (read-chunks in)
    404404    (let get-chunks ([data '()])
    405       (let* ((szln (read-line in))
    406              ;;XXX workaround for "read-line" dropping the "\n" in certain situations
    407              ;;    (#568)
    408              (size (string->number (string-chomp szln "\r") 16)))
     405      (let ((size (string->number (read-line in) 16)))
    409406        (cond ((not size)
    410407               (error "invalid response from server - please try again"))
    411408              ((zero? size)
  • tcp.scm

    diff --git a/tcp.scm b/tcp.scm
    index 5072adf..d0657a4 100644
    a b EOF 
    429429                              m
    430430                              (loop n m start) ) ) ) ) )
    431431               (lambda (p limit)        ; read-line
    432                  (let loop ((str #f)
    433                             (limit (or limit (##sys#fudge 21))))
    434                    (cond ((fx< bufindex buflen)
    435                           (##sys#scan-buffer-line
    436                            buf
    437                            (fxmin buflen limit)
    438                            bufindex
    439                            (lambda (pos2 next)
    440                              (let* ((len (fx- pos2 bufindex))
    441                                     (dest (##sys#make-string len)))
    442                                (##core#inline "C_substring_copy" buf dest bufindex pos2 0)
    443                                (set! bufindex next)
    444                                (cond ((eq? pos2 limit) ; no line-terminator, hit limit
    445                                       (if str (##sys#string-append str dest) dest))
    446                                      ((eq? pos2 next) ; no line-terminator, hit buflen
    447                                       (read-input)
    448                                       (if (fx>= bufindex buflen)
    449                                           (or str "")
    450                                           (loop (if str (##sys#string-append str dest) dest)
    451                                                 (fx- limit len)) ) )
    452                                      (else
    453                                       (##sys#setislot p 4 (fx+ (##sys#slot p 4) 1))
    454                                       (if str (##sys#string-append str dest) dest)) ) ) ) ) )
    455                          (else
    456                           (read-input)
    457                           (if (fx< bufindex buflen)
    458                               (loop str limit)
    459                               #!eof) ) ) ) )
     432                 (when (fx>= bufindex buflen)
     433                   (read-input))
     434                 (if (fx>= bufindex buflen)
     435                     #!eof
     436                     (let ((limit (or limit (##sys#fudge 21))))
     437                       (receive (next line)
     438                           (##sys#scan-buffer-line
     439                            buf
     440                            (fxmin buflen (fx+ bufindex limit))
     441                            bufindex
     442                            (lambda (pos)
     443                              (let ((nbytes (fx- pos bufindex)))
     444                                (cond ((fx>= nbytes limit)
     445                                       (values #f pos #f))
     446                                      (else (read-input)
     447                                            (set! limit (fx- limit nbytes))
     448                                            (if (fx< bufindex buflen)
     449                                                (values buf bufindex
     450                                                        (fxmin buflen
     451                                                               (fx+ bufindex limit)))
     452                                                (values #f bufindex #f))))) ) )
     453                         (##sys#setislot p 4 (fx+ (##sys#slot p 4) 1)) ; lineno
     454                         (set! bufindex next)
     455                         line) )) )
    460456               (lambda (p)              ; read-buffered
    461457                 (if (fx>= bufindex buflen)
    462458                     ""