Le web de Dominique Guebey – IBM AS/400 iSeries

Page : http://www.dg77.net/tekno/as400/rpg4.htm


   D o m i n i q u e   G u e b e y    J u n g l e      IBM AS/400 iSeries

Notes sur le langage RPG IV et ILE

Sommaire

Définitions

RPG IV est l'évolution du RPG III apparue avec la V3R1 de l'AS/400 sous le nom de ILE RPG for AS/400. La dénomination ILE signifie simplement qu'un programme écrit en RPG IV peut être compilé comme module ILE, mais il n'y a là aucune obligation. Les améliorations du RPG IV sur le III sont principalement :


Différences entre OPM et ILE

Les programmes non ILE sont dits OPM (Original Program Model). Dans le modèle OPM classique, un source est compilé en un programme exécutable.

La création d'un programme ILE passe par un processus en deux étapes. D'abord les sources sont convertis en modules (objets de type *MOD). Ceci se fait par l'option 15 sous PDM ou la commande CRTRPGMOD. Ensuite, un ou plusieurs modules sont liés en un exécutable (CRTPGM). Une des forces du concept d'ILE est qu'on peut lier des modules écrits dans différents langages : RPG, COBOL, C...

La commande CRTBNDRPG (option 14 sous PDM) (create bound RPG) réalise d'une façon transparente (dans QTEMP) la double opération (CRTRPGMOD et CRTPGM). Si on veut voir par WRKPGM des attributs (ex: date de modification) d'un programme ILE, il faudra chercher dans la liste des modules qu'il contient puis examiner le(s) module(s) qu'on veut connaître. Le programme ILE contient normalement une copie des modules qui ont été liés ; une exception notable se trouve dans les programmes de service, qui font référence à des modules externes.


Conversion RPG III - RPG IV et première compilation

La commande CVTRPGSRC convertit un source RPG III en RPG IV : CVTRPGSRC FROMFILE(biblio/fich.source) FROMMBR(membre) TOFILE(biblio/fich.source) TOMBR(membre)

En cas de message "Log file QRNCVTLG in library *LIBL not found", copier (CRTDUPOBJ) le log QARNCVTLG de QRPLE dans un QARNCVTLG d'une bibliothèque figurant dans la *LIBLISTE. Ou : spécifier LOGFILE(*NONE) dans la commande CVTRPGSRC. S'il y a des clauses "/copy", ne pas oublier de convertir les membres concernés.

Dans PDM, compiler avec l'option 14. La commande CRTBNDRPG est utilisée à la place de CRTRPGPGM. C'est une compilation en une phase, au lieu de la compilation en deux étapes des programmes ILE.


Minuscules et longs noms de zones

Utilisation des minuscules et majuscules, et longueur des noms de variables

« Case-tolerance »
Il est maintenant possible d'utiliser les minuscules dans les programmes. Noter que la TOLERANCE n'est pas la même chose que la SENSIBILITE (case-sensitivity) à la casse. Celà signifie qu'en RPG IV, les expressions "Z-ADD *ZERO ITEMNUMBER", "z-add *zero itemnumber" et "z-add *zero ItemNumber" seront les mêmes pour le compilateur. Ceci ne s'applique pas aux littéraux exprimés entre-guillemets : "call 'TOTOCHE'" est différent de "call 'Totoche'".
Longs noms de zones
Finie la limitation à 6 caractères. Maintenant la limite est de 4096... En pratique, on évitera les noms de plus de 15 caractères qui imposent des complications.
Préfixes et "souligné"
Il est possible de préfixer les zones en fonction de leur origine. Par exemple "@" pour les variables définies par le programme. On a droit aussi à l'UNDERSCORE ("_") dans les noms de zones.

Carte H

Spécification de contrôle (ou Header). Maintenant en format libre, il est possible d'en mettre plusieurs. Exemple en RPG III :

*...1....+....2....+....3....+....4....+....5....+....6....+....7... 
H Y

La même en RPG IV :

*...1....+....2....+....3....+....4....+....5....+....6....+....7... 
H Datedit(*YMD)

Il existe de nombreux mots-clef. En général ils permettent d'outrepasser les options par défaut à la compilation. Certains permettent d'utiliser les fonctionnalités avancées d'ILE

BNDDIR('repertoire-de-liaison' {:'repertoire-de-liaison'...})
Donne le(s) répertoire où les modules sont liés.
DATEDIT(fmt{separator})
Spécifie le format de UDATE et *DATE (*DMY, *MDY, *YMD)
DATFMT(fmt{separateur})
Spécifie le caractère séparateur de date. Par défaut, c'est *ISO (ssaa/mm/dd).
DEBUG{(*NO | *YES)}
Déclenchera un DUMP (défaut : *NO)
NOMAIN
Option destinée aux modules. Le compilateur ne générera pas la partie du code prenant en compte le cycle RPG (« cycle GAP ».
OPTION(*{NO}SRCSTMT *{NO}DEBUGIO)
Deux options intéressantes parmi d'autres. OPTION(*NOSRCSTMT) provoque la renumérotation (à éviter) ; *NODEBUGIO provoque une interruption une seule fois par le débugueur interactif (sinon : ce sera pour chaque entrée/sortie).

Exemple :

*...1....+....2....+....3....+....4....+....5....+....6....+....7... 
H datedit(*YMD) datfmt(*ISO) option(*SRCSTMT *NODEBUGIO)

Si on ne met pas de carte H en tête de programme, le compilateur recherchera une data area nommée RPGLEHSPEC dans la *LIBL. Il peut y en avoir plusieurs.


Cartes F

Peu de modifications dans les specs F. Il n'y a plus de continuation ("K"), les paramètres les plus courants sont déplacés à gauche ; les autres sont passés en format libre.

*.. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 ...+... 9 ...+... 10
FFilename++IPEASFRlen+LKlen+AIDevice+.Keywords+++++++++++++++++++++++++++++Comments+++++++++++++

La partie droite contient les mots-clef en format libre. Par exemple SFILE est devenu SFILE(enrformat: rrnzone). Au lieu de "KRENAME", on utilisera le mot-clef RENAME(external-rec-name: internal-rec-name). Noter la très utile spécification PREFIX(chaine) qui permet de renommer toutes les zones d'un fichier à description externe en leur attachant un préfixe, ce qui permet de résoudre simplement le problème des homonymies de noms de zones.


Cartes D et nouveaux types de données

En RPG IV, les spéclifications I servent uniquement à définir les fichiers à description INTERNE, les spécifications D concernent toutes les autres données. Outre les data structures, on peut définir des constantes nommées et des zones fixes. La position 24-25 identifie le type d'élément utilisé.

*.. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 ...+... 9 ...+... 10
DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords+++++++++++++++++++++++++++++Comments++++++++++++
DS
Structure de donnée
C
Constante nommée. La valeur est fixée par le mot-clef CONST(value).
S
Zones fixes ("stand-alone"), déterminées par le mot-clef INZ(valeur)
PI et PR
Définition de procédures d'interfaces et de prototype (voir plus loin)

Les cartes D permettent d'initialiser toutes les zones en un seul endroit du programme, au lieu de les disperser dans les spécifications de traitement. Il est permis d'indenter les enregistrements, ce qui facilite la lecture. Outre INZ et CONST, noter quelques mots-clefs intéressants :

DIM(constante_numerique)
Remplace les spécifications E pour définir une table (table) ou un tableau (array). En association avec DIM, on peut utiliser les mots-clefs CTDATA, FROMFILE et TOFILE. CTDATA fait référence aux données chargées à la compilation (décrites en fin de membre source). FROMFILE et TOFILE concernent les fichiers lus ou chargés à l'exécution.
DTAARA{(nom_data_area)}
Associe une donnée avec une data area externe. S'il s'agit d'une structure de donnée ("DS" en positions 24-25) et qu'un "U" figure en 23, la data area est récupérée à l'initialisation du programme, et mise-à-jour à la fin de celui-ci.
EXPORT{(nom_externe)} et IMPORT{(nom_externe)}
Partage de données entre modules d'un programme ILE
LIKE(nom_RPG)
Utilise le même type et longueur d'une autre zone.
OCCURSconstante_numerique)
Spécifie le nombre d'occurences d'une structure de donnée multiple.
OVERLAY(nom{:pos | *NEXT})
Redéfinie une structure de donnée ou une de ses parties.
DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords++++++++++++++++++++++++++++
D DataStructure   DS
D  Zone1010                     10
D   Zoneto5                      5    overlay(Zone10)
D   Zone6a10                     5    overlay(Zone10:*next)

De nouveaux types de données sont apparus, notamment :

Support horodatage : Date (D), Time (T), et Timestamp (Z)
Timestamp combine la date et l'heure (en micro-secondes) en une seule zone. INZ(*SYS) permet d'initialiser la valeur en cours sur le système 
DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords++++++++++++++++++++++++++++
D @CurrDate       S               D   inz(*sys)
D @CurrTime       S               T   inz(*sys)
D @CurrTimestmp   S               Z   inz(*sys)
Virgule flottante (F)
DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords++++++++++++++++++++++++++++
D @Float S 4F
D @FloatDouble S 8F
En simple précision, la valeur peut aller de 1.1754944-38 à 3.4028235+38. En double precision, ce sera 2.225073858507201-308 à 1.797693134862315+308.
Indicateurs (N)
On peut créer ses propres booléens et s'affranchir ainsi de la limite ancienne des 99 indicateurs du RPG.
Pointeurs (*)
Utilisés avec le mots-clefs BASED, et les options ALLOC et DEALLOC.

Cartes C

A côté du mélange minuscules-majuscules, la structure des spécifications de traîtement (C="calculation") a beaucoup évoluée. A cause d'abord des noms longs de zones, et aussi du fait d'opérations qui peuvent maintenant s'exprimer en format libre.

Format fixe

*.. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 ...+... 9 ...+... 10
CL0N01Factor1+++++++Opcode(E)+Factor2+++++++Result++++++++Len++D+HiLoEq....Comments+++++++++++++

Format libre

*.. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 ...+... 9 ...+... 10
CL0N01Factor1+++++++Opcode(E)+Extended-factor2+++++++++++++++++++++++++++++Comments+++++++++++++

Noter que PDM présente par défaut les lignes RPG IV à partir de la position 6. Noter aussi qu'il n'y a qu'un indicateur conditionnel au lieu de 3 par ligne ; utiliser des instructions conditionnelles (IF...) plutôt que des jeux d'indicateur. A présent les Facteurs 1 et 2 acceptent des noms de 14 caractères, ce qui permet d'utiliser des noms plus "parlants" qu'avec 6. Une bonne pratique est de ne pas succomber à la facilité de définir une zone en carte C mais en carte D. Le nom des codes opération a lui aussi été allongé, ce qui fait maintenant qu'on a DELETE (au lieu de DELET), LOOKUP (au lieu de LOKUP), BITOFF (au lieu de BITOF)...

Facteur 2 étendu
Un certain nombre de codes opérations RPG IV bénéficient de la nouvelle structure. On peut ainsi entrer des expressions en format libre et utiliser les fonctions intégrées ("Built-in-functions")
Toutes les opérations de comparaison (IFEQ, DOWLT, etc.) peuvent utiliser le format libre. Par exemple
CL0N01Factor1+++++++Opcode(E)+Factor2+++++++
C *in99 ifeq *off
C client# andne @SaveCli#
peut être écrit ainsi :
C if *in99 = *off and
C client# <> @SaveCli#
Les deux fonctionnent aussi bien, mais le format libre est plus lisible. Noter que le facteur 1 est inutile, est que ANDxx ou ORxx ne sont pas nécessaires pour continuer l'expression sur la ligne suivante.
On peut aussi utiliser des parenthèses.
C if (*in99 = *off and
C Client# <> @SaveCli#) or
C (Client# = *blanks or
C Client# = '00000') or
C (*in03 = *on)
Les expressions en format libre peuvent inclure des opérations
C if x = y + z and 
C (a = (b * c) - d) or 
C (Client# = *blanks or
C Client# = '00000') or
C (*in03 = *on)
Opérations qui autorisent le facteur 2 étendu
IF (RPG III : IFxx -IFEQ, IFLE, etc.)
DOW (RPG III : DOWxx)
DOU (RPG III : DOUxx)
WHEN (dans un groupe SELECT) (RPG III : WHxx)
EVAL
EVALR (nouveauté de la V4R4)
FOR (nouveauté de la V4R4)

Voir la documentation IBM pour une description complète des instructions.


Opérations EVAL et EVALR

La nouvelle opération EVAL permet d'assigner des valeurs aux variables par une expression en format libre. EVAL a les possibilités de Z-ADD, MOVEL, ADD, SUB, MULT, DIV.

C eval x = y + z
C eval @String = "Midware Services"

Formulation en format RPG classique

D @DailyRate      S              4F
C     @WeeklyRate   div      7              @DailyRate
C     @NumberDays   mult     @DailyRate     @InvoiceAmt

Utilisation de EVAL (noter qu'on se passe alors de la zone de travail @DailyRate.

C eval @InvoiceAmt = (@WeeklyRate / 7) *
C @NumberDays

Avec des zones alphanumériques, EVAL fonctionnera comme MOVEL, inversement EVALR callera à droite comme MOVE

Attention : si la zone numérique résultat est trop courte, le nombre ne sera pas tronqué comme avec Z-ADD, MULT etc. Il y aura un message d'erreur à l'exécution, ce qui impose d'inclure une routine *PSSR pour la "monitorer".

Se méfier des outils de conversion automatique offerts par certaines sociétés : les résultats ne sont pas nécessairement les mêmes

C X div Y @Temp
C @Temp mult 3.14159 Z

ne donne pas le même résultat que :

C eval Z = (X / Y) * 3.14159

Support horodatage

Depuis la V3R1, l'AS400 et RPG supportent les types de données de date et heure, ce qui dispense d'écrire laborieusement ses propres routines de calculs, interprétations et comparaison. Toute une série de fonctions permettent de valider, formater, comparer et manipuler des dates et heures. Le développement de fonctions spécifiques s'en trouvera grandement simplifié.

Déclaration de zones de dates/heures. On peut utiliser une DDS ou les cartes D dans le programme. On peut aussi définir des zones timestamp englobant date et heure (jusqu'à la micro-seconde). Dans les cartes D, le mot-clef INZ peut être utilisé.

DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords++++++++++++++++++++++++++++
D @CurrDate       S               D   inz(d'2000-01-01')
D @CurrTime       S               T   inz(t'23:59:59')
D @CurrTimestmp   S               Z   inz(*sys)

*SYS permet d'initialiser la date et l'heure à la valeur système. Il existe différents formats, identifiés par le mot clef DATFMT en carte D ou H. Le format "timestamp" unique est SSAN-MM-JJ-hh.mn.ss.xxxxxx

Liste des autres formats
DATFMT ou TIMFMT Format Exemple
*MDY mm/jj/an 12/31/99
*DMY jj/mm/an 31/12/99
*YMD an/mm/jj 99/12/31
*JUL an/jjd 99/365
*ISO ssan-mm-jj 1999-12-31
*USA mm/jj/ssan 12/31/1999
*EUR jj.mm.ssan 31.12.1999
*JIS ssan-mm-jj 1999-12-31
*HMS hh:mn:ss 13:59:00
*ISO hh.mn.ss 13.59.00
*USA hh:mn am 1:59 pm
*EUR hh.mn.ss 13.59.00
*JIS hh:mn:ss 13:59:00

Les 6 dernières positions de la zone "timestamp" sont des microsecondes. Cette donnée est un moyen pratique d'obtenir une zone-clef unique. Le format par défaut est *ISO sauf format spécifié dans la carte H.


Fonctions intégrées

Les fonctions intégrées (BIF = Built-in-functions) sont une avancée majeure du RPG IV. Il s'agit en fait de procédures fournies par IBM qu'on peut utiliser au sein des expressions RPG (IF, EVAL, etc.) comme de simples variables. Les procédures sont un concept ILE, mais il suffit ici de savoir qu'il et permis d'écrire ses propres fonctions. Toutes les BIF commencent par % (caractè "pourcentage"), beaucoup s'utilisent avec des paramètres passés entre-parenthèse (s'il y a plusieurs paramètres, on les sépare avec ":" La syntaxe est : %name{(parm1{:parm2…})}.

Les BIF peuvent étre utilisées dans toute expression à format libren, elles peuvent être englobées dans une autre BIF. Exemple :

 eval @Index = %int(%abs(@Value))

La BIF %ABS fournit la valeur absolue du paramètre numérlique. %INT donne la partie entière. Dans cet exemple si @index est initialisé à -3.14, le résultat sera 3. Les BIF voient leur nombre régulièrement augmenté. En voici quelques-unes très utiles :

%ABS(expression numérique)
Retourne la valeur absolue (i.e. positive)
%EDITW(numeric : editword) et %EDITC(numeric : editcode {: *ASTFILL | *CURSYM | symbol_monetaire})
Applique un masque ou un mot d'éditio sur une expression numérique.
Exemple :
eval @Message = 'Le solde en cours pour ' +
'Numéro de Sécurité Sociale + 
%editw(@SSN: '0 - - ') + 
' est ' + %editc(@Solde: 'J') 
%EOF{(file_name)}
Remplace l'indicateur de fin de fichier (opérations READ, READE…)
%EQUAL{(file_name)}
Utilisé avec SETLL
%FOUND{(file_name)}
Remplace l'indicateur de non aboutissement (opérations CHAIN, DELETE…)
Exemples :
read file1
read file2
if %eof(file1) or %eof(file2)
:
:
read file1
dow not %eof
:
read file1
enddo
%INT(expression numérique)
Retourne la partie entière
Exemple :
eval @Message = 'Votre facture se monte à ' +
%char(%int(@Mt_Fact)) + ' Euros and '
%char((@Mt_Fact - %int(@Mt_Fact)) * 100)
+ ' centimes')
%LEN(expression)
Donne la longueur de l'expression ou fixe la longueur d'une zone variable.
%SCAN(argument : chaîne source {: début})
Analyse ("scanne") une chaîne de caractères de gauche àdroit. Par défaut, la position de départ est 1. On récupère la 1ère position trouvé. Sinon on récupère zéro.
%TRIM(chaîne)
Supprime les blancs de début et de fin.
%TRIML(string)
Supprime les blancs de début.
%TRIMR(string)
Supprime les blancs de fin.
Exemple :
eval @Name = %trim(@Prenom) + ' ' +
@MiddleInit + '. ' +
%trim(@NomFam)

ILE : le concept

Convertir des programmes OPM en ILE peut exiger beaucoup d'efforts et amener un surcroît de complexité si on veut exploiter tous les avantages du concept. Il convient d'abord d'analyser les besoins et la conception, afin de déterminer jusqu'où il peut être utile de pousser le travail et de choisir une stratégie.

Un des intérêts d'ILE est la possibilité d'avoir les fonctions principales d'une application subdivisées en une multitude de taches élémentaires figurant une seule fois dans le logiciel, d'où une simplification de la maintenance, puisqu'une modification d'un de ces modules élés sera effective immédiatement pour l'ensemble du système.


Notion de procédure ILE

Les procédures sont les briques de base d’une application ILE. Elles peuvent être incluses dans le source ou figurer dans d’autres qui seront compilés en modules. On peut concevoir des procédures constituées d’autres procédures et ainsi de suite. L’idée est de réutiliser au maximum des modules de petite taille.

On commencera par concevoir les fonctions de fondamentales, puis on en fera des ensembles plus élaborés. Ces procédures sont destinées à être appelées par les programmes, comme les subroutines. Cet effort préliminaire sera payant ensuite puisque la programmation consistera pour une part importante à assembler des procédures préétablies. Ce processus permet de gagner du temps, y compris en maintenance, avec une bonne fiabilité. En outre, IBM fournit de nombreuses procédures qui sont déjà installées dans le système. Les procédures offrent les avantages de l’encapsulation, et permettent d’assembler des éléments écrits en différents langages.

Néanmoins, pour bénéficier des avantages d’ILE, on n’est pas obligé de redéfinir du départ toute l’application, des approches plus progressives ou partielles sont possibles.


Procédures internes

Introduction

Une internal procedure est codée à la fin du sources, après les subroutines. Attention :

Définition de la procédure

Une procédure est définie par des spécifications P de début et de fin.

*.. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5
PName+++++++++++..B...................Keywords 

Le B en position 24 indique le commencement d’une procédure. Un E en spécifiera la fin. Un mot-clef export peut être spécifié.

Ci-dessous, on définit une procédure RPG pour dire si une date tombe en semaine ou le week-end. Elle est nommée JourTrav.

P JourTrav B
:
P JourTrav E 
Interface de la procédure

Figure dans les cartes D. Le fonctionnement se compare à *ENTRY PLIST lors d’un appel de programme.

*.. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+
DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords++++
D JourTrav PI N
D @Date D datfmt(*iso) 

Le PI indique qu’on a affaire à une interface de procédure. Le N en position 40 signifie que la valeur récupérée sera de type indicateur (booléen). Dans d’autres cas une longueur pourrait être ajoutée.

La seconde ligne indique qu’un paramètre est attendu (nommé @Date).

Pour les besoins de la procédure, on définit ensuite des variables locales. Noter que le 2 janvier 2000 est un dimanche.

DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords+++++++++++
D @BaseDate S D inz(d'2000-01-02')
D @Jours S 9 0
D @NumeroJour S 1 0
D @JourTrav S N 
Traîtement (spécifications C)
C @BaseDate subdur @Date @Jours:*d
*
C eval @NumeroJour = %rem(@Jours: 7)
*
C if @NumeroJour = 0 or
C @NumeroJour = 6
C eval @JBoulot = *off
C else
C eval @JBoulot = *on
C endif
*
C return @JBoulot 

L’opération subdur met dans @Jours le nombre de jours depuis 1e dimanche 2/1/2000. La fonction intégré REM donne le reste de la division par 7. Si par exemple le reste est 1, ce sera un lundi, etc. Si on est un jour 6 (samedi) ou 0 (dimanche) le booléen @JBoulot sera false.


Appel de Procédure et prototypes

Définition du Prototype

Un prototype nécessite une interface codée dans les spécifications D, comme on l’a déjà vu pour les procédures. Cette interface a quelques particularités : on met PR en positions 24-25 au lieu de PI. Les paramètres n’ont pas besoin d’être exactement ceux qui sont définis dans l’interface de procédure. En fait, ils ne sont même pas nécessaires. Exemple :

D JourTrav PR N
D D datfmt(*iso) 
Appel
Lancement dans le style format libre (comme une fonction intégré)
Exemple (si plusieurs paramètres, les séparer par « : ») :
C if JourTrav(@TestDate1)
C*** faire ceci...
C else
C*** ...sinon cela
C endif 
Lancement à l’aide de Callp
C callp JourTrav(@TestDate3) 
Résumé
Les différentes parties du source rassemblées :
H datedit(*ymd) option(*srcstmt)
* Definit le prototype
D JourTrav PR N
D D datfmt(*iso)

* Quelques zones pour les besoins de la demonstration
D @TestDate1 S D inz(d'2000-04-29')
D @TestDate2 S D inz(d'2000-04-28')
D @TestDate3 S D inz(d'2000-01-02')
 
* Appelle la procedure dans un test
C if JourTrav(@TestDate1)
C*** faire ceci...
C else
C*** ...faire cela
C endif

* Appelle la procedure dans un EVAL
C eval *in99 =
C JourTrav(@TestDate2)

* Appel avec CALLP...
C callp JourTrav(@TestDate3)

* FIN de programme...
C eval *inlr = *on
*======================================================*
* JourTrav: Determiner si on est un jour de semaine
P JourTrav B

D JourTrav PI N
D @Date D datfmt(*iso)

* Definir @BaseDate comme etant un dimanche
D @BaseDate S D inz(d'2000-01-02')

D @Jours S 9 0
D @NumeroJour S 1 0
D @JBoulot S N
Nombre de jours entre date de départ et date passé en argument
->
C @BaseDate subdur @Date @Jours:*d
Donner le jour de la semaine (0=dimanche, etc.) à partir du nombre de jours transmis.
->
C eval @NumeroJour = %rem(@Jours: 7)
Indiquer si le jour tombera le week-end ou pas
->
C if @NumeroJour = 0 or
C @NumeroJour = 6
C eval @JBoulot = *off
C* Sinon...
C else
C eval @JBoulot = *on
C endif
*
C return @JBoulot

P JourTrav E 
Compilation

L’exécutable RPG IV à procédures internes peut être créé directement par CRTBNDRPG (en fait la commande crée d’abord un module puis génère le programme).

Lors de la compilation on peut rencontrer des difficultés liées venant du paramètre de groupe d’activation : on peut généralement s’en tirer en spécifiant DFTACTGRP(*NO) et ACTGRP(QILE).


A SUIVRE