Project Oxygen & Ideo-LabIDEO LAB Dashboard 2026

🟩 PL/I (IBM) – Guide complet (AnnĂ©es 70/80 → toujours vivant)

Syntaxe, types, structures, exceptions (ON), fichiers, perf, mainframe, interop COBOL/ASM/C, modernisation.

Style
Structured + data-heavy
Platform
z/OS & enterprise
Strength
Strings + numerics + I/O
Ops
Batch & online
1.1

Pourquoi PL/I ?

Langage “general purpose” IBM : science + business, riche, et trĂšs productif sur donnĂ©es.

HistoryIBMEnterprise
1.2

Structure d’un programme

PROC, DCL, BEGIN/END, statements, options compiler, style modulaire.

PROCDCLBEGIN/END
2.1

Types & déclarations

FIXED/BIN/DEC, FLOAT, CHAR/VARYING, BIT, structure, arrays, pointers.

FIXEDVARYINGSTRUCT
2.2

ContrĂŽle & boucles

IF/THEN/ELSE, SELECT, DO loops, iteration, LEAVE/ITERATE, GOTO (rare).

DOSELECTLEAVE
3.1

Strings & manipulation

CHAR/VARYING, substr, index, translate, concat, formatting, parsing.

CHARSUBSTRINDEX
3.2

I/O fichiers

OPEN/CLOSE/READ/WRITE, GET/PUT, record vs stream, formats, erreurs.

I/OGET/PUTFiles
4.1

Gestion d’erreurs (ON)

ON condition, SIGNAL, RESIGNAL, built-in conditions, “fail fast” contrĂŽlĂ©.

ONSIGNALDiagnostics
4.2

Modularité & appels

PROC options, paramĂštres, ENTRY, external, interop (COBOL/C/ASM).

ENTRYExternalInterop
4.3

Mémoire, pointeurs, ALLOCATE

BASED, POINTER, ALLOCATE/FREE, lifetimes, structures dynamiques.

POINTERBASEDALLOCATE
5.1

Performance & tuning

Design des données, conversions, I/O, options compiler, hot loops.

TuningCompilerI/O
5.2

Mainframe: batch & ops

Retour codes, logs, rerun safe, JCL integration, datasets, production.

z/OSBatchJCL

0.x Carte mentale PL/I

Architecture : PROC, data model, I/O, exceptions ON, interop, migration.

MapBig Picture

Cheat-sheet

Rappels : DCL, PROC, DO, SELECT, ON, GET/PUT, VARYING, ALLOCATE.

Quick RefSnippets
0.x PL/I – Overview (architecture et contexte IBM)
PL/I en une phrase

PL/I (IBM) vise Ă  ĂȘtre un langage “gĂ©nĂ©raliste” pour les environnements enterprise : fort sur la manipulation de donnĂ©es, I/O, gestion d’erreurs (ON), structures, et intĂ©gration mainframe.

Objectif du guide
Lire/maintenir du code PL/I, écrire des modules robustes, maßtriser I/O, exceptions, et comprendre les patterns batch/production.
Carte mentale
Program (PL/I)
  ├─ PROC (entry point)
  ├─ Declarations (DCL)
  │   ├─ numeric: FIXED BIN / FIXED DEC / FLOAT
  │   ├─ strings: CHAR / VARYING / BIT
  │   ├─ struct: 1/2/3 levels (LIKE, BASED)
  │   └─ arrays
  ├─ Control
  │   ├─ IF/THEN/ELSE
  │   ├─ SELECT
  │   └─ DO loops (LEAVE/ITERATE)
  ├─ I/O
  │   ├─ OPEN/CLOSE
  │   ├─ GET/PUT (record/stream)
  │   └─ formats, errors
  ├─ Errors
  │   ├─ ON conditions
  │   └─ SIGNAL/RESIGNAL
  └─ Ops
      ├─ return codes, logs
      └─ batch rerun safe
            
Forces PL/I (pratiques)
ZonePourquoi c’est fortUsage
StringsOpérations riches + VARYINGParsing, formats, protocoles legacy
Data structsStructures proches “records”Interfaces, layouts fichiers
ExceptionsON conditionsErreurs contrÎlées, robustesse
I/OGET/PUT + formatsBatch, reports, fichiers
Runtime & Ops (batch)
  • Le pilotage prod se fait souvent via RC, logs, et datasets.
  • Rerun safe : outputs temporaires, checkpoints, invariants de totals.
  • Perf : I/O patterns + conversions (DEC/BIN/CHAR), compiler options.
Batch flow:
  extract → transform → report/load
Ops:
  RC + totals + diagnostics
        
1.1 Pourquoi PL/I ? Histoire, rîle, posture “enterprise”
Ce qu’il faut retenir
  • PL/I a Ă©tĂ© conçu pour couvrir des besoins variĂ©s (scientifique + business).
  • TrĂšs orientĂ© “manipulation de donnĂ©es” : strings, formats, structures.
  • Riche en contrĂŽle d’erreurs via ON conditions.
  • Fortement intĂ©grĂ© aux environnements IBM (notamment z/OS).
Rùgle d’or
Commencez par comprendre les types et les formats I/O : le reste découle.
Quand on le rencontre encore
ContexteExemples
Batch “core”Compta, reporting, consolidation, transformations
Tools internesUtilitaires, parsing, contrÎles de qualité data
InteropModules appelés depuis COBOL/ASM/C
1.2 Structure d’un programme PL/I : PROC, DCL, BEGIN/END
Programme minimal
HELLO: PROC OPTIONS(MAIN);

  DCL msg CHAR(26) VARYING;
  msg = 'HELLO FROM PL/I';
  PUT SKIP LIST(msg);

END HELLO;
            
Lecture
  • PROC : point d’entrĂ©e (ou routine).
  • DCL : dĂ©clarations (types, structures, fichiers).
  • BEGIN/END : bloc ; style structurĂ©.
  • PUT : sortie (ici console/stream).
Tip
Un style propre : un PROC court qui appelle des PROC “worker”.
DCL : déclarer clairement
DCL i FIXED BIN(31);
DCL amount FIXED DEC(15,2);
DCL code CHAR(3);
DCL name CHAR(30) VARYING;
DCL flags BIT(8);
        

Les conversions implicites existent, mais en production, il vaut mieux les contrĂŽler.

Style modulaire “batch”
MAIN: PROC OPTIONS(MAIN);

  CALL init();
  DO WHILE( more_input() );
    CALL process_one();
  END;
  CALL finalize();

END MAIN;
        

Objectif : lisibilité + testabilité + rerun safe.

Compile/build (concepts)
  • Options compiler influencent perf, diagnostics, runtime checks.
  • En legacy, conventions site : naming, link-edit, load libs.
  • RĂšgle : activer les diagnostics en dev/QA, puis durcir en prod.
Think in environments:
  DEV: max diagnostics
  QA: strict + test harness
  PROD: stable options + monitoring
        
2.1 Types & dĂ©clarations – FIXED, FLOAT, CHAR/VARYING, BIT, STRUCT, ARRAY
Fixed binary / fixed decimal
DCL cnt FIXED BIN(31);
DCL id  FIXED BIN(31) INIT(0);

DCL price FIXED DEC(15,2);
DCL tax   FIXED DEC(7,2);

price = 12345.67;
tax   = price * 0.20;
            
Float (scientifique)
DCL x FLOAT(53);
x = 3.1415926535;
            
Tip perf
Choisir DEC pour finance, BIN pour compteurs, FLOAT pour calcul.
CHAR vs VARYING
DCL a CHAR(10);
DCL b CHAR(30) VARYING;

a = 'ABC';
b = 'HELLO';
b = b || ' WORLD';
            
BIT strings
DCL mask BIT(8);
mask = '10101010'B;
            

Les strings sont une force de PL/I : parsing, formats, manipulation.

Structures (records)
DCL 1 customer,
      2 cust_id FIXED BIN(31),
      2 cust_name CHAR(30) VARYING,
      2 address,
        3 street CHAR(40) VARYING,
        3 city   CHAR(20) VARYING,
        3 zip    CHAR(10);

customer.cust_id = 42;
customer.address.city = 'LYON';
        
Tip
Documentez les structures comme des contrats (interop, I/O fichiers).
Arrays
DCL i FIXED BIN(31);
DCL items(10) FIXED DEC(9,2);

DO i = 1 TO 10;
  items(i) = i * 10.00;
END;
        

Les arrays + DO loops donnent un style “structurĂ©â€ et lisible.

2.2 Contrîle & boucles – IF, SELECT, DO, LEAVE/ITERATE
IF / THEN / ELSE
IF price > 0 THEN
  total = total + price;
ELSE
  rc = 12;
          
SELECT (case)
SELECT(action);
  WHEN('C') CALL create();
  WHEN('U') CALL update();
  WHEN('D') CALL delete();
  OTHERWISE rc = 16;
END;
          
DO loops
DO i = 1 TO 10;
  sum = sum + items(i);
END;

DO WHILE(has_more());
  CALL process_one();
END;
          
LEAVE / ITERATE
DO i = 1 TO 100;
  IF i = 10 THEN LEAVE;
  IF MOD(i,2)=0 THEN ITERATE;
  CALL work(i);
END;
          

Anti-patterns
Anti-patternPourquoiAlternative
Conversions implicites non maßtriséesBugs data silencieuxCast/format explicite
Un seul gros blocDebug difficilePROC modulaires
GOTO partoutFlow opaqueDO/SELECT + helpers
3.1 Strings – CHAR/VARYING, SUBSTR, INDEX, parsing & formats
Concatenation & VARYING
DCL s CHAR(80) VARYING;
s = 'A';
s = s || '-' || 'B';
PUT SKIP LIST(s);
        
SUBSTR / INDEX
DCL line CHAR(200) VARYING;
DCL pos FIXED BIN(31);

pos = INDEX(line, ':');
IF pos > 0 THEN DO;
  key = SUBSTR(line, 1, pos-1);
  val = SUBSTR(line, pos+1);
END;
        
Parsing robuste : checklist
  • Valider la prĂ©sence des sĂ©parateurs (INDEX).
  • Trimmer / normaliser.
  • Limiter les longueurs (avoid overflow).
  • Tracer les lignes invalides dans un fichier “reject”.
IF pos = 0 THEN DO;
  reject_count = reject_count + 1;
  CALL write_reject(line);
  ITERATE;
END;
        
Formatting (idée)
DCL amount FIXED DEC(15,2);
DCL out CHAR(40) VARYING;

out = 'AMOUNT=' || amount;
PUT SKIP LIST(out);
        

En production, standardiser les formats (longueur, séparateurs, encodage).

3.2 I/O fichiers – OPEN/CLOSE, GET/PUT, stream vs record
Déclarer un fichier
DCL in FILE;
DCL out FILE;
            

Les détails exacts (DD names, attributes) dépendent des conventions runtime/site.

Open / get / put
OPEN FILE(in) INPUT;
OPEN FILE(out) OUTPUT;

GET FILE(in) EDIT(line) (A);
PUT FILE(out) LIST(line);

CLOSE FILE(in);
CLOSE FILE(out);
            
Pattern batch : loop + counters
DCL cnt FIXED BIN(31) INIT(0);

DO WHILE( has_more_input() );
  CALL read_one(line);
  cnt = cnt + 1;
  CALL process_one(line);
  CALL write_one(line);
END;

PUT SKIP LIST('COUNT=', cnt);
        
Tip
Toujours sortir des totals (count/sum) pour validation et rerun.
Gestion erreurs I/O
  • Capturer exceptions via ON (condition) autour des GET/PUT.
  • Tracer le record en erreur + position + totals.
  • Écrire un “reject file” plutĂŽt que crasher sans preuve.
ON ENDFILE(in) eof = 1;
ON ERROR CALL handle_io_error();
        
Contracts fichiers : le vrai sujet
ContratPourquoiAction
Record layoutÉvite corruption silencieuseDoc + tests
EncodingCharset issuesStandardize
Control totalsDetect regressionsCount/sum checks
4.1 Gestion d’erreurs PL/I – ON conditions, SIGNAL, RESIGNAL
ON condition (concept)
ON ERROR DO;
  rc = 12;
  PUT SKIP LIST('ERROR DETECTED');
END;
            
ON ENDFILE (EOF)
ON ENDFILE(in) eof = 1;

DO WHILE(eof = 0);
  GET FILE(in) LIST(line);
  CALL process_one(line);
END;
            
SIGNAL / RESIGNAL (concept)

SIGNAL déclenche une condition ; RESIGNAL propage aprÚs traitement local.

ON ERROR DO;
  CALL log_context();
  RESIGNAL;
END;
        
Patterns de robustesse
PatternButAction
Fail fast contrÎléStop avec preuveLog + totals + RC
Reject fileContinuer malgré records badWrite bad lines
Retry IO/locksRésilienceBackoff + limit
4.2 ModularitĂ© – PROC, paramĂštres, ENTRY, external, interop
Procédure avec paramÚtres
calc_tax: PROC(amount, rate) RETURNS(FIXED DEC(15,2));
  DCL amount FIXED DEC(15,2);
  DCL rate   FIXED DEC(7,4);
  RETURN amount * rate;
END;
          
Tip
Documenter les contrats (types exacts) pour éviter conversions implicites.
Interop (concept)
  • PL/I peut cohabiter avec COBOL/C/ASM dans des load libs.
  • Le vrai sujet : calling convention + layout structures + encoding.
  • Standardiser les “interface copybooks/struct defs”.
Interop checklist:
  params order/types
  alignment/packing
  strings encoding
  error codes
          
4.3 MĂ©moire – POINTER, BASED, ALLOCATE/FREE (structures dynamiques)
ALLOCATE / FREE (concept)
DCL p POINTER;

DCL 1 node BASED(p),
      2 key FIXED BIN(31),
      2 next POINTER;

ALLOCATE node;
node.key = 123;
node.next = NULL();

FREE node;
          

Based structures : puissant, mais exige discipline (lifetime, free).

RÚgles de sécurité mémoire
RisqueCausePrévention
LeakFREE oubliéOwnership clair
Use-after-freePointeur gardéNullify pointers
CorruptionLayout mismatchStruct contracts
Tip
Limiter la dynamique si possible en batch, sauf besoin réel.
5.1 Performance & tuning – data design, conversions, I/O, compiler options
Leviers principaux
  • Constructions data : Ă©viter casts en boucle.
  • I/O : rĂ©duire le nombre de passes fichiers, bufferiser.
  • Strings : attention aux concat rĂ©pĂ©tĂ©es sur gros volumes.
  • Compiler : options de debug vs perf (selon environnements).
Rule of thumb:
  avoid heavy conversions inside hot loops
  move formatting to the edges (I/O)
          
Symptîme → action
SymptĂŽmeCause probableAction
Batch plus lentI/O excessifSingle pass, fewer writes
CPU highConversions + stringsPrecompute, reduce concat
Errors sporadiquesON/conditions mal cadréesCentralize handlers
5.2 Mainframe ops – return codes, batch discipline, rerun safe
Checklist prod
  • RC cohĂ©rents (0/4/8/12/16 selon conventions).
  • Logs utiles : count, totals, time markers.
  • Outputs temporaires + switch final pour rerun safe.
  • Tests NRT sur jeux reprĂ©sentatifs.
Audit items:
  job/step
  input/output datasets
  record counts
  totals
  return code
          
Batch pattern (concept)
extract → validate → transform → output
  + totals
  + rejects
  + RC
          
Tip
Quand ça casse : le record fautif + totals + RC = diagnostic rapide.
Modernisation PL/I – encapsulation, strangler, refactor safe
Approches
ApprocheAvantageRisque
EncapsulateLow risk, quick winsLegacy stays
StranglerRemplacement progressifComplex routing
Refactor insideQualité/maintNeeds strong tests
Big bangClean slateHigh failure rate
Conseil
Commencer par la visibilité : cartographier jobs, contrats I/O, tests + totals.
Wrapper (concept)
API/service
  → adapt request
  → call PL/I module
  → adapt response
            
Contract-first
Define:
  schema fields/types
  error codes
  idempotency
  versioning
            
Safe refactor
  1. Golden outputs + totals
  2. Isoler I/O et formats
  3. Modulariser PROC
  4. Centraliser ON handlers
  5. Shadow runs + compare
Shadow run:
  legacy output A
  new output B
  compare A vs B
  switch only when identical
        
Migration data : piĂšges
  • Conversions DEC/BIN/CHAR (rounding, formats).
  • Encodage (EBCDIC/ASCII selon environnements).
  • Contrats fichiers : longueur fixe, records, separators.
  • Anomalies historiques : valeurs “impossibles” mais prĂ©sentes en prod.
Tip
Profiler les datasets avant migration : distributions, invalids, edge cases.
0.x Carte mentale PL/I – rĂ©sumĂ© “1 Ă©cran”
PL/I Big Picture
  1) PROC + DCL (types/structs)
  2) Control (IF/SELECT/DO)
  3) Data work (strings, arrays, records)
  4) I/O (GET/PUT + formats)
  5) Errors (ON + SIGNAL/RESIGNAL)
  6) Ops (RC, totals, rerun)
  7) Modernization (wrappers, strangler, safe refactor)
      
Rappel
PL/I = “data language” : types + formats + handlers d’erreurs sont la clĂ©.
Cheat-sheet PL/I – quick ref
Core syntax
PROC OPTIONS(MAIN);
DCL x FIXED BIN(31);
DCL y FIXED DEC(15,2);
DCL s CHAR(80) VARYING;

IF cond THEN ... ELSE ...
SELECT(expr); WHEN(... ) ... OTHERWISE ... END;

DO i = 1 TO n; ... END;
DO WHILE(cond); ... END;

ON ERROR DO; ... END;
ON ENDFILE(file) eof = 1;

OPEN FILE(f) INPUT/OUTPUT;
GET FILE(f) LIST(x);
PUT FILE(f) LIST(x);
CLOSE FILE(f);
          
Template program
MAIN: PROC OPTIONS(MAIN);

  DCL rc FIXED BIN(31) INIT(0);
  DCL eof FIXED BIN(31) INIT(0);
  DCL line CHAR(200) VARYING;

  ON ERROR DO;
    rc = 12;
    PUT SKIP LIST('ERROR');
  END;

  CALL init();

  DO WHILE(eof = 0);
    /* read_one should set eof=1 at end */
    CALL read_one(line, eof);
    IF eof = 0 THEN DO;
      CALL process_one(line, rc);
      IF rc ^= 0 THEN LEAVE;
    END;
  END;

  CALL finalize(rc);

END MAIN;