~ chicken-core (chicken-5) /csi.scm


   1;;;; csi.scm - Interpreter stub for CHICKEN
   2;
   3; Copyright (c) 2008-2022, The CHICKEN Team
   4; Copyright (c) 2000-2007, Felix L. Winkelmann
   5; All rights reserved.
   6;
   7; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
   8; conditions are met:
   9;
  10;   Redistributions of source code must retain the above copyright notice, this list of conditions and the following
  11;     disclaimer. 
  12;   Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
  13;     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 promote
  15;     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 EXPRESS
  18; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  19; AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
  20; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  21; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  23; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  24; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25; POSSIBILITY OF SUCH DAMAGE.
  26
  27
  28(declare
  29  (usual-integrations)
  30  (disable-interrupts)
  31  (always-bound ##sys#windows-platform)
  32  (foreign-declare #<<EOF
  33#include <signal.h>
  34
  35#if defined(HAVE_DIRECT_H)
  36# include <direct.h>
  37#else
  38# define _getcwd(buf, len)       NULL
  39#endif
  40EOF
  41) )
  42
  43(module chicken.csi
  44  (editor-command toplevel-command set-describer! default-evaluator)
  45
  46(import scheme
  47	chicken.base
  48	chicken.condition
  49	chicken.fixnum
  50	chicken.foreign
  51	chicken.format
  52	chicken.file
  53	chicken.gc
  54	chicken.internal
  55	chicken.io
  56	chicken.keyword
  57	chicken.load
  58	chicken.pathname
  59	chicken.platform
  60	chicken.port
  61	chicken.pretty-print
  62	chicken.process
  63	chicken.process-context
  64	chicken.repl
  65	chicken.sort
  66	chicken.string
  67	chicken.syntax
  68	chicken.time)
  69
  70(include "banner.scm")
  71(include "mini-srfi-1.scm")
  72
  73;;; Parameters:
  74
  75(define-constant init-file "csirc")
  76
  77(set! ##sys#repl-print-length-limit 2048)
  78(set! ##sys#features (cons #:csi ##sys#features))
  79(set! ##sys#notices-enabled #t)
  80
  81(define editor-command (make-parameter #f))
  82(define selected-frame #f)
  83
  84(define default-editor 
  85  (or (get-environment-variable "EDITOR")
  86      (get-environment-variable "VISUAL")
  87      (if (get-environment-variable "EMACS")
  88	  "emacsclient"
  89	  "vi")))			; shudder
  90
  91
  92;;; Print all sorts of information:
  93
  94(define (print-usage)
  95  (display #<<EOF
  96usage: csi [OPTION ...] [FILENAME ...]
  97
  98  `csi' is the CHICKEN interpreter.
  99  
 100  FILENAME is a Scheme source file name with optional extension. OPTION may be
 101  one of the following:
 102
 103    -h  -help                     display this text and exit
 104        -version                  display version and exit
 105        -release                  print release number and exit
 106    -i  -case-insensitive         enable case-insensitive reading
 107    -e  -eval EXPRESSION          evaluate given expression
 108    -p  -print EXPRESSION         evaluate and print result(s)
 109    -P  -pretty-print EXPRESSION  evaluate and print result(s) prettily
 110    -D  -feature SYMBOL           register feature identifier
 111        -no-feature SYMBOL        disable built-in feature identifier
 112    -q  -quiet                    do not print banner
 113
 114EOF
 115)
 116  (display #<#EOF
 117    -n  -no-init                  do not load initialization file #{#\`} #{init-file} #{#\'}
 118
 119EOF
 120)
 121  (display  #<<EOF
 122    -b  -batch                    terminate after command-line processing
 123    -w  -no-warnings              disable all warnings
 124    -K  -keyword-style STYLE      enable alternative keyword-syntax
 125                                   (prefix, suffix or none)
 126        -no-parentheses-synonyms  disables list delimiter synonyms
 127        -no-symbol-escape         disables support for escaped symbols
 128        -r5rs-syntax              disables the CHICKEN extensions to
 129                                   R5RS syntax
 130    -s  -script PATHNAME          use csi as interpreter for Scheme scripts
 131        -ss PATHNAME              same as `-s', but invoke `main' procedure
 132        -sx PATHNAME              same as `-s', but print each expression
 133                                   as it is evaluated
 134        -setup-mode               prefer the current directory when locating extensions
 135    -R  -require-extension NAME   require extension and import before
 136                                   executing code
 137    -I  -include-path PATHNAME    add PATHNAME to include path
 138    --                            ignore all following options
 139
 140EOF
 141) ) ;|  <--- for emacs font-lock
 142
 143(define (print-banner)
 144  (print +banner+ (chicken-version #t) "\n"))
 145
 146
 147;;; Chop terminating separator from pathname:
 148
 149(define (dirseparator? c)
 150  (or (and ##sys#windows-platform (char=? c #\\))
 151      (char=? c #\/)))
 152
 153(define chop-separator 
 154  (let ([substring substring] )
 155    (lambda (str)
 156      (let* ((len (sub1 (##sys#size str)))
 157	     (c (string-ref str len)))
 158	(if (and (fx> len 0) (dirseparator? c))
 159	    (substring str 0 len)
 160	    str) ) ) ) )
 161
 162
 163;;; Find script in PATH (only used for Windows/DOS):
 164
 165(define lookup-script-file 
 166  (let* ([buf (make-string 256)]
 167	 [_getcwd (foreign-lambda nonnull-c-string "_getcwd" scheme-pointer int)] )
 168    (define (addext name)
 169      (if (file-exists? name)
 170	  name
 171	  (let ([n2 (string-append name ".bat")])
 172	    (and (file-exists? n2) n2) ) ) )
 173    (define (string-index proc str1)
 174      (let ((len (##sys#size str1)))
 175	(let loop ((i 0))
 176	  (cond ((fx>= i len) #f)
 177		((proc (##core#inline "C_subchar" str1 i)) i)
 178		(else (loop (fx+ i 1))) ) ) ) )
 179    (lambda (name)
 180      (let ([path (get-environment-variable "PATH")])
 181	(and (> (##sys#size name) 0)
 182	     (cond [(dirseparator? (string-ref name 0)) (addext name)]
 183		   [(string-index dirseparator? name)
 184		    (let ((p (_getcwd buf 256)))
 185		      (addext (string-append (chop-separator p) "/" name)) ) ]
 186		   [(addext name)]
 187		   [else
 188		    (let ([name2 (string-append "/" name)])
 189		      (let loop ((ps (##sys#split-path path)))
 190			(and (pair? ps)
 191			     (let ([name2 (string-append (chop-separator (##sys#slot ps 0)) name2)])
 192			       (or (addext name2)
 193				   (loop (##sys#slot ps 1)) ) ) ) ) ) ] ) ) ) ) ) )
 194				   
 195
 196
 197;;; REPL history references:
 198
 199(define history-list (make-vector 32))
 200(define history-count 1)
 201
 202(define history-add
 203  (let ([vector-resize vector-resize])
 204    (lambda (vals)
 205      (let ([x (if (null? vals) (##sys#void) (##sys#slot vals 0))]
 206	    [size (##sys#size history-list)] )
 207	(when (fx>= history-count size)
 208	  (set! history-list (vector-resize history-list (fx* 2 size))) )
 209	(vector-set! history-list history-count x)
 210	(set! history-count (fx+ history-count 1))
 211	x) ) ) )
 212
 213(define (history-clear)
 214  (vector-fill! history-list (##sys#void)))
 215
 216(define history-show
 217  (let ((newline newline))
 218    (lambda ()
 219      (do ((i 1 (fx+ i 1)))
 220	  ((>= i history-count))
 221	(printf "#~a: " i)
 222	(##sys#with-print-length-limit
 223	 80
 224	 (lambda ()
 225	   (##sys#print (vector-ref history-list i) #t ##sys#standard-output)))
 226	(newline)))))
 227
 228(define (history-ref index)
 229  (let ([i (inexact->exact index)])
 230    (if (and (fx> i 0) (fx<= i history-count))
 231	(vector-ref history-list i) 
 232	(##sys#error "history entry index out of range" index) ) ) )
 233
 234;;; Reader hooks for REPL history:
 235
 236(define (register-repl-history!)
 237  (set! ##sys#user-read-hook
 238    (let ((old-hook ##sys#user-read-hook))
 239      (lambda (char port)
 240	(cond ((or (char=? #\) char) (char-whitespace? char))
 241	       `',(history-ref (fx- history-count 1)))
 242	      (else (old-hook char port))))))
 243  (set! ##sys#sharp-number-hook
 244    (lambda (port n) `',(history-ref n))))
 245
 246(repl-prompt
 247 (let ((sprintf sprintf))
 248   (lambda ()
 249     (sprintf "#;~A~A> "
 250       (let ((m (##sys#current-module)))
 251	 (if m
 252	     (sprintf "~a:" (##sys#module-name m))
 253	     ""))
 254       history-count))))
 255
 256
 257;;; Other REPL customizations:
 258
 259(define (tty-input?)
 260  (or (##core#inline "C_i_tty_forcedp")
 261      (##sys#tty-port? ##sys#standard-input)))
 262
 263(set! ##sys#read-prompt-hook
 264  (let ([old ##sys#read-prompt-hook])
 265    (lambda ()
 266      (when (tty-input?) (old)) ) ) )
 267
 268(define command-table '())
 269
 270(define (toplevel-command name proc #!optional help)
 271  (##sys#check-symbol name 'toplevel-command)
 272  (when help (##sys#check-string help 'toplevel-command))
 273  (cond ((assq name command-table) =>
 274	 (lambda (a)
 275	   (set-cdr! a (list proc help)) ))
 276	(else
 277	 (set! command-table (cons (list name proc help) command-table))))
 278  (##sys#void))
 279
 280(define default-evaluator
 281  (let ((eval eval)
 282	(load-noisily load-noisily)
 283	(read (lambda () (chicken.syntax#read-with-source-info (current-input-port)))) ; OBSOLETE - after bootstrapping we can get rid of this explicit namespacing
 284	(read-line read-line)
 285	(display display)
 286	(string-split string-split)
 287	(printf printf)
 288	(expand expand)
 289	(pretty-print pretty-print)
 290	(values values) )
 291    (lambda (form)
 292      (cond ((eof-object? form) (quit))
 293	    ((and (pair? form)
 294		  (eq? 'unquote (##sys#slot form 0)) )
 295	     (let ((cmd (cadr form)))
 296	       (cond ((assq cmd command-table) =>
 297		      (lambda (p)
 298			((cadr p))
 299			(##sys#void) ) )
 300		     (else
 301		      ;;XXX use `toplevel-command' to define as many as possible of these
 302		      (case cmd
 303			((x)
 304			 (let ([x (read)])
 305			   (pretty-print (strip-syntax (expand x)))
 306			   (##sys#void) ) )
 307			((p)
 308			 (let* ([x (read)]
 309				[xe (eval x)] )
 310			   (pretty-print xe)
 311			   (##sys#void) ) )
 312			((d)
 313			 (let* ([x (read)]
 314				[xe (eval x)] )
 315			   (describe xe) ) )
 316			((du)
 317			 (let* ([x (read)]
 318				[xe (eval x)] )
 319			   (dump xe) ) )
 320			((dur)
 321			 (let* ([x (read)]
 322				[n (read)]
 323				[xe (eval x)] 
 324				[xn (eval n)] )
 325			   (dump xe xn) ) )
 326			((r) (report))
 327			((q) (quit))
 328			((l)
 329			 (let ((fns (string-split (read-line))))
 330			   (for-each load fns)
 331			   (##sys#void) ) )
 332			((ln) 
 333			 (let ((fns (string-split (read-line))))
 334			   (for-each (cut load-noisily <> printer: (lambda (x) (pretty-print x) (print* "==> "))) fns)
 335			   (##sys#void) ) )
 336			((t)
 337			 (let ((x (read)))
 338			   (receive rs (time (eval x))
 339			     (history-add rs)
 340			     (apply values rs) ) ) )
 341			((exn) 
 342			 (when ##sys#last-exception
 343			   (history-add (list ##sys#last-exception))
 344			   (describe ##sys#last-exception) ) )
 345			((e)
 346			 (let ((r (system
 347				   (string-append 
 348				    (or (editor-command) default-editor)
 349				    " " (read-line)))))
 350			   (if (not (zero? r))
 351			       (printf "editor returned with non-zero exit status ~a" r))))
 352			((ch)
 353			 (history-clear)
 354			 (##sys#void))
 355			((h)
 356			 (history-show)
 357			 (##sys#void))
 358			((c)
 359			 (show-frameinfo selected-frame)
 360			 (##sys#void))
 361			((f)
 362			 (select-frame (read))
 363			 (##sys#void))
 364			((g)
 365			 (copy-from-frame (read)))
 366			((s)
 367			 (let* ((str (read-line))
 368				(r (system str)) )
 369			   (history-add (list r))
 370			   r) )
 371			((?)
 372			 (display 
 373			  "Toplevel commands:
 374
 375 ,?                Show this text
 376 ,p EXP            Pretty print evaluated expression EXP
 377 ,d EXP            Describe result of evaluated expression EXP
 378 ,du EXP           Dump data of expression EXP
 379 ,dur EXP N        Dump range
 380 ,q                Quit interpreter
 381 ,l FILENAME ...   Load one or more files
 382 ,ln FILENAME ...  Load one or more files and print result of each top-level expression
 383 ,r                Show system information
 384 ,h                Show history of expression results
 385 ,ch               Clear history of expression results
 386 ,e FILENAME       Run external editor
 387 ,s TEXT ...       Execute shell-command
 388 ,exn              Describe last exception
 389 ,c                Show call-chain of most recent error
 390 ,f N              Select frame N
 391 ,g NAME           Get variable NAME from current frame
 392 ,t EXP            Evaluate form and print elapsed time
 393 ,x EXP            Pretty print expanded expression EXP\n")
 394			 (for-each
 395			  (lambda (a) 
 396			    (let ((help (caddr a)))
 397			      (if help
 398				  (print #\space help)
 399				  (print " ," (car a)) ) ) )
 400			  command-table)
 401			 (##sys#void) )
 402			(else
 403			 (printf "undefined toplevel command ~s - enter `,?' for help~%" form) 
 404			 (##sys#void) ) ) ) ) ) )
 405	    (else
 406	     (receive rs (eval form)
 407	       (history-add rs)
 408	       (apply values rs) ) ) ) ) ) )
 409
 410
 411;;; Builtin toplevel commands:
 412
 413(toplevel-command
 414 'm 
 415 (let ((printf printf))
 416   (lambda ()
 417     (let ((name (read)))
 418       (cond ((not name)
 419	      (##sys#switch-module #f)
 420	      (printf "; resetting current module to toplevel~%"))
 421	     ((##sys#find-module (##sys#resolve-module-name name #f) #f) =>
 422	      (lambda (m)
 423		(##sys#switch-module m)
 424		(printf "; switching current module to `~a'~%" name)))
 425	     (else
 426	      (printf "undefined module `~a'~%" name))))))
 427 ",m MODULE         switch to module with name `MODULE'")
 428
 429
 430;;; Parse options from string:
 431
 432(define (parse-option-string str)
 433  (let ([ins (open-input-string str)])
 434    (map (lambda (o)
 435	   (if (string? o)
 436	       o
 437	       (let ([os (open-output-string)])
 438		 (write o os)
 439		 (get-output-string os) ) ) )
 440	 (handle-exceptions ex (##sys#error "invalid option syntax" str)
 441	   (do ([x (read ins) (read ins)]
 442		[xs '() (cons x xs)] )
 443	       ((eof-object? x) (reverse xs)) ) ) ) ) )
 444
 445
 446;;; Print status information:
 447
 448(define report
 449  (let ((printf printf)
 450	(sort sort)
 451	(with-output-to-port with-output-to-port)
 452	(current-output-port current-output-port) 
 453	(argv argv)
 454	(prefix (foreign-value "C_INSTALL_PREFIX" c-string)))
 455    (lambda port
 456      (with-output-to-port (if (pair? port) (car port) (current-output-port))
 457	(lambda ()
 458	  (gc)
 459	  (let ((sinfo (##sys#symbol-table-info))
 460		(minfo (memory-statistics))
 461		(interrupts (foreign-value "C_interrupts_enabled" bool))
 462		(fixed-heap (foreign-value "C_heap_size_is_fixed" bool))
 463		(downward-stack (foreign-value "C_STACK_GROWS_DOWNWARD" bool)))
 464	    (define (shorten n) (/ (truncate (* n 100)) 100))
 465	    (printf "Features:~%~%")
 466	    (let ((fs (sort (map keyword->string ##sys#features) string<?))
 467		  (c 0))
 468	      (for-each
 469	       (lambda (f)
 470		 (printf "  ~a" f)
 471		 (let* ((len (string-length f))
 472			(pad (- 16 len)))
 473		   (set! c (add1 c))
 474		   (when (<= pad 0)
 475		     (set! c (add1 c))
 476		     (set! pad (+ pad 18)))
 477		   (cond ((>= c 3)
 478			  (display "\n")
 479			  (set! c 0))
 480			 (else 
 481			  (display (make-string pad #\space))))))
 482	       fs))
 483	    (printf "~%~%~
 484                   Machine type:    \t~A (~A-bit)~%~
 485                   Software type:   \t~A~%~
 486                   Software version:\t~A~%~
 487                   Build platform:  \t~A~%~
 488                   Installation prefix:\t~A~%~
 489                   Extension installation location:\t~A~%~
 490                   Extension path:  \t~A~%~
 491                   Include path:    \t~A~%~
 492                   Keyword style:   \t~A~%~
 493                   Symbol-table load:\t~S~%  ~
 494                     Avg bucket length:\t~S~%  ~
 495                     Total symbol count:\t~S~%~
 496                   Memory:\theap size is ~S bytes~A with ~S bytes currently in use~%~  
 497                     nursery size is ~S bytes, stack grows ~A~%~
 498                   Command line:    \t~S~%"
 499		    (machine-type)
 500		    (foreign-value "C_WORD_SIZE" int)
 501		    (software-type)
 502		    (software-version)
 503		    (build-platform)
 504		    prefix
 505                    (installation-repository)
 506		    (repository-path)
 507		    ##sys#include-pathnames
 508		    (keyword->string (keyword-style))
 509		    (shorten (vector-ref sinfo 0))
 510		    (shorten (vector-ref sinfo 1))
 511		    (vector-ref sinfo 2)
 512		    (vector-ref minfo 0)
 513		    (if fixed-heap " (fixed)" "")
 514		    (vector-ref minfo 1)
 515		    (vector-ref minfo 2)
 516		    (if downward-stack "downward" "upward")
 517		    (argv))
 518	    (##sys#write-char-0 #\newline ##sys#standard-output)
 519	    (when interrupts (display "interrupts are enabled\n"))
 520	    (##core#undefined) ) ) ) ) ) )
 521
 522
 523;;; Describe & dump:
 524
 525(define bytevector-data
 526  '((u8vector "vector of unsigned bytes" u8vector-length u8vector-ref)
 527    (s8vector "vector of signed bytes" s8vector-length s8vector-ref)
 528    (u16vector "vector of unsigned 16-bit words" u16vector-length u16vector-ref)
 529    (s16vector "vector of signed 16-bit words" s16vector-length s16vector-ref)
 530    (u32vector "vector of unsigned 32-bit words" u32vector-length u32vector-ref)
 531    (s32vector "vector of signed 32-bit words" s32vector-length s32vector-ref)
 532    (u64vector "vector of unsigned 64-bit words" u64vector-length u64vector-ref)
 533    (s64vector "vector of signed 64-bit words" s64vector-length s64vector-ref)
 534    (f32vector "vector of 32-bit floats" f32vector-length f32vector-ref)
 535    (f64vector "vector of 64-bit floats" f64vector-length f64vector-ref) ) )
 536
 537(define (circular-list? x)
 538  (let lp ((x x) (lag x))
 539    (and (pair? x)
 540	 (let ((x (cdr x)))
 541	   (and (pair? x)
 542		(let ((x   (cdr x))
 543		      (lag (cdr lag)))
 544		  (or (eq? x lag) (lp x lag))))))))
 545
 546(define (improper-pairs? x)
 547  (let lp ((x x))
 548    (if (not (pair? x)) #f
 549       (or (eq? x (car x))
 550           (lp (cdr x))))))
 551
 552(define-constant max-describe-lines 40)
 553
 554(define describer-table (make-vector 37 '()))
 555
 556(define describe
 557  (let ([sprintf sprintf]
 558	[printf printf] 
 559	[fprintf fprintf]
 560	[length length]
 561	[list-ref list-ref]
 562	[string-ref string-ref])
 563    (lambda (x #!optional (out ##sys#standard-output))
 564      (define (descseq name plen pref start)
 565	(let ((len (fx- (plen x) start)))
 566	  (when name (fprintf out "~A of length ~S~%" name len))
 567	  (let loop1 ((i 0))
 568	    (cond ((fx>= i len))
 569		  ((fx>= i max-describe-lines)
 570		   (fprintf out "~% (~A elements not displayed)~%" (fx- len i)) )
 571		  (else
 572		   (let ((v (pref x (fx+ start i))))
 573		     (let loop2 ((n 1) (j (fx+ i (fx+ start 1))))
 574		       (cond ((fx>= j len)
 575			      (##sys#with-print-length-limit
 576			       1000
 577			       (lambda ()
 578				 (fprintf out " ~S: ~S" i v)))
 579			      (if (fx> n 1)
 580				  (fprintf out "\t(followed by ~A identical instance~a)~% ...~%" 
 581					   (fx- n 1)
 582					   (if (eq? n 2) "" "s"))
 583				  (newline out) )
 584			      (loop1 (fx+ i n)) )
 585			     ((eq? v (pref x j)) (loop2 (fx+ n 1) (fx+ j 1)))
 586			     (else (loop2 n len)) ) ) ) ) ) ) ) )
 587      (when (##sys#permanent? x)
 588	(fprintf out "statically allocated (0x~X) " (##sys#block-address x)) )
 589      (cond ((char? x)
 590	     (let ([code (char->integer x)])
 591	       (fprintf out "character ~S, code: ~S, #x~X, #o~O~%" x code code code) ) )
 592	    ((eq? x #t) (fprintf out "boolean true~%"))
 593	    ((eq? x #f) (fprintf out "boolean false~%"))
 594	    ((null? x) (fprintf out "empty list~%"))
 595            ((##core#inline "C_bwpp" x) 
 596             ;; TODO: replace with bwp-object? later
 597             (fprintf out "broken weak pointer~%"))
 598	    ((eof-object? x) (fprintf out "end-of-file object~%"))
 599	    ((eq? (##sys#void) x) (fprintf out "unspecified object~%"))
 600	    ((fixnum? x)
 601	     (fprintf out "exact immediate integer ~S~%  #x~X~%  #o~O~%  #b~B"
 602	       x x x x)
 603	     (let ([code (integer->char x)])
 604	       (when (fx< x #x10000) (fprintf out ", character ~S" code)) )
 605	     (##sys#write-char-0 #\newline ##sys#standard-output) )
 606	    ((bignum? x)
 607	     (fprintf out "exact large integer ~S~%  #x~X~%  #o~O~%  #b~B~%"
 608	       x x x x) )
 609	    ((##core#inline "C_unboundvaluep" x)
 610	     (fprintf out "unbound value~%"))
 611	    ((flonum? x) (fprintf out "inexact rational number ~S~%" x))
 612	    ((ratnum? x) (fprintf out "exact ratio ~S~%" x))
 613	    ((cplxnum? x) (fprintf out "~A complex number ~S~%"
 614			    (if (exact? x) "exact" "inexact") x))
 615	    ((number? x) (fprintf out "number ~S~%" x))
 616	    ((string? x) (descseq "string" ##sys#size string-ref 0))
 617	    ((vector? x) (descseq "vector" ##sys#size ##sys#slot 0))
 618	    ((keyword? x)
 619	     (fprintf out "keyword symbol with name ~s~%" 
 620	       (##sys#symbol->string x)))
 621	    ((symbol? x)
 622	     (unless (##sys#symbol-has-toplevel-binding? x)
 623	       (display "unbound " out))
 624	     (fprintf out "~asymbol with name ~S~%"
 625	       (if (##sys#interned-symbol? x) "" "uninterned ")
 626	       (##sys#symbol->string x))
 627	     (let ((plist (##sys#slot x 2)))
 628	       (unless (null? plist)
 629		 (display "  \nproperties:\n\n" out)
 630		 (do ((plist plist (cddr plist)))
 631		     ((null? plist))
 632		   (fprintf out "  ~s\t" (car plist))
 633		   (##sys#with-print-length-limit
 634		    1000
 635		    (lambda ()
 636		      (write (cadr plist) out) ) )
 637		   (newline out) ) ) ) )
 638	    ((or (circular-list? x) (improper-pairs? x))
 639	     (fprintf out "circular structure: ")
 640	     (let loop-print ((x x)
 641			      (cdr-refs (list x)))
 642	       (cond ((or (atom? x)
 643			  (null? x)) (printf "eol~%"))
 644		     ((memq (car x) cdr-refs)
 645		      (fprintf out "(circle)~%" ))
 646		     ((not (memq (car x) cdr-refs))
 647		      (fprintf out "~S -> " (car x))
 648		      (loop-print (cdr x) (cons (car x)  cdr-refs) )))))
 649	    ((list? x) (descseq "list" length list-ref 0))
 650	    ((pair? x) (fprintf out "pair with car ~S~%and cdr ~S~%" (car x) (cdr x)))
 651	    ((procedure? x)
 652	     (let ([len (##sys#size x)])
 653	       (descseq 
 654		(sprintf "procedure with code pointer 0x~X" (##sys#peek-unsigned-integer x 0))
 655		##sys#size ##sys#slot 1) ) )
 656	    ((port? x)
 657	     (fprintf out
 658		 "~A port of type ~A with name ~S and file pointer ~X~%"
 659	       (if (##sys#slot x 1) "input" "output")
 660	       (##sys#slot x 7)
 661	       (##sys#slot x 3)
 662	       (##sys#peek-unsigned-integer x 0) ) )
 663            ((not (##core#inline "C_blockp" x)) 
 664             ;; catch immediates here, as ##sys#locative? crashes on non-block
 665             (fprintf out "unknown immediate object~%"))
 666	    ((##sys#locative? x)
 667	     (fprintf out "locative~%  pointer ~X~%  index ~A~%  type ~A~%"
 668	       (##sys#peek-unsigned-integer x 0)
 669	       (##sys#slot x 1)
 670	       (case (##sys#slot x 2) 
 671		 ((0) "slot")
 672		 ((1) "char")
 673		 ((2) "u8vector")
 674		 ((3) "s8vector")
 675		 ((4) "u16vector")
 676		 ((5) "s16vector")
 677		 ((6) "u32vector")
 678		 ((7) "s32vector")
 679		 ((8) "u64vector")
 680		 ((9) "s64vector")
 681		 ((10) "f32vector")
 682		 ((11) "f64vector") ) ) )
 683	    ((##sys#pointer? x) (fprintf out "machine pointer ~X~%" (##sys#peek-unsigned-integer x 0)))
 684	    ((##sys#bytevector? x)
 685	     (let ([len (##sys#size x)])
 686	       (fprintf out "blob of size ~S:~%" len)
 687	       (hexdump x len ##sys#byte out) ) )
 688	    ((##core#inline "C_lambdainfop" x)
 689	     (fprintf out "lambda information: ~s~%" (##sys#lambda-info->string x)) )
 690	    ((##sys#structure? x 'hash-table)
 691	     (let ((n (##sys#slot x 2)))
 692	       (fprintf out "hash-table with ~S element~a~%  comparison procedure: ~A~%"
 693		 n (if (fx= n 1) "" "s")  (##sys#slot x 3)) )
 694	     (fprintf out "  hash function: ~a~%" (##sys#slot x 4))
 695	     ;; this copies code out of srfi-69.scm, but we don't want to depend on it
 696	     (let* ((vec (##sys#slot x 1))
 697		    (len (##sys#size vec)) )
 698	       (do ((i 0 (fx+ i 1)) )
 699		   ((fx>= i len))
 700		 (for-each
 701		  (lambda (bucket)
 702		    (fprintf out " ~S\t-> ~S~%"
 703		      (##sys#slot bucket 0) (##sys#slot bucket 1)) )
 704		  (##sys#slot vec i)) ) ) )
 705	    ((##sys#structure? x 'condition)
 706	     (fprintf out "condition: ~s~%" (##sys#slot x 1))
 707	     (for-each
 708	      (lambda (k)
 709		(fprintf out " ~s~%" k)
 710		(let loop ((props (##sys#slot x 2)))
 711		  (unless (null? props)
 712		    (when (eq? k (caar props))
 713		      (##sys#with-print-length-limit
 714		       100
 715		       (lambda ()
 716			 (fprintf out "\t~s: ~s" (cdar props) (cadr props)) ))
 717		      (newline out))
 718		    (loop (cddr props)) ) ) )
 719	      (##sys#slot x 1) ) )
 720	    ((##sys#generic-structure? x)
 721	     (let ([st (##sys#slot x 0)])
 722	       (cond ((hash-table-ref describer-table st) => (cut <> x out))
 723		     ((assq st bytevector-data) =>
 724		      (lambda (data)
 725			(apply descseq (append (map eval (cdr data)) (list 0)))) )
 726		     (else
 727		      (fprintf out "structure of type `~S':~%" (##sys#slot x 0))
 728		      (descseq #f ##sys#size ##sys#slot 1) ) ) ) )
 729	    (else (fprintf out "unknown object~%")) )
 730      (##sys#void) ) ) )
 731
 732(define (set-describer! tag proc)
 733  (##sys#check-symbol tag 'set-describer!)
 734  (hash-table-set! describer-table tag proc))
 735
 736
 737;;; Display hexdump:
 738
 739(define dump
 740  (lambda (x . len-out)
 741    (let-optionals len-out
 742	([len #f]
 743	 [out ##sys#standard-output] )
 744      (define (bestlen n) (if len (min len n) n))
 745      (cond [(##sys#immediate? x) (##sys#error 'dump "cannot dump immediate object" x)]
 746	    [(##sys#bytevector? x) (hexdump x (bestlen (##sys#size x)) ##sys#byte out)]
 747	    [(string? x) (hexdump x (bestlen (##sys#size x)) ##sys#byte out)]
 748	    [(and (not (##sys#immediate? x)) (##sys#pointer? x))
 749	     (hexdump x 32 ##sys#peek-byte out) ]
 750	    [(and (##sys#generic-structure? x) (assq (##sys#slot x 0) bytevector-data))
 751	     (let ([bv (##sys#slot x 1)])
 752	       (hexdump bv (bestlen (##sys#size bv)) ##sys#byte out) ) ]
 753	    [else (##sys#error 'dump "cannot dump object" x)] ) ) ) )
 754
 755(define hexdump
 756  (let ([display display]
 757	[string-append string-append]
 758	[make-string make-string]
 759	[write-char write-char] )
 760    (lambda (bv len ref out)
 761
 762      (define (justify n m base lead)
 763	(let* ([s (number->string n base)]
 764	       [len (##sys#size s)] )
 765	  (if (fx< len m)
 766	      (string-append (make-string (fx- m len) lead) s)
 767	      s) ) )
 768
 769      (do ([a 0 (fx+ a 16)])
 770	  ((fx>= a len))
 771	(display (justify a 4 10 #\space) out)
 772	(write-char #\: out)
 773	(do ([j 0 (fx+ j 1)]
 774	     [a a (fx+ a 1)] )
 775	    ((or (fx>= j 16) (fx>= a len))
 776	     (when (fx>= a len)
 777	       (let ((o (fxmod len 16)))
 778		 (unless (fx= o 0)
 779		   (do ((k (fx- 16 o) (fx- k 1)))
 780		       ((fx= k 0))
 781		     (display "   " out) ) ) ) ) ) 
 782	  (write-char #\space out)
 783	  (display (justify (ref bv a) 2 16 #\0) out) )
 784	(write-char #\space out)
 785	(do ([j 0 (fx+ j 1)]
 786	     [a a (fx+ a 1)] )
 787	    ((or (fx>= j 16) (fx>= a len)))
 788	  (let ([c (ref bv a)])
 789	    (if (and (fx>= c 32) (fx< c 128))
 790		(write-char (integer->char c) out)
 791		(write-char #\. out) ) ) ) 
 792	(write-char #\newline out) ) ) ) )
 793
 794
 795;;; Frame-info operations:
 796
 797(define show-frameinfo
 798  (let ((newline newline)
 799	(display display))
 800    (lambda (fn)
 801      (define (prin1 x)
 802	(##sys#with-print-length-limit
 803	 100
 804	 (lambda ()
 805	   (##sys#print x #t ##sys#standard-output))))
 806      (let* ((ct (or ##sys#repl-recent-call-chain '()))
 807	     (len (length ct)))
 808	(set! selected-frame 
 809	  (or (and (memq fn ct) fn)
 810	      (and (fx> len 0)
 811		   (list-ref ct (fx- len 1)))))
 812	(do ((ct ct (cdr ct))
 813	     (i (fx- len 1) (fx- i 1)))
 814	    ((null? ct))
 815	  (let* ((info (car ct))
 816		 (here (eq? selected-frame info))
 817		 (form (##sys#slot info 1)) ; cooked1 (expr/form)
 818		 (data (##sys#slot info 2)) ; cooked2 (cntr/frameinfo)
 819		 (finfo (##sys#structure? data 'frameinfo))
 820		 (cntr (if finfo (##sys#slot data 1) data))) ; cntr
 821	    (printf "~a~a:~a\t~a\t  " 
 822	      (if here #\* #\space)
 823	      i
 824	      (if (and finfo (pair? (##sys#slot data 2))) "[]" "  ") ; e
 825	      (##sys#slot info 0))	; raw
 826	    (when cntr (printf "[~a] " cntr))
 827	    (when form (prin1 form))
 828	    (newline)
 829	    (when (and here finfo)
 830	      (for-each
 831	       (lambda (e v)
 832		 (unless (null? e)
 833		   (display "  ---\n")
 834		   (do ((i 0 (fx+ i 1))
 835			(be e (cdr be)))
 836		       ((null? be))
 837		     (printf "  ~s:\t  " (car be))
 838		     (prin1 (##sys#slot v i))
 839		     (newline))))
 840	       (##sys#slot data 2)	   ; e
 841	       (##sys#slot data 3)))))))))	   ; v
 842	  
 843(define select-frame
 844  (let ((display display))
 845    (lambda (n)
 846      (cond ((or (not (number? n))
 847		 (not ##sys#repl-recent-call-chain)
 848		 (fx< n 0)
 849		 (fx>= n (length ##sys#repl-recent-call-chain)))
 850	     (display "no such frame\n"))
 851	    (else
 852	     (set! selected-frame
 853	       (list-ref 
 854		##sys#repl-recent-call-chain
 855		(fx- (length ##sys#repl-recent-call-chain) (fx+ n 1))))
 856	     (show-frameinfo selected-frame))))))
 857
 858(define copy-from-frame
 859  (let ((display display)
 860	(newline newline)
 861	(call/cc call/cc))
 862    (lambda (name)
 863      (let* ((ct (or ##sys#repl-recent-call-chain '()))
 864	     (len (length ct))
 865	     (name 
 866	      (cond ((symbol? name) (##sys#slot name 1)) ; name
 867		    ((string? name) name)
 868		    (else 
 869		     (display "string or symbol required for `,g'\n")
 870		     #f))))
 871	(define (compare sym)
 872	  (let ((str (##sys#slot sym 1))) ; name
 873	    (string=?
 874	     name
 875	     (substring str 0 (min (string-length name) (string-length str))))))
 876	(if name
 877	    (call/cc
 878	     (lambda (return)
 879	       (define (fail msg)
 880		 (display msg)
 881		 (newline)
 882		 (return (##sys#void)))
 883	       (do ((ct ct (cdr ct)))
 884		   ((null? ct) (fail "no environment in frame")) 
 885		 ;;XXX this should be refactored as it duplicates the code above
 886		 (let* ((info (car ct))
 887			(here (eq? selected-frame info))
 888			(data (##sys#slot info 2)) ; cooked2 (cntr/frameinfo)
 889			(finfo (##sys#structure? data 'frameinfo)))
 890		   (when (and here finfo)
 891		     (for-each
 892		      (lambda (e v)
 893			(do ((i 0 (fx+ i 1))
 894			     (be e (cdr be)))
 895			    ((null? be))
 896			  (when (compare (car be))
 897			    (display "; getting ")
 898			    (display (car be))
 899			    (newline)
 900			    (history-add (list (##sys#slot v i)))
 901			    (return (##sys#slot v i)))))
 902		      (##sys#slot data 2)	; e
 903		      (##sys#slot data 3))	; v
 904		     (fail (##sys#string-append "no such variable: " name)))))))
 905	    (##sys#void))))))
 906
 907
 908;;; Handle some signals:
 909
 910(define-foreign-variable _sigint int "SIGINT")
 911
 912(define-syntax defhandler 
 913  (syntax-rules ()
 914    ((_ sig handler)
 915     (begin
 916       (##core#inline "C_establish_signal_handler" sig sig)
 917       (##sys#setslot ##sys#signal-vector sig handler)))))
 918
 919(defhandler _sigint (lambda (n) (##sys#user-interrupt-hook)))
 920
 921
 922;;; Start interpreting:
 923
 924(define (member* keys set)
 925  (let loop ((set set))
 926    (and (pair? set)
 927	 (let find ((ks keys))
 928	   (cond ((null? ks) (loop (cdr set)))
 929		 ((equal? (car ks) (car set)) set)
 930		 (else (find (cdr ks))) ) ) ) ) )
 931
 932(define-constant short-options 
 933  '(#\k #\s #\h #\D #\e #\i #\R #\b #\n #\q #\w #\- #\I #\p #\P #\K) )
 934
 935(define-constant long-options
 936  '("-ss" "-sx" "-script" "-version" "-help" "--help" "-feature" "-no-feature" "-eval"
 937    "-case-insensitive" "-keyword-style" "-no-parentheses-synonyms" "-no-symbol-escape"
 938    "-r5rs-syntax" "-setup-mode"
 939    "-require-extension" "-batch" "-quiet" "-no-warnings" "-no-init" 
 940    "-include-path" "-release" "-print" "-pretty-print" "--") )
 941
 942(define (canonicalize-args args)
 943  (let loop ((args args))
 944    (if (null? args)
 945	'()
 946	(let ((x (car args)))
 947	  (cond ((member x '("-s" "-ss" "-script" "-sx" "--")) args)
 948                ((and (fx= (##sys#size x) 2)
 949                      (char=? #\- (##core#inline "C_subchar" x 0)))
 950                 (if (memq (##core#inline "C_subchar" x 1) short-options)
 951                     (cons x (loop (cdr args)))
 952                     (##sys#error "invalid option" x)))
 953                ((and (fx> (##sys#size x) 2)
 954                       (char=? #\- (##core#inline "C_subchar" x 0))
 955                       (not (member x long-options)) )
 956                 (if (char=? #\: (##core#inline "C_subchar" x 1))
 957                     (loop (cdr args))
 958                     (let ((cs (string->list (substring x 1))))
 959                       (if (findall cs short-options)
 960                           (append (map (cut string #\- <>) cs) (loop (cdr args)))
 961                           (##sys#error "invalid option" x) ) ) ) )
 962	        (else (cons x (loop (cdr args)))))))))
 963
 964(define (findall chars clist)
 965  (let loop ((chars chars))
 966    (or (null? chars)
 967	(and (memq (car chars) clist)
 968	     (loop (cdr chars))))))
 969
 970(define-constant simple-options
 971  '("--" "-b" "-batch" "-q" "-quiet" "-n" "-no-init" "-w" "-no-warnings" 
 972    "-i" "-case-insensitive"
 973    "-no-parentheses-synonyms" "-no-symbol-escape" "-r5rs-syntax" "-setup-mode"
 974    ; Not "simple" but processed early
 975    "-ss" "-sx" "-s" "-script") )
 976
 977(define-constant complex-options
 978  '("-D" "-feature" "-I" "-include-path" "-K" "-keyword-style" "-no-feature") )
 979
 980(define (string-trim str)
 981  (let loop ((front 0)
 982	     (back (string-length str)))
 983    (cond ((= front back) "")
 984	  ((char-whitespace? (string-ref str front))
 985	   (loop (add1 front) back))
 986	  ((char-whitespace? (string-ref str (sub1 back)))
 987	   (loop front (sub1 back)))
 988	  (else (substring str front back)))))
 989   
 990(define (string->extension-name str)
 991  (let ((str (string-trim str)))
 992    (if (and (positive? (string-length str))
 993             (char=? #\( (string-ref str 0)))
 994        (handle-exceptions ex 
 995          (##sys#error "invalid import specification" str)
 996          (with-input-from-string str read))
 997        (string->symbol str))))
 998
 999(define (run)
 1000  (let* ([extraopts (parse-option-string (or (get-environment-variable "CSI_OPTIONS") ""))]
1001	 [args (canonicalize-args (command-line-arguments))]
1002	 ; Check for these before 'args' is updated by any 'extraopts'
1003	 [kwstyle (member* '("-K" "-keyword-style") args)]
1004	 [script (member* '("-ss" "-sx" "-s" "-script") args)])
1005    (cond [script
1006	   (when (or (not (pair? (cdr script)))
1007		     (zero? (string-length (cadr script)))
1008		     (char=? #\- (string-ref (cadr script) 0)) )
1009	     (##sys#error "missing or invalid script argument"))
1010	   (program-name (cadr script))
1011	   (command-line-arguments (cddr script))
1012	   ;; 2012-10-04 (felix) left 'script activated to avoid breaking too much code
1013	   (register-feature! 'chicken-script)
1014	   (set-cdr! (cdr script) '()) 
1015	   (when ##sys#windows-platform
1016	     (and-let* ((sname (lookup-script-file (cadr script))))
1017	       (set-car! (cdr script) sname) ) ) ]
1018	  [else
1019	   (set! args (append (canonicalize-args extraopts) args))
1020	   (and-let* ([p (member "--" args)])
1021	     (set-cdr! p '()) ) ] )
1022    (let* ([eval? (member* '("-e" "-p" "-P" "-eval" "-print" "-pretty-print") args)]
1023	   [batch (or script (member* '("-b" "-batch") args) eval?)]
1024	   [quietflag (member* '("-q" "-quiet") args)]
1025	   [quiet (or script quietflag eval?)])
1026      (define (collect-options opt)
1027	(let loop ([opts args])
1028	  (cond [(member opt opts)
1029		 => (lambda (p)
1030		      (if (null? (cdr p))
1031			  (##sys#error "missing argument to command-line option" opt)
1032			  (cons (cadr p) (loop (cddr p)))) ) ]
1033		[else '()] ) ) )
1034      (define (loadinit)
1035        (let* ((sys-dir (system-config-directory))
1036               (cfg-fn (and sys-dir (make-pathname (list sys-dir "chicken")
1037                                                   init-file)))
1038               (home (get-environment-variable "HOME"))
1039               (home-fn (and home (not (string=? home ""))
1040                             (make-pathname home (string-append "." init-file)))))
1041          (cond ((and cfg-fn (file-exists? cfg-fn))
1042                 (load cfg-fn))
1043                ((and home-fn (file-exists? home-fn))
1044                 (load home-fn) ) ) ) )
1045      (define (evalstring str #!optional (rec (lambda _ (void))))
1046	(let ((in (open-input-string str))
1047	      (read-with-source-info chicken.syntax#read-with-source-info)) ; OBSOLETE - after bootstrapping we can get rid of this explicit namespacing
1048	  (do ([x (read-with-source-info in) (read-with-source-info in)])
1049	      ((eof-object? x))
1050	    (rec (receive (eval x))) ) ) )
1051      (when (member* '("-h" "-help" "--help") args)
1052	(print-usage)
1053	(exit 0) )
1054      (when (member "-version" args)
1055	(print-banner)
1056	(exit 0) )
1057      (when (member "-setup-mode" args)
1058	(set! ##sys#setup-mode #t))
1059      (when (member "-release" args)
1060	(print (chicken-version))
1061	(exit 0) )
1062      (when (member* '("-w" "-no-warnings") args)
1063	(unless quiet (display "Warnings are disabled\n"))
1064	(set! ##sys#warnings-enabled #f) )
1065      (when (member* '("-i" "-case-insensitive") args)
1066	(unless quiet (display "Identifiers and symbols are case insensitive\n"))
1067	(register-feature! 'case-insensitive)
1068	(case-sensitive #f) )
1069      (for-each register-feature! (collect-options "-feature"))
1070      (for-each register-feature! (collect-options "-D"))
1071      (for-each unregister-feature! (collect-options "-no-feature"))
1072      (set! ##sys#include-pathnames
1073	(delete-duplicates
1074	 (append (map chop-separator (collect-options "-include-path"))
1075		 (map chop-separator (collect-options "-I"))
1076		 ##sys#include-pathnames)
1077	 string=?) )
1078      (when kwstyle
1079	(cond [(not (pair? (cdr kwstyle)))
1080	       (##sys#error "missing argument to `-keyword-style' option") ]
1081	      [(string=? "prefix" (cadr kwstyle))
1082	       (keyword-style #:prefix) ]
1083	      [(string=? "none" (cadr kwstyle))
1084	       (keyword-style #:none) ]
1085	      [(string=? "suffix" (cadr kwstyle))
1086	       (keyword-style #:suffix) ] ) )
1087      (when (member* '("-no-parentheses-synonyms") args)
1088	(unless quiet (display "Disabled support for parentheses synonyms\n"))
1089        (parentheses-synonyms #f) )
1090      (when (member* '("-no-symbol-escape") args)
1091	(unless quiet (display "Disabled support for escaped symbols\n"))
1092	(symbol-escape #f) )
1093      (when (member* '("-r5rs-syntax") args)
1094	(unless quiet (display "Disabled the CHICKEN extensions to R5RS syntax\n"))
1095	(case-sensitive #f)
1096	(keyword-style #:none)
1097	(parentheses-synonyms #f)
1098	(symbol-escape #f) )
1099      ;; Load the default modules into the evaluation environment.
1100      ;; This is done before setting load-verbose => #t to avoid
1101      ;; spurious import messages.
1102      (eval `(import-for-syntax ,@default-syntax-imports))
1103      (eval `(import ,@default-imports))
1104      (unless quiet
1105	(load-verbose #t)
1106	(print-banner)
1107	(print "Type ,? for help."))
1108      (unless (or (member* '("-n" "-no-init") args) script eval?)
1109	(loadinit))
1110      (when batch
1111	(set! ##sys#notices-enabled #f))
1112      (do ([args args (cdr args)])
1113	  ((null? args)
1114	   (register-repl-history!)
1115	   (unless batch
1116	     (repl default-evaluator)
1117	     (##sys#write-char-0 #\newline ##sys#standard-output) ) )
1118	(let* ((arg (car args)))
1119	  (cond ((member arg simple-options))
1120		((member arg complex-options)
1121		 (set! args (cdr args)) )
1122		((or (string=? "-R" arg) (string=? "-require-extension" arg))
1123		 (eval `(import ,(string->extension-name (cadr args))))
1124		 (set! args (cdr args)) )
1125		((or (string=? "-e" arg) (string=? "-eval" arg))
1126		 (evalstring (cadr args))
1127		 (set! args (cdr args)) )
1128		((or (string=? "-p" arg) (string=? "-print" arg))
1129		 (evalstring (cadr args) (cut for-each print <...>))
1130		 (set! args (cdr args)) )
1131		((or (string=? "-P" arg) (string=? "-pretty-print" arg))
1132		 (evalstring (cadr args) (cut for-each pretty-print <...>) )
1133		 (set! args (cdr args)) )
1134		(else
1135		 (let ((scr (and script (car script))))
1136		   (load
1137		    arg
1138		    (and (equal? "-sx" scr)
1139			 (lambda (x)
1140			   (let* ((str (with-output-to-string (cut pretty-print x)))
1141				  (len (string-length str)))
1142			     (flush-output ##sys#standard-output)
1143			     (display "\n; " ##sys#standard-error)
1144			     (do ((i 0 (fx+ i 1)))
1145				 ((fx>= i len))
1146			       (let ((c (string-ref str i)))
1147				 (write-char c ##sys#standard-error)
1148				 (when (char=? #\newline c)
1149				   (display "; " ##sys#standard-error))))
1150			     (newline ##sys#standard-error)
1151			     (eval x)))))
1152		   (when (equal? "-ss" scr)
1153		     (receive rs ((eval 'main) (command-line-arguments))
1154		       (let ((r (optional rs)))
1155			 (exit (if (fixnum? r) r 0)))))))))))))
1156
1157(run))
Trap