Wednesday, September 21, 2016

Working with IFS in RPGLE

Read IFS file in RPGLE

Working with IFS file has always been one of the important things while programming with RPGLE.

The most common way to deal with IFS file is 
  • Copy the IFS file to Flat file using CPYFRMIMPF/CPYFRMSTMF.
  • Read the Flat file in RPGLE.
  • Write the Data into File in RPGLE.
  • Copy the File to IFS by using CPYTOIMPF/CPYTOSTMF.
This involves writing additional CL Program or using QCMDEXC API to execute CL Command to copy the data from/to IFS and Creation of Temporary/Permanent Database file. 

Accessing IFS files has become easy by using 'open', 'close', 'read' and 'write' functions.

Below is an Simple Example on how to Read data from IFS and write into Database file.

     Ctl-Opt DftActGrp(*No) ;

     // ProtoType Declaration for 'open'
     Dcl-PR OpenIfs Int(10) ExtProc('open') ;
       pIfsPath Pointer Value Options(*String) ;
       pFileStatusFlag Int(10) Value ;
       pFilePermission Uns(10) Value Options(*NoPass) ;
       pOutputCcsId Uns(10) Value Options(*NoPass) ;
     End-PR ;

     // ProtoType Declaration for 'read'
     Dcl-PR ReadIfs Int(10) ExtProc('read') ;
       pFileDescriptor Int(10) Value ;
       pIfsData Pointer Value ;
       pBytesRetrieved Uns(10) Value ;
     End-PR ;

     // ProtoType Declaration for 'close'
     Dcl-PR CloseIfs Int(10) ExtProc('close') ;
       pFileDescriptor Int(10) Value ;
     End-PR ;

     // Constants Declaration
     Dcl-C ReadOnly 1 ;
     Dcl-C Text 16777216 ;
     Dcl-C CcsId 32 ;
     Dcl-C GroupAuthority 32 ;
     Dcl-C Path '/home/PREDDY/SampleIfs.txt' ;

     // Stand Alone Variables Declaration
     Dcl-S FileDescriptor Int(10) ;
     Dcl-S Length Int(10) ;
     Dcl-S IfsData Char(100) ;
     Dcl-S IfsRecord Char(100) ;
     Dcl-S StartPos Packed(3) ;
     Dcl-S EndPos Like(StartPos) ;

     // Open IFS File
     FileDescriptor = OpenIfs(Path
                             :ReadOnly + Text + CcsId
                             :37) ;

     If FileDescriptor < 0 ;
       Dsply ('Problem While accessing IFS file.') ;
       *InLr = *On ;
       Return ;
     Else ;
       Dow 1 = 1 ;

         // Read IFS File
         Length = ReadIfs(FileDescriptor : %Addr(IfsData) : %Size(IfsData) ) ;
         If Length = 0 ;
           Leave ;
         ElseIf Length < %Size(IfsData) ;
           %SubSt(IfsData : (Length + 1)) = ' ' ;
         EndIf ;

         StartPos = *Zeros ;

         Dow 2 = 2 ;

           // Write Data into IFS file
           EndPos = %Scan(x'25' : IfsData : StartPos + 1) ;
           If EndPos > *Zeros ;
             IfsRecord = %SubSt(IfsData : StartPos + 1 :
                          EndPos - StartPos - 1) ;
             Dsply IfsRecord ;
             StartPos = EndPos ;
           Else ;
             Leave ;
           EndIf ;
         EndDo ;
       EndDo ;
     EndIf ;

     // Close File
     CloseIfs(FileDescriptor) ;
     *InLr = *On ;

This example has been written in Full Free format RPGLE. Declarations has to be modified to Fixed Format, if any restrictions in writing Full Free Format.

Refer to Scott Klement's ebook for detailed info on IFS in RPG.

Thursday, September 15, 2016

Advantages of using Free-format RPGLE

Advantages of Using Free-Format RPGLE

IBM has always been focusing on making the RPG easy for Non-RPG Programmers. One such Important move is introducing the Free-Format into RPG for C-Spec. 

Introducing Eclipse based RDi is another biggest move. This encourages young developers in learning RPG like any other web based languages. RDi has an addition to convert your Fixed Format code to Free-Format. 

Almost after a Decade of Introducing Free-Format, IBM took major Step to Convert RPG into Full-Free format.

As a Core RPG Developer, I can say this as 'Really Huge' change to the way how RPG was being coded and how the RPG has become now. This has changed its way from RPG II, RPG III and to Full-Free Format.

We will have a quick look at the Major advantages of Using Free-Format RPGLE in this article.

  • Readability
  • Efficient use of Space
  • New Features Specific to Free Format
  • Easy to Understand/Maintain


  • No need to stick to specific columns and thinking about the limitations of Factor or Extended Factor for writing any calculations.
  • Maintaining Proper Indentation makes easy for Analyzing the code.
  • Declaring Variables with Proper Meaning. E.g.: 'IsPurchaseOrderFulfilled' makes more Sense than 'IsPOfulfld'.  This helps understanding the Purpose of Variable and Logic.

Efficient Use of Space:

  • Biggest Advantage of Full-Free format RPGLE is making efficient use of Space instead of Restricting to work from 6th Position to 80th Position. Code can be written Starting from 1st Position.
  • Free Format Declarations allows to Declaring the large variable names in a single line by avoiding ellipsis (...) in D-Spec.
  • Business Logic will appear clean in Free Format and can save the number of lines coded compared to Fixed Format.

New Features to Free Format:

  • Defining Keys directly in Chain/Setll instead of maintaining the KLIST. This helps eliminating multiple KLIST entries and Code looks cleaner for Modification/Analysis.
  • EXCEPT keyword can be avoided with Free-Format Specific %Fields(). This eliminates the O-Spec and Fields can be mentioned directly with UPDATE Keyword.

Easy to Understand/Maintain:

  • Free-Format File declarations has changed the way of File Declarations in F-Specs. You no longer need to remember the Position & Possible Values. This can be as simple as your Variables Declaration.
  • No need to follow the sequence. Variables can be declared in middle of File Declarations. This helps declaring the Stand alone fields used for file processing to be defined immediately after File Declaration.
Not to Miss, It helps young developer to understand RPG quickly and learn.

Saturday, September 10, 2016

IBM i Updates Android Application

Happy to share the Android Application for this website.

Click Here to download the application.

You might have to allow installation of Third Party Applications to be able to install this app.

Working with 5250 Emulator from IBM Navigator for i

The Web based Navigator for i is a new interface for IBM i. This will change the way you look at IBM i completely.

This advanced Set Target System feature lets you manage any IBM i in your environment from a single browser. But its real power is allowing you to use the newest version of the web console against systems at older releases, including IBM i 6.1 and IBM i 5.4.

The web based console now includes a 5250 Emulator for those times when you just need a good old fashioned command-line interface. The integrated DB2 Database has enhancements on both the web-based and Windows based consoles to improve performance analysis and provide more gradual user access.

Speaking of performance, the Performance Data Investigator continues enhancing its visual yet power fun analysis and reporting interface. Journal now provides a full set of options to display and control journal objects.

I felt very excited to see this change happening in IBM i and looking forward for more such enhancements which will benefit the IBM i's end customers as well as developers :-)

Below screenshots will give you quick steps on how to get started with Web navigator for i.

Source : IBM

Monday, March 28, 2016

Working with XML in RPGLE : XML-SAX

Working with XML in RPGLE : XML-SAX

Working with XML has never been easier before IBM's introduction of XML-INTO and XML-SAX compatibility to RPGLE.

My earlier post did contain detailed info about basics on XML with RPGLE and compatibility of XML-INTO with RPGLE along with its own advantages and disadvantages. If you haven't gone through them yet, Click on those links to have quick look.


Even though XML-INTO provides the greatest comfort to programmers by directly bringing the data to Respective variable/data structure. But, this doesn't help programmers when the XML elements/data has been inconsistent.

XML-SAX is the best way of handling such XMLs. This will read the XML character by character and calls Handling Procedure when the even gets triggered.


Xml-Sax(e) %Handler(XMLHandler_Procedure : CommsArea_DataStructure ) %XML(wXmlString: 'doc=string')

Below are some possible events that can occur while parsing XML. 

This has been split by the phase those events can occur along with its description to understand better.

Events discovered before the first XML element:

  • *XML_START_DOCUMENT - Indicates that parsing has begun
  • *XML_VERSION_INFO - The "version" value from the XML declaration
  • *XML_ENCODING_DECL - The "encoding" value from the XML declaration
  • *XML_STANDALONE_DECL - The "standalone" value from the XML declaration
  • *XML_DOCTYPE_DECL - The value of the Document Type Declaration

Events related to XML elements

  • *XML_START_ELEMENT- The name of the XML element that is starting
  • *XML_CHARS - The value of the XML element
  • *XML_PREDEF_REF - The value of a predefined reference
  • *XML_UCS2_REF - The value of a UCS-2 reference
  • *XML_UNKNOWN_REF - The name of an unknown entity reference
  • *XML_END_ELEMENT - The name of the XML element that is ending

Events related to XML attributes

  • *XML_ATTR_NAME - The name of the attribute
  • *XML_ATTR_CHARS - The value of the attribute
  • *XML_ATTR_PREDEF_REF - The value of a predefined reference
  • *XML_ATTR_UCS2_REF - The value of a UCS-2 reference
  • *XML_UNKNOWN_ATTR_REF - The name of an unknown entity reference
  • *XML_END_ATTR - Indicates the end of the attribute

Events related to XML processing instructions

  • *XML_PI_TARGET - The name of the target
  • *XML_PI_DATA - The value of the data

Events related to XML CDATA sections

  • *XML_START_CDATA - The beginning of the CDATA section
  • *XML_CHARS - The value of the CDATA section
  • *XML_END_CDATA - The end of the CDATA section

Other events

  • *XML_COMMENT - The value of the XML comment
  • *XML_EXCEPTION - Indicates that the parser discovered an error
  • *XML_END_DOCUMENT - Indicates that parsing has ended
Below example will show on how to use some of the basic events that usually occur. 


H DftActGrp(*No)                                                           
 // Standalone Variables Declaration                                       
D wSampleXml      S            512A                                        
D wXmlOptions     S            512A   Varying                              
D SaveElement     S             50A                                        
 // Data Structure for Communication Area                                  
D DsCommunicationArea...                                                   
D                 DS                                                       
D  AttrName                     20A   Varying                              
D  HaveAttr                       N                                        
D  AttrValue                    20A   Varying                              
D DsCommArea      DS                  LikeDs(DsCommunicationArea)          
 // Handling Procedure Prototype                                           
D pHandlingProcedure...                                                    
D                 PR            10I 0                                      
D  pCommArea                          LikeDs(DsCommunicationArea)          
D  pEvent                       10I 0 Value                                
D  pString                        *   Value                                
D  pStringLen                   20I 0 Value                                
D  pExceptionId                 10I 0 Value                                
   wSampleXml  = '<Order>'                                                 
               + '<Type>Weborder</Type>'                                   
               + '<Number>123456789</Number>'                              
               + '<Customer>Mr. John</Customer>'                           
               + '<Status>Despatched</Status>'                             
               + '</Order>' ;                                              
   wSampleXml  = %Xlate(x'3f' : x'40' : wSampleXml) ;                      
   wXmlOptions = 'doc=string ';                                            
   Xml-Sax(E) %Handler(pHandlingProcedure : DsCommArea)                    
              %Xml(wSampleXml : wXmlOptions) ;                             
   If %Error() ;                                                           
      Dsply 'Error Occured While Parsing XML. Please Review.' ;            
   EndIf ;                                                                 
   *InLr = *On ;                                                           
 // Handling Procedure for XML-SAX                                         
P pHandlingProcedure...                                                    
P                 B                                                        
D pHandlingProcedure...                                                    
D                 PI            10I 0                                      
D  pCommArea                          LikeDs(DsCommunicationArea)          
D  pEvent                       10I 0 Value                                
D  pString                        *   Value                                
D  pStringLen                   20I 0 Value                                
D  pExceptionId                 10I 0 Value                                
 // Work Variables Declaration                                             
D wReturnValue    S             10I 0 Inz(0)                               
D Value           S          65535A   Based(pString)                       
    Select ;                                                               
    When pEvent = *XML_START_DOCUMENT ;                                    
      pCommArea.HaveAttr = *Off ;                                          
      Dsply 'Initialize Local Variables. If any' ;                         
    When pEvent = *XML_START_ELEMENT ;                                     
      SaveElement = %Subst(Value:1:pStringLen);                            
      Dsply SaveElement ;                                                  
    When pEvent = *XML_CHARS ;                                             
      SaveElement = %Subst(Value:1:pStringLen);                            
      Dsply SaveElement ;                                                  
    When pEvent = *XML_END_ELEMENT ;                                       
      SaveElement = %Subst(Value:1:pStringLen);                            
      Dsply SaveElement ;                                                  
    When pEvent = *XML_ATTR_NAME ;                                         
      pCommArea.AttrName = %Subst(Value:1:pStringLen);                     
      Dsply pCommArea.AttrName ;                                           
    When pEvent = *XML_ATTR_CHARS ;                                        
      pCommArea.AttrValue = %Subst(Value:1:pStringLen);                    
      Dsply pCommArea.AttrValue ;                                          
    When pEvent = *XML_END_ATTR ;                                          
      pCommArea.AttrName = %Subst(Value:1:pStringLen);                     
      Dsply pCommArea.AttrName ;                                           
    When pEvent = *XML_END_DOCUMENT ;                                      
      wReturnValue = -1 ;                                                  
      Dsply 'No Further Parsing is Needed' ;                               
    EndSl ;                                                                
    Return wReturnValue ;                                                  
P pHandlingProcedure...                                                    
P                 E                                                    
In this example, we are storing XML data into Variable and using Option 'doc=string'. 

If the XML has been stored on IFS path. Same program can be considered as an example by just simple change.
  • Initialize the wSampleXml with IFS path.
D wSampleXml      S            512A   Inz('home/PReddy/SampleXml.xml')   
  • Remove the XML Population into wSampleXml variable.
  • Use 'doc=file' in XML options.
   wXmlOptions = 'doc=string ';        

You can try on by replacing 'Dsply' Statements with actual requirement.

Tuesday, March 15, 2016

Working with XML in RPGLE - Contd.

Working with XML in RPGLE

We have seen how to read XML in RPG by using XML-INTO in the previous post.

If you have not gone through this yet, Click Here to have quick look.

Before we get started with XML-SAX here are some other key points to be noted about XML.

Key Points to Remember:

The XML documents can be in a character or UCS-2 RPG variable, or they can be in an Integrated File System file.
  • This would give freedom to the programmer to choose the best suited form. 

The parser is a SAX (Simple API for XML) parser. A SAX parser operates by reading the XML document character by character.
  • Whenever it has located a fragment of the XML document, such as an element name, or an attribute value, it calls back to a handling procedure provided by the caller of the parser, passing it information about the fragment of XML that it has found.
It'd be easier to understand with an example.


When the parser has found an XML element name, it calls the handling procedure indicating that the "event" is a "start element" event and passing it the name of the element.
The handling procedure processes the information and returns to the parser which continues to read the XML document until it has enough information to call the handling procedure with another event. This process repeats until the entire XML document has been parsed, or until the handling procedure indicates that parsing should end.

Here you go with simple example to see how the events are defined.

<email type="text">

Lets break this data and see how the Parser will read the XML by Events & Event Data.

  • If the Parsed Text is '<email' or '<sendto>', Event would be Start Element and Event Data would be 'email' or 'sendto' respectively.
  • If the Parsed Text is 'type=', Event would be Attribute value and Event Data would be 'type'.
  • If the Parsed Text is '', Event would be Element Content and Event data would be ''.
  • If the Parsed Text is '</email>' or '</sendto>', Event would be End Element and Event Data would be 'email' or 'sendto' respectively.
The XML-SAX and XML-INTO operation codes allow you to use the XML parser. Some more points to make a note about these Opcodes.

  • The XML-SAX operation allows you to specify an event handling procedure to handle every event that the parser generates. This is useful if you do not know in advance what an XML document may contain (XML-INTO will be useful when you know what XML will contain exactly).


    • If you know that an XML document will contain an XML attribute with the name type, and you want to know the value of this attribute, your handling procedure can wait for the "attribute name" event to have a value of "type". Then the next time the handler is called, it should be an "attribute value" event, with the required data ("text" in the example above).

  • The XML-INTO operation allows you to read the contents of an XML document directly into an RPG variable. This is useful if you know the format of the XML document and you know that the names of the XML elements in the document will be the same as the names you have given to your RPG variables.


    • If you know that the XML document will always have the form of the document above, you can define an RPG data structure with the name "email", and with subfields "type" and "sendto".
    • Then you can use the XML-INTO operation to read the XML document directly into the data structure. When the operation is complete, the "type" subfield would have the value "text" and the "sendto" subfield would have the value "".

  • The XML-INTO operation also allows you to obtain the values of an unknown number of repeated XML elements. You provide a handling procedure that receives the values of a fixed number of elements each time the handling procedure is called. This is useful if you know that the XML document will contain a series of identical XML elements, but you don't know in advance how many there will be.
  • The XML data is always returned by the parser in text form. If the data is known to represent other datatypes such as numeric data, or date data, the XML-SAX handling procedure must use conversion functions such as %INT or %DATE to convert the data.

We'll see more about XML-SAX & %Handler along with an example in next post. Click Here to go through.

Wednesday, March 2, 2016

Working with XML in RPGLE : XML-INTO

Working with XML in RPGLE

XML has been one of the best format to pass a communication message between different Applications/Servers. This can be easily readable by both Humans & Machines.

With the introduction of XML-INTO Opcode in RPGLE, Reading XML has become easier in RPG.


XML-INTO is an Opcode introduced for RPG programmers to retrieve XML data directly to RPG Variable. This Opcode need to be used in conjuction with %XML & %HANDLER.

This can be used in both Free & Fixed Formats. Yet, There will be limitations for using in fixed format.

  1. One of the Main Reasons being the its limitation on Number of digits.

XML-INTO parses an XML document extracting a single element directly into a variable (Or an array). Usually, This will be used to extract multiple elements and values will be populated to Data Structure.

But, This approach would be better suited if number of items retrieved is known.

The basic syntax of the basic variant of XML-INTO is:

XML-INTO { (E H} } variable %XML( xmlDoc { : options } );

E - will set on %Error BIF if there is any occured while parsing xml.
H - will be used if we require any numeric to be rounding during charecter - numeric conversion.

But, These are Optional. And, cannot be using in Fixed format.

variable - This parameter can be a simple variable or an array or Data Structure based on XML.
The parser will be looking to match the names, nesting levels of the fields in the receiver with element and attribute names as per XML.

Here is a Small example to show how the data will be parsed into RPG variable.



<Order Type = "Weborder">
   <Customer>Mr. John</Customer>

Data Structure to recieve Data:

D Order           DS              
D  Type                         10A
D  Customer                     30A
D  Status                       10A


XML-INTO Order %XML('/home/PReddy/Orders.xml' : 'doc=file')

This Statement will retrieve the xml data directly into Data Structure "Order".

Here is one more example on how the data can be retrieved if there are multiple layers of data.
This can be done using Nested Data Structures.



<Order Type = "Weborder">
   <Customer Name = "Mr. John">
      <Address1>West Street</Address1>
      <Country>United States</Country>

Data Structure:

D Order           DS              
D  Type                         10A
D  Customer                          LikeDs(wCustomer)
D  Status                       10A

D wCustomer       DS
D  Name                         30A
D  Address1                     30A
D  Address2                     30A
D  Country                      25A


XML-INTO Order %XML('/home/PReddy/Orders.xml' : 'doc=file')

Below are the few additional Options that can be used along with %XML BIF.

  1. path option
  2. doc option
  3. ccsid option
  4. case option
  5. trim option
  6. allow missing option
  7. allow extra option
  8. data subfield
  9. count prefix

Signing off with the basics. Click Here to see more details about XML.

Different Ways of Sorting Data in a List - Python

Sorting Data in a List List is a collection of data (of different data types), much like an array. Like any data structure or data set, dat...