5.2. Writing text data to a stream file

As mentioned previously, some human-readable text, followed by the CR and LF characters, will be viewed as a line of text. Consider the following code snippet:

     D CRLF            C                   const(x'0d25')                  
     D text            S             14a                                    
     c                   eval      text = 'Hello there.' + CRLF 

If I whip out my handy-dandy EBCDIC chart, I see that x'0D' is the EBCDIC code for carriage return, and x'25' is the EBCDIC code for line feed. Therefore, the variable called "text" above contains one line of text.

Consider this, more complicated, example:

     D CRLF            C                   const(x'0d25')                  
     D text            S            500                                    
     c                   eval      text = 'Hello there.' + CRLF + CRLF +   
     c                                'Nice day for a cruise.' + CRLF +    
     c                                'Maybe I''ll buy a yacht!'           

Think about this: How many lines are stored in the variable called "text", above? Be careful before you answer, it's a trick question.

The answer is three and a half. Why? The first CRLF ends the first line, so the first line will read "Hello there!" in the text file. The next line ends when we encounter the next CRLF, which happens right away! That means the second line is blank. The third line says "Nice day for a cruise." and ends with another CRLF. The rest of the text, however, does not end with a CRLF. It's just part of a line.

All we have to do to put that text into a text file is call write(). This code would do the job:

     c                   callp     write(fd: %addr(text):                 
     c                                       %len(%trimr(text)) )         

One small problem: If we let it be written like this, our text file would be invalid. Why? Because, remember, we left off the CRLF at the end of the last line.

To make sure that we don't make that mistake again, why not create some helper routines? What we'll do is create a service program, called IFSTEXTR4 and put our text file routines into it. Then, we'll use it for all the text files we write.

The routine to write a line will be simple. All it needs to do is accept parameters (just like write() does) for the descriptor, the text, and the text length. Then, we'll just stick a CRLF into the file after that.

Here's our IFSTEXTR4 service program, with the writeline() procedure:

      ** Service program to assist in creating TEXT files in the IFS     
     H NOMAIN OPTION(*NOSHOWCPY: *SRCSTMT)                               
     D/copy ifsebook/qrpglesrc,ifsio_h                                    
     D/copy ifsebook/qrpglesrc,ifstext_h                                  
      *  The concept here is very simple:                                
      *     1) Write the data passed to us into the stream file.         
      *     2) Add the end of line characters.                           
     P writeline       B                   export                        
     D writeline       PI            10I 0                               
     D   fd                          10I 0 value                         
     D   text                          *   value                         
     D   len                         10I 0 value                         
     D rc1             S             10I 0                               
     D rc2             S             10I 0                            
     D eol             S              2A                              
     C* write the text provided                                       
     c                   if        len > 0                            
     c                   eval      rc1 = write(fd: text: len)         
     c                   if        rc1 < 1                            
     c                   return    rc1                                
     c                   endif                                        
     c                   endif                                        
     C* then add the end-of-line chars                                
     c                   eval      eol = x'0d25'                      
     c                   eval      rc2 = write(fd: %addr(eol): 2)     
     c                   if        rc2 < 1                            
     c                   return    rc2                                
     c                   endif                                        
     c                   return    rc1 + rc2                          
     P                 E                                              

And then, we'll also need a prototype. That's what the /copy line for the "IFSTEXT_H" member is for. We'll put our prototypes in that member, so they can be easily accessed from other programs.

Here's the IFSTEXT_H member, so far:

      /if defined(IFSTEXT_H)                                      
      /define IFSTEXT_H                                           
     D writeline       PR            10I 0                        
     D   fd                          10I 0 value                  
     D   text                          *   value                  
     D   len                         10I 0 value                  

Don't compile it, yet! We're also going to add a routine for reading text files.