Showing posts with label COBOL. Show all posts
Showing posts with label COBOL. Show all posts

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.

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/ 


Sunday, August 10, 2025

It is twenty-six to one — A retro clock built with COBOL

📸 Heads up! This is a highly visual post! Expect plenty of screenshots and photos from my gallery to make the walkthrough more fun and easy to follow.

Since the first image in a blog post often becomes its thumbnail, I wanted something deliberate—not a random, awkwardly cropped photo. So, I made this 👇 one in Canva.

The Spark ✨

I started collecting watches in 2021. I started off this hobby by collecting HMT watches, and now my collection includes HMT, a bunch of G-Shocks and Casio watches, a few Timex models, and watches from microbrands like Pagani Design. I like collecting watches with unique designs. Here are the pics of some unique watches from my collection.

Picto Stick and Ball watch

Kalaksh Time-Turner

Titan Geometrix

Casio G-Shock GA-V01

Fastrack x Coca-Cola


The latest one that I added to my collection was the SKMEI 2312

SKMEI is a Chinese watch brand known for offering a wide variety of affordable timepieces. They make watches that look very similar to popular brands (like Casio) but are affordable and considered homage. SKMEI 2312 is an homage to the QlockTwo W Watch, which is a unique watch that doesn't use hands or digital numbers to tell the time. Then, how does it show the time, you may wonder? It tells time in words like "IT IS FIVE PAST ONE." 



Here 👇 are some pics of the SKMEI 2312.

Wrist Shot



My inspiration for this little project, which, btw, you're reading as a blog post now, came from the SKMEI 2312, which got me thinking, if a watch can tell time in words, why not make a COBOL program do the same? 

First time with OpenCOBOL IDE

I usually prefer JDoodle's Online COBOL compiler to write COBOL programs on the go. But, for this project, I thought of trying the OpenCOBOL IDE on my personal laptop. I really loved the coding experience. It's a lightweight IDE with some useful features like a syntax highlighter, vertical grid lines indicating Area A and Area B, a navigation window showing the structure of the program with collapsible buttons, an offset calculator, etc. It would've been fantastic if there was an in-built debugger.

Here is a snapshot of my code on OpenCobolIDE.

The Logic 🧠 

The initial idea was to use the intrinsic function, FUNCTION CURRENT-DATE in COBOL, to get the hour and minute. Process the hour and minute separately to determine how to express them in words. The code heavily relies on several EVALs, which do the magic of expressing the time in words. 
Click on this -> link to execute the code on JDoodle. 

Please note that this code displays the time in words the moment you hit the Execute button, referring to the hour and minute during that moment. It doesn't act like an actual clock (which updates the time every minute). 

Testing Like a Modern Mainframer

After coding the logic, I decided to test it for every possible minute in the day. I asked ChatGPT to generate an input file of LRECL 4, with each line having the time in HHMM format starting from 0000 to 2359. I also shared the COBOL logic I created on OpenCobolIDE and asked the AI assistant to modify the code to accommodate logic for reading the input file and writing to the output file. The intent was to write a record to the output file with the time expressed in words for each record read from the input file. For example, "IT IS TWELVE IN THE MORNING" for 0000. 

Screenshot of the input file that ChatGPT generated.


Screenshot of the output file generated by the program that ChatGPT helped modify by adding code to read the input file and write to the output file. The code did have some mistakes (not major ones, though), and I corrected them with several trials and errors. 

The logic that I wrote in COBOL expresses the time in words for each minute of the day. The program handles the AM/PM by representing the time period at the end of the sentence, like this:
  • Hours < 12 → “IN THE MORNING”
  • Hour = 12 → “IN THE NOON”
  • Hours > 12 & < 17 → “IN THE AFTERNOON”
  • Hours ≥ 17 & < 21 → “IN THE EVENING”
  • Hours ≥ 21 → “IN THE NIGHT”
The SKMEI 2312 watch (or the QlockTwo W watch for that matter) doesn't express the time in words for each minute. The watch displays the time in five-minute intervals. For example, it will show the time as "IT IS FIVE PAST TWO.", then "IT IS TEN PAST TWO." To indicate the exact minutes, there are 4 dots at each corner of the square grid of letters. The number of dots lit up at a specific time equals that many minutes plus the minute part of the time expressed in words. For example, if the time is displayed as "IT IS FIVE PAST TWO" with two dots lit up, the exact time is "IT IS SEVEN PAST TWO."

The watch displays "IT IS    TO TWO" with a dot lit up on the top left corner of the watch. This means, "IT IS ONE TO TWO" i.e., 01:59. 

The Blog widget idea 💡

I'm running this blog on Blogger by Google. It allows me to edit the layout of the site. I can add/edit gadgets to my blog. For example, the IBM Champions badge that you see on the right side (if you're reading this post using the web version of this blog) is an HTML/Javascript gadget. IBM provided this badge through Credly, and Credly provides me with the code to display the badge on a web page, blog, or anywhere else that accepts HTML.



Since I had already added a number of gadgets to my blog, I thought, "Why not add this Time In words gadget as well?" 

Once the logic was stable, I leaned on ChatGPT (again) with the following prompt:
How can I show this time-in-words as a live widget on my blog?
Out of many ideas that it provided,  I chose the one that suggested,
  • hosting OUTPUT.txt file on GitHub Pages
  • Use Javascript to read the current time (in HHMM format)
  • Use the HHMM value to look up the matching line in the file hosted on GitHub Pages
  • Display the time in words, updating every minute

First time with GitHub Pages

I had never used GitHub Pages before, but it turned out to be perfect. In a nutshell, GitHub Pages is like a website for your GitHub repository. 

I created this GitHub repo and added the COBOL program and input/output files. I set up the GitHub Pages on my repo to host the OUTPUT.txt file so that it's available in public and can be fetched by the blog widget. 

GitHub Pages on the repo is disabled by default, and you can enable it by configuring a publishing source for your site. Publishing source, in my case, is the main branch root folder of the repo. All the files that I added/will be adding to the repo will be immediately published on the site. 

Settings on the GitHub Pages on my repo.

Here is the link to the site.

If you know the exact filename in the repository, you can view its contents directly by appending the filename to the site’s URL.
For example, starting from the main site URL, https://jvsrinivasan.github.io/time-in-words/ adding OUTPUT.txt at the end (https://jvsrinivasan.github.io/time-in-words/OUTPUT.txt) will open that file’s contents in your browser.

It's time to show time 🕐 

After hosting the OUTPUT.txt file using GitHub Pages, I asked ChatGPT to help me with the HTML/JavaScript code for the blog's widget. 

After some interaction, I was able to obtain a working code that,
  • Runs every minute (setInterval)
  • Gets the current time (new Date())
  • Formats it to HHMM
  • Looks up the matching line from OUTPUT.txt
  • Displays the time in words in a black background with green monospaced text to give the blog widget that nostalgic Mainframe terminal look 😎🟩⬛
Here is the code:
 <div id="time-in-words-widget" style="background-color:black; color:#00ff00; font-family:monospace; font-size:20px; padding:10px; border-radius:5px; text-align:center;">  
  Loading time in words...  
 </div>  
   
 <script>  
  async function showTimeInWords() {  
   const now = new Date();  
   const hours = now.getHours().toString().padStart(2, '0');  
   const minutes = now.getMinutes().toString().padStart(2, '0');  
   const hhmm = hours + minutes;  
   
   try {  
    const response = await fetch("https://your-username.github.io/time-in-words/OUTPUT.txt?cache=" + Date.now());  
    const text = await response.text();  
    const lines = text.split('\n');  
    const match = lines.find(line => line.startsWith(hhmm));  
    const output = match ? match.substring(5).trim() : "Time not found";  
   
    document.getElementById("time-in-words-widget").innerText = output;  
   } catch (error) {  
    document.getElementById("time-in-words-widget").innerText = "Error loading time.";  
   }  
  }  
   
  showTimeInWords();  
   
  // Align with start of next minute  
  const delay = (60 - new Date().getSeconds()) * 1000;  
  setTimeout(() => {  
   showTimeInWords();  
   setInterval(showTimeInWords, 60000);  
  }, delay);  
 </script>  
   

Here is a pic of the blog with the gadget in action:



Closer look at the 'Time in Words' Gadget


Closing thoughts

I could’ve done this in Python/Javascript. But I blog about COBOL—not because it’s trendy, but because it powers the systems most people don’t realize they depend on. This was my way of showing that COBOL can still surprise you. And sometimes, inspiration (for a little project) comes from something as simple as your watch. 

As a side note, a big thank you to IBM for sending me the IBM Champion merch package. This year marks my 4th consecutive year as an IBM Champion. Here is a pic of everything that IBM sent me in the package:

Thanks for reading! Should you have any comments, please write them in the Comments section below.