Aller au contenu

%TARGET

Cible d'un message d'erreur

Précise, dans un snd-msg, quel niveau de la pile d'appels reçoit le message.

Syntaxe

snd-msg *ESCAPE message %TARGET(*CALLER)
snd-msg *ESCAPE message %TARGET(*CALLER : saut)
snd-msg *ESCAPE message %TARGET(*SELF)
*CALLER
Le message part vers un appelant de la procédure courante.
saut
Facultatif : nombre de niveaux à remonter. 0 désigne l'appelant direct, 1 l'appelant de l'appelant, et ainsi de suite.
*SELF
Le message est envoyé à la procédure courante elle-même.
Résultat
Aucune : %TARGET n'est utilisable que dans une instruction snd-msg, après le message.

À quoi ça sert

Un message d'erreur de type *ESCAPE arrête la procédure et remonte vers un appelant, qui peut l'attraper avec monitor. Sans précision, le message va à l'appelant direct. Mais quand une petite procédure de contrôle est appelée par une autre, c'est parfois deux niveaux plus haut que la décision doit être prise. %TARGET choisit le niveau qui reçoit l'erreur.

Exemple 1 : Trois niveaux, trois destinataires

**free
// %TARGET : a quel niveau de la pile d'appels le message d'erreur est-il envoye ?
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-ds sds psds qualified;
  msgid char(7) pos(40);
end-ds;
dcl-s saut int(10);

// Trois niveaux d'appel, chacun surveille les erreurs (monitor).
for saut = 0 to 2;
  monitor;
    niveau1(saut);
  on-error;
    snd-msg 'saut ' + %char(saut) + ' : le PRINCIPAL recoit ' + sds.msgid;
  endmon;
endfor;

*inlr = *on;

dcl-proc niveau1;
  dcl-pi *n;
    saut int(10) value;
  end-pi;
  monitor;
    niveau2(saut);
  on-error;
    snd-msg 'saut ' + %char(saut) + ' : NIVEAU1 recoit ' + sds.msgid;
  endmon;
end-proc;

dcl-proc niveau2;
  dcl-pi *n;
    saut int(10) value;
  end-pi;
  monitor;
    niveau3(saut);
  on-error;
    snd-msg 'saut ' + %char(saut) + ' : NIVEAU2 recoit ' + sds.msgid;
  endmon;
end-proc;

dcl-proc niveau3;
  dcl-pi *n;
    saut int(10) value;
  end-pi;
  snd-msg *escape %msg('CPF9898' : 'QCPFMSG' : 'Montant negatif')
          %target(*caller : saut);
end-proc;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

saut 0 : NIVEAU2 recoit CPF9898
saut 1 : NIVEAU1 recoit CPF9898
saut 2 : le PRINCIPAL recoit CPF9898

Chaque niveau surveille les erreurs avec monitor. Le saut est transmis jusqu'à niveau3. Avec 0, l'erreur est reçue par NIVEAU2, l'appelant direct. Avec 1, elle saute NIVEAU2 et arrive à NIVEAU1. Avec 2, c'est la partie principale qui la reçoit. Le programme lit l'identifiant du message dans la zone d'état du programme (psds, positions 40 à 46).

Exemple 2 : Un saut trop grand

**free
// %TARGET : un saut trop grand envoie le message hors du programme, sans monitor pour le recevoir.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-ds sds psds qualified;
  msgid char(7) pos(40);
end-ds;
dcl-s saut int(10);

// Trois niveaux d'appel, chacun surveille les erreurs (monitor).
for saut = 3 to 3;
  monitor;
    niveau1(saut);
  on-error;
    snd-msg 'saut ' + %char(saut) + ' : le PRINCIPAL recoit ' + sds.msgid;
  endmon;
endfor;

*inlr = *on;

dcl-proc niveau1;
  dcl-pi *n;
    saut int(10) value;
  end-pi;
  monitor;
    niveau2(saut);
  on-error;
    snd-msg 'saut ' + %char(saut) + ' : NIVEAU1 recoit ' + sds.msgid;
  endmon;
end-proc;

dcl-proc niveau2;
  dcl-pi *n;
    saut int(10) value;
  end-pi;
  monitor;
    niveau3(saut);
  on-error;
    snd-msg 'saut ' + %char(saut) + ' : NIVEAU2 recoit ' + sds.msgid;
  endmon;
end-proc;

dcl-proc niveau3;
  dcl-pi *n;
    saut int(10) value;
  end-pi;
  snd-msg *escape %msg('CPF9898' : 'QCPFMSG' : 'Montant negatif')
          %target(*caller : saut);
end-proc;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

Erreur : CPF9898 - Montant negatif.

Avec 3, il n'y a plus de niveau au-dessus de la partie principale : aucun monitor ne reçoit le message, et le programme se termine sur l'erreur CPF9898.

Le piège

Les monitor des niveaux sautés ne voient rien. Avec un saut de 1, l'erreur passe par-dessus le monitor de NIVEAU2 : il n'affiche rien (exemple 1). Un saut plus grand que la pile laisse l'erreur sans preneur, et le programme s'arrête (exemple 2).