Ravi
Welcome
Documentation
Documentation
About Ravi
Documentation
Introduction
Premiers pas avec Ravi
ravitool
Scheme Tutorial
Objets Scheme
Le shell ravi
Starting Ravi
Le module trace
Les ports d'E/S
The C Parser
load, require, modules
Système d'interruptions
Scheme compiler
C++ mode
Generating C++ Modules
La déclaration struct
Le type "C-object"
More information
Installation

[PREV][SUIV]

Les ports d'E/S

Un port représente un flot de données; on peut le voir comme l'adaptation à Scheme du type stream dans d'autres langages.

Un port peut correspondre à

  • un fichier
  • une console
  • une chaine de caractères
  • un tube
  • un socket
  • un processus pvm distant
  • une fenêtre xforms

Chaque sous-type de ports possède des caractéristiques particuliers qui seront développées dans la documentation spécifique.

Notons que Scheme propose des fonctions très commodes et puissantes qu'on n'a pas l'habitude de voir dans un langage de programmation:

  • with-input-from-port
  • with-output-to-port
  • with-error-to-port

qui redéfinissent, pour une exécution donnée, les ports standards.

Généralités

Les fonctions essentielles opérant sur des ports ont toutes le port comme argument optionnel; si aucun port n'est précisé, l'opération s'effectue avec un des ports standards définis par les variables *scstdin*, *scstdout*, *scstderr*. Ces fonctions sont:

  • read
  • read-char
  • read-line
  • display
  • display-l
  • write
  • write-char
  • pretty-print

display-l est non-standard: (display-l e1 e2 ...) équivaut à (begin (display e1) (display e2) ...). Pour diriger l'impression de display-l vers un port de sortie explicite, on donne ce port comme premier argument. ATTENTION Cette convention est différente de celle de la fonction display!

Fonctions de création de ports

Un port est soit de type entrée, soit de type sortie.

  • open-input-file
  • close-input-port
  • open-output-file
  • open-output-file-option
  • close-output-port
  • create-child-with-pipe

Fonctions diverses

  • current-error-port
  • current-input-port
  • current-output-port
  • flush-port
  • input-port?
  • output-port?
  • set-current-error-port
  • set-current-input-port
  • set-current-output-port
  • with-error-to-port
  • with-input-from-port
  • with-output-to-port

Création d'un tube / pipe en Ravi

Les tubes fournissent des ports d'entrées/sorties particuliers. Ces ports sont créés par la fonction suivante qui effectue les appels système nécessaires:


 (create-child-with-pipe com modes args)

Arguments: com type string: nom d'une commande Unix modes type string args type string: les arguments de la commande Résultat: liste de ports

La fonction create-child-with-pipe crée un processus Unix P selon les paramètres com args; elle retourne une liste de ports qui sont connectés au stdin stdout stderr de P. Plus exactement: il y a 1, 2, ou 3 ports selon le paramètre mode, qui spécifie les ports avec les lettres ioe {pour in out err}. Si mode = "i", on crée juste un port pour le stdin, avec mode = "io" deux ports stdin, stdout, etc.

Attention:

  • le stdin de P est un port de sortie pour Scheme, etc.!
  • il y a liste de ports même s'il y en a qu'un seul.

Exemple, avec un seul port d'entrée:

La fonction sys affiche tout simplement toute la sortie standard d'une commande.


(define (sys x y)
  (let ((p (car (create-child-with-pipe x "o" y)))) ; "ioe"
    (do ((l (read-line p) (read-line p)))
	((eof-object? l) #f)
      (display l)
      (newline))))

Utilisation:


 (sys "ls" "")
 (sys "ls" "-l")

Remarques

La communication via tube se fait par tampon - il faut utiliser la fonction flush-port pour s'assurer que toutes les données ont été transférées.

Les ports standards non-redirigés de P sont ceux du processus Ravi. Cela peut être pratique, mais aussi avoir des effets surprenants!

Dans l'exemple de la fonction sys, cela signifie que, si la commande créée (comme le ls) effectue une lecture, elle lira dans le stdin de Ravi; et les messages d'erreur s'affichent sur l'écran.

L'intérêt de créer des tubes avec des ports Ravi tient qu fait qu'un programme Scheme peut commander un autre processus (via stdin), et analyser ses sorties, normales ou d'erreur. =============================================================

Les ports chaine

Une chaine de caractères peut servir de port d'entrée ou de sortie. C'est équivalent à un passage par un fichier, mais beaucoup plus simple.

Les fonctions de base dans Ravi - non-standards en Scheme, mais il existe l'équivalent dans d'autres versions de Scheme - sont:

Pour une chaine en lecture:


	(open-input-string s)  ouverture
	(set-input-string! port s) remplace la chaine du port
	(input-string? x)  test de type

Pour une chaine en sortie:


	(open-output-string)   ouverture
	(output-string->string port)  on recupère la chaine
	(output-string? x)  test de type

Noter qu'il n'y a pas de fermeture explicite des ports chaines.

Le module ravi_string_port contient quelques fonctions de plus:


		 (with-input-from-string s th)  th fonction sans arg
		 (with-output-to-string th)     th fonction sans arg
		 (call-with-output-string fn)   fn fonction avec 1 arg port
		 string-upcase
		 string-downcase
		 string-capitalize
========================================

Exemples


(define (initiales l)
  (let ((pp (open-output-string)))
    (with-output-to-port pp
      (lambda ()
	(for-each (lambda (x) (display (string-ref x 0)))
		  l)))
    (output-string->string pp)))

:>(initiales '("La" "belle" "Epoque")) = "LbE"

Plus simplement, on peut utiliser call-with-output-string:


(define (initiales l)
  (call-with-output-string
   (lambda (p)
     (for-each (lambda (x) (display (string-ref x 0) p))
	       l))))

ou, encore plus simple, utiliser with-output-to-string :


(define (initiales l)
  (with-output-to-string
   (lambda ()
     (for-each (lambda (x) (display (string-ref x 0) p))
	       l))))
==============