Fino a questo momento gli articoli del blog hanno trattato di programmi scritti in linguaggio Tcl e gestiti direttamente dell’interprete Tcl.
Tra le caratteristiche peculiari del linguaggio Tcl c’è però quella di essere un linguaggio di scripting che riesce a legare il proprio programma ad altri pacchetti o programmi esterni, indipendenti e scritti in un qualsiasi altro linguaggio di programmazione.
Con il termine legare si intende quindi la realizzazione di un collegamento per lo scambio di informazioni tra diversi programmi.
Per realizzare questa funzione, Tcl ha due comandi principali:
open: avvia un programma esterno e crea una connessione tra questo programma e la propria applicazione;exec: avvia un programma esterno come sottoprocesso indipendente.
Comando open
Il comando open è lo stesso comando utilizzato per aprire un comune file di testo.
Il meccanismo che permette l’utilizzo di questo comando anche per l’avvio di un programma esterno si basa sul primo carattere dell’argomento utilizzato per il nome del file: se il primo carattere è la barra verticale (|), allora il comando tratterà il resto dell’argomento come nome del programma esterno da avviare.
La scelta della barra verticale come carattere per identificare questo tipo di connessione, dipende dal fatto che questo carattere in inglese si chiama pipe (tubo, in italiano): quindi possiamo immaginarci questo collegamento come un tubo su cui il nostro programma Tcl può inviare informazioni verso il programma esterno, riceverne, oppure fare entrambe le cose.
Attenzione! Occorre essere consapevoli che l’informazione in Input/Output è bufferizzata: ciò significa che se stiamo utilizzando il comando read o gets per ricevere (Input) dei dati, questi saranno ricevuti soltanto quando il buffer di invio del programma esterno si sarà riempito. Stessa cosa avviene se utilizziamo il comando puts per inviare (Output) dei dati verso il programma esterno, in questo caso però, siccome sul nostro programma abbiamo il pieno controllo, possiamo anticipare l’invio dei dati con il comando flush.
# sintassi
open |programName ?access?
Se l’argomento programName viene racchiuso tra doppi apici alti o tra parentesi graffe, allora è possibile inserire ulteriori argomenti per specifici sottoprocessi.
Ricordiamo infine che il comando open restituisce un identificatore (token) che ci permetterà in seguito di far riferimento con facilità alla risorsa utilizzata.
# esempio
puts "Token ID: [open |firefox]"
---
Token ID: file3
Comando exec
Possiamo assimilare la chiamata al comando exec alla invocazione di un programma (o di più programmi inseriti tutti nello stesso pipe) fatta dalla finestra Terminale.
# sintassi
exec ?switches? arg1 ?arg2? ... ?argN?
Gli argomenti (arg...) del comando sono i nomi dei programmi da avviare. Se il primo argomento inizia con il carattere trattino (-) allora gli argomenti saranno trattati come switches del comando invece che essere invocati come sottoprocessi o opzioni di un sottoprocesso.
L’argomento facoltativo switches può avere i seguenti valori:
-keepnewline: con questa opzione si conserva il carattere di nuova linea nel flusso dei dati;--: segna la fine degliswitchese quindi la stringa successiva viene trattata comearg1anche se preceduta dal trattino.
Gli argomenti arg1 ?arg2? ... ?argN? possono avere i seguenti significati:
- il nome di un programma da eseguire;
- l’argomento di una linea di comando per un sottoprocesso;
- una istruzione per il reindirizzamento dell’Input/Output;
Tra le principali istruzioni per il reindirizzamento dell’Input/Output abbiamo:
| Con questo carattere si collegano due comandi esterni e viene preso l'output del primo comando ed inviato direttamente come input al secondo senza passare da un file intermedio.
< filename Il primo programma nel pipe leggerà l'input da filename.
<@ fileID Il primo programma nel pipe leggerà l'input da dalla risorsa identificata dal token restituito dal comando open ... "r".
<< value Il primo programma nel pipe leggerà il valore come suo input.
> filename L'output dell'ultimo programma nel pipe invierà a filename (qualsiasi precedente contenuto di filename verrà perso).
>> filename L'output dell'ultimo programma nel pipe sarà aggiunto a filename.
2> filename L'errore standard causato dai programmi presenti nel pipe verrà inviato a filename (qualsiasi precedente contenuto di filename verrà perso).
2>> filename L'errore standard causato dai programmi presenti nel pipe verrà aggiunto a filename.
>@ fileID L'output dell'ultimo programma nel pipe sarà scritto sulla risorsa identificata dal token restituito dal comando open ... "w".
Infine, se come ultimo carattere inseriamo il carattere &, allora il programma esterno verrà avviato in modalità background e non avrà alcun collegamento con il nostro programma.
# esempio
exec myProg &
Nel prossimo articolo vedremo come gestire un canale di Input/Output.