Cours gratuits » Cours informatique » Cours programmation » Cours NetRexx » Traitement par lots pour créer et envoyer masse rapports Excel Utilisation de NETREXX, SAS, HTML (XML) et le système e-mail

Traitement par lots pour créer et envoyer masse rapports Excel Utilisation de NETREXX, SAS, HTML (XML) et le système e-mail

Problème à signaler:

Télécharger



★★★★★★★★★★3.5 étoiles sur 5 basé sur 1 votes.
Votez ce document:

Traitement par lots pour créer et envoyer masse rapports Excel Utilisation de NETREXX, SAS, HTML (XML) et le système e-mai

...

LES MOTS CLEFS (communs à toutes les implémentations)

Address env send a command to environment ENV Address ISPEXEC « display panel(panel1) »

Attention : l’environnement n’existe pas forcément sur le Système

Arg Utilisé pour recuperer les arguments passés au REXX .

En f

ait c‘est la version ‘courte’ de Parse upper ARG

CALL appel d’une routine interne ou externe. S’il y a des resultats, ils sont dans la variable result

DO départ de boucle (c.f control structures)

DROP pour vider une variable

EXIT sortir (fin) d’un EXEC (programme principal).

IF Execution conditionelle du code (C ;F control structures).

Iterate Recommencer (une boucle – c.f control structures).

Leave Quitter une boucle (c.f control structure).

NOP ne fait rien.

Parse Eclater un argument (c.f mise en forme de données).

Procedure Protège les variables de l’appelant en les rendant invisible à l’appelé.

Le paramètre EXPOSE rend les variables de l’appelant spécifiées visibles.

Push mettre dans le stack (LIFO, c.f stack).

Queue Mettre dans le stack. (FIFO c.f stack).

Return retourne le contrôle à l’appelant avec , le cas échéant, un résultat au point d’invocation.

SAY Affiche le texte qui suit, ou les valeurs des vairiables si elles sont initialisées.

Select La structure de cas (case structure).

Signal go to (c.f tracing et debugging)

Trace Demarre ou arrete la fonction tracing (c.f tracing et debugging)

Ecrire un programme REXX en TSO

Tout le monde peut faire ses premiers pas de REXX sous TSO (OS/390 V1R3) et on commence généralement par un programme qui affiche "Hello world!".

Il est nécessaire d’avoir un PDS pour faire ces exercices, c’est le seul ‘pre-requisite’. Nous allons assumer que vous connaissez l’option 3.4 de ISPF

Aller dans votre PDS (librairies) créez un membre essai (Surtout ne choisissez pas TEST car c’est une commande TSO) et tapez ce code :

/* REXX */ This program says "Hello world!"

say "Hello world!"

sortez et sauvegardez (généralement PF3 ) puis taper EX sur la ligne de votre REXX

Hello world! S’affiche

Vous venez d’exécuter votre premier REXX (on dit aussi EXEC)

NOTES :

Les Execs REXX commencent toujours par /* REXX */, Sauf si la recherche

automatique de SYSEXEC est activée

Vu la simplicité du codage, nous commencerons toujours nos EXEC par /* REXX */.

Nous allons attaquer les variables par le chapitre arithmétique

VARIABLES

  • arithmétique

REXX a une vaste collection d’opérateurs pour exécuter des opérations Nous n’allons pas tous les voir ... mais les principaux, cela nous permettra d’aborder les variables en REXX car il y a quelques différences subtiles comparé aux autres langages.

Ecrivez ce code dans un membre ARITH

/* REXX */

say ‘give a number’

pull a

b=a*a

c=1/a

d=3+a

e=2**(a-1)

say 'Results are:' a b c d e

Sortir par PF3 et refaire la manipulation indiquée au debut, voici un exemple (page suivante) :

Ecrire un programme REXX

GIVE A NUMBER 5

Results are: 5 25 0.2 8 16

les résultats affichés sont le chiffre original (5), son carré (25), sa réciproque (0.2), le chiffre original +3 (8) et deux à la puissance 1 - le chiffre (16). Cet exemple montre :

  • Dans cet exemple a, b, c, d, e sont des variables ici elles sont facilement reconnaissables grâce à l’opérateur ‘=’ Et c’est la valeur de la variable (à droite de l’opérateur) qui est utilisée dans les opérations où la variable est appelée
  • input: l’instruction PULL permet de récupérer une valeur dans une variable soit par le terminal soit par la ‘queue ‘ ATTENTION l’instruction PULL ne récupère pas BLIGATOIREMENT du terminal
  • arithmétique: les symboles usuels (+ - * /) ainsi que ** (à la puissance) ont été utilisé pour effectuer les calculs
  • Les parenthèses ont été utilisées pour grouper les expressions... en fait, il s’agit d’influencer l’ordre de précédence des opérateurs.
  • la dernière ligne affiche les résultats : noter que si les variables ne sont pas initialisées les mots

A B C D E seront affichés (voir point 4). Noter aussi l’absence de caractère de concaténation.

Le blanc entre l’expression (une expression peut-être littérale, ou même évaluée) et les variables est en fait considéré par l’interpréter (REXX) comme une concaténation avec blanc.

'Results are:' a b c d e

S’affichent 6 composants : le constant littéral et les 5 variables.

Un constant littéral est toute séquence de caractère commençant et terminant par : ‘ ou ‘’ Dans ce programme il sera possible de changer la précision décimale de l’interpreteur par l’ordre numérique digit XX ou XX est un chiffre

  • Variables non typées dans l’exemple déjà donné, il est possible de donner un nom (par exemple). REXX (l’interpreteur) ne détectera pas d’erreur, mais les opérations exécutées sur ces variables se planterons. (on ne peut effectuer des calculs sur des noms ) en erreur de syntaxe.

Ecrire un programme REXX

REXX ne vérifie pas la validité des opérations sur les variables ceci afin d’être plus souple et de ne pas ‘ennuyer’ l’utilisateur avec des détails de type de déclarations de variables comme dans d’autres langages (ref plus haut), cela entraîne que si l’on fait une instruction say sur une variable après l’avoir ‘vidée’ le nom de la variable s’affichera.

Concaténation : On a déjà abordé ce sujet pour une concaténation avec espace.

/* REXX */ Ce rexx affichera :

SAY ‘il fait’ ! !’beau’ il faitbeau

say ‘il fait’ ‘beau’ il fait beau

Exit

utilisation de ! ! ou || selon les sites. Il y a concaténation sans blanc utilisation d’un blanc (ou espace) concaténation avec espace.

On a vu les variables et la concaténation, les variables utilisées jusque là n’utilisaient qu’une lettre à titre d’exemple.

Une variables peut faire jusque 250 caractères de long et peut inclure des chiffres et les 6 caractères "@#$!?_". La fonction SYMBOL permet de savoir si elle a été initialisée correctement.

Tableaux a plusieurs dimensions

Une notion importante dans les variables est LES VARIABLES COMPOSEES. En anglais ARRAY PROCESSING. Ce système permet de donner plusieurs valeurs à une variables l’une après l’autre.

/* REXX */ et voilà l’affichage

bk.1 = 'le rexx by da kine'

bk.2 = 'le rexx by GABE'

bk.3 = 'le rexx by yen amarre'

bk.4 = 'le rexx by jean epleinlcu'

bk.5 = 'le rexx by who else'

bk.6 = 'le rexx by mike cowlishaw'

say bk.6 'est 6ieme arg' le rexx by mike cowlishaw est 6ieme arg

say bk.2 'est deuxieme arg' le rexx by GABE est le 2eme arg

Ecrire un programme REXX

Il est possible d’améliorer l’exec page précédente comme suit : rajouter 2 instructions

n say ‘donner un numéro de bouquin’

n pull n

Modifier l’instruction say déjà présente : SAY bk.6 ‘est 6eme arg’ par : SAY BK .N ‘est’

N ! !’ieme bouquin’

Retirer la deuxième instruction SAY

Exécutez le : EX devant le nom de membre.

Donnez numéro de bouquin

6

le rexx by mike cowlishaw est 6ieme bouquin

***

note : La variable BK.N est dite composée (Compound variable). BK. Est la première partie et est appelé RACINE (STEM en anglais). N est l’extension.

Il est possible de combiner 2 noms de variables, REXX ne limitant pas les variables (elles peuvent être numérique ou alphabétiques) rien n’empêche d’avoir une variables composée dont la racine et l’extension soient des caractères.

Exemple un répertoire téléphonique avec nom et prénom : /* REXX */

say 'donnez prénom et nom' donnez prenom et nom

pull pren nom Eric bouladoux

say nom pren ERIC BOULADOUX * 8238 *

03.20.60.82.38 *

ERIC.BOULADOUX='* 8238 * 03.20.60.82.38 *' ***

ERIC.MARMOUZE= '* 7690 * 03.20.60.76.90 *'

MIKE.CORMIER= '* 7071 * 01.43.12.70.71 *' say pren ' ' nom value(pren'.'nom)

Exit

Ainsi, les variables de chaque coté du point doivent être résolues.

Déjà il est possible de développer des utilitaires, ici une liste téléphonique, quoique il a fallu utiliser une fonction que l’on a pas encore vu.

Autre point que l’on verra plus tard, l’instruction ARG, elle permet de passer des arguments directement à notre programme, mais il est necessaire que le REXX puisse etre appelé directe-ment depuis le champs commande d’ISPF, necessitant une manipulation spéciale que nous verrons plus loin.

Nous venons de voir les variables, un des éléments importants de REXX. et d’autres langages. Le chapitre suivant vous présente les structures de contrôle (IF/ELSE, WHEN, et boucle). Les tableaux à plusieurs dimensions sont fort utiles dans la construction de boucle.

Structure de controle

Nous avons vu un terme précédemment, la boucle, celle ci est ce que l’on appelle une ‘control structure’ tout comme if then else (conditionnels)

IF then else conditionnels créez le REXX suivant :

/* REXX */ affiche :

say ‘donnes moi un chiffre’ donnes moi un chiffre

pull a 5

if a<10 then say a "is less than 50" 5 is less than 50

else say a "is not less than 50" ***

exit

Dans cet exemple, a<10 then say ... est une expression conditionnelle, elle ressemble à toute autre expression à tel point qu’une expression numérique ordinaire est interchangeable avec une conditionnelle.

Le programme s’exécute comme il a été tapé..

IF instruction Vrai ? 1 ou 0

else si if faux (0) alors exécute else

C’est un résultat d’exécution gràce à l’instruction TRACE I l’instruction IF est évaluée à un (1) or ici elle est vraie donc 1 = vrai 0 = faux.

POINT important, Le REXX se lit de gauche à droite (c’est écrit par des anglo-saxons mais quand même...) le REXX s’exécute de gauche à droite... (comme il se lit) c’est important pour la précédence des opérateurs, Structures de contrôle ainsi le jeux d’instruction :

N=6

SAY N* 100/50’%’ sont des rejets

Affichera 12% sont des rejets, on en deduit que les operations arithmetiques ont une plus grande priorité que la concatenation.

Et surprise pour les anglophobes, IF veut dire SI...et ELSE veut dire SINON.

De là il n’y a rien de plus facile à comprendre....

OPERATEURS :

_ (égal à) < (plus petit que) > (plus grand que) <_ (plus petit que ou égal à)

>_ (plus grand ou égal) <> (plus grand ou plus petit) ^_ (non-égal) ^> (pas plus grand) ^< (pas plus petit) les opérateurs comparent non seulement les chiffres mais aussi les littéraux en enlevant les blancs de début et de fin + ‘ eric ‘ = ‘eric’

OPERATEURS stricts (Ceux la n’enlèvent pas les blancs des arguments => ‘ eric ‘ = ‘eric’ est faux (0)) :

= = (égal) << (plus petit) >> (plus grand) <<= (plus petit ou égal) >>= (plus grand ou égal) ^== (non égal) ^>> (pas plus grand) ^<< (pas plus petit)

LES OPERATEURS BOOLEENS :

& (et), ! (ou ) and && ou exclusif). Ces opérateurs peuvent eux aussi être inversé comme précédemment..

Structures de controle

Boucles

REXX a une collection complète d’instruction pour exécuter des loops (boucles).

  1. Boucles comptées (Counted loops)

les instructions spécifiées dans une boucle comptée sont exécutés le nombre de fois spécifiée

/* REXX */ Say "Hello" ten times

do 10

say "Hello" end

Une variation de la précédente :.

/* REXX */ il faudra presser la clef interrupt pour l’arrêter

do forever

nop end

  1. Boucle de contrôle

Ce type de boucle rappelle la ‘counted loop’. Ici une variable est utilisée comme compteur et devient une ‘Variable de contrôle’. Elle peut compter (s’incrementer) de 1 à n valeur c’est à vous de le spécifié..

/* REXX */ compte jusqu'à 20

do c=1 to 20 say c end

/* REXX */ affiche tous les multiples de 2.3 jusqu'à 20

do m=0 to 20 by 2.3 say m

end

/* REXX */ Affiche les 6 premiers multiple de 5.7

do m=0 for 6 by 5.7 say m

end

Structures de controle

Boucles

/* REXX */ Print all the natural numbers

do n=0 say n end n

Le caractère ‘n’ est ici optionnel. Placée à la fin cette variable sera vérifiée pour voir si elle est égale à la variable du début (son contenu).

  1. Conditional loops

Un jeu d’instructions peut etre repete jusqu’a ce qu’une condition ‘VRAIE’ soit rencontree :

/* REXX */ I won't take no for an answer

do until answer \= "NO" pull answer end

Elles peuvent etre executees pour autant qu’une condition soit vraie

/* REXX */ on repete a tant qu’il ny a pas d’erreur

do while error=0

pull a

if a="ERROR" then error=1

else say a

end

Notez qu’ici la variable zero doit etre a 0 (pas d’erreur) pour demarrer sinon le jeu d’instructions ne sera pas éecuté

Dans l’exemple C, les instructions seront au moins execute une fois. En effet les expression d’un « UNTIL » sont évaluees àla fin de la boucle, alors que dans un « WHILE » elles sont evaluées au début de la boucle.

  1. Controlled conditional loops

il est possible de combiner a ou b avec c, comme ceci ::

/* REXX */ won't take no for an answer unless it is typed 3

times

do 3 until answer \= "NO" pull answer

end

Structures de controle

Boucles

Ou comme ceci :

/* REXX */ input ten answers, but stop when empty string is entered

do n=1 to 10 until ans==""

pull ans a.n=ans end

les instructions "iterate" et "leave" vous permettent de continuer ou de quitter une boucle

/* REXX */ input ten answers, but stop when empty string is entered

do n=1 to 10 pull a.n

if a.n=="" then leave on quitte la boucle en cours

end

/* REXX */ print all integers from 1-10 except 3

do n=1 to 10

if n=3 then iterate 3 ne sera pas affiche, l’ordre iterate arrivant avant le SAY

say n

end

il est possible de controler l’execution ou la sortie d’une boucle par la variable qui la definie :

/* Print pairs (i,j) where 1 <= i,j <= 5, except (2,j) if j>=3 */

do i=1 to 5 /* la variable de la bouce est I */

do j=1 to 5

if i=2 & j=3 then iterate i /* "leave j" serait ok,

say "("i","j")" ou leave tout seul */

end

end

SELECT (test case)

Permet de choisir une condition parmi plusieurs choix possible. Une clause SELECT se termine TOUJOURS par END

/* REXX */

ARG K

Select

When k=’1’ then say k=1 When k=’2’ then say k=2 When k=’3’ then say k=3 Otherwise say ‘number too big’ end

SELECT remplace les instructions IF imbriquées

/* REXX */

If K=’1’ then say k=1

Else if k=’2’ then say k=2 Else if k=’3’ then say k=3 Else say ‘number too big’

Les structures de controle permettent de controler l’execution d’instructions base sur des conditions ou cas particuliers.

Elles sont d’une importance capitale dans toute programmation, mais seul REXX les rend aussi facile d’utilisation.

Mise en forme de données

Parsing opération qui consiste à éclater l’argument passer en plusieurs variables (Note

la casse est gardée) instructions ARG et/ou PARSE.

Avant d’eclater des arguments il est nécessaire de les ‘recevoir’, pour ce faire il existe plusieurs instructions :

PULL (lis dans le stack), ARG (recois directement les arguments passés a l’appel). L’instruction PARSE manipulera les arguments passés à loisir.

/* REXX */ eclate l’argument en 4 variables

parse arg a.1 a.2 a.3 a.4 ici ARG est un sous paramètre de parse

do i=1 to 4

say "Argument" i "was:" a.i end

Pour l’exécuter, il est nécessaire de taper son nom puis "alpha beta gamma delta" dans la ligne de commande :

ex arguments alpha beta gamma delta le programme affiche

Argument 1 was: alpha Argument 2 was: beta Argument 3 was: gamma Argument 4 was: delta

Le programme a séparé la chaîne passée en quatre arguments. La chaîne a été découpée au niveau des blancs en entrée. Si vous oubliez un argument alors, la dernière ligne affichera Argument 4 was:

Si vous entrez plus de 4 arguments alors la quatrième ligne affiche les arguments supplémentaires.

Aussi si vous entrez des blancs avant chaque argument, seul le dernier argument affichera SES blancs. On appelle ça "tokenisation".

Il n’y a pas que les arguments passés au moment de l’appel qui peuvent être tokenisés, toutes les variables peuvent être tokenisee. Par exemple remplacez ARG par PULL dans le pgm précédent. Le pgm attend une entrée clavier qui sera tokenisée.

Note, la casse des paramètres passes dépend de l’instruction utilisée pour les récupérer, ainsi ARG recevra TOUT en Majuscule, alors que PARSE ARG gardera la casse.

Les deux utilisations les plus utiles de PARSE sont PARSE VAR et PARSE VALUE qui vous permettent de séparer des donnes arbitraires renvoyées par le pgm ainsi :

  Mise en forme de données

/* REXX */

d=date()

parse var d day month year

parse value time() with hour ':' min ':' sec 

La dernière ligne ci dessus montre une autre manière de séparer les données : elles sont séparées au niveau d’un caractère ‘ :’.

Testez ces trois lignes pour voir le résultat  :

/* rexx */

parse value time() with hh ':' MM ':' ss ':'  ici, time sera eclatée au niveau

say hh ' heure ' MM ' minutes ' SS 'secondes '

parse arg first "beta" second "delta"  des 2 point (:) .

Ici tout ce qui est avant beta sera dans first et ce qui est entre beta et delta sera dans second si il y a quelque chose après delta ce sera perdu.

Si Beta n’apparait pas dans le string alors tout va dans first et second est vide.

Si Beta seul est code dans le string alors tout ira dans second.

On peut répartir ce qui apparaît entre 2 arguments, ainsi, parse arg "alpha" first second "delta", placera tout ce qui apparaît entre ALPHA et BETA dans FIRST et SECOND.

Un point entre deux variables, parse pull a . c . e jettera la valeur intermédiaire (dans notre cas la deuxième et quatrième valeurs passées seront jetées).

Il est préférable de coder un point après le dernier argument, afin de s’assurer de la validité des arguments passés :

parse pull first second third .

Et cela permet de s’assurer qu’aucun des arguments ne contient de ‘blancs’ seul le dernier argument pouvant en contenir et ici le dernier est un point.

Enfin, il est possible de délimiter des variables par des champs numériques :

/* REXX */ execution :

say 'test numeric delimiter enter string ' test numeric delimiter enter string

pull string input =>full monty terrasse test et hop

parse var string premier 6 second 15 trois 25 résultat :

say premier 'deux : ' second 'trois : ' trois FULL deux : MONTY TER trois : RASSE TEST

Premier contient tout jusqu’à la position 5 incluse, second contient depuis la position 6 jusque 14 incluse et trois 15 à 24 incluses

Mise en forme de données

PARSE EXTERNAL restreint L’INPUT AU CLAVIER (voir chapitre sur le stack).

Sous TSO, il est possible de connaître certaines infos concernant la version du REXX utilise ainsi que l’environnement et le REXX appelant en utilisant PARSE :

parse source env ici tout le contenu de source est envoye dans la variable ENV

parse version sysrx versrx rxinst_date ici des renseignements concernant le produit

REXX, type de Rexx, version, date d’installation.

Lecture et ecriture de fichiers

Ceci étant une doc TSO-REXX, il m’apparait important de parler de l’ecriture et lecture de fichiers.

Comme en JCL, il est nécessaire d’allouer les fichiers à utiliser, ceci ce fait par la commande TSO ALLOC :

"ALLOC FI(EXOOUT) DA('"USERID()".test.exo') new catalog Space(5,2) TRACK “, " RECFM(F B) " BLKSIZE(29720) LRECL(80) REUSE".

Cette allocation influe sur l’EXECIO, ainsi une alloc de MOD permet de rajouter des enregistrements a la fin du fichier

  1. lecture d’un fichier :

« execio Number diSkR DDNAME pos (finis »

Number le nombre de lignes a lire, ou * pour lire tout le fichier

Pos la position de la ligne à lire ou a partir de laquelle on lit. Ce chiffre est

facultatif.

exemple : lecture totale d’un fichier fixe existant

/* REXX */

"ALLOC FI(EXOOUT) DA('HH594D.EXOOUT.EX01') shr reuse"

"execio * diskr exoout (finis"

do I=1 to queued()

pull whatever

say whatever

end

Notez :

Le fichier étant alloue préalablement et rempli, point n’est besoin de lui spécifier les attributs du dit fichier. Dans cet exemple, le fichier contient des numéros de téléphone et des villes :

****** ***************************** Top of Data *********************

000001 eric bouladoux 26.20.28.92 lux

000002 rene van broken 03.82.75.62.59 kuntzig

000003 gustave eiffel 03.82.88.72.41 basse ham

****** **************************** Bottom of Data *******************

La fonction Queued() sera vue avec le STACK, mais ici il permet de savoir le nombre de lignes du fichier. Dans la commande EXECIO le paramètre STEM assigne un nom de variable accessible par le ‘nom de la variable’.‘Position dans le stack’.

Lecture et ecriture de fichiers

La position dans le stack est spécifiée par la variable attribuée à la boucle :

"ALLOC FI(EXOOUT) DA('HH594D.EXOOUT.EX01') shr reuse"

"execio * diskr exoout (stem ex. finis"

do I = 1 to ex.0

say ex.i ‘is arg ‘ I

end

Après avoir manipulé le stack vous vous apercevrez que l’utilisation de STEM permet de récupérer plus facilement les arguments du fichier.

POSITIONNEMENT DANS LE FICHIER :

1 en utilisant la commande execio avec un positiionnement (pos dans l’exemple de début).

"execio 1 diskr inf 2 (stem x. finis" say x.0 x.1

2 En passant par la technique du SKIP :

"execio 1 diskr inf (skip "  on skip une (1) ligne

"execio 1 diskr inf (stem x. finis"  on lit donc la deuxieme (2eme) ligne

say x.0 x.1 "free fi(infile)" 

Dans ces exemples on voit l’utilisation de variables dans des tableaux à deux dimensions (voir page 11), en REXX elles ont le format stem.ext ou stem est le nom de la variable et ext est le positionnement dans le tableau.. Notez que X. peut etre remplacer par X . Dans ce cas il faudra remplacer X.i par XI . Mais l’utilisation du format stem.ext est plus intuitif.

Il est aussi possible d’acceder à la directory d’un Partitioned Dataset grace a DISKR, voir chapitre particularité MVS.

Lecture et ecriture de fichiers

b.Ecriture d’un fichier :

Comme pour la lecture, la commande d’allocation influence l’accès au fichier, ainsi, une alloc en disp SHR ou OLD écrasera le fichier alors que MOD le mettra à jour par la fin, une alloc en NEW suivi de CATALOG créera et cataloguera le fichier.

/* REXX */

"delete '"userid()".test.exo'"

"ALLOC FI(EXOOUT) DA('"USERID()".test.exo') new catalog Space(5,2)",

"TRACK RECFM(F B) BLKSIZE(27920) LRECL(80)"

parse source hh Ë KKk ll mm nn

queue 'hello ' userid()

queue 'env ' hh Ë kkk

queue 'env ' ll mm nn

"execio " queued() " diskW exoout (finis"

Ce petit REXX va écrire des informations concernant votre procédure de LOGON et l’EXEC appelant dans un fichier (EXOOUT).

Ici, j’ai utilisé la fonction queud() plutot que la paramètre * de la commande EXECIO car ce paramètre attend une ligne vide comme ordre de fin d’input (ce qui ne l’empêche pas d’etre écrite dans le fichier)..

Pour vous entraîner, écrivez un REXX pour écrire la date, l’heure, le userid, la version du REXX que vous utilisez ainsi que l’année d’installation dans un fichier NON-existant.

Lecture et ecriture de fichiers

  1. Update d’un fichier :

Il est possible d’updater une ligne dans un fichier, pour ce faire il faut le lire et traiter les infos ligne par ligne, grâce a la commande EXECIO DSKRU.

Faire un diskru sur la ligne à lire et garder, Modifier la ligne lue, Faire un diskw d’une ligne.

Format du diskru :

"execio k diskru exoout C ( stem m." K est le nombre de ligne a updater C est le numero de ligne a updater

Dans cet exemple on update la dernière ligne

/* REXX */

"ALLOC FI(EXOOUT) DA('"USERID()".test.exo') shr "

"execio * diskr exoout (finis"  on lit totalement et ferme le fichier

C=queued()

"execio 1 diskru exoout " C "( stem m."

Say m.1

m.1=strip(m,l,t,”)

M.1=m.1 !!' updated at :' time()

ligne.

push M.1

"execio 1 diskW exoout (finis"

qu’elle a ete lue

say rc ' rc on write '  la function queued() nous retourne le nombre de lignes.

on recupere la derniere ligne et on la holde pour update.

colle ‘updated ‘ et l’heure au cul de la

Met la variable M1 dans le stack

elle est ecrite a la meme position

DSKRU est peu employé. Mais diskr et diskw sont communément utilises. Pour vous entraîner, reprenez l’exemple d’écriture et updatez la 3eme ligne par exemple.

Le stack

REXX a un ‘data STACK’ ou ‘pile de données’ accessible par les instructions : «PUSH» « QUEUE» et «PULL». PULL (PARSE PULL comme vous le savez) va chercher dans le stack, Les données entres au clavier vont directement dans le stack donc s’il y a quelque chose dans le stack Il vaut mieux utiliser l’instruction « PARSE EXTERNAL » pour limiter l’entrée de données au clavier.

/* REXX */ Accède le stack Rexx

queue "Hello!"

parse pull a /* a contains "Hello!" */

parse pull b /* b is input from the user */

push "67890" push "12345"

parse pull c /* c contains "12345" */

La différence entre les instructions PUSH et QUEUE se voit lorsque que ce qui a été pushé et queué est récupéré

«QUEUE» les donnes sont recuperees dans l’ordre ou elles ont été queuees (FIFO)

«PUSH » c’est l’inverse. (LIFO).

Si la queue (pile) contient un mélange de données (« QUEUED » et PUSHED ») les données «pushed» seront prises les premières.

Le stack est utilise pour passer des données dans un programme REXX, entre programme REXX, a des subroutines, il peut même être utilise pour passer des données entre un programme REXX et un programme COBOL ou assembleur.

Avant d’attaquer le stack, il est préférable de s’assurer qu’il est vide :

/* REXX */

if queued()>0 then do c=1 to queued()

pull .

end

Avant de continuer avec les routines, deux instructions à utiliser avec ces routines : «NEWSTACK » et « DELSTACK » : elles permettent de créer et détruire un stack au-dessus de celui en cours isolant ainsi les données de l’appelant des données d’exécution de l’appelé.

Interpret

Cette instruction exécute le contenu d’une variable.

Par exemple 2 variables sont passées à un pgm l’une d’elle est une opération arithmétique (‘-‘,’+’) l’autre est un chiffre, je passe au rexx mes deux valeurs lors de l’appel et le pgm va effectuer l’opération avec un chiffre hardcoder (5) et le chiffre passé :

/* rexx */

arg ope num

say ope 'is operation' oper='j=5'!!ope!!num interpret oper

say j

Dans une instruction IF THEN ELSE on peut assigner une variable si une condition est rencontrée sinon on execute une instruction..

La manipulation de données est l’un des points forts de REXX. Il est donc important de bien le comprendre.

fonctions et sous routines

Cette partie n’est pas importante à ce stade... Pourtant par expérience elle m’apparaît vitale pour la compréhension de l’exécution d’un programme REXX et peut aider a comblé certaines lacunes de l’interpréteur sous TSO.

Il existe trois sortes de fonctions : Built-in (livrées avec le langage), interne et externe.

Built-in :

Le Rexx Summary contient une liste de fonctions disponibles en REXX. Toutes ces fonctions peuvent recevoir des paramètres :

 /* REXX */

say date("W")',' date()  

affichera (le vendredi 22 mai 1992) "Friday, 22 May 1992".

Pour appeler une fonction il suffit d’écrire son nom suivi de l’argument ou paramètre entre parenthèses sans blanc entre le nom et la parenthèse ouvrante car le blanc serait considéré comme opérateur de concaténation..

Ici, je vais présenter les plus utiles :

Les fonctions de temps (date, heure, etc...)

Il existe une fonction date dont la réelle utilisation semble mal perçue, la fonction date : Les classiques :

DATE() retourne DD Month CCYY – pareil que DATE(‘Normal’).

DATE(‘Base’) retourne le nombre de jours écoulés depuis le premier jour de l’an 1.

DATE(‘Century’) retourne le nombre de jours écoulés depuis le début du siècle.

DATE(‘Days’) retourne le nombre de jours écoulés depuis le début de cette

année.

DATE(‘European’) retourne le date au format européen.

Pour le reste trouvez vous le manuel REXX d’IBM. Maintenant voyons un exercice plus marrant :

month = Date('Month', 177 ,'Days')

traduire par retourne moi le mois du 177ème Jour de l’année say DATE('B','07/02/02','E')

Renvoie-moi la base date de la date passée au format européen

En clair, le format d’appel de la fonction date est : DATE(‘X’,’argument’, ‘y’)

X est ce que l’on veut recevoir (date en Base, US, Euro ?) argument est la valeur a traité

Y le format de la valeur passée (date en Base, US, Euro ?) . fonctions et sous routines

Ecriture de fonctions

Tout d’abord, la différence entre SUBroutines et functions :

Une ‘SUB routine’ – sous-routine – n’a pas besoin de valeur derrière son return de fin, mais il peut y en avoir une auquel cas l’appelant recevra le résultat dans la variable result

Elle est appelle par CALL.

Elle partage les variables du programme principal.

Elle ne peut etre qu’interne

ARG en en-tete est optionel

Une function –fonction-

a besoin de valeur derrière le return.

ARG en entete est obligatoire

Peut etre externe ou interne

Elle ne recupere qu’une ligne à la fois (pas de tableau)

REXX permet à la plupart des fonctions d’être appelées comme une sous-routine (CALL) Que ce soit lors d’un appel a une sous-routine ou une fonction, les arguments passés doivent suivre le même format qu’a la réception.

Fonctions internes

Voici un exemple de fonction interne :

/* REXX */   Define a function   

say "The results are:" square(3) square(5) square(9) exit   

on s’arrete ! ! !  

square: /* function to square its argument */   le label  

parse arg in     on recoit l’argument 

return in*in     on renvoie tout en calculant

l’output aura cette ‘tronche’ : "The results are: 9 25 81"

Quand REXX trouve l’appel à la fonction (nom(arg)) SQUARE(3) il recherche un label de ce nom – un label commence en colonne 1 et se termine par deux points ‘:’ – il l’exécute jusqu’a la première expression RETURN qui dans notre cas calcul le carre d’un argument en input. l’EXIT de fin de programme évite a celui ci de continuer dans la fonction après le say.

 fonctions et sous routines

Ce type de fonction est intéressant si un morceau de code n’est utilise que dans un seul programme et ce plusieurs fois.

/* Define a function with three arguments */

say "The results are:" conditional(5,"Yes","No") conditional(10,"X","Y")

exit

conditional:

/* if the first argument is less than 10 then return the second, else return the third. */

parse arg c,x,y

if c<10 then return x

else return y

Il est important de noter le point suivant : l’appelant doit passer les arguments comme l’appelé les attend.

Ainsi si les arguments sont reçus avec une virgule comme séparateur, l’appelant devra respecter ce format.

De plus, si la sous-routine ou fonction doit être appelée directement, le seul moyen de séparer les arguments passés est l’espace.

Afin de protéger les variables de l’appelant, on peut utiliser l’instruction PROCEDURE qui préparera un nouveau jeu de variables pour l’exécution de l’appelé SEULEMENT, les variables de l’appelant ne sont plus accessibles par l’appelé.

Pour passer des variables (rendre visibles) de l’appelant vers l’appelé on utilise EXPOSE surtout si on a utilise PROCEDURE dans le codage de l’appelé. :

/* REXX */

parse pull x .

say x"!="factorial(x) exit Calculate factorial x, that is, 1*2*3* ... *x

factorial: Calcule la factorielle de

l’argument

/* REXX */

procedure

parse arg p

if p<3 then return p

else return factorial(p-1) * p

Un nouveau paramètre est apparut dans l’exemple précédent, PROCEDURE dont le but est de protéger les variables du programme appelant des instructions de l’appelé. Ce type de paramètre est surtout utile lors du codage de fonctions internes Fonctions Externes :

Ce type de fonction se code comme une fonction interne, la différence étant que l’appelant ne contient pas le code appelé, mais celui ci est stocké dans un fichier à part (généralement un PDS alloué au même DDNAME que l’appelant – SYSPROC, voire SYSEXEC).

Il permet de palier aux ‘oublis’ d’IBM. Ex. : une fonction linein pour lire un certain numéro de ligne dans un fichier sans passer par l’instruction EXECIO.

IBM conseille de permettre aux fonctions externes de pouvoir être appelées soit en tant que fonction soit en tant que Sous-routine comme c’est le cas pour leurs fonctions built-in. Les fonctions seront utilisées surtout pour coder des utilitaires à utilisation récurante (formatage de date, fonction linein, lineout, etc...) appelable par d’autre EXEC, alors que les sous-routines seront codées à usage interne (dans le programme).

De plus, il est conseillé d’avoir un standard de codage de fonctions au niveau de la réception des paramètres, à savoir soit les arguments sont séparés par une virgule (le choix d’IBM.) soit ils sont séparés par un blanc.

Enfin, pour en terminer avec les fonctions, différentes invocations de la même fonction : Fonction FUNC01 :

/* REXX */ TRACE OFF ARG VAL1,VAL2 JJ=VAL1 * VAL2 RETURN JJ

Appelée comme fonction :

/* REXX */ say func01(5,2)

Appelée comme une sous-routine (externe) :

/* REXX */ call func01 5,2 say result

Liste de fonctions : (1/3)

num = ABS(number) valeur absolue d’un nombre

str = ADDRESS() interroge l’environnement courant

num = ARG() retourne le nombre d’arguments

val = ARG(n) retourne le nth argument

bit = ARG(n,'Exists') l’argument numero N existe ?

bit = ARG(n,'Omitted') l’argument N a ete omis ?

str = BITAND(str1[,[str2][,pad]]) Logically and strings

str = BITOR(str1[,[str2][,pad]]) Logically or strings

str = BITXOR(str1[,[str2][,pad]]) Logically xor strings

str = B2X(str) Binaire vers Hex (0F=00001111)

str = CENTER(str,length[,pad]) centrer str

str = CENTRE(str,length[,pad]) CENTER pour les anglais (hunour cowlishawesque)

str = CHARIN([name][,[start][,length]]) lecture de name, start –a partir de, length – sur-

num = CHAROUT([name][,[start][,length]]) ecrire dans name , aprtir de, sur

bit = CHARS([name]) il y a t’il quelquechose dans name ?

cix = COMPARE(str1,str2[,pad]) comparaison de str1 et str2 0 ou premiere différence

str = CONDITION('Condition') nom de la condition capturée

str = CONDITION(['Instruction']) retourne le type (CALL ou Signal)

str = CONDITION('Description') Description or null

str = CONDITION('Status') ON, OFF, or DELAY

str = COPIES(str,n) N copies de str

rc = CSL('rtnname retcode parms') Callable services library

num = C2D(str[,n]) Caaractere vers decimal

str = C2X(str) Caractère vers Hexadecimal

str = DATATYPE(str) NUM ou CHAR

bit = DATATYPE(str,type) STR correspond a type ?

str = DATE() date du jour(dd Mmm yyyy)

str = DATE(dopt) Date info (voir l’exemple date)

... = DB...(str,...) 13 DBCS support functions

str = DELSTR(str,n) Delete str de n jussqu’a la fin

str = DELSTR(str,n,length) Delete str a partir de n sur length

str = DELWORD(str,n) Delete le mot de n jussqu’a la fin

str = DELWORD(str,n,length) Delete wix a partir de n sur length

str = DIAG(hex[?][,data][,data]...) ? displays diagnostics

str = DIAGRC(hex[?][,data][,data]...) rtourne CP codes (VM)

str = D2C(wholenumber[,n]) Decimal vers Caractère

str = D2X(wholenumber[,n]) Decimal vers Hexadecimal

str = ERRORTEXT(n) texte msg d’erreur associé avec le RC n (0-99)

num = EXTERNALS() See PARSE EXTERNAL

wix = FIND(str,arg) 0=not found; preferez WORDPOS

str = FORM() verifie le format numérique

str = FORMAT(num[,[before][,[after]]]) Around decimal place

str = FUZZ() Query NUMERIC FUZZ

cix = INDEX(haystack,needle[,start]) Default start=1; prefer POS

str = INSERT(new,str[,[n][,[length][,pad]]]) Insert after cix n

str = JUSTIFY(str,length[,pad]) Right-left justify

cix = LASTPOS(needle,haystack[,start]) POS de droite a gauche.

str = LEFT(str,length[,pad]) aligne a gauche

num = LENGTH(str) longueur de str.

str = LINEIN([name][,[line][,count]]) list la ligne de name

bit = LINEOUT([name][,[string][,line]]) ecrit dans name

num = LINES([name]) Input nombre de lignes restante en input

num = LINESIZE() longueur de ligne du terminal (VM)

num = MAX(num[,num...]) Maximum (jusque 10 chiffres)

num = MIN(num[,num...]) Minimum (jusque 10 chiffres)

str = OVERLAY(new,str[,[n][,[length][,pad]]]) remplace str par new a partir de n sur lentgh

cix = POS(substr,str[,n]) position de substr dans str a partir de n 0=not found

num = QUEUED() nombre de lignes dans la pile

num = RANDOM() nombre entire au hasard 0-999

num = RANDOM([min][,[max][,seed]]) nombres entier se suivant au hasard

str = REVERSE(str) retourne str

str = RIGHT(str,length[,pad]) aligne sur la droite

num = SIGN(num) signe de num -1, 0, or 1

num = SOURCELINE() nombre de lignes dans fichier exec appelant

str = SOURCELINE(n) nieme ligne du fichier appelant

str = SPACE(str[,[n][,pad]]) arrance les blancs

hex = STORAGE() taille de la memoire virtuelle en hex

hex = STORAGE(address,length) lecture memoire virtuelle

hex = STORAGE(address,length,data) ecriture dans la memoire virtuelle

str = STREAM(name[,'State']) etat dustream

str = STREAM(name,'Description') State of stream, more detail

str = STREAM(name,'Command',cmd) appliquer la commande au stream

str = STRIP(str[,[option][,char]]) L, T, ou default=Both retirer caractere de str (ou blanc –defaut).

str = SUBSTR(str,firstcix[,[length][,pad]]) Substring

str = SUBWORD(str,firstwix[,length]) Def length=rest of string

str = SYMBOL(name) State: BAD, VAR, or LIT

str = TIME() heure (hh:mm:ss)

str = TIME(topt) info heure

str = TRACE() montre les options de trace

str = TRACE(option) change l’option de trace

str = TRANSLATE(str[,[new][,[old][,pad]]]) Map old to new

num = TRUNC(num[,n]) tronque num a n decimal

str = USERID()logon userid

val = VALUE(name) interroge sur la valeur de name

val = VALUE(name,val) change la valeur de name

val = VALUE(name[,val],selector [groupname]) GLOBAL/LASTING/SESSION var

cix = VERIFY(str,okchars[,['Nomatch'],start]) First bad cix; 0=all ok

cix = VERIFY(str,okchars,'Match'[,start]) First good cix; 0=none

str = WORD(str,wix) extrait le nieme mot

cix = WORDINDEX(str,n) position du nieme mot dans str

num = WORDLENGTH(str,n) retourne la longueur du nieme mot de str

wix = WORDPOS(word,str[,start]) retourne la position du mot word dans str (depuis start).

Liste de fonctions : (3/3)

Il existe 6 fonctions NON-SAA disponibles sous TSO (elles ne sont pas forcement disponibles dans d’autres environnements IBM). :

EXTERNALS, FIND, INDEX, JUSTIFY, LINESIZE, and USERID. If you plan to write REXX programs that run on other SAA environments, note that these functions are not available to all the environments.

EXTERNALS - returns the number of elements in the terminal input buffer (always 0 for TSO/E)

FIND - returns the word number of a substring in its string (for SAA use WORDPOS) INDEX - returns the position of one string within another string (for SAA use POS) JUSTIFY - returns a formatted string from blank-delimited words to justify both margins LINESIZE - returns the current terminal line width minus 1

USERID - returns the TSO/E user ID

TSO/E External Functions

GETMSG – recupère les messages d’une session console TSO/E CONSOLE dans des variables

LISTDSI – retourne des information sur des fichiers

MSG – retourne la valeur de display des message TSO (peut la modifier) ON/OFF.

MVSVAR – retourne des informations systèmes mvs dans des variables.

OUTTRAP – sert a capturer l’output de commandes TSO dans des variables

PROMPT - returns / sets the current value of TSO/E command prompting within an exec

SETLANG - returns / sets a code that indicates the langageof displayed REXX messages

STORAGE – affiche la memoire virtuelle comprise entre 2 valeurs (modif possible).

SYSCPUS – retourne des informations sur les CPUs dans une variablecomposée.

SYSDSN retourne des informations sur l’existance d’un dataset.

SYSVAR – retourne des informations sur une variable spécifié.

Vous pouvez utiliser les functions MVSVAR, SETLANG, STORAGE and SYSCPUS dans n’mporte quel espace addresse, TSO/E et non-TSO/E., pour les autres, il est nécessaire d’executer dans un espace adresse TSO/E.

 REXX S390er

DEBUGGING and tracing errors Execution de commandes

REXX peut être utilisé sur de nombreuses plate-formes (Windows, VM, UNIX, MVS, VSE). Voici ce qui se passe quand un REXX est exécuté :

Quand REXX (l’interpréteur) rencontre une ligne qui ne ressemble pas à une instruction (REXX) ou à un assignement de valeur a une variable (c=’2’) il evalue la ligne et l’envoie à l’environnement (sous TSO cela peut être TSO, ISPF, MVS, ou tout autre environnement appelé par la commande ADDRESS ).

Par exemple :

/* REXX */

say ‘addressing ispexec ‘ address ispexec

« Display panel(TESTP) »

/* REXX */

say ‘addressing ispexec ‘

« Display panel(TESTP) »

 Execution

addressing ispexec

Affiche le panel TESTP

addressing ispexec

IKJ56500I COMMAND DISPLAY NOT FOUND 3 *-* "DISPLAY PANEL(TESTP)"

+++ RC(-3) +++

Dans le 2eme cas la commande n’est pas trouvée dans l’interpréteur REXX ni dans les commandes TSO.

Les environnements disponibles en REXX sous MVS sont : MVS, TSO, ISPF (ISPEXEC), l’éditeur ISPF (ISREDIT), la linklib (LINK).

L’instruction ADDRESS() permet de connaître l’environnement courant..

Signal

Les COBOListes peuvent comparer cette instruction au GOTO, en effet, le programme ‘saute’ directement au label spécifié. Un label est aussi utilisé dans le codage de FONCTIONS INTERNES, et c’est d’ailleurs le même type – LABEL: en colonne 1-. Le hic, c’est que Signal nettoie derrière lui, en clair si on ‘signal ‘ dans une structure de contrôle, il est impossible d’y revenir. Voilà pourquoi SIGNAL est surtout utilisé pour trapper les erreurs afin de sortir proprement du programme.

Il est possible de limiter le ‘trap’ à certaines conditions :

"syntax" (Erreur de syntaxe), "error" (toute commande d’environnement ne reournant pas un code retour Zero), "halt" (interruption d’execution – PA1-) et "novalue" (un symbole n’a pas de valeur).

La capture de ces erreurs se déclenche par signal on <condition> « s ‘éteint » par signal off <condition> 


102