Wednesday, August 19, 2026

That time COBOL turned my "5" into "50"

So there I was... working on this batch COBOL program. The program was responsible for calculating the next settlement day based on a day-of-week code. The code is stored in a Db2 table as a 2-character field.

MOVE SETTLEMENT-DAY-CD TO WS-DESIED-WDAY

COMPUTE WS-DELTA-DAYS = WS-DESIRED-WDAY - WS-CUR-WDAY


Ship it. Done. Let's grab a coffee.

But THEY had other plans. It was not, in fact, done. 

The results were awkward. Instead of scheduling settlements for Friday (2 days away), the program wants to schedule them for 47 days from now.

Wait. What? 

Down the rabbit hole

So, I'm staring at the code and I notice something weird. 

The DCLGEN says

10 SETTLEMENT-DAY-CD  PIC X(2).


I assumed this meant values like '05' for Friday: 2 digits and zero-padded. 

But the actual value in the database was different. '5 ' (that's 5 followed by a space).

In Hex mode: F5 40 (EBCDIC for "5" and " ")

What COBOL did with that?

When I did:
MOVE '5 ' TO WS-DESIRED-WDAY (where WS-DESIRED-WDAY is defined with PIC 9(2))

COBOL was like, "Ok, two characters going into two numeric positions. The first character is '5' and the second character is a space. Since the destination field is a numeric, I'll rather put a zero than a space."
Result: 50

Not 5. Not 05. Fifty.

The fix

COBOL has this function called NUMVAL that actually thinks about what you're trying to do. 

COMPUTE WS-DESIRED-WDAY = FUNCTION NUMVAL(SETTLEMENT-DAY-CD)

Now, NUMVAL looks at '5 ' and goes, "Ah! You mean the number 5. Got it. Ignoring that trailing space for you."

The Before & After

Before (me being naive):

  MOVE SETTLEMENT-DAY-CD TO WS-DESIRED-WDAY
* '5 ' becomes 50

After (me being slightly less naive)

  COMPUTE WS-DESIRED-WDAY = FUNCTION NUMVAL(SETTLEMENT-DAY-CD)
* '5 ' becomes 5

Quick Reference



TL:DR

If you are moving character data to a numeric field and it might have spaces or inconsistent formatting,
Don't: MOVE CHAR-FIELD TO NUMERIC-FIELD
Do: COMPUTE NUMERIC-FIELD = FUNCTION NUMVAL(CHAR-FIELD)

Got your own COBOL horror stories? Drop them in the comments section below. Misery loves company.

Friday, May 22, 2026

AI in my daily Mainframe life - Episode 1: The day I deleted the wrong rows.

Hi there! Welcome to the first post of the brand new series, "AI in my daily Mainframe life" where my intent is to share AI usage stories in my daily work as a Mainframe developer. 

Here is a relatable thumbnail I generated using ChatGPT that I'll be using throughout the series. I love that coffee mug though, and would love to have it on my table. 

AI in my daily Mainframe Life

There are days at work where things go exactly as planned. And then, there are also days where you learn something the hard way. Yesterday was the latter. 

A colleague of mine asked me to get rid of some rows from a DB2 table that I was maintaining.

The request came over MS Teams, and there was a series of messages. It contained a set of rows to delete and a set of rows to retain. Both were listed next to each other.

I glanced through the message, assumed I understood it… and went ahead.

I prepared a JCL with my usual approach:

  • A SELECT SQL to verify what will be deleted
  • Followed by the DELETE SQL & commit statement
  • The same SELECT SQL as the first step to ensure intended rows are deleted from the table.
I submitted the JCL after a round of manual scanning, and the job returned a MAXCC=00. Everything looked clean. Until today.

My colleague came back reporting several issues. I had deleted the rows that were supposed to be retained. I immediately informed him and took ownership to restore the deleted rows.

Recovery Plan

Luckily, the job I had submitted had a SELECT SQL before DELETE statement. This printed the rows in the job log.

I had Zowe Explorer on my VS Code setup along with GitHub Copilot. But the job that I had submitted the previous day had moved to $AVRS ($AVRS stands for Sysout/Syslog Accumulation Viewing & Retrieval Solution. It's a product from SEA and it helps with the archival of sysout, syslog and JES datasets). 

I couldn’t access the job log via Zowe Explorer.

Coincidentally, I've signed up for an event titled, "$AVRS: Modernizing IBM Z Sysout and Syslog Management for Today’s Hybrid Enterprise". I'm hoping that I'll be able to figure out a way to access $AVRS job logs on Zowe with Rest API's after attending the webinar. The webinar is on May 26th. If you are interested, you can register here.

Now, let's go back to the main topic.

I switched to $AVRS on the Mainframe and created an XDC. I ran into a different problem. The XDC created from $AVRS was in RECFM=F and LRECL=255. This file was not readable on Zowe.

I then ran a SORT COPY and converted the RECFM to FB.

Now, I had the dataset opened on Zowe.

Enter AI

Instead of manually writing the INSERT statements for each row, I gave the dataset as context to GitHub Copilot and wrote a prompt explaining my needs.

GitHub Copilot did the heavy lifting for me by generating bulk INSERT SQL straight out of the logs. It helped save significant effort.

But not blind trust the results. 

The results from Copilot weren’t perfect though. I had to validate against the XDC data and fix minor formatting/data issues.

For instance, Copilot prepared the following SQL:

 INSERT INTO TABLE_NAME  
 (COLUMN1,  
  COLUMN2,  
  COLUMN3)  
 VALUES  
 -- values for row 1  
 ('VALUE1',  
  'VALUE2',  
  'VALUE3'),  
 -- values for row 2  
 ('VALUE1',  
  'VALUE2',  
  'VALUE3');  
 COMMIT;  

When I executed this SQL after validating the data, I got the following error:
 DSNT408I SQLCODE = -4743 ERROR: ATTEMPT TO USE A FUNCTION  
          WHEN THE APPLICATION COMPATIBILITY SETTING IS SET   
          FOR A PREVIOUS LEVEL.  
 DSNT418I SQLSTATE = 56038 SQLSTATE RETURN CODE  

After some research, I found that the error was because of the multi-row INSERT SQL that Copilot had created. Unfortunately, this Db2 capability was not supported by the current application compatibility level. 

I again used GitHub Copilot to rewrite the multi-row INSERT SQL into multiple individual INSERT statements for each row.

And yes! The recovery was successful.

Where AI actually helped

Not in decision-making or in understanding the requirements. AI helped me in speeding up the repetitive work, thereby reducing the recovery time. 

Do you have a similar story? I'd love to read it in the comments section below.

See you in the next post. 




Friday, May 15, 2026

Handling character columns in generated SQL

This blog post is a continuation of my earlier post titled "Using DFSORT to Generate Bulk SQL Queries: A Step-By-Step Guide", where I had explained in detail how IBM’s DFSORT can be used to automatically generate thousands of DB2 SQL UPDATE statements as output based on an input file (typically an Excel sheet converted to CSV).

If you haven’t read it yet, grab a cup of coffee, then start reading it here.

I felt my previous post was missing an important detail. The post implicitly assumed that all substituted values in the SET and WHERE clauses were numeric. In real DB2 tables, however, you often need to work with character columns, which must be enclosed in single quotes in SQL. It then becomes tricky with DFSORT because DFSORT also uses single quotes to delimit character constants.

This was even pointed out by one of our blog readers, who DM’ed me on LinkedIn.


Fortunately, DFSORT provides a simple way to handle this.

To generate a single quote in the output, you must code two single quotes within a DFSORT constant. For example, what DB2 expects as'VALUE' must be written in DFSORT as ''VALUE''.

Does this ring a bell? Have you heard of escape sequences? I came across escape sequences when I was learning the C programming language years back. Well, the escape sequence is something not specific to one language.

Back to the main topic. Let’s extend the earlier example and add a condition on the FIRST_NAME column in the WHERE clause. The updated DFSORT step would look like this:

 //SORTSTEP EXEC PGM=SORT  
 //SYSOUT   DD SYSOUT=*  
 //SORTIN   DD DSN=INPUT.DATA,DISP=SHR  
 //SORTOUT  DD DSN=OUTPUT.SQL,  
 //         DISP=(NEW,CATLG,DELETE),  
 //         SPACE=(CYL,(1,1),RLSE),UNIT=SYSDA  
 //SYSIN    DD *  
  OPTION COPY  
  OUTFIL BUILD=(  
   C'--- UPDATE FOR ',7,6,X,15,7,80:X,/,  
   C'UPDATE EMPLOYEES ',80:X,/,  
   C'   SET SALARY = ',38,5,80:X,/,  
   C' WHERE EMP-ID = ',1,3,80:X,/,  
   C'   AND FIRST_NAME = ''',7,6,C'''',80:X,/,  
   C'   AND SALARY = ',31,5,80:X,/,  
   ';',80:X,/,  
   80:X)  
 /*  

Notice the line:

C'   AND FIRST_NAME = ''',7,6,C''''

Here is how it works:

  • The opening ''' (i.e. '' inside a constant) produces a single quote.
  • 7,6 inserts the FIRST_NAME value (e.g., John)
  • The closing C'''' again produces a single quote.

As a result, the generated SQL output will correctly include the string literal.

 --- UPDATE FOR JOHN SMITH  
 UPDATE EMPLOYEES  
    SET SALARY = 5500  
  WHERE EMP-ID = 001  
    AND FIRST_NAME = 'John '  
    AND SALARY = 5000  
 ;  

That’s it. By incorporating this technique, you can extend the original solution to generate fully functional SQL statements for tables with mixed data types, making the approach much more practical for real-world batch updates.

Hope this helps. Thanks for reading!



Wednesday, April 22, 2026

Moving Backward and Forward at the same time

Hey everyone! Long time.

I haven't posted anything here since my last post on November 21st last year. Life has been a bit busy,  balancing work and home, especially with the delightful chaos my 2-year-old twin boys bring into the picture. 🙂

Over the last five months, I’ve constantly thought about writing my next blog post. I even created rough drafts on several topics, but somehow never found the time to complete them.

Last month, I visited the Chennai Pen Show and bought an acrylic fountain pen from Click Pens. 


                                    
The Acrylic Fountain Pen that I bought from Click Pens. The model name is Renaissance.

I came to a realization when I went back home and began writing with it. I already had a number of great fountain pens in my stationery drawer and bag, but I wasn't using them enough. 

So, I decided to change something.

Instead of typing the blog drafts directly on my laptop, I'll be writing them on my notebook using my fountain pens. 



And here is my first blog post following the new trend. 

Recently, I had the opportunity to write a COBOL DB2 program from scratch. As a Mainframe developer, this isn’t unusual. But the tools and the way I approached development this time were completely different.

About 99% of the code was written on VS Code using IBM Z Open Editor and Zowe Explorer.

Alongside the development process, I conversed with GitHub Copilot (mostly using Claude Opus 4.5 & 4.6 models) to better design the structure and flow of the program. 

It was a great experience compared to the traditional way of coding. You always have the AI assistant at your service, helping you structure logic, name your paragraphs, write loops, and handle repetitive tasks. You provide clear context, and the AI does a lot of the heavy lifting.

However, one thing became very clear to me:

AI is powerful, but not perfect without human oversight. Human involvement is still essential for effective collaboration.

For instance, when the initial cut of development was complete, I asked the AI assistant to perform a robust and comprehensive peer review. It highlighted several issues, which I fixed. Confident with the changes, I began staging the program in Endevor. To my surprise, the staging still failed due to several issues. 

One of them was related to MOVE statements.

In my initial version, I had the MOVE statements like the following:

MOVE GROUP-A.VAR-1 TO GROUP-B.VAR-1.

However, during compilation, these MOVE statements were flagged as errors.

What’s worth noting is that the initial version of these MOVE statements was suggested by the AI assistant. Although it captured the intent correctly, it overlooked COBOL-specific syntax requirements, which eventually caused compilation failures.

To fix this, I had to replace all such occurrences of the MOVE statement with dot notation to OF notation like below:

MOVE VAR-1 OF GROUP-A TO VAR-1 OF GROUP-B.

There were plenty of such occurrences that I instructed the AI assistant to replace all the MOVE statements with proper notation.

Based on my overall experience, I found that Claude models did a fairly better job when it came to generating COBOL code, especially when clear context was provided.

For instance, I had a requirement to perform a credit limit check for all customers within a group. The logic was simple in intent but required careful structuring. The program should proceed to the next step only if all customers in the group pass the check. If even one customer fails, the entire group should be skipped, and processing should continue with the next group.

When I described this to the model, it suggested an “all-or-nothing” approach and generated the corresponding COBOL logic. What stood out was that the solution was not just syntactically correct but also logically aligned with the requirement, and it worked as expected with minimal changes.

This experience showed me that AI is particularly effective when the problem is clearly defined.

That’s all for now. I’ll be back soon with another blog post and possibly a new series: “AI in My Daily Mainframe Life.”

As a closing thought, I recently added a cool little piece to my work desk, a 3D-printed z17 model that also doubles as a pen stand.

3D Printed z17 model Pen Stand

For the curious folks, I used the 3D design files that I found here 

Would love to hear what you think. Let me know in the comments.

Thanks for reading!



Friday, November 21, 2025

Printing the Numbers 0 to 9's shape using COBOL

This blog post is an extension to the previous post and we'll be extending the COBOL program's capability to print the shape of numbers, in addition to the alphabets.

Introduction

The existing COBOL program to print the shape of 26 alphabets using the respective letter itself can be found here. In this blog post, we'll be adding additional paragraphs and logic to print the shape of the numbers 0 to 9. Everything else remains the same (the program will still accept only 10 characters as input, and it doesn't accept any spaces in the user input).

Approach

The approach is pretty similar to that of printing the alphabet's shape. First and foremost, the shape of the numbers will be drawn on an Excel sheet, where the shape will be spread across a 7x7 cell, as shown below. This will be a reference to writing the logic.


In the existing logic, once the user input is entered, the input string is converted to uppercase letters, user input is then checked for spaces, and once it's deemed OK to be used, we'll go over each and every character of the input with the help of a PERFORM loop and reference modification and invoke the corresponding para to print the character's shape. All of these remain as they are. We'll be adding 10 additional paras to print the shape of the numbers.

Code

Here 👇 is the complete code to print the shape of the numbers in addition to the alphabets. N0-PARA, N1-PARA, N2-PARA, N3-PARA, N4-PARA, N5-PARA, N6-PARA, N7-PARA, N8-PARA and N9-PARA are added to print the shape of the numbers from 0 to 9, respectively. There aren't any hard-and-fast rules for printing the shape of the numbers.

ID DIVISION.                                                     
PROGRAM-ID. PATTERN.                                             
AUTHOR. SRINIVASAN.                                              
DATE-WRITTEN. 13-JUL-2024.                                       
DATA DIVISION.                                                   
WORKING-STORAGE SECTION.                                         
01 WS-DATA-ITEMS.                                                
   05 WS-INPUT                     PIC X(10).                    
   05 WS-INPUT-UPPER               PIC X(10).                    
   05 WS-PART1                     PIC X(10).                    
   05 WS-PART2                     PIC X(10).                    
   05 WS-COUNT                     PIC 9(2) COMP.                
   05 WS-I                         PIC 9(2).                     
   05 WS-J                         PIC 9(2).                     
   05 WS-K                         PIC 9(2).                     
   05 WS-L                         PIC 9(2).                     
   05 WS-TEMP                      PIC 9(2).                     
01 WS-TABLE1.                                                    
   05 WS-LINE OCCURS 7 TIMES.                                    
      10 WS-LETTER OCCURS 70 TIMES PIC X(1).                     
01 WS-TABLE2.                                                    
   05 WS-DISPLAY-LINE OCCURS 7 TIMES.                            
      10 WS-DISPLAY OCCURS 10 TIMES.                             
         15 WS-DATA                PIC X(7).                     
         15 WS-FILLER              PIC X.                        
PROCEDURE DIVISION.                                              
    INITIALIZE WS-TABLE1                                         
               WS-TABLE2                                         
               WS-DATA-ITEMS.                                    
    PERFORM ASK-USER THRU ASK-EXIT                               
    PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > WS-COUNT       
    EVALUATE WS-INPUT-UPPER(WS-I:1)                              
    WHEN 'A'                                                     
    PERFORM A-PARA THRU A-EXIT                                   
    WHEN 'B'                                                     
    PERFORM B-PARA THRU B-EXIT                                   
    WHEN 'C'                                                     
    PERFORM C-PARA THRU C-EXIT                                   
    WHEN 'D'                                                     
    PERFORM D-PARA THRU D-EXIT                                   
    WHEN 'E'                                                     
    PERFORM E-PARA THRU E-EXIT                                   
    WHEN 'F'                                                     
    PERFORM F-PARA THRU F-EXIT                                   
    WHEN 'G'                                                     
    PERFORM G-PARA THRU G-EXIT                                   
    WHEN 'H'                                                     
    PERFORM H-PARA THRU H-EXIT                                   
    WHEN 'I'                                                     
    PERFORM I-PARA THRU I-EXIT                                   
    WHEN 'J'                                                     
    PERFORM J-PARA THRU J-EXIT                                   
    WHEN 'K'                                                     
    PERFORM K-PARA THRU K-EXIT                                   
    WHEN 'L'                                                     
    PERFORM L-PARA THRU L-EXIT                                   
    WHEN 'M'                                                     
    PERFORM M-PARA THRU M-EXIT                                   
    WHEN 'N'                                                     
    PERFORM N-PARA THRU N-EXIT                                   
    WHEN 'O'                                                     
    PERFORM O-PARA THRU O-EXIT                                   
    WHEN 'P'                                                     
    PERFORM P-PARA THRU P-EXIT                                   
    WHEN 'Q'                                                     
    PERFORM Q-PARA THRU Q-EXIT                                   
    WHEN 'R'                                                     
    PERFORM R-PARA THRU R-EXIT                                   
    WHEN 'S'                                                     
    PERFORM S-PARA THRU S-EXIT                                   
    WHEN 'T'                                                     
    PERFORM T-PARA THRU T-EXIT                                   
    WHEN 'U'                                                     
    PERFORM U-PARA THRU U-EXIT                                   
    WHEN 'V'                                                     
    PERFORM V-PARA THRU V-EXIT                                   
    WHEN 'W'                                                     
    PERFORM W-PARA THRU W-EXIT                                   
    WHEN 'X'                                                     
    PERFORM X-PARA THRU X-EXIT                                   
    WHEN 'Y'                                                     
    PERFORM Y-PARA THRU Y-EXIT                                   
    WHEN 'Z'                                                     
    PERFORM Z-PARA THRU Z-EXIT    
    WHEN '0'
    PERFORM N0-PARA THRU N0-EXIT
    WHEN '1'
    PERFORM N1-PARA THRU N1-EXIT
    WHEN '2'
    PERFORM N2-PARA THRU N2-EXIT
    WHEN '3'
    PERFORM N3-PARA THRU N3-EXIT
    WHEN '4'
    PERFORM N4-PARA THRU N4-EXIT
    WHEN '5'
    PERFORM N5-PARA THRU N5-EXIT
    WHEN '6'
    PERFORM N6-PARA THRU N6-EXIT
    WHEN '7'
    PERFORM N7-PARA THRU N7-EXIT
    WHEN '8'
    PERFORM N8-PARA THRU N8-EXIT
    WHEN '9'
    PERFORM N9-PARA THRU N9-EXIT
    END-EVALUATE                                                 
    END-PERFORM                                                  
    PERFORM DISPLAY-PARA THRU DISPLAY-EXIT.                      
    STOP RUN.                                                    

N0-PARA.
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J > 5
    COMPUTE WS-TEMP = WS-I * 7 - WS-J
    MOVE '0' TO WS-LETTER(1, WS-TEMP)
    MOVE '0' TO WS-LETTER(7, WS-TEMP)
    END-PERFORM
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J > 6
    COMPUTE WS-TEMP = WS-I * 7
    MOVE '0' TO WS-LETTER(WS-J, WS-TEMP)
    COMPUTE WS-TEMP = WS-I * 7 - 6
    MOVE '0' TO WS-LETTER(WS-J, WS-TEMP)
    END-PERFORM.
N0-EXIT. EXIT.

N1-PARA.
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J > 6
    COMPUTE WS-TEMP = WS-I * 7 - 3
    MOVE '1' TO WS-LETTER(WS-J, WS-TEMP)
    IF WS-J EQUAL 2 THEN
    COMPUTE WS-TEMP = WS-I * 7 - 4
    MOVE '1' TO WS-LETTER(WS-J, WS-TEMP)
    END-IF
    IF WS-J EQUAL 3 THEN
    COMPUTE WS-TEMP = WS-I * 7 - 5
    MOVE '1' TO WS-LETTER(WS-J, WS-TEMP)
    END-IF
    IF WS-J EQUAL 4 THEN
    COMPUTE WS-TEMP = WS-I * 7 - 6
    MOVE '1' TO WS-LETTER(WS-J, WS-TEMP)
    END-IF
    END-PERFORM
    PERFORM VARYING WS-J FROM 0 BY 1 UNTIL WS-J > 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE '1' TO WS-LETTER( 7, WS-TEMP )
    END-PERFORM.
N1-EXIT. EXIT.

N2-PARA.
    PERFORM VARYING WS-J FROM 0 BY 1 UNTIL WS-J > 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE '2' TO WS-LETTER( 7, WS-TEMP )
    END-PERFORM
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J > 5
    COMPUTE WS-TEMP = WS-I * 7 - WS-J
    MOVE '2' TO WS-LETTER(1, WS-TEMP)
    END-PERFORM
    MOVE 0 TO WS-L
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J > 6
    IF WS-J EQUAL 2 THEN
    COMPUTE WS-TEMP = WS-I * 7 - 6
    MOVE '2' TO WS-LETTER(WS-J, WS-TEMP)
    END-IF
    COMPUTE WS-TEMP = WS-I * 7 - WS-L
    MOVE '2' TO WS-LETTER(WS-J, WS-TEMP)
    COMPUTE WS-TEMP = WS-I * 7 - WS-L - 1
    MOVE '2' TO WS-LETTER(WS-J, WS-TEMP)
    ADD 1 TO WS-L 
    END-PERFORM.
N2-EXIT. EXIT.

N3-PARA.
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J > 6
    COMPUTE WS-TEMP = WS-I * 7 - WS-J
    MOVE '3' TO WS-LETTER(1, WS-TEMP)
    MOVE '3' TO WS-LETTER(7, WS-TEMP)
    END-PERFORM
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J > 5
    COMPUTE WS-TEMP = WS-I * 7 - WS-J
    MOVE '3' TO WS-LETTER(4, WS-TEMP)
    END-PERFORM
    COMPUTE WS-TEMP = WS-I * 7
    MOVE '3' TO WS-LETTER(2, WS-TEMP)
    MOVE '3' TO WS-LETTER(3, WS-TEMP)
    MOVE '3' TO WS-LETTER(5, WS-TEMP)
    MOVE '3' TO WS-LETTER(6, WS-TEMP).
N3-EXIT. EXIT.

N4-PARA.
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J > 3
    COMPUTE WS-TEMP = WS-I * 7
    MOVE '4' TO WS-LETTER(WS-J, WS-TEMP)
    COMPUTE WS-TEMP = WS-I * 7 - 6
    MOVE '4' TO WS-LETTER(WS-J, WS-TEMP)
    END-PERFORM
    PERFORM VARYING WS-J FROM 0 BY 1 UNTIL WS-J > 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE '4' TO WS-LETTER(4, WS-TEMP )
    END-PERFORM
    PERFORM VARYING WS-J FROM 5 BY 1 UNTIL WS-J > 7
    COMPUTE WS-TEMP = WS-I * 7
    MOVE '4' TO WS-LETTER(WS-J, WS-TEMP)
    END-PERFORM.
N4-EXIT. EXIT.

N5-PARA.
    PERFORM VARYING WS-J FROM 0 BY 1 UNTIL WS-J > 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE '5' TO WS-LETTER(1, WS-TEMP )
    END-PERFORM
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J > 3
    COMPUTE WS-TEMP = WS-I * 7 - 6
    MOVE '5' TO WS-LETTER(WS-J, WS-TEMP)
    END-PERFORM
    PERFORM VARYING WS-J FROM 5 BY 1 UNTIL WS-J > 6
    COMPUTE WS-TEMP = WS-I * 7
    MOVE '5' TO WS-LETTER(WS-J, WS-TEMP)
    END-PERFORM
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J > 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE '5' TO WS-LETTER(4, WS-TEMP)
    MOVE '5' TO WS-LETTER(7, WS-TEMP)
    END-PERFORM.
N5-EXIT. EXIT.

N6-PARA.
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J > 5
    COMPUTE WS-TEMP = WS-I * 7 - WS-J
    MOVE '6' TO WS-LETTER(1, WS-TEMP)
    MOVE '6' TO WS-LETTER(7, WS-TEMP)
    END-PERFORM
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J > 3
    COMPUTE WS-TEMP = WS-I * 7 - 6
    MOVE '6' TO WS-LETTER(WS-J, WS-TEMP)
    END-PERFORM
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J > 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE '6' TO WS-LETTER(4, WS-TEMP)
    END-PERFORM
    PERFORM VARYING WS-J FROM 5 BY 1 UNTIL WS-J > 6
    COMPUTE WS-TEMP = WS-I * 7
    MOVE '6' TO WS-LETTER(WS-J, WS-TEMP)
    COMPUTE WS-TEMP = WS-I * 7 - 6
    MOVE '6' TO WS-LETTER(WS-J, WS-TEMP)
    END-PERFORM.
N6-EXIT. EXIT.

N7-PARA.
    PERFORM VARYING WS-J FROM 0 BY 1 UNTIL WS-J > 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE '7' TO WS-LETTER(1, WS-TEMP )
    END-PERFORM
    MOVE 0 TO WS-L
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J > 7
    COMPUTE WS-TEMP = WS-I * 7 - WS-L
    MOVE '7' TO WS-LETTER(WS-J, WS-TEMP)
    ADD 1 TO WS-L 
    END-PERFORM.
N7-EXIT. EXIT.

N8-PARA.
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J > 5
    COMPUTE WS-TEMP = WS-I * 7 - WS-J
    MOVE '8' TO WS-LETTER(1, WS-TEMP)
    MOVE '8' TO WS-LETTER(4, WS-TEMP)
    MOVE '8' TO WS-LETTER(7, WS-TEMP)
    END-PERFORM
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J > 3
    COMPUTE WS-TEMP = WS-I * 7
    MOVE '8' TO WS-LETTER(WS-J, WS-TEMP)
    COMPUTE WS-TEMP = WS-I * 7 - 6
    MOVE '8' TO WS-LETTER(WS-J, WS-TEMP)
    END-PERFORM
    PERFORM VARYING WS-J FROM 5 BY 1 UNTIL WS-J > 6
    COMPUTE WS-TEMP = WS-I * 7
    MOVE '8' TO WS-LETTER(WS-J, WS-TEMP)
    COMPUTE WS-TEMP = WS-I * 7 - 6
    MOVE '8' TO WS-LETTER(WS-J, WS-TEMP)
    END-PERFORM.
N8-EXIT. EXIT.

N9-PARA.
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J > 5
    COMPUTE WS-TEMP = WS-I * 7 - WS-J
    MOVE '9' TO WS-LETTER(1, WS-TEMP)
    MOVE '9' TO WS-LETTER(7, WS-TEMP)
    END-PERFORM
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J > 3
    COMPUTE WS-TEMP = WS-I * 7
    MOVE '9' TO WS-LETTER(WS-J, WS-TEMP)
    COMPUTE WS-TEMP = WS-I * 7 - 6
    MOVE '9' TO WS-LETTER(WS-J, WS-TEMP)
    END-PERFORM
    PERFORM VARYING WS-J FROM 0 BY 1 UNTIL WS-J > 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE '9' TO WS-LETTER(4, WS-TEMP)
    END-PERFORM
    PERFORM VARYING WS-J FROM 5 BY 1 UNTIL WS-J > 6
    COMPUTE WS-TEMP = WS-I * 7
    MOVE '9' TO WS-LETTER(WS-J, WS-TEMP)
    END-PERFORM.
N9-EXIT. EXIT.

A-PARA.                                                          
    COMPUTE WS-TEMP = WS-I * 7 - 3                               
    MOVE 'A' TO WS-LETTER( 1, WS-TEMP )                          
    COMPUTE WS-TEMP = WS-I * 7 - 4                               
    MOVE 'A' TO WS-LETTER( 2, WS-TEMP )                          
    COMPUTE WS-TEMP = WS-I * 7 - 2                               
    MOVE 'A' TO WS-LETTER( 2, WS-TEMP )                          
    COMPUTE WS-TEMP = WS-I * 7 - 5                               
    MOVE 'A' TO WS-LETTER( 3, WS-TEMP )                          
    COMPUTE WS-TEMP = WS-I * 7 - 1                               
    MOVE 'A' TO WS-LETTER( 3, WS-TEMP )                          
    PERFORM VARYING WS-J FROM 4 BY 1 UNTIL WS-J > 7              
    COMPUTE WS-TEMP = WS-I * 7                                   
    MOVE 'A' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'A' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J > 5              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'A' TO WS-LETTER( 5, WS-TEMP )                          
    END-PERFORM.                                                 
A-EXIT. EXIT.                                                    

B-PARA.                                                          
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J > 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'B' TO WS-LETTER( 1, WS-TEMP )                          
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'B' TO WS-LETTER( 7, WS-TEMP )                          
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J > 6              
    COMPUTE WS-TEMP = WS-I * 7                                   
    MOVE 'B' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'B' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J > 5              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'B' TO WS-LETTER( 4, WS-TEMP )                          
    END-PERFORM.                                                 
B-EXIT. EXIT.                                                    

C-PARA.                                                          
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J > 6              
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'C' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 0 BY 1 UNTIL WS-J = 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'C' TO WS-LETTER( 1, WS-TEMP )                          
    MOVE 'C' TO WS-LETTER( 7, WS-TEMP )                          
    END-PERFORM.                                                 
C-EXIT. EXIT.                                                    

D-PARA.                                                          
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 7              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'D' TO WS-LETTER( 1, WS-TEMP )                          
    MOVE 'D' TO WS-LETTER( 7, WS-TEMP )                          
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J = 7              
    COMPUTE WS-TEMP = WS-I * 7                                   
    MOVE 'D' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'D' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM.                                                 
D-EXIT. EXIT.                                                    

E-PARA.                                                          
    PERFORM VARYING WS-J FROM 0 BY 1 UNTIL WS-J > 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'E' TO WS-LETTER( 1, WS-TEMP )                          
    MOVE 'E' TO WS-LETTER( 7, WS-TEMP )                          
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J = 7              
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'E' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'E' TO WS-LETTER( 4, WS-TEMP )                          
    END-PERFORM.                                                 
E-EXIT. EXIT.                                                    

F-PARA.                                                          
    PERFORM VARYING WS-J FROM 0 BY 1 UNTIL WS-J > 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'F' TO WS-LETTER( 1, WS-TEMP )                          
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J = 8              
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'F' TO WS-LETTER( WS-J, WS-TEMP)                        
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J = 7              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'F' TO WS-LETTER( 4, WS-TEMP )                          
    END-PERFORM.                                                 
F-EXIT. EXIT.                                                    

G-PARA.                                                          
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'G' TO WS-LETTER( 1, WS-TEMP )                          
    MOVE 'G' TO WS-LETTER( 7, WS-TEMP )                          
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J > 6              
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'G' TO WS-LETTER( WS-J, WS-TEMP )                       
    IF WS-J NOT EQUAL 3 THEN                                     
    COMPUTE WS-TEMP = WS-I * 7                                   
    MOVE 'G' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    IF WS-J EQUAL 4 THEN                                         
    COMPUTE WS-TEMP = WS-I * 7 - 1                               
    MOVE 'G' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7 - 2                               
    MOVE 'G' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7 - 3                               
    MOVE 'G' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    IF WS-J EQUAL 5 THEN                                         
    COMPUTE WS-TEMP = WS-I * 7 - 3                               
    MOVE 'G' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    END-PERFORM.                                                 
G-EXIT. EXIT.                                                    

H-PARA.                                                          
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 8              
    COMPUTE WS-TEMP = WS-I * 7                                   
    MOVE 'H' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'H' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'H' TO WS-LETTER( 4, WS-TEMP )                          
    END-PERFORM.                                                 
H-EXIT. EXIT.                                                    

I-PARA.                                                          
    PERFORM VARYING WS-J FROM 0 BY 1 UNTIL WS-J > 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'I' TO WS-LETTER( 1, WS-TEMP )                          
    MOVE 'I' TO WS-LETTER( 7, WS-TEMP )                          
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J = 7              
    COMPUTE WS-TEMP = WS-I * 7 - 3                               
    MOVE 'I' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM.                                                 
I-EXIT. EXIT.                                                    

J-PARA.                                                          
    PERFORM VARYING WS-J FROM 0 BY 1 UNTIL WS-J > 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'J' TO WS-LETTER( 1, WS-TEMP )                          
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J = 8              
    IF WS-J EQUAL 5 OR WS-J EQUAL 6 THEN                         
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'J' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    COMPUTE WS-TEMP = WS-I * 7 - 3                               
    MOVE 'J' TO WS-LETTER( WS-J, WS-TEMP )                       
    IF WS-J EQUAL 7 THEN                                         
    COMPUTE WS-TEMP = WS-I * 7 - 5                               
    MOVE 'J' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7 - 4                               
    MOVE 'J' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    END-PERFORM.                                                 
J-EXIT. EXIT.                                                    

K-PARA.                                                          
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 8              
    IF WS-J EQUAL 1 OR WS-J EQUAL 7 THEN                         
    COMPUTE WS-TEMP = WS-I * 7                                   
    MOVE 'K' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'K' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    IF WS-J EQUAL 2 OR WS-J EQUAL 6 THEN                         
    COMPUTE WS-TEMP = WS-I * 7 - 2                               
    MOVE 'K' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7 - 1                               
    MOVE 'K' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'K' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    IF WS-J EQUAL 3 OR WS-J EQUAL 5 THEN                         
    COMPUTE WS-TEMP = WS-I * 7 - 4                               
    MOVE 'K' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7 - 3                               
    MOVE 'K' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'K' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    IF WS-J EQUAL 4 THEN                                         
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'K' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7 - 5                               
    MOVE 'K' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    END-PERFORM.                                                 
K-EXIT. EXIT.                                                    

L-PARA.                                                          
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 7              
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'L' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 0 BY 1 UNTIL WS-J = 7              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'L' TO WS-LETTER( 7, WS-TEMP )                          
    END-PERFORM.                                                 
L-EXIT. EXIT.                                                    

M-PARA.                                                          
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 8              
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'M' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7                                   
    MOVE 'M' TO WS-LETTER( WS-J, WS-TEMP )                       
    IF WS-J EQUAL 2 THEN                                         
    COMPUTE WS-TEMP = WS-I * 7 - 5                               
    MOVE 'M' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7 - 1                               
    MOVE 'M' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    IF WS-J EQUAL 3 THEN                                         
    COMPUTE WS-TEMP = WS-I * 7 - 4                               
    MOVE 'M' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7 - 2                               
    MOVE 'M' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    IF WS-J EQUAL 4 THEN                                         
    COMPUTE WS-TEMP = WS-I * 7 - 3                               
    MOVE 'M' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    END-PERFORM.                                                 
M-EXIT. EXIT.                                                    

N-PARA.                                                          
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 8              
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'N' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7                                   
    MOVE 'N' TO WS-LETTER( WS-J, WS-TEMP )                       
    IF WS-J EQUAL 2 THEN                                         
    COMPUTE WS-TEMP = WS-I * 7 - 5                               
    MOVE 'N' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    IF WS-J EQUAL 3 THEN                                         
    COMPUTE WS-TEMP = WS-I * 7 - 4                               
    MOVE 'N' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    IF WS-J EQUAL 4 THEN                                         
    COMPUTE WS-TEMP = WS-I * 7 - 3                               
    MOVE 'N' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    IF WS-J EQUAL 5 THEN                                         
    COMPUTE WS-TEMP = WS-I * 7 - 2                               
    MOVE 'N' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    IF WS-J EQUAL 6 THEN                                         
    COMPUTE WS-TEMP = WS-I * 7 - 1                               
    MOVE 'N' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    END-PERFORM.                                                 
N-EXIT. EXIT.                                                    

O-PARA.                                                          
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J = 7              
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'O' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7                                   
    MOVE 'O' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'O' TO WS-LETTER( 1, WS-TEMP )                          
    MOVE 'O' TO WS-LETTER( 7, WS-TEMP )                          
    END-PERFORM.                                                 
O-EXIT. EXIT.                                                    

P-PARA.                                                          
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 7              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'P' TO WS-LETTER( 1, WS-TEMP )                          
    MOVE 'P' TO WS-LETTER( 4, WS-TEMP )                          
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J = 4              
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'P' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7                                   
    MOVE 'P' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 5 BY 1 UNTIL WS-J = 8              
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'P' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM.                                                 
P-EXIT. EXIT.                                                    

Q-PARA.                                                          
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'Q' TO WS-LETTER( 1, WS-TEMP )                          
    MOVE 'Q' TO WS-LETTER( 6, WS-TEMP )                          
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J = 6              
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'Q' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7                                   
    MOVE 'Q' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM                                                  
    COMPUTE WS-TEMP = WS-I * 7                                   
    MOVE 'Q' TO WS-LETTER( 7, WS-TEMP).                          
Q-EXIT. EXIT.                                                    

R-PARA.                                                          
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 7              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'R' TO WS-LETTER( 1, WS-TEMP )                          
    MOVE 'R' TO WS-LETTER( 4, WS-TEMP )                          
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J = 4              
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'R' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7                                   
    MOVE 'R' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 5 BY 1 UNTIL WS-J = 8              
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'R' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7                                   
    MOVE 'R' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM.                                                 
R-EXIT. EXIT.                                                    

S-PARA.                                                          
    PERFORM VARYING WS-J FROM 0 BY 1 UNTIL WS-J = 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'S' TO WS-LETTER( 1, WS-TEMP )                          
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 7              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'S' TO WS-LETTER( 7, WS-TEMP )                          
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'S' TO WS-LETTER( 4, WS-TEMP )                          
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J = 4              
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'S' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 5 BY 1 UNTIL WS-J = 7              
    COMPUTE WS-TEMP = WS-I * 7                                   
    MOVE 'S' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM.                                                 
S-EXIT. EXIT.                                                    

T-PARA.                                                          
    PERFORM VARYING WS-J FROM 0 BY 1 UNTIL WS-J = 7              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'T' TO WS-LETTER( 1, WS-TEMP )                          
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 2 BY 1 UNTIL WS-J = 8              
    COMPUTE WS-TEMP = WS-I * 7 - 3                               
    MOVE 'T' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM.                                                 
T-EXIT. EXIT.                                                    

U-PARA.                                                          
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 7              
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'U' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7                                   
    MOVE 'U' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 6              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'U' TO WS-LETTER( 7, WS-TEMP )                          
    END-PERFORM.                                                 
U-EXIT. EXIT.                                                    

V-PARA.                                                          
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 4              
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'V' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7                                   
    MOVE 'V' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM                                                  
    PERFORM VARYING WS-J FROM 4 BY 1 UNTIL WS-J = 6              
    COMPUTE WS-TEMP = WS-I * 7 - 5                               
    MOVE 'V' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7 - 1                               
    MOVE 'V' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-PERFORM                                                  
    COMPUTE WS-TEMP = WS-I * 7 - 4                               
    MOVE 'V' TO WS-LETTER( 6, WS-TEMP )                          
    COMPUTE WS-TEMP = WS-I * 7 - 2                               
    MOVE 'V' TO WS-LETTER( 6, WS-TEMP )                          
    COMPUTE WS-TEMP = WS-I * 7 - 3                               
    MOVE 'V' TO WS-LETTER( 7, WS-TEMP ).                         
V-EXIT. EXIT.                                                    

W-PARA.                                                          
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 7              
    COMPUTE WS-TEMP = WS-I * 7 - 6                               
    MOVE 'W' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7                                   
    MOVE 'W' TO WS-LETTER( WS-J, WS-TEMP )                       
    IF WS-J EQUAL 5 THEN                                         
    COMPUTE WS-TEMP = WS-I * 7 - 3                               
    MOVE 'W' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    IF WS-J EQUAL 6 THEN                                         
    COMPUTE WS-TEMP = WS-I * 7 - 4                               
    MOVE 'W' TO WS-LETTER( WS-J, WS-TEMP )                       
    COMPUTE WS-TEMP = WS-I * 7 - 2                               
    MOVE 'W' TO WS-LETTER( WS-J, WS-TEMP )                       
    END-IF                                                       
    END-PERFORM                                                  
    COMPUTE WS-TEMP = WS-I * 7 - 5                               
    MOVE 'W' TO WS-LETTER( 7, WS-TEMP )                          
    COMPUTE WS-TEMP = WS-I * 7 - 1                               
    MOVE 'W' TO WS-LETTER( 7, WS-TEMP ).                         
W-EXIT. EXIT.                                                    

X-PARA.                                                          
    MOVE 6 TO WS-L                                               
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 8              
    COMPUTE WS-TEMP = WS-I * 7 - WS-L                            
    MOVE 'X' TO WS-LETTER( WS-J, WS-TEMP )                       
    SUBTRACT 1 FROM WS-L                                         
    END-PERFORM                                                  
    MOVE 6 TO WS-L                                               
    PERFORM VARYING WS-J FROM 7 BY -1 UNTIL WS-J = 0             
    COMPUTE WS-TEMP = WS-I * 7 - WS-L                            
    MOVE 'X' TO WS-LETTER( WS-J, WS-TEMP )                       
    SUBTRACT 1 FROM WS-L                                         
    END-PERFORM.                                                 
X-EXIT. EXIT.                                                    

Y-PARA.                                                          
    MOVE 6 TO WS-L                                               
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J = 5              
    COMPUTE WS-TEMP = WS-I * 7 - WS-L                            
    MOVE 'Y' TO WS-LETTER( WS-J, WS-TEMP )                       
    SUBTRACT 1 FROM WS-L                                         
    END-PERFORM                                                  
    MOVE 6 TO WS-L                                               
    PERFORM VARYING WS-J FROM 7 BY -1 UNTIL WS-J = 0             
    COMPUTE WS-TEMP = WS-I * 7 - WS-L                            
    MOVE 'Y' TO WS-LETTER( WS-J, WS-TEMP )                       
    SUBTRACT 1 FROM WS-L                                         
    END-PERFORM.                                                 
Y-EXIT. EXIT.                                                    

Z-PARA.                                                          
    PERFORM VARYING WS-J FROM 0 BY 1 UNTIL WS-J = 7              
    COMPUTE WS-TEMP = WS-I * 7 - WS-J                            
    MOVE 'Z' TO WS-LETTER( 1, WS-TEMP )                          
    MOVE 'Z' TO WS-LETTER( 7, WS-TEMP )                          
    END-PERFORM                                                  
    MOVE 6 TO WS-L                                               
    PERFORM VARYING WS-J FROM 7 BY -1 UNTIL WS-J = 0             
    COMPUTE WS-TEMP = WS-I * 7 - WS-L                            
    MOVE 'Z' TO WS-LETTER( WS-J, WS-TEMP )                       
    SUBTRACT 1 FROM WS-L                                         
    END-PERFORM.                                                 
Z-EXIT. EXIT.                                                    

ASK-USER.                                                        
    DISPLAY 'ENTER A STRING. PLEASE LIMIT TO'                    
    DISPLAY 'MAX 10 CHARACTERS. THE PROGRAM '                    
    DISPLAY 'WILL NOT KNOW THE CHARACTERS   '                    
    DISPLAY 'ENTERED BEYOND 10 ;)           '                    
    ACCEPT WS-INPUT                                              
    DISPLAY ' '                                                  
    DISPLAY 'ENTERED STRING IS ' WS-INPUT                        
    DISPLAY ' '                                                  
    MOVE FUNCTION UPPER-CASE(WS-INPUT) TO WS-INPUT-UPPER
    INITIALIZE WS-PART1
               WS-PART2
    UNSTRING WS-INPUT DELIMITED BY SPACE INTO                    
             WS-PART1, WS-PART2                                  
    IF WS-PART2 NOT EQUAL SPACES THEN                            
       DISPLAY 'ENTER A STRING WITHOUT SPACES IN BETWEEN.'       
       PERFORM ASK-USER THRU ASK-EXIT                            
    ELSE                                                         
       INSPECT WS-INPUT TALLYING WS-COUNT FOR CHARACTERS.        
ASK-EXIT. EXIT.                                                  

DISPLAY-PARA.                                                    
    PERFORM ANOTHER-TABLE-PARA THRU ANOTHER-EXIT                 
            VARYING WS-K FROM 1 BY 1 UNTIL WS-K = 8              
    PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J > 7              
    DISPLAY WS-DISPLAY-LINE(WS-J)                                
    END-PERFORM                                                  
    DISPLAY ' '                                                  
    DISPLAY ' '.                                                 
DISPLAY-EXIT. EXIT.                                              

ANOTHER-TABLE-PARA.                                              
    MOVE 1 TO WS-L                                               
    PERFORM VARYING WS-J FROM 1 BY 7 UNTIL WS-J > 70             
    MOVE WS-LINE(WS-K)(WS-J:7) TO WS-DATA(WS-K, WS-L)            
    MOVE ' ' TO WS-FILLER(WS-K, WS-L)                            
    ADD 1 TO WS-L                                                
    END-PERFORM.                                                 
ANOTHER-EXIT. EXIT.

You can execute this code on JDoodle by clicking 👉 here.

Explanation

Learn the logic to print each number's shape in an interactive way.


Output

Here 👇 is the output after executing the code. The program now prints the shape of both numbers as well as alphabets 👍.


If you want to play with this code, feel free to create a fork of this 👉 repository in GitHub.

Conclusion

You've reached the end. In the next post, we'll extend the capability of this program further by allowing it to print spaces and to also allow the user to enter an input up to 20 characters long.

I hope this helps!


P.S: This article is reposted from https://iamamainframer.hashnode.dev/ 


Thursday, September 18, 2025

Why SRCHFOR didn’t find my string (and how I fixed it)

 Not long ago, I was trying to search for a string inside a PDS using the SRCHFOR command. To my surprise, the command returned the message:String(s) not found

Invoking the SRCHFOR command with the search string

String(s) not found

But I knew for sure that the member contained the exact string!

Here is the member in PDS with the exact string that we are searching for.

This reminded me of a post I had read about two years ago where someone faced the same issue. At that time, I noted it as an interesting quirk of ISPF. Now that I’ve stumbled upon it again, I thought I’d document the problem, the solutions I explored, and how I eventually rediscovered that original tip.

The problem: SRCHFOR and case sensitivity

The root cause is simple: SRCHFOR automatically converts the search string to uppercase after you press Enter.

So if your dataset member has mixed-case text (e.g., HelloWorld) and you try:

SRCHFOR 'HelloWorld'

it silently changes it to:

SRCHFOR 'HELLOWORLD'

…and of course, the match fails.

Step 1: Checking the documentation

To be sure I wasn’t missing something, I pulled out the z/OS ISPF User Guide. I even uploaded the manual to NotebookLM and asked how to prevent SRCHFOR from changing the case of my search string.

NotebookLM suggested two options:

    1. Use ISPF 3.15 (Extended Search-For)

  • This option provides an ASIS field.
  • When you specify ASIS=YES, the search is performed without converting the string to uppercase.
  • This worked perfectly.

Type the search string in the Asis field. As you see, multiple search strings can be searched in one go. 


String(s) found. Yeahh!

    2. Use the SFE Command

  • SFE is a panel-driven version of SRCHFOR.
  • You can invoke it directly against a PDS and provide the search key.
  • This also respected the case and gave correct results.
Type 'SFE' in the line command area against the PDS.

Type the search string. Put a '/' on the Any case process option at the bottom left to select it. 

String(s) found.

Both solutions worked, but I still felt there must be a simpler way.

Step 2: Rediscovering the Reddit Tip

While searching online, I found the exact Reddit post I had read two years ago. The OP there had shared a neat trick:

  • Invoke SRCHFOR without parameters:

    SRCHFOR
  • This opens up the Search-For Options panel.

  • From there, select the “Any case” process option.

Once you do this, SRCHFOR will no longer force your search string to uppercase. Problem solved!

(Credit to the Redditor who originally shared this tip)

Invoke SRCHFOR from the command line without passing a search string.

In the SRCHFOR options displayed, put a '/' on the Any case process option at the bottom left.

Try searching for the string (with lowercase) again

String(s) found.

Three Ways to Solve the Problem

Here’s a quick summary of the methods I tested:

  1. ISPF 3.15 (Extended Search-For) with ASIS

    • Best for detailed searches with lots of parameters.

  2. SFE Command

    • Quick, panel-based, and respects the case.

  3. SRCHFOR (no parameters) → Select “Any case”

    • Simple, and once set, it keeps SRCHFOR from changing your string.

Bonus: SRCHFOR vs. SRCHFORE

While digging around, I also refreshed my memory on the difference between the two commands:

  • SRCHFOR → Searches within a single dataset (PDS or sequential).

  • SRCHFORE → The extended version, which lets you search across multiple datasets or a dataset list.

So if you often search across a group of libraries, SRCHFORE is your friend.

Wrap-Up

This little exercise was a reminder that even tools we’ve used for years can have hidden quirks. SRCHFOR changing case silently tripped me up, but now I know at least three ways around it.

If you ever find SRCHFOR telling you “No strings found” when you’re sure otherwise, try one of these fixes. And a big thanks to that Redditor from two years ago—your tip still saves the day!