;; scheme_wish: A portable interface between Scheme and Tcl/Tk. ;; It is based on the idea to start a wish process from the Scheme process and ;; to communicate using pipes. ;; scheme_wish has been tested for the following Scheme systems: ;; Gambit, guile, and SCM. ;; version 0.1 - 1998-04-26 ;; The current version is available from my home page ;; (http://www.informatik.fernuni-hagen.de/pi7/hartrumpf/). ;; I supply this file without any guarantees and for noncommercial use only. ;; Sven Hartrumpf (C) 1997-1998 ;; Applied Computer Science VII, FernUniversität Hagen, 58084 Hagen, Germany ;; email: Sven.Hartrumpf@FernUni-Hagen.de ;; A small example is given in function test-wish. ;; To test it, do the following: ;; 1. Change the six global constants below (if necessary). ;; 2. Uncomment the necessary system-dependent part at the end of this file. ;; 3. Start Scheme. ;; 4. Load this file into Scheme. ;; 5. Type: (test-wish). ;; to do list ;; - solve bigloo problem ;; global constants ;; One might have to adjust the following six definitions. ;; A true value causes all data that flows from Scheme to wish to be written on ;; standard output by Scheme. (define *wish-debug-input* #f) ;; A true value causes all data that flows from wish to Scheme to be written on ;; standard output by Scheme. (define *wish-debug-output* #f) ;; The message that will be send to the wish process to close it. (define *wish-exit-message* "after 200 exit") ;; The name of the file that will become the input of the wish process. (define *wish-input-filename* "/tmp/scheme_wish_i") ;; The name of the file that will become the output of the wish process. (define *wish-output-filename* "/tmp/scheme_wish_o") ;; The name of the shell command that starts a wish process. (define *wish-program* "wish") ;; global variables ; (define *wish-input* #f) ; The input stream of the wish process. ; (define *wish-output* #f) ; The output stream of the wish process. ;; functions ;; relevant high level functions: start-wish, wish, read-wish, end-wish ;; (end-wish) = unspecified ;; Side effect: terminates the wish process. (define end-wish (lambda () (wish *wish-exit-message*))) ;; (flush-wish) = unspecified ;; Flushes the output to wish. (define flush-wish (lambda () (flush-output *wish-input*))) ;; (read-wish) = ;; reads a term from wish. (define read-wish (lambda () (let ((term (read *wish-output*))) (cond (*wish-debug-output* (display "wish->scheme: ") (write term) (newline))) term))) ;; (read-wish-chars) = ;; a line from wish as a list of characters. (define read-wish-chars (lambda () (read-bytes-until *wish-output* '(#\newline)))) (define read-bytes-until (lambda (port stop-characters) (let ((char (read-char port))) (cond ((eof-object? char) '()) ((memq char stop-characters) '()) (else (cons char (read-bytes-until port stop-characters))))))) ;; (run-program p) ;; Side effect: runs the program p with input and output bound to streams. ; (define run-program ; (lambda (program input-filename output-filename) ; (let ((command #f) ; (input #f) ; (output #f) ; (result #f)) ; (delete-file-if-exists input-filename) ; ;;(write "input file deleted")(newline) ; (delete-file-if-exists output-filename) ; ;;(write "output file deleted")(newline) ; (set! result (system (string-append "mknod " input-filename " p"))) ; ;;(write result)(newline) ; (set! result (system (string-append "mknod " output-filename " p"))) ; ;;(write result)(newline) ; (set! command (string-append program " < " ; input-filename " > " ; output-filename " 2>&1")) ; ;; 2>&1 associates file descriptor 2 (standard error) with the file associated ; ;; with file descriptor 1. ; (set! result (system (string-append "/bin/sh -c \"" command "\" &"))) ; ;;(write result)(newline) ; (set! input (open-output-file input-filename)) ; ;;(write input)(newline) ; (set! output (open-input-file output-filename)) ; ;;(write output)(newline) ; (list input output)))) ;; start-wish ;; Starts a wish process. ; (define start-wish ; (lambda () ; (let ((result (run-program *wish-program* *wish-input-filename* *wish-output-filename*))) ; (set! *wish-input* (car result)) ; (set! *wish-output* (cadr result))))) ;; test-wish ;; A simple test program. (define test-wish (lambda () (start-wish) ;; Tcl procedures ;; scm is used to send something from wish to Scheme. (w " proc scm {s} { puts $s flush stdout } ") ;; widget definitions (w " label .l -text \"scheme_wish: A portable interface between Scheme and Tcl/Tk; version 0.1; written by Sven Hartrumpf\" frame .alternative radiobutton .alternative.a -borderwidth 2 -relief raised -pady 4 -text \"A\" -value a -variable alternative -command {scm \"(alternative-value $alternative)\"} -foreground #0000af radiobutton .alternative.b -borderwidth 2 -relief raised -pady 4 -text \"B\" -value b -variable alternative -command {scm \"(alternative-value $alternative)\"} -foreground #2060ff radiobutton .alternative.c -borderwidth 2 -relief raised -pady 4 -text \"C\" -value c -variable alternative -command {scm \"(alternative-value $alternative)\"} -foreground #60d0ff button .end -text \"Quit\" -command {scm \"(quit)\"} ") ;; widget placements (w " pack .alternative.a .alternative.b .alternative.c -expand yes -fill x -side left pack .l .alternative .end -expand yes -fill both -side top ") (test-wish-handler) (end-wish) )) (define test-wish-handler (lambda () (do ((alternative #f) (end #f)) (end alternative) (let ((term (read-wish))) (display "test-wish-handler: term: ") (write term) (newline) (cond ((pair? term) (case (car term) ((alternative-value) (set! alternative (cadr term)) (display "alternative: ") (write alternative) (newline)) ((quit) (set! end #t)) (else (display "test-wish-handler: unexpected term: ") (write term) (newline)))) ((eof-object? term) (display "eof object received") (newline) (set! end #t)) (else (display "test-wish-handler: unexpected term: ") (write term) (newline))))))) ;; (wish . l) ;; Sends all arguments to wish's input using display. (define wish (lambda arguments (for-each (lambda (argument) (cond (*wish-debug-input* (display "scheme->wish: ") (display argument) (newline))) (display argument *wish-input*) (newline *wish-input*)) arguments) (flush-wish))) ;; w ;; An abbreviation for wish. (define w wish) ;; system-dependent functions: delete-file-if-exists, flush-output, system ;; Uncomment the part for the Scheme system you are using. ;; bigloo part: doesn't work because bigloo can't open a pipe as an input file. ;; builtin functions: system ;;(define delete-file-if-exists (lambda (name) ;; (delete-file name))) ;;(define flush-output flush-output-port) ;; gambit part ;; builtin functions: flush-output ;;(define delete-file-if-exists (lambda (name) ;; (system (string-append "/bin/rm -f " name)))) ;;(define system ##shell-command) ;; guile part ;; builtin functions: system (define delete-file-if-exists (lambda (name) (cond ((file-exists? name) (delete-file name))))) ;;(define flush-output force-output) ;; SCM part ;; builtin functions: system ;;(define delete-file-if-exists delete-file) ;;(define flush-output force-output)