Sviluppo

Corso di programmazione in REXX - Lezione 4 - nozioni di base

Alessandro Cantatore
 


Nota: i sorgenti descritti in questo numero sono stati raccolti nel file rxsource.zip (12.388 byte).


I comandi
I comandi sono istruzioni che il REXX passa ad un altro ambiente.
Tramite i comandi, i programmi REXX possono controllare altri programmi o il sistema operativo stesso. Il REXX può perciò vantaggiosamente sostituire i classici programmi batch per automatizzare una serie di operazioni.

L'ambiente
Come ambiente si intende l'area di lavoro riservata ai singoli programmi.
Relativamente al REXX il termine ambiente non si riferisce tanto alle caratteristiche proprie dell'applicazione, quanto al suo modo di operare.
Il REXX non impone un suo proprio ambiente, ma opera interamente entro l'ambiente da cui è chiamato. Questo può essere l'ambiente dell'interprete dei comandi di OS/2 (CMD.EXE) o quello di una qualsiasi applicazione che usi il REXX come linguaggio di macro o scripting.

La regola di base è che qualsiasi cosa il REXX non può elaborare viene valutata e quindi passata all'ambiente di default.

Il concetto di ambiente diventa importante quando si usa il REXX per passare dei comandi ad altri programmi.

Dal REXX all'interprete dei comandi
Ci sono tre modi di passare un comando alla shell dei comandi di OS/2:

  • lasciando valutare al REXX in parte o completamente un'espressione passando poi la stringa risultante all'interprete dei comandi.
  • racchiudendo l'intera espressione tra virgolette, rendendola così una stringa letterrale che verrà passata inalterata alla shell dei comandi.
  • passando esplicitamente un comando alla shell di OS/2 tramite l'istruzione ADDRESS.

Lo script REXX viene esaminato una riga per volta per determinare se ogni espressione sia:

  • una parola chiave come per esempio:
    say "Introduci il totale"
    
    oppure
    pull input
    
  • un'operazione di assegnamento (qualsiasi simbolo valido seguito da segno di uguale) come per esempio:
    prezzo = costo * 2
    
  • un etichetta di richiamo di altre routine
  • un'espressione null

Se l'espressione non ricade in alcuna delle suddescritte categorie, il REXX valuta l'intera riga come un'espressione, passandone la stringa risultante alla shell dei comandi.

Se la stringa è un comando valido (per esempio DIR o COPY) allora l'interprete dei comandi del sistema operativo lo processa come se fosse stato introdotto da tastiera.

Esempi:

/* DIRREX.CMD: mostra la directory corrente */
say "comando DIR tramite REXX"
DIR

Non essendo la parola DIR nè un'istruzione REXX nè un'etichetta, il REXX la valuta e la passa all'interprete dei comandi di OS/2, il quale, riconoscendo DIR come uno dei suoi comandi lo esegue come se fosse stato introdotto da tastiera.

Echoing dei comandi os2

Il passaggio del comando all'interprete dei comandi comporta la riscrittura sullo schermo del comando stesso (echoing). Per eliminare questa noiosa ripetizione si può far precedere ciascun comando dal carattere @ o inserire all'inizio dello script il comando:

"@ECHO OFF"

Esecuzione di uno script REXX esterno
Per eseguire un comando interno dell'interprete dei comandi od un programma esterno da uno script REXX, come abbiamo visto, è sufficiente richiamarlo tramite il proprio nome. Per eseguire uno script REXX esterno è invece necessario ricorrere all'istruzione CALL.

Ci sono due tipi di CALL che è possibile usare:

  • l'istruzione CALL del REXX
  • il comando CALL dell'OS/2

L'istruzione CALL del REXX richiama uno script REXX esterno:

CALL MYSCRIPT
esegue il programma REXX MYSCRIPT.CMD.
L'istruzione CALL non è in grado di richiamare un file .CMD che non sia uno script REXX (cioè un semplice file BATCH). Per quest'ultimo è necessario usare CALL come comando dell'interprete dei comandi:
"CALL MYSCRIPT"
La presenza delle virgolette fa sì che la riga "CALL MYSCRIPT" venga valutata dall'interprete del REXX e che il risultato CALL MYSCRIPT venga passato all'interprete dei comandi di OS/2.
Le virgolette che racchiudono il comando permettono di distinguerlo dall'omonima istruzione REXX.

Uso di variabili
Il comando da passare al sistema operativo può anche essere costruito dinamicamente.
Nel programma di esempio che segue viene richiesto all'utente di introdurre il nome di un file, il cui contenuto viene poi mostrato sullo schermo tramite il comando type.

/* SHOWFILE.CMD                                             */

/* chiede all'utente di introdurre il nome di un file       */
say "Introduci il nome di un file:"

/* assegna la rsiposta alla variabile FILENAME              */
pull filename

/* costruisce il comando tramite concatenazione             */
commandstr = "@TYPE" filename

/* se l'utente ha introdotto, per esempio, "AUTOEXEC.BAT"   */
/* la variabile COMMANDSTR conterrà: "@TYPE AUTOEXEC.BAT"   */
commandstr           /* il REXX passa il comando al sistema */
Quando lo script viene eseguito si avrà:
[C:\]SHOWFILE
Introduci il nome di un file:
AUTOEXEC.BAT

@ECHO OFF
ECHO.
PROMPT $i$p$g
REM SET DELDIR=C:\DELETE,512;
SET WIN3DIR=C:\OS2\MDOS\WINOS2
PATH=C:\OS2;C:\OS2\MDOS;C:\;C:\OS2\MDOS\WINOS2;
LOADHIGH APPEND C:\OS2;C:\OS2\SYSTEM
SET TMP=C:\
REM LOADHIGH DOSKEY FINDFILE=DIR /A /S /B $*
REM DOSKEY EDIT=QBASIC/EDITOR $*
REM SET DIRCMD=/A
SET TEMP=C:\OS2\MDOS\WINOS2\TEMP
[C:\]

Uso delle virgolette
Le regole per formare un comando da un'espressione sono esattamente le stesse di quelle usate per formare le espressioni. Particolare attenzione deve essere prestata a quei simboli che sono sia istruzioni REXX che comandi OS/2.
Per determinare come il REXX valuta un comando quando questo ha lo stesso nome di una variabile usiamo il seguente esempio:

/* DIRREX2.CMD                        */

/* assegna un valore al simbolo DIR   */
say "comando DIR tramite REXX"
dir = "echo Questa non è una directory!"

/* passa al sistema l'espressione DIR */
dir
In questo esempio dir è una variabile che contiene la stringa "echo Questa non è una directory!".
Quando il programma viene eseguito sullo schermo si otterrà:
[C:\]dirrex
comando DIR tramite REXX
Questa non è una directory!
[C:\]
Il REXX valuta una stringa racchiusa tra virgolette esattamente come è.
Per assicurarsi che un simbolo di un comando non sia valutato come variabile è necessario racchiuderlo tra virgolette, come si può vedere nel seguente esempio:
/* DIRREX3.CMD" */

/* assegna un valore al simbolo DIR */
say "comando DIR tramite REXX"
dir = "echo Questa non è una directory!"

/* passa al sistema la stringa letterale DIR */
"dir"
Eseguendo lo script, questa volta, otterremo l'elenco dei file contenuti nella directory corrente.

L'uso delle virgolette è essenziale anche quando il comando che si vuole passare al sistema include un operatore REXX.
Per esempio in comandi come "DEL *.TMP" o "DIR /W", i caratteri * e / verrebbero interpretati dal REXX come gli operatori di moltiplicazione e divisione. Se i comandi non venissero racchiusi tra virgolette l'interprete del REXX cercherebbe di moltiplicare DEL per .TMP o di dividere DIR per W e dato che a tali simboli non corrispondono grandezze numeriche si otterrebbe solo un messaggio di errore: "Bad arithmetic conversion".
Versioni corrette dei precedenti esempi sono:

DEL "*.TMP"
DIR "/W"
oppure
"DEL *.TMP"
"DIR /W"
Se è necessario usare una variabile nella stringa del comando, questa deve essere lasciata fuori dalla virgolette:
extension = "BAK"
option = "/W"
"DEL *." || extension
"DIR" || option
altre forme valide di concatenazione sono:
"DEL *."extension     /* senza spazi tra le virgolette e la variabile */
"DIR "option

L'istruzione ADDRESS
Un metodo più esplicito per passare un comando all'ambiente è tramite l'uso del comando ADDRESS:

ADDRESS environment expression
dove:
environment
rappresenta l'ambiente di destinazione della stringa. Per esempio se si vuole usare l'ambiente di OS/2 questo parametro sarà CMD (l'interprete dei comandi CMD.EXE).
expression
è la stringa che viene valutata dal REXX e passata all'ambiente environment
Alcuni esempi di uso dell'istruzione ADDRESS:
address CMD "dir"       /* passa il comando DIR a CMD.EXE         */

cmdstr = "dir *.txt"
address CMD cmdstr      /* passa la stringa "dir *.txt" a CMD.EXE */
Quando si usa l'istruzione ADDRESS il REXX dapprima valuta il valore dell'espressione e poi lo passa al programma CMD.
Anche per la stringa che si vuole passare all'ambiente tramite ADDRESS valgono le stesse considerazioni menzionati per i comandi passati al sistema: usare sempre le virgolette se ci sono ambiguità con variabili, istruzioni o con operatori REXX!

Attraverso l'istruzione ADDRESS lo stesso script REXX può indirizzare dei comandi a due o più ambienti diversi. Questo può essere usato nel caso che si voglia impiegare il REXX come linguaggio di macro.

Dall'interprete dei comandi al REXX
Le informazioni tra i programmi OS/2 e il REXX passano in entrambi i sensi.
Se un programma fallisce, per esempio se si cerca di copiare un file che non esiste, viene mostrato un messaggio sullo schermo riportante la causa del problema.
La stessa cosa accade quando, per esempio, un programma REXX cerca di copiare un file che non esiste, tranne che il programma REXX non è in grado di rispondere adeguatamente al problema se non si includono le istruzioni necessarie per rilevarlo. Dato che un errore di sistema non ferma il programma REXX, questo potrebbe continuare dando per scontata l'esecuzione di un comando che invece è fallito.

Con l'esecuzione di ogni comando l'interprete dei comandi genera un codice di ritorno che quando il comando viene eseguito tramite il REXX viene assegnato automaticamente ad una speciale variabile REXX chiamata RC.

Quando un comando viene eseguito senza problemi, di solito, il valore restituito è 0, mentre se qualcosa va storto viene restituito un valore diverso da zero, che dipende dal comando stesso e dal tipo di problema verificatosi.

Lettura dei codici di ritorno
Il seguente esempio è in grado di leggere il valore di ritorno di un comando dalla variabile RC:

/* GETRC.CMD: prova a scrivere sullo schermo un file */
/* che non esiste tramite il comando type riportando */
/* il valore di ritorno del comando                  */
"@TYPE nosuch.fil"
 say "il valore di ritorno  è" RC
Il valore di ritorno è utile per comunicare all'utente il tipo di problema che si è verificato ed, eventualmente, per intraprendere un'azione alternativa:
/* REPORTRC.CMD: prova a scrivere un file sullo schermo */
/* tramite il comando type, se questo fallisce chiede   */
/* all'utente di inserire un nuovo nome di file         */
"@TYPE nosuch.fil"
if RC \= 0        /* se il valore di ritorno è diverso da zero */
   then do
   say "impossibile trovare nosuch.fil! Introduci il nome di un nuovo file:"
   pull filename
   "@TYPE" filename
   end /* do */
In una lezione successiva approfondiremo l'uso delle istruzioni che, come IF...THEN...ELSE, ci permettono di controllare lo svolgimento del programma in base al vereficarsi di date condizioni.

Il programma REXXTRY
Il programma REXXTRY è un programma REXX che permette di eseguire un'istruzione REXX per volta verificandone immediatamente il risultato.
REXXTRY può essere eseguito sia in una finestra comandi OS/2 che a schermo intero.
Per iniziare una sessione REXXTRY è sufficiente digitare al prompt dei comandi REXXTRY e EXIT o RETURN per terminare.

Ecco alcuni esempi del funzionamento di REXXTRY:

REXXTRY say 1 + 2               /* mostra 3    */

REXXTRY say 2 + 3; say 3 + 4    /* mostr 5 e 7 */

/* mostra "la media è 2.5" */
REXXTRY somma=1+2+3+4; say "la media è" somma/4
Quando si esegue REXXTRY dalla riga di comando seguito da alcune istruzioni REXX, l'interprete dei comandi di OS/2 elabora la riga di comando nel modo usuale. Nel seguente esempio:
REXXTRY say AB > CD
l'argomento di REXXTRY non è say AB > CD, ma l'interprete dei comandi considererà il simbolo > come operatore di redirezione dell'uscita, per cui REXXTRY verrà eseguito con say AB come argomento e la stringa AB verrà scritta nel file CD.

Quando REXXTRY viene eseguito senza argomenti, le istruzioni REXX possono essere introdotte ininterrottamente dalla riga di comando finché, per terminare, non si introduce l'struzione EXIT o RETURN.
Provate a seguire il seguente esempio premendo Invio dopo ogni istruzione REXX introdotta (il testo scritto dal programma REXXTRY è qui riportato in corsivo per distinguerlo dal testo scritto tramite la tastiera):

[C:\]rexxtry
  REXXTRY.CMD lets you interactively try REXX statements.
    Each string is executed when you hit Enter.
      Enter 'call tell' for a description of the features.
  Go on - try a few...             Enter 'exit' to end.
say AB > CD
0
  ................................................ REXXTRY.CMD on OS/2
somma = 1 + 2 + 3 + 4
  ................................................ REXXTRY.CMD on OS/2
say "la media è" somma / 4
la media è 2.5
  ................................................ REXXTRY.CMD on OS/2
exit

[C:\]
Tra i sorgenti inclusi in questo numero c'è una versione migliorata del programma REXXTRY (EREXXTRY.CMD) grazie alle routine di input scritte da Bernd Schemmer pubblicate nel suo ottimo REXX tips and tricks reperibile su internet come rxtt27.zip.


[Pagina precedente] [Sommario] [Pagina successiva]