~ chicken-core (chicken-5) /extras.scm
Trap1;;; extras.scm - Optional non-standard extensions2;3; Copyright (c) 2008-2022, The CHICKEN Team4; Copyright (c) 2000-2007, Felix L. Winkelmann5; All rights reserved.6;7; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following8; conditions are met:9;10; Redistributions of source code must retain the above copyright notice, this list of conditions and the following11; disclaimer.12; Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following13; disclaimer in the documentation and/or other materials provided with the distribution.14; Neither the name of the author nor the names of its contributors may be used to endorse or promote15; products derived from this software without specific prior written permission.16;17; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS18; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY19; AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR20; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR21; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR22; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY23; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR24; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE25; POSSIBILITY OF SUCH DAMAGE.262728(declare29 (unit extras)30 (uses data-structures))3132(module chicken.io33 (read-list read-buffered read-byte read-line34 read-lines read-string read-string! read-token35 write-byte write-line write-string)3637(import scheme chicken.base chicken.fixnum)3839(include "common-declarations.scm")404142;;; Read expressions from file:4344(define read-list45 (let ((read read))46 (lambda (#!optional (port ##sys#standard-input) (reader read) max)47 (##sys#check-input-port port #t 'read-list)48 (do ((x (reader port) (reader port))49 (i 0 (fx+ i 1))50 (xs '() (cons x xs)))51 ((or (eof-object? x) (and max (fx>= i max)))52 (##sys#fast-reverse xs))))))535455;;; Line I/O:5657(define read-line58 (let ()59 (lambda args60 (let* ([parg (pair? args)]61 [p (if parg (car args) ##sys#standard-input)]62 [limit (and parg (pair? (cdr args)) (cadr args))])63 (##sys#check-input-port p #t 'read-line)64 (cond ((##sys#slot (##sys#slot p 2) 8) => (lambda (rl) (rl p limit)))65 (else66 (let* ((buffer-len (if limit limit 256))67 (buffer (##sys#make-string buffer-len)))68 (let loop ([i 0])69 (if (and limit (fx>= i limit))70 (##sys#substring buffer 0 i)71 (let ([c (##sys#read-char-0 p)])72 (if (eof-object? c)73 (if (fx= i 0)74 c75 (##sys#substring buffer 0 i) )76 (case c77 [(#\newline) (##sys#substring buffer 0 i)]78 [(#\return)79 (let ([c (peek-char p)])80 (if (char=? c #\newline)81 (begin (##sys#read-char-0 p)82 (##sys#substring buffer 0 i))83 (##sys#substring buffer 0 i) ) ) ]84 [else85 (when (fx>= i buffer-len)86 (set! buffer87 (##sys#string-append buffer (make-string buffer-len)))88 (set! buffer-len (fx+ buffer-len buffer-len)) )89 (##core#inline "C_setsubchar" buffer i c)90 (loop (fx+ i 1)) ] ) ) ) ) ) ) ) ) ) ) ) )9192(define read-lines93 (lambda (#!optional (port ##sys#standard-input) max)94 (##sys#check-input-port port #t 'read-lines)95 (when max (##sys#check-fixnum max 'read-lines))96 (let loop ((lns '())97 (n (or max most-positive-fixnum)))98 (if (eq? n 0)99 (##sys#fast-reverse lns)100 (let ((ln (read-line port)))101 (if (eof-object? ln)102 (##sys#fast-reverse lns)103 (loop (cons ln lns) (fx- n 1))))))))104105(define write-line106 (lambda (str . port)107 (let* ((p (if (##core#inline "C_eqp" port '())108 ##sys#standard-output109 (##sys#slot port 0) ) ))110 (##sys#check-output-port p #t 'write-line)111 (##sys#check-string str 'write-line)112 ((##sys#slot (##sys#slot p 2) 3) p str) ; write-string method113 (##sys#write-char-0 #\newline p))))114115116;;; Extended I/O117118(define (read-string!/port n dest port start)119 (cond ((eq? n 0) 0)120 (else121 (let ((rdstring (##sys#slot (##sys#slot port 2) 7)))122 (if rdstring123 (let loop ((start start) (n n) (m 0))124 (let ((n2 (rdstring port n dest start)))125 (##sys#setislot port 5 ; update port-position126 (fx+ (##sys#slot port 5) n2))127 (cond ((eq? n2 0) m)128 ((or (not n) (fx< n2 n))129 (loop (fx+ start n2) (and n (fx- n n2)) (fx+ m n2)))130 (else (fx+ n2 m)))))131 (let loop ((start start) (n n) (m 0))132 (let ((n2 (let ((c (##sys#read-char-0 port)))133 (if (eof-object? c)134 0135 (begin136 (##core#inline "C_setsubchar" dest start c)137 1) ) ) ) )138 (cond ((eq? n2 0) m)139 ((or (not n) (fx< n2 n))140 (loop (fx+ start n2) (and n (fx- n n2)) (fx+ m n2)) )141 (else (fx+ n2 m))) )))))))142143(define (read-string! n dest #!optional (port ##sys#standard-input) (start 0))144 (##sys#check-input-port port #t 'read-string!)145 (##sys#check-string dest 'read-string!)146 (when n (##sys#check-fixnum n 'read-string!))147 (let ((dest-size (##sys#size dest)))148 (unless (and n (fx<= (fx+ start n) dest-size))149 (set! n (fx- dest-size start))))150 (##sys#check-fixnum start 'read-string!)151 (read-string!/port n dest port start))152153(define-constant read-string-buffer-size 2048)154155(define read-string/port156 (lambda (n p)157 (cond ((eq? n 0) "") ; Don't attempt to peek (fd might not be ready)158 ((eof-object? (##sys#peek-char-0 p)) #!eof)159 (n (let* ((str (##sys#make-string n))160 (n2 (read-string!/port n str p 0)))161 (if (eq? n n2)162 str163 (##sys#substring str 0 n2))))164 (else165 (let ([out (open-output-string)]166 (buf (make-string read-string-buffer-size)))167 (let loop ()168 (let ((n (read-string!/port read-string-buffer-size buf p 0)))169 (cond ((eq? n 0)170 (get-output-string out))171 (else172 (write-string buf n out)173 (loop))))))))))174175(define (read-string #!optional n (port ##sys#standard-input))176 (##sys#check-input-port port #t 'read-string)177 (when n (##sys#check-fixnum n 'read-string))178 (read-string/port n port))179180181;; Make internal reader procedures available for use in srfi-4.scm:182183(define chicken.io#read-string/port read-string/port)184(define chicken.io#read-string!/port read-string!/port)185186(define (read-buffered #!optional (port ##sys#standard-input))187 (##sys#check-input-port port #t 'read-buffered)188 (let ((rb (##sys#slot (##sys#slot port 2) 9))) ; read-buffered method189 (if rb190 (rb port)191 "")))192193194;;; read token of characters that satisfy a predicate195196(define read-token197 (lambda (pred . port)198 (let ([port (optional port ##sys#standard-input)])199 (##sys#check-input-port port #t 'read-token)200 (let ([out (open-output-string)])201 (let loop ()202 (let ([c (##sys#peek-char-0 port)])203 (if (and (not (eof-object? c)) (pred c))204 (begin205 (##sys#write-char-0 (##sys#read-char-0 port) out)206 (loop) )207 (get-output-string out) ) ) ) ) ) ) )208209(define write-string210 (lambda (s . more)211 (##sys#check-string s 'write-string)212 (let-optionals more ([n #f] [port ##sys#standard-output])213 (##sys#check-output-port port #t 'write-string)214 (when n (##sys#check-fixnum n 'write-string))215 ((##sys#slot (##sys#slot port 2) 3) ; write-string216 port217 (if (and n (fx< n (##sys#size s)))218 (##sys#substring s 0 n)219 s)))))220221222;;; Binary I/O223224(define (read-byte #!optional (port ##sys#standard-input))225 (##sys#check-input-port port #t 'read-byte)226 (let ((x (##sys#read-char-0 port)))227 (if (eof-object? x)228 x229 (char->integer x) ) ) )230231(define (write-byte byte #!optional (port ##sys#standard-output))232 (##sys#check-fixnum byte 'write-byte)233 (##sys#check-output-port port #t 'write-byte)234 (##sys#write-char-0 (integer->char byte) port) )235236) ; module chicken.io237238239;;; Pretty print:240;241; Copyright (c) 1991, Marc Feeley242; Author: Marc Feeley (feeley@iro.umontreal.ca)243; Distribution restrictions: none244;245; Modified by felix for use with CHICKEN246;247248(module chicken.pretty-print249 (pp pretty-print pretty-print-width)250251(import scheme chicken.base chicken.fixnum chicken.keyword chicken.string)252253(define generic-write254 (lambda (obj display? width output)255256 (define (read-macro? l)257 (define (length1? l) (and (pair? l) (null? (cdr l))))258 (let ((head (car l)) (tail (cdr l)))259 (case head260 ((quote quasiquote unquote unquote-splicing) (length1? tail))261 (else #f))))262263 (define (read-macro-body l)264 (cadr l))265266 (define (read-macro-prefix l)267 (let ((head (car l)) (tail (cdr l)))268 (case head269 ((quote) "'")270 ((quasiquote) "`")271 ((unquote) ",")272 ((unquote-splicing) ",@"))))273274 (define (out str col)275 (and col (output str) (+ col (string-length str))))276277 (define (wr obj col)278279 (define (wr-expr expr col)280 (if (read-macro? expr)281 (wr (read-macro-body expr) (out (read-macro-prefix expr) col))282 (wr-lst expr col)))283284 (define (wr-lst l col)285 (if (pair? l)286 (let loop ((l (cdr l))287 (col (and col (wr (car l) (out "(" col)))))288 (cond ((not col) col)289 ((pair? l)290 (loop (cdr l) (wr (car l) (out " " col))))291 ((null? l) (out ")" col))292 (else (out ")" (wr l (out " . " col))))))293 (out "()" col)))294295 (cond ((pair? obj) (wr-expr obj col))296 ((null? obj) (wr-lst obj col))297 ((eof-object? obj) (out "#!eof" col))298 ;; TODO: Remove once we have a bootstrapping libchicken with bwp-object?299 ((##core#inline "C_bwpp" obj) #;(bwp-object? obj) (out "#!bwp" col))300 ((vector? obj) (wr-lst (vector->list obj) (out "#" col)))301 ((boolean? obj) (out (if obj "#t" "#f") col))302 ((##sys#number? obj) (out (##sys#number->string obj) col))303 ((or (keyword? obj) (symbol? obj))304 (let ((s (open-output-string)))305 (##sys#print obj #t s)306 (out (get-output-string s) col) ) )307 ((procedure? obj) (out (##sys#procedure->string obj) col))308 ((string? obj)309 (if display?310 (out obj col)311 (let loop ((i 0) (j 0) (col (out "\"" col)))312 (if (and col (fx< j (string-length obj)))313 (let ((c (string-ref obj j)))314 (cond315 ((or (char=? c #\\)316 (char=? c #\"))317 (loop j318 (+ j 1)319 (out "\\"320 (out (##sys#substring obj i j)321 col))))322 ((or (char<? c #\x20)323 (char=? c #\x7f))324 (loop (fx+ j 1)325 (fx+ j 1)326 (let ((col2327 (out (##sys#substring obj i j) col)))328 (cond ((assq c '((#\tab . "\\t")329 (#\newline . "\\n")330 (#\return . "\\r")331 (#\vtab . "\\v")332 (#\page . "\\f")333 (#\alarm . "\\a")334 (#\backspace . "\\b")))335 =>336 (lambda (a)337 (out (cdr a) col2)))338 (else339 (out (number->string (char->integer c) 16)340 (out (if (char<? c #\x10) "0" "")341 (out "\\x" col2))))))))342 (else (loop i (fx+ j 1) col))))343 (out "\""344 (out (##sys#substring obj i j) col))))))345 ((char? obj) (if display?346 (out (make-string 1 obj) col)347 (let ([code (char->integer obj)])348 (out "#\\" col)349 (cond [(char-name obj)350 => (lambda (cn)351 (out (##sys#slot cn 1) col) ) ]352 [(fx< code 32)353 (out "x" col)354 (out (number->string code 16) col) ]355 [(fx> code 255)356 (out (if (fx> code #xffff) "U" "u") col)357 (out (number->string code 16) col) ]358 [else (out (make-string 1 obj) col)] ) ) ) )359 ((##core#inline "C_undefinedp" obj) (out "#<unspecified>" col))360 ((##core#inline "C_unboundvaluep" obj) (out "#<unbound value>" col))361 ((##core#inline "C_immp" obj) (out "#<unprintable object>" col))362 ((##core#inline "C_anypointerp" obj) (out (##sys#pointer->string obj) col))363 ((##sys#generic-structure? obj)364 (let ([o (open-output-string)])365 (##sys#user-print-hook obj #t o)366 (out (get-output-string o) col) ) )367 ((port? obj) (out (string-append "#<port " (##sys#slot obj 3) ">") col))368 ((##core#inline "C_bytevectorp" obj)369 (out "#${" col)370 (let ((len (##sys#size obj)))371 (do ((i 0 (fx+ i 1)))372 ((fx>= i len))373 (let ((b (##sys#byte obj i)))374 (when (fx< b 16)375 (out "0" col))376 (out (##sys#number->string b 16) col)))377 (out "}" col)))378 ((##core#inline "C_lambdainfop" obj)379 (out "#<lambda info " col)380 (out (##sys#lambda-info->string obj) col)381 (out ">" col) )382 (else (out "#<unprintable object>" col)) ) )383384 (define (pp obj col)385386 (define (spaces n col)387 (if (> n 0)388 (if (> n 7)389 (spaces (- n 8) (out " " col))390 (out (##sys#substring " " 0 n) col))391 col))392393 (define (indent to col)394 (and col395 (if (< to col)396 (and (out (make-string 1 #\newline) col) (spaces to 0))397 (spaces (- to col) col))))398399 (define (pr obj col extra pp-pair)400 (if (or (pair? obj) (vector? obj)) ; may have to split on multiple lines401 (let ((result '())402 (left (max (+ (- (- width col) extra) 1) max-expr-width)))403 (generic-write obj display? #f404 (lambda (str)405 (set! result (cons str result))406 (set! left (- left (string-length str)))407 (> left 0)))408 (if (> left 0) ; all can be printed on one line409 (out (reverse-string-append result) col)410 (if (pair? obj)411 (pp-pair obj col extra)412 (pp-list (vector->list obj) (out "#" col) extra pp-expr))))413 (wr obj col)))414415 (define (pp-expr expr col extra)416 (if (read-macro? expr)417 (pr (read-macro-body expr)418 (out (read-macro-prefix expr) col)419 extra420 pp-expr)421 (let ((head (car expr)))422 (if (symbol? head)423 (let ((proc (style head)))424 (if proc425 (proc expr col extra)426 (if (> (string-length (##sys#symbol->string head))427 max-call-head-width)428 (pp-general expr col extra #f #f #f pp-expr)429 (pp-call expr col extra pp-expr))))430 (pp-list expr col extra pp-expr)))))431432 ; (head item1433 ; item2434 ; item3)435 (define (pp-call expr col extra pp-item)436 (let ((col* (wr (car expr) (out "(" col))))437 (and col438 (pp-down (cdr expr) col* (+ col* 1) extra pp-item))))439440 ; (item1441 ; item2442 ; item3)443 (define (pp-list l col extra pp-item)444 (let ((col (out "(" col)))445 (pp-down l col col extra pp-item)))446447 (define (pp-down l col1 col2 extra pp-item)448 (let loop ((l l) (col col1))449 (and col450 (cond ((pair? l)451 (let ((rest (cdr l)))452 (let ((extra (if (null? rest) (+ extra 1) 0)))453 (loop rest454 (pr (car l) (indent col2 col) extra pp-item)))))455 ((null? l)456 (out ")" col))457 (else458 (out ")"459 (pr l460 (indent col2 (out "." (indent col2 col)))461 (+ extra 1)462 pp-item)))))))463464 (define (pp-general expr col extra named? pp-1 pp-2 pp-3)465466 (define (tail1 rest col1 col2 col3)467 (if (and pp-1 (pair? rest))468 (let* ((val1 (car rest))469 (rest (cdr rest))470 (extra (if (null? rest) (+ extra 1) 0)))471 (tail2 rest col1 (pr val1 (indent col3 col2) extra pp-1) col3))472 (tail2 rest col1 col2 col3)))473474 (define (tail2 rest col1 col2 col3)475 (if (and pp-2 (pair? rest))476 (let* ((val1 (car rest))477 (rest (cdr rest))478 (extra (if (null? rest) (+ extra 1) 0)))479 (tail3 rest col1 (pr val1 (indent col3 col2) extra pp-2)))480 (tail3 rest col1 col2)))481482 (define (tail3 rest col1 col2)483 (pp-down rest col2 col1 extra pp-3))484485 (let* ((head (car expr))486 (rest (cdr expr))487 (col* (wr head (out "(" col))))488 (if (and named? (pair? rest))489 (let* ((name (car rest))490 (rest (cdr rest))491 (col** (wr name (out " " col*))))492 (tail1 rest (+ col indent-general) col** (+ col** 1)))493 (tail1 rest (+ col indent-general) col* (+ col* 1)))))494495 (define (pp-expr-list l col extra)496 (pp-list l col extra pp-expr))497498 (define (pp-lambda expr col extra)499 (pp-general expr col extra #f pp-expr-list #f pp-expr))500501 (define (pp-if expr col extra)502 (pp-general expr col extra #f pp-expr #f pp-expr))503504 (define (pp-cond expr col extra)505 (pp-call expr col extra pp-expr-list))506507 (define (pp-case expr col extra)508 (pp-general expr col extra #f pp-expr #f pp-expr-list))509510 (define (pp-and expr col extra)511 (pp-call expr col extra pp-expr))512513 (define (pp-let expr col extra)514 (let* ((rest (cdr expr))515 (named? (and (pair? rest) (symbol? (car rest)))))516 (pp-general expr col extra named? pp-expr-list #f pp-expr)))517518 (define (pp-begin expr col extra)519 (pp-general expr col extra #f #f #f pp-expr))520521 (define (pp-do expr col extra)522 (pp-general expr col extra #f pp-expr-list pp-expr-list pp-expr))523524 ;; define formatting style (change these to suit your style)525526 (define indent-general 2)527528 (define max-call-head-width 5)529530 (define max-expr-width 50)531532 (define (style head)533 (case head534 ((lambda let* letrec letrec* define) pp-lambda)535 ((if set!) pp-if)536 ((cond) pp-cond)537 ((case) pp-case)538 ((and or) pp-and)539 ((let) pp-let)540 ((begin) pp-begin)541 ((do) pp-do)542 (else #f)))543544 (pr obj col 0 pp-expr))545546 (if width547 (out (make-string 1 #\newline) (pp obj 0))548 (wr obj 0))))549550; (pretty-print obj port) pretty prints 'obj' on 'port'. The current551; output port is used if 'port' is not specified.552553(define pretty-print-width (make-parameter 79))554555(define (pretty-print obj . opt)556 (let ((port (if (pair? opt) (car opt) (current-output-port))))557 (generic-write obj #f (pretty-print-width) (lambda (s) (display s port) #t))558 (##core#undefined) ) )559560(define pp pretty-print))561562563;;; Write simple formatted output:564565(module chicken.format566 (format fprintf printf sprintf)567568(import scheme chicken.base chicken.fixnum chicken.platform)569570(define fprintf0571 (lambda (loc port msg args)572 (when port (##sys#check-output-port port #t loc))573 (let ((out (if (and port (##sys#tty-port? port))574 port575 (open-output-string))))576 (let rec ([msg msg] [args args])577 (##sys#check-string msg loc)578 (let ((index 0)579 (len (##sys#size msg)) )580 (define (fetch)581 (let ((c (##core#inline "C_subchar" msg index)))582 (set! index (fx+ index 1))583 c) )584 (define (next)585 (if (##core#inline "C_eqp" args '())586 (##sys#error loc "too few arguments to formatted output procedure")587 (let ((x (##sys#slot args 0)))588 (set! args (##sys#slot args 1))589 x) ) )590 (let loop ()591 (unless (fx>= index len)592 (let ((c (fetch)))593 (if (and (eq? c #\~) (fx< index len))594 (let ((dchar (fetch)))595 (case (char-upcase dchar)596 ((#\S) (write (next) out))597 ((#\A) (display (next) out))598 ((#\C) (##sys#write-char-0 (next) out))599 ((#\B) (display (##sys#number->string (next) 2) out))600 ((#\O) (display (##sys#number->string (next) 8) out))601 ((#\X) (display (##sys#number->string (next) 16) out))602 ((#\!) (##sys#flush-output out))603 ((#\?)604 (let* ([fstr (next)]605 [lst (next)] )606 (##sys#check-list lst loc)607 (rec fstr lst) out) )608 ((#\~) (##sys#write-char-0 #\~ out))609 ((#\% #\N) (newline out))610 (else611 (if (char-whitespace? dchar)612 (let skip ((c (fetch)))613 (if (char-whitespace? c)614 (skip (fetch))615 (set! index (fx- index 1)) ) )616 (##sys#error loc "illegal format-string character" dchar) ) ) ) )617 (##sys#write-char-0 c out) )618 (loop) ) ) ) ) )619 (cond ((not port) (get-output-string out))620 ((not (eq? out port))621 (##sys#print (get-output-string out) #f port) ) ) ) ) )622623(define (fprintf port fstr . args)624 (fprintf0 'fprintf port fstr args) )625626(define (printf fstr . args)627 (fprintf0 'printf ##sys#standard-output fstr args) )628629(define (sprintf fstr . args)630 (fprintf0 'sprintf #f fstr args) )631632(define format633 (lambda (fmt-or-dst . args)634 (apply (cond [(not fmt-or-dst) sprintf]635 [(boolean? fmt-or-dst) printf]636 [(string? fmt-or-dst) (set! args (cons fmt-or-dst args)) sprintf]637 [(output-port? fmt-or-dst) (set! args (cons fmt-or-dst args)) fprintf]638 [else639 (##sys#error 'format "illegal destination" fmt-or-dst args)])640 args) ) )641642(register-feature! 'srfi-28))643644645;;; Random numbers:646647(module chicken.random648 (set-pseudo-random-seed! pseudo-random-integer pseudo-random-real random-bytes)649650(import scheme chicken.base chicken.time chicken.io chicken.foreign)651652(define (set-pseudo-random-seed! buf #!optional n)653 (cond (n (##sys#check-fixnum n 'set-pseudo-random-seed!)654 (when (##core#inline "C_fixnum_lessp" n 0)655 (##sys#error 'set-pseudo-random-seed! "invalid size" n)))656 (else (set! n (##sys#size buf))))657 (unless (##core#inline "C_byteblockp" buf)658 (##sys#error 'set-pseudo-random-seed! "invalid buffer type" buf))659 (##core#inline "C_set_random_seed" buf660 (##core#inline "C_i_fixnum_min"661 n662 (##sys#size buf))))663664(define (pseudo-random-integer n)665 (cond ((##core#inline "C_fixnump" n)666 (##core#inline "C_random_fixnum" n))667 ((not (##core#inline "C_i_bignump" n))668 (##sys#error 'pseudo-random-integer "bad argument type" n))669 (else670 (##core#inline_allocate ("C_s_a_u_i_random_int" 2) n))))671672(define (pseudo-random-real)673 (##core#inline_allocate ("C_a_i_random_real" 2)))674675(define random-bytes676 (let ((nstate (foreign-value "C_RANDOM_STATE_SIZE" unsigned-int)))677 (lambda (#!optional buf size)678 (when size679 (##sys#check-fixnum size 'random-bytes)680 (when (< size 0)681 (##sys#error 'random-bytes "invalid size" size)))682 (let* ((dest (cond (buf683 (when (or (##sys#immediate? buf)684 (not (##core#inline "C_byteblockp" buf)))685 (##sys#error 'random-bytes686 "invalid buffer type" buf))687 buf)688 (else (make-string (or size nstate)))))689 (r (##core#inline "C_random_bytes" dest690 (or size (##sys#size dest)))))691 (unless r692 (##sys#error 'random-bytes "unable to read random bytes"))693 (unless (eq? buf dest)694 (##core#inline "C_string_to_bytevector" dest))695 dest))))696697)