 




<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Handling errors in CL Programs</title>
	<atom:link href="http://itknowledgeexchange.techtarget.com/itanswers/handling-errors-in-cl-programs/feed/" rel="self" type="application/rss+xml" />
	<link>http://itknowledgeexchange.techtarget.com/itanswers/handling-errors-in-cl-programs/</link>
	<description></description>
	<lastBuildDate>Mon, 20 May 2013 12:39:25 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
	<item>
		<title>By: The Most-Watched IT Questions: March 8, 2011 - ITKE Community Blog</title>
		<link>http://itknowledgeexchange.techtarget.com/itanswers/handling-errors-in-cl-programs/#comment-89076</link>
		<dc:creator>The Most-Watched IT Questions: March 8, 2011 - ITKE Community Blog</dc:creator>
		<pubDate>Tue, 08 Mar 2011 06:10:29 +0000</pubDate>
		<guid isPermaLink="false">#comment-89076</guid>
		<description><![CDATA[[...] CharlieBrowne and TomLiotta are thorough and helpful in this inquiry about handling errors in CL programs.  6. The whole gang&#8217;s here! Mrdenny, Ingram87, IceCubbe, Rechil, Sixball, Redtyke, and [...]]]></description>
		<content:encoded><![CDATA[<p>[...] CharlieBrowne and TomLiotta are thorough and helpful in this inquiry about handling errors in CL programs.  6. The whole gang&#8217;s here! Mrdenny, Ingram87, IceCubbe, Rechil, Sixball, Redtyke, and [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: dcantwell</title>
		<link>http://itknowledgeexchange.techtarget.com/itanswers/handling-errors-in-cl-programs/#comment-88577</link>
		<dc:creator>dcantwell</dc:creator>
		<pubDate>Wed, 23 Feb 2011 16:54:30 +0000</pubDate>
		<guid isPermaLink="false">#comment-88577</guid>
		<description><![CDATA[OK.  Thanks for the info Tom and Charlie. 

I&#039;ve come up with some code based on your posted code Tom:
&lt;pre&gt;
             PGM

             DCL        VAR(&amp;KEYVAR) TYPE(*CHAR) LEN(4)
             DCL        VAR(&amp;MSGTXT) TYPE(*CHAR) LEN(132)
             DCL        VAR(&amp;MSGLEN) TYPE(*DEC) LEN(5 0)
             DCL        VAR(&amp;MSGDTA) TYPE(*CHAR) LEN(512)
             DCL        VAR(&amp;MSGDTALEN) TYPE(*DEC) LEN(5 0)
             DCL        VAR(&amp;MSGID) TYPE(*CHAR) LEN(7)
             DCL        VAR(&amp;SENDER) TYPE(*CHAR) LEN(720)
             DCL        VAR(&amp;EMAIL) TYPE(*CHAR) LEN(60) +
                          VALUE(email@email.COM)
             DCL        VAR(&amp;N) TYPE(*CHAR) LEN(3) VALUE(&#039;:/N&#039;)
             DCL        VAR(&amp;P) TYPE(*CHAR) LEN(3) VALUE(&#039;:/P&#039;)

             /*Let&#039;s call this a hard error. We want to leave the program*/
             CALL       PGM(ABCDXYZMN)
             MONMSG     MSGID(CPF0000) EXEC(CALLSUBR HANDLEERR)

             RETURN
             SUBR       SUBR(HANDLEERR)

                RCVMSG     MSGTYPE(*LAST) RMV(*NO) KEYVAR(&amp;KEYVAR) +
                             MSG(&amp;MSGTXT) MSGLEN(&amp;MSGLEN) MSGDTA(&amp;MSGDTA) +
                             MSGDTALEN(&amp;MSGDTALEN) MSGID(&amp;MSGID) +
                             SENDER(&amp;SENDER) SENDERFMT(*LONG)

                SNDDST     TYPE(*LMSG) TOINTNET((&amp;EMAIL) (*NONE *CC)) +
                             DSTD(&#039;FINANCIAL SERVICES IMAGING ERROR&#039;) +
                             LONGMSG(&#039;MSGID:&#039; &#124;&gt; &amp;MSGID &#124;&gt; &amp;P &#124;&#124; &#039;Message +
                             Text:&#039; &#124;&gt; &amp;MSGTXT &#124;&gt; &amp;P &#124;&#124; &#039;Message Data:&#039; &#124;&gt; +
                             &amp;MSGDTA &#124;&gt; &amp;P &#124;&#124; &#039;END ERROR&#039;) AUTHOR(DAVEC) +
                             DISCLOSE(*YES) ALWX400CNV(*NO)

                RCVMSG     MSGTYPE(*PRV) MSGKEY(&amp;KEYVAR) RMV(*NO) +
                             KEYVAR(&amp;KEYVAR) MSG(&amp;MSGTXT) MSGLEN(&amp;MSGLEN) +
                             MSGDTA(&amp;MSGDTA) MSGDTALEN(&amp;MSGDTALEN) +
                             MSGID(&amp;MSGID) SENDER(&amp;SENDER) SENDERFMT(*LONG)

                SNDDST     TYPE(*LMSG) TOINTNET((&amp;EMAIL) (*NONE *CC)) +
                             DSTD(&#039;FINANCIAL SERVICES IMAGING ERROR&#039;) +
                             LONGMSG(&#039;MSGID:&#039; &#124;&gt; &amp;MSGID &#124;&gt; &amp;P &#124;&#124; &#039;Message +
                             Text:&#039; &#124;&gt; &amp;MSGTXT &#124;&gt; &amp;P &#124;&#124; &#039;Message Data:&#039; &#124;&gt; +
                             &amp;MSGDTA &#124;&gt; &amp;P &#124;&#124; &#039;END ERROR&#039;) AUTHOR(DAVEC) +
                             DISCLOSE(*YES) ALWX400CNV(*NO)
             ENDSUBR

             ENDPGM     
&lt;/pre&gt;

Here&#039;s my new questions:
&lt;ol&gt;
	&lt;li&gt;Will there always be two messages?  If not, will I have to monitor another message ID to make sure I don&#039;t retrieve a non-existent message?&lt;/li&gt;&lt;li&gt;I&#039;ve identified I&#039;d like to do a hard stop as you mentioned Charlie.  How Do I make sure the program stops?  With the subroutine as it is, I can&#039;t use &quot;GOTO&quot; with a command label because it causes a compile error.  Can I simply use a &quot;RETURN&quot; statement in the subroutine?  ENDPGM? &lt;/li&gt;&lt;li&gt;Looking a the &amp;Sender value I noticed the error was coming at &#039;000F&#039;, which would be 16 and corresponds to the 16th line of my code which is the program call. Am I reading this correctly Tom?&lt;/li&gt;
&lt;/ol&gt;]]></description>
		<content:encoded><![CDATA[<p>OK.  Thanks for the info Tom and Charlie. </p>
<p>I&#8217;ve come up with some code based on your posted code Tom:</p>
<pre>
             PGM

             DCL        VAR(&amp;KEYVAR) TYPE(*CHAR) LEN(4)
             DCL        VAR(&amp;MSGTXT) TYPE(*CHAR) LEN(132)
             DCL        VAR(&amp;MSGLEN) TYPE(*DEC) LEN(5 0)
             DCL        VAR(&amp;MSGDTA) TYPE(*CHAR) LEN(512)
             DCL        VAR(&amp;MSGDTALEN) TYPE(*DEC) LEN(5 0)
             DCL        VAR(&amp;MSGID) TYPE(*CHAR) LEN(7)
             DCL        VAR(&amp;SENDER) TYPE(*CHAR) LEN(720)
             DCL        VAR(&amp;EMAIL) TYPE(*CHAR) LEN(60) +
                          VALUE(email@email.COM)
             DCL        VAR(&amp;N) TYPE(*CHAR) LEN(3) VALUE(':/N')
             DCL        VAR(&amp;P) TYPE(*CHAR) LEN(3) VALUE(':/P')

             /*Let's call this a hard error. We want to leave the program*/
             CALL       PGM(ABCDXYZMN)
             MONMSG     MSGID(CPF0000) EXEC(CALLSUBR HANDLEERR)

             RETURN
             SUBR       SUBR(HANDLEERR)

                RCVMSG     MSGTYPE(*LAST) RMV(*NO) KEYVAR(&amp;KEYVAR) +
                             MSG(&amp;MSGTXT) MSGLEN(&amp;MSGLEN) MSGDTA(&amp;MSGDTA) +
                             MSGDTALEN(&amp;MSGDTALEN) MSGID(&amp;MSGID) +
                             SENDER(&amp;SENDER) SENDERFMT(*LONG)

                SNDDST     TYPE(*LMSG) TOINTNET((&amp;EMAIL) (*NONE *CC)) +
                             DSTD('FINANCIAL SERVICES IMAGING ERROR') +
                             LONGMSG('MSGID:' |&gt; &amp;MSGID |&gt; &amp;P || 'Message +
                             Text:' |&gt; &amp;MSGTXT |&gt; &amp;P || 'Message Data:' |&gt; +
                             &amp;MSGDTA |&gt; &amp;P || 'END ERROR') AUTHOR(DAVEC) +
                             DISCLOSE(*YES) ALWX400CNV(*NO)

                RCVMSG     MSGTYPE(*PRV) MSGKEY(&amp;KEYVAR) RMV(*NO) +
                             KEYVAR(&amp;KEYVAR) MSG(&amp;MSGTXT) MSGLEN(&amp;MSGLEN) +
                             MSGDTA(&amp;MSGDTA) MSGDTALEN(&amp;MSGDTALEN) +
                             MSGID(&amp;MSGID) SENDER(&amp;SENDER) SENDERFMT(*LONG)

                SNDDST     TYPE(*LMSG) TOINTNET((&amp;EMAIL) (*NONE *CC)) +
                             DSTD('FINANCIAL SERVICES IMAGING ERROR') +
                             LONGMSG('MSGID:' |&gt; &amp;MSGID |&gt; &amp;P || 'Message +
                             Text:' |&gt; &amp;MSGTXT |&gt; &amp;P || 'Message Data:' |&gt; +
                             &amp;MSGDTA |&gt; &amp;P || 'END ERROR') AUTHOR(DAVEC) +
                             DISCLOSE(*YES) ALWX400CNV(*NO)
             ENDSUBR

             ENDPGM     
</pre>
<p>Here&#8217;s my new questions:</p>
<ol>
<li>Will there always be two messages?  If not, will I have to monitor another message ID to make sure I don&#8217;t retrieve a non-existent message?</li>
<li>I&#8217;ve identified I&#8217;d like to do a hard stop as you mentioned Charlie.  How Do I make sure the program stops?  With the subroutine as it is, I can&#8217;t use &#8220;GOTO&#8221; with a command label because it causes a compile error.  Can I simply use a &#8220;RETURN&#8221; statement in the subroutine?  ENDPGM? </li>
<li>Looking a the &amp;Sender value I noticed the error was coming at &#8217;000F&#8217;, which would be 16 and corresponds to the 16th line of my code which is the program call. Am I reading this correctly Tom?</li>
</ol>
]]></content:encoded>
	</item>
	<item>
		<title>By: tomliotta</title>
		<link>http://itknowledgeexchange.techtarget.com/itanswers/handling-errors-in-cl-programs/#comment-88522</link>
		<dc:creator>tomliotta</dc:creator>
		<pubDate>Wed, 23 Feb 2011 02:43:12 +0000</pubDate>
		<guid isPermaLink="false">#comment-88522</guid>
		<description><![CDATA[The handling of errors in CL (or any compiled language under the OS/400 scheme) essentially requires a basic understanding of how messages are handled. Exceptions are generally signaled through the sending of messages. If you receive those messages, you can extract almost anything you&#039;d ever need to know.

As an introduction, here is a trivial CL program that causes an error and then receives the two relevant messages:&lt;pre&gt;
pgm

   dcl   &amp;KeyVar      *char    4
   dcl   &amp;MsgTxt      *char  132
   dcl   &amp;MsgLen      *dec (   5 0 )
   dcl   &amp;MsgDta      *char  512
   dcl   &amp;MsgDtaLen   *dec (   5 0 )
   dcl   &amp;MsgId       *char    7
   dcl   &amp;Sender      *char  720

   call     ABCDXYZMN
   monmsg ( cpf0000 )  exec( callsubr HandleErr )

   return

   subr     HandleErr

   rcvmsg      msgtype( *LAST ) rmv( *NO ) +
                 keyvar( &amp;KeyVar ) +
                 msg( &amp;MsgTxt ) msglen( &amp;MsgLen ) +
                 msgdta( &amp;MsgDta ) msgdtalen( &amp;MsgDtaLen ) +
                 msgid( &amp;MsgId ) +
                 sender( &amp;Sender ) +
                 senderfmt( *LONG )

   dmpclpgm

   rcvmsg      msgtype( *PRV ) msgkey( &amp;KEYVAR ) rmv( *NO ) +
                 keyvar( &amp;KeyVar ) +
                 msg( &amp;MsgTxt ) msglen( &amp;MsgLen ) +
                 msgdta( &amp;MsgDta ) msgdtalen( &amp;MsgDtaLen ) +
                 msgid( &amp;MsgId ) +
                 sender( &amp;Sender ) +
                 senderfmt( *LONG )

   dmpclpgm

   endsubr

endpgm&lt;/pre&gt;
The program simply calls another program named &quot;ABCDXYZMN&quot;. Assuming that no such program exists in the library list, that will cause an error.

The general error will be CPF0001, &quot;Error found on CALL command.&quot; That&#039;s an error relating to almost any kind of command on the system, and it indicates that the command simply can&#039;t complete as compiled. There&#039;s nothing wrong with the syntax; it just won&#039;t work. The CPF0001 is sent as a fairly non-specific *ESCAPE message. The *ESCAPE message is the signaling of failure.

But before that message was sent, another one was sent -- CPD0170, &quot;Program ABCDXYZMN in library *LIBL not found.&quot; That was sent as a *DIAG (Diagnostic) message. Diagnostic messages carry some details about exactly what went wrong.

There might be multiple *DIAG messages accompanying an *ESCAPE message. In this case there is only one. In practice, you &lt;i&gt;might&lt;/i&gt; have the second RCVMSG in a loop for the Diagnostics in order to receive all of them.

Now, the example doesn&#039;t actually do anything except retrieve message attributes in some variables and then run dumps. Without knowing what you&#039;ll do, there&#039;s no way to really code any actions. But you can compile and run the program, and then compare the dumped variables against the help text of the RCVMSG parms. Also, compare the values against message details that you might see in the joblog.

You should be able to recognize stuff. For example, if you look at positions 645-648 of the &amp;Sender variable in the dump, you should see that it matches the &quot;To statement&quot; statement number in the message details for the message in the joblog.

There is too much information about sending and receiving messages. A truly &quot;generic&quot; handling of them could probably be done, but specific handling usually works out better.

Try running the above program. Review the info that gets captured. Compare it against the RCVMSG help text for the parms that I used (and note that others are available). See what comes to mind.

Then ask followup questions for any details that aren&#039;t clear.

Keep in mind that *ESCAPE messages signal failure of something. I&#039;ve had circumstances where &quot;failures&quot; mean that attempts to run any additional processing simply cause additional errors. &#039;Generic&#039; handling of errors just might not work in a failure scenario.

Tom]]></description>
		<content:encoded><![CDATA[<p>The handling of errors in CL (or any compiled language under the OS/400 scheme) essentially requires a basic understanding of how messages are handled. Exceptions are generally signaled through the sending of messages. If you receive those messages, you can extract almost anything you&#8217;d ever need to know.</p>
<p>As an introduction, here is a trivial CL program that causes an error and then receives the two relevant messages:
<pre>
pgm

   dcl   &amp;KeyVar      *char    4
   dcl   &amp;MsgTxt      *char  132
   dcl   &amp;MsgLen      *dec (   5 0 )
   dcl   &amp;MsgDta      *char  512
   dcl   &amp;MsgDtaLen   *dec (   5 0 )
   dcl   &amp;MsgId       *char    7
   dcl   &amp;Sender      *char  720

   call     ABCDXYZMN
   monmsg ( cpf0000 )  exec( callsubr HandleErr )

   return

   subr     HandleErr

   rcvmsg      msgtype( *LAST ) rmv( *NO ) +
                 keyvar( &amp;KeyVar ) +
                 msg( &amp;MsgTxt ) msglen( &amp;MsgLen ) +
                 msgdta( &amp;MsgDta ) msgdtalen( &amp;MsgDtaLen ) +
                 msgid( &amp;MsgId ) +
                 sender( &amp;Sender ) +
                 senderfmt( *LONG )

   dmpclpgm

   rcvmsg      msgtype( *PRV ) msgkey( &amp;KEYVAR ) rmv( *NO ) +
                 keyvar( &amp;KeyVar ) +
                 msg( &amp;MsgTxt ) msglen( &amp;MsgLen ) +
                 msgdta( &amp;MsgDta ) msgdtalen( &amp;MsgDtaLen ) +
                 msgid( &amp;MsgId ) +
                 sender( &amp;Sender ) +
                 senderfmt( *LONG )

   dmpclpgm

   endsubr

endpgm</pre>
<p>The program simply calls another program named &#8220;ABCDXYZMN&#8221;. Assuming that no such program exists in the library list, that will cause an error.</p>
<p>The general error will be CPF0001, &#8220;Error found on CALL command.&#8221; That&#8217;s an error relating to almost any kind of command on the system, and it indicates that the command simply can&#8217;t complete as compiled. There&#8217;s nothing wrong with the syntax; it just won&#8217;t work. The CPF0001 is sent as a fairly non-specific *ESCAPE message. The *ESCAPE message is the signaling of failure.</p>
<p>But before that message was sent, another one was sent &#8212; CPD0170, &#8220;Program ABCDXYZMN in library *LIBL not found.&#8221; That was sent as a *DIAG (Diagnostic) message. Diagnostic messages carry some details about exactly what went wrong.</p>
<p>There might be multiple *DIAG messages accompanying an *ESCAPE message. In this case there is only one. In practice, you <i>might</i> have the second RCVMSG in a loop for the Diagnostics in order to receive all of them.</p>
<p>Now, the example doesn&#8217;t actually do anything except retrieve message attributes in some variables and then run dumps. Without knowing what you&#8217;ll do, there&#8217;s no way to really code any actions. But you can compile and run the program, and then compare the dumped variables against the help text of the RCVMSG parms. Also, compare the values against message details that you might see in the joblog.</p>
<p>You should be able to recognize stuff. For example, if you look at positions 645-648 of the &amp;Sender variable in the dump, you should see that it matches the &#8220;To statement&#8221; statement number in the message details for the message in the joblog.</p>
<p>There is too much information about sending and receiving messages. A truly &#8220;generic&#8221; handling of them could probably be done, but specific handling usually works out better.</p>
<p>Try running the above program. Review the info that gets captured. Compare it against the RCVMSG help text for the parms that I used (and note that others are available). See what comes to mind.</p>
<p>Then ask followup questions for any details that aren&#8217;t clear.</p>
<p>Keep in mind that *ESCAPE messages signal failure of something. I&#8217;ve had circumstances where &#8220;failures&#8221; mean that attempts to run any additional processing simply cause additional errors. &#8216;Generic&#8217; handling of errors just might not work in a failure scenario.</p>
<p>Tom</p>
]]></content:encoded>
	</item>
</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using memcached
Database Caching 6/9 queries in 0.012 seconds using memcached
Object Caching 296/299 objects using memcached

Served from: itknowledgeexchange.techtarget.com @ 2013-05-20 13:05:08 -->