Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

"STRING" a paragraph name? 1

Status
Not open for further replies.

kruiser02

Programmer
Nov 21, 2008
5
Hello,

I have two STRING operations I want to accomplish:

1. Depending upon the value in a field, say W-COUNT, I want to perform a Paragraph named "MY-PARA-(W-COUNT)". e.g., if the value of W-COUNT is 01, I want to perform MY-PARA-01 and so on.
I know I can string the para name into a variable, but how do I perform it then?

2. Based on the length of a field, I want to move that into a working storage variable of same length.
I have Working storage variables defined as VAR1, VAR2 upto VAR18.
I have the length of the field in W-LEN. Apart from using an EVALUATE statement with 18 WHEN statements, is there a more efficient way to move my input data into appropriate VAR*?

Thanks for your help!
 
I think, there is only that way with evaluate

1.
Code:
EVALUATE W-COUNT
  WHEN 01
    PERFORM MY-PARA-01
  WHEN 02
    PERFORM MY-PARA-02
  ..
END-EVALUATE

2.
Code:
EVALUATE W-LEN
  WHEN 01
    MOVE MY-FIELD TO VAR01
  WHEN 02
    MOVE MY-FIELD TO VAR02
  ..
  WHEN 18
    MOVE MY-FIELD TO VAR18
END-EVALUATE
:)
 
Thanks mikrom, I can use Evaluate for my second question, but in first scenario, there can be thousands of values for paragrapg name suffix. Any other ideas?
 
As I now with paragrafs you need to use names literally only.
But with calling programs it's other:
1. You can use program literally, e.g.
Code:
CALL "MYPROG01"
or
2. you can call it with it's name stored in a variable
Code:
MOVE "MYPROG01" TO PROGNAME
CALL PROGNAME

So one way would be to create for every subtask a standalone program and than in your main caller to construct the subprogram name depending on context and then call that subprogram.

But look in manual for your compiler: Maybe there are some manufacturer extensions to ANSI standard.
Which compiler are you using?
 
Thanks ,mikrom. I dont think I can use the multi program approach.
I will have to look at my compiler version.. I am working on Z/OS, Cobol 370.
 
>I dont think I can use the multi program approach.
Why?

>but in first scenario, there can be thousands of values for paragrapg name suffix.
Thousands of values? What a monster program should it be?
Can you imagine a COBOL program with thousands of paragraphs. I cannot.
Probably would be something bad in your program design.
 
OK, I apologize for not being clear. Here is the scanario -
I have a DB2 table that has a column for fields, some other columns and a column indicating if special processing is required.

Only if the SPECIAL_PROCESS = Y, then I need to perform the paragraph corresponding that field code. So the program will only have limited number of paragraphs, those for which Special-process is required, but if I write evaluate, it will have to check the thousand fields in the table.

Probably not a good design, but that is what I have thougt so far.

Multiple programs are not preferable (definitely possible), because there will be only 10-15 statements for special processing. So I will end up doing a static call to a program for just 15 lines of code.

Here is how the table looks:
Code:
Field Code     Field Name    Field Length ....    Spl_Proc
0001            ABC             nnn        ..        Y
0002            XYZ             mmm        ..        N
....
....
..
 
Hi kruiser02,

COBOL is not suitable for such things, but if you are on mainframe you have REXX, which is perfectly suitable for that partial task.
REXX has an 'INTERPRET' statement so you can create new REXX-statement in your REXX program dynamically and interpret them.
Hier is the sceleton of such an program:

Given is a data file proc_tab.dat, which contains your table data:
Code:
0001            ABC             nnn              y
0002            XYZ             mmm              N
0003            KPQ             nnn              Y
and this REXX-script proc_pgm.rex which does the work:
Code:
/***************************/
/*      Main program       */
/***************************/
input_file  = 'proc_tab.dat'

/* Read lines in loop and process them */
do while lines(input_file) \= 0
  line = strip(linein(input_file))
  say "Processing line:"
  say line
  /* strip blanks and uppercase 4.th column*/
  special_process = translate(strip(word(line, 4)))
  if special_process = 'Y' then do
     /*compose procedure name from 2.nd column*/
     procname = "proc_"||translate(strip(word(line, 2)))
     say "creating procname: "||procname
     /* fill arguments */
     arg1 = 'my_argument1'
     arg2 = 'my_argument2'
     /* compose call statement */
     callstmt= "call "||procname||" arg1, arg2"
     say "creating call statement: "||callstmt
     /* call using REXX-interpret-statement */
     interpret callstmt      
  end
  else do
     say "special_process = '"||special_process||"'=> nothig to do."
  end
  say
end
/* close file */
call lineout input_file
/*-------------------------*/
exit

/***************************/
/*        Procedures       */
/***************************/
proc_ABC: procedure
  parse upper arg arg1, arg2
  say "Processing arguments:"
  say "   arg1='"||arg1||"', arg2='"||arg2||"'"
  say "from proc_ABC"
return

proc_KPQ: procedure
  parse upper arg arg1, arg2
  say "Processing arguments:"
  say "   arg1='"||arg1||"', arg2='"||arg2||"'"
  say "from proc_KPQ"
return
Running the script I got this result:
Code:
D:\>rexx proc_pgm.rex
Processing line:
0001            ABC             nnn              y
creating procname: proc_ABC
creating call statement: call proc_ABC arg1, arg2
Processing arguments:
   arg1='MY_ARGUMENT1', arg2='MY_ARGUMENT2'
from proc_ABC

Processing line:
0002            XYZ             mmm              N
special_process = 'N'=> nothig to do.

Processing line:
0003            KPQ             nnn              Y
creating procname: proc_KPQ
creating call statement: call proc_KPQ arg1, arg2
Processing arguments:
   arg1='MY_ARGUMENT1', arg2='MY_ARGUMENT2'
from proc_KPQ
The script reads the file line by line and if it founds the field Spl_Proc='Y' it construct the procedure name from he other field (column 2) and then calls the procedure using INTERPRET statement.

However, as I am now on windows I'm using text file for data.
But on IBM iSeries REXX has embedded SQL build in so I would use it for reading data from DB2 table.
With mainframes I'm not familiar, but if you have DB2 on it, you probably can use ESQL from REXX too.
 
>Only if the SPECIAL_PROCESS = Y, then I need to perform the paragraph corresponding that field code. So the program will only have limited number of paragraphs, those for which Special-process is required, but if I write evaluate, it will have to check the thousand fields in the table.

No you will not have to check the thousands fields, only those with SPECIAL_PROCESS = Y, i.e. those for which you need to write the paragrafs.
E.g. for the above table I used for REXX you will have to write this
Code:
       ...
           EVALUATE WS-FIELD-NAME ALSO WS-SPECIAL-PROCESS   
           WHEN 'ABC' ALSO 'Y'
                PERFORM PARA-ABC 
           WHEN 'KPQ' ALSO 'Y'
                PERFORM PARA-KPQ                
           WHEN OTHER
                PERFORM DO-SOMETHING-OTHER
           END-EVALUATE.
       ...

       PARA-ABC.
      * code the paragraph
       ...

       PARA-KPQ.
      * code the paragraph
       ...

Then if you insert in your table a new record with SPECIAL_PROCESS = Y, or you update old record setting it to Y, in order to process it you have to go in your COBOL source and add 2 new lines to the EVALUATE statement and code a new paragraf.

I don't know how frequently will your table field SPECIAL_PROCESS change from N to Y and vice versa.
When it is very often, then the COBOL EVALUATE approach becomes to be maintenace hell.


>Multiple programs are not preferable (definitely possible), because there will be only 10-15 statements for special processing.

When there are only 10-15 lines for every paragraph, is the processing for every field similar?
Would it not to be possible to design one paragraph variable to process all such fields?
 
I must be a dinousar. I read this topic and the 1st thing that comes in my mind is:
Code:
go to depending on
No-one else is advising this so I must be the last of my kind :(

 
Hi Truus vlug in de wind,

Never seen GO TO .. DEPENDING ON before :) but it seems good.
As I'm now looking at it, this seems to be the COBOL CASE-Statement:
Code:
       PARA-CASE-DECISION.
      * jump to paragraf depending on W-COUNT (1, 2, 3,..) 
           GOTO PARA-001 
                PARA-002
                PARA-003
                ...
           DEPENDING ON W-COUNT

      * in other case  
           GO TO CASE-END
           .

       PARA-001.
      * code the paragraph
           ...
           GO TO CASE-END.

       PARA-002.
      * code the paragraph
           ...
           GO TO CASE-END.

       PARA-003.
      * code the paragraph
           ...
           GO TO CASE-END.

       ...

       ...
       CASE-END.
           EXIT.
I have learned something new, so you earned the star.
 
No mikrom, you learned something OLD. :-D

Regards, Jack.

"A problem well stated is a problem half solved" -- Charles F. Kettering
 
If you would prefer above proposed REXX solution for the task discussed here, then here is the lightly improved REXX-prototype:
Code:
[COLOR=#0000ff]/***************************/[/color]
[COLOR=#0000ff]/*      Main program       */[/color]
[COLOR=#0000ff]/***************************/[/color]
input_file  [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]'proc_tab.dat'[/color]

[COLOR=#0000ff]/* Read lines in loop and process them */[/color]
[COLOR=#008080]process_lines[/color]:
[COLOR=#804040][b]do[/b][/color][COLOR=#804040][b] while [/b][/color][COLOR=#008080]lines([/color]input_file[COLOR=#008080])[/color] [COLOR=#804040][b]\=[/b][/color] 0
  line [COLOR=#804040][b]=[/b][/color] [COLOR=#008080]strip(linein([/color]input_file[COLOR=#008080]))[/color]
  [COLOR=#804040][b]say[/b][/color] [COLOR=#ff00ff]"Processing line:"[/color]
  [COLOR=#804040][b]say[/b][/color] line
  [COLOR=#0000ff]/* strip blanks and uppercase 4.th column*/[/color]
  special_process [COLOR=#804040][b]=[/b][/color] [COLOR=#008080]translate(strip(word([/color]line[COLOR=#804040][b],[/b][/color] 4[COLOR=#008080])))[/color]
[COLOR=#804040][b]  if special_process = 'Y' then do[/b][/color]
     [COLOR=#0000ff]/*compose procedure name from 2.nd column*/[/color]
     procname [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]"proc_"[/color][COLOR=#804040][b]||[/b][/color][COLOR=#008080]translate(strip(word([/color]line[COLOR=#804040][b],[/b][/color] 2[COLOR=#008080])))[/color]
     [COLOR=#804040][b]say[/b][/color] [COLOR=#ff00ff]"creating procname: "[/color][COLOR=#804040][b]||[/b][/color]procname
     [COLOR=#0000ff]/* fill arguments */[/color]
     arg1 [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]'my_argument1'[/color]
     arg2 [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]'my_argument2'[/color]
     [COLOR=#0000ff]/* compose call statement */[/color]
     callstmt[COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]"call "[/color][COLOR=#804040][b]||[/b][/color]procname[COLOR=#804040][b]||[/b][/color][COLOR=#ff00ff]" arg1, arg2"[/color]
     [COLOR=#804040][b]say[/b][/color] [COLOR=#ff00ff]"creating call statement: "[/color][COLOR=#804040][b]||[/b][/color]callstmt
     [COLOR=#0000ff]/* call using REXX-interpret-statement */[/color]
     [COLOR=#804040][b]say[/b][/color] [COLOR=#ff00ff]"Try to call procedure.."[/color]
     [COLOR=#804040][b]signal on syntax name[/b][/color] interpret_error
     [COLOR=#804040][b]interpret[/b][/color] callstmt
  [COLOR=#804040][b]end[/b][/color]
[COLOR=#804040][b]  else [/b][/color]do
     [COLOR=#804040][b]say[/b][/color] [COLOR=#ff00ff]"special_process = '"[/color][COLOR=#804040][b]||[/b][/color]special_process[COLOR=#804040][b]||[/b][/color][COLOR=#ff00ff]"'=> nothig to do."[/color]
  [COLOR=#804040][b]end[/b][/color]
  [COLOR=#804040][b]say[/b][/color]
[COLOR=#804040][b]end[/b][/color]
[COLOR=#0000ff]/* close file */[/color]
[COLOR=#804040][b]call[/b][/color][COLOR=#008080] lineout[/color] input_file
[COLOR=#0000ff]/*-------------------------*/[/color]
[COLOR=#804040][b]exit[/b][/color]

[COLOR=#0000ff]/***************************/[/color]
[COLOR=#0000ff]/*        Procedures       */[/color]
[COLOR=#0000ff]/***************************/[/color]
[COLOR=#008080]proc_ABC[/color]: [COLOR=#804040][b]procedure[/b][/color]
  [COLOR=#804040][b]parse upper arg[/b][/color] arg1[COLOR=#804040][b],[/b][/color] arg2
  [COLOR=#804040][b]say[/b][/color] [COLOR=#ff00ff]"Processing arguments:"[/color]
  [COLOR=#804040][b]say[/b][/color] [COLOR=#ff00ff]"   arg1='"[/color][COLOR=#804040][b]||[/b][/color]arg1[COLOR=#804040][b]||[/b][/color][COLOR=#ff00ff]"', arg2='"[/color][COLOR=#804040][b]||[/b][/color]arg2[COLOR=#804040][b]||[/b][/color][COLOR=#ff00ff]"'"[/color]
  [COLOR=#804040][b]say[/b][/color] [COLOR=#ff00ff]"from proc_ABC"[/color]
  [COLOR=#804040][b]return[/b][/color]

[COLOR=#008080]proc_KPQ[/color]: [COLOR=#804040][b]procedure[/b][/color]
  [COLOR=#804040][b]parse upper arg[/b][/color] arg1[COLOR=#804040][b],[/b][/color] arg2
  [COLOR=#804040][b]say[/b][/color] [COLOR=#ff00ff]"Processing arguments:"[/color]
  [COLOR=#804040][b]say[/b][/color] [COLOR=#ff00ff]"   arg1='"[/color][COLOR=#804040][b]||[/b][/color]arg1[COLOR=#804040][b]||[/b][/color][COLOR=#ff00ff]"', arg2='"[/color][COLOR=#804040][b]||[/b][/color]arg2[COLOR=#804040][b]||[/b][/color][COLOR=#ff00ff]"'"[/color]
  [COLOR=#804040][b]say[/b][/color] [COLOR=#ff00ff]"from proc_KPQ"[/color]
  [COLOR=#804040][b]return[/b][/color]

[COLOR=#008080]interpret_error[/color]:
  [COLOR=#804040][b]say[/b][/color] [COLOR=#ff00ff]"Error RC="[/color][COLOR=#804040][b]||[/b][/color][COLOR=#6a5acd]RC[/color] 
[COLOR=#804040][b]  if RC='43' then do[/b][/color]
    [COLOR=#804040][b]say[/b][/color] [COLOR=#ff00ff]"**********************************************"[/color]
    [COLOR=#804040][b]say[/b][/color] [COLOR=#ff00ff]"*Procedure "[/color][COLOR=#804040][b]||[/b][/color]procname[COLOR=#804040][b]||[/b][/color][COLOR=#ff00ff]" not defined in program !*"[/color]
    [COLOR=#804040][b]say[/b][/color] [COLOR=#ff00ff]"**********************************************"[/color]
    [COLOR=#804040][b]say[/b][/color]
    [COLOR=#0000ff]/* Continue with next line*/[/color]
    [COLOR=#804040][b]signal[/b][/color] process_lines
  [COLOR=#804040][b]end[/b][/color]
[COLOR=#804040][b]  else [/b][/color]do
    [COLOR=#804040][b]say[/b][/color] [COLOR=#008080]errortext([/color][COLOR=#6a5acd]RC[/color][COLOR=#008080])[/color]
  [COLOR=#804040][b]end[/b][/color]
  [COLOR=#804040][b]return[/b][/color]

Potential problems are diskussed in this REXX-thread:
 
Yeah, Slade is right: it's very old. Carefull with this statement. It has it's pro's and con's:
PRO
very very fast at excution time. I've seen it (re-)introduced to solve performance problems (in an ACU cobol env) and it impoved speed a lot.
CON
It is killing for you program structure. I'd say: only allow this to jump to a paragraph in the current section. Never (I mean never) allow this statement to "leave" your section (that's right: I am propagating the use of SECTIONS and PARAGRAPHs (I'm old remember?))
Exapmple:
Code:
0100-WHATEVER section.
0100-010.
     go to
           0100-020-do-this in 0100-WHATEVER
           0100-030-do that in 0100-WHATEVER
        depending on W-whocares.
     go to 0100-090         in 0100-WHATEVER. 
0100-020-do-this.
     add 1                  to W-count. 
     go to 0100-090         in 0100-WHATEVER. 

0100-030-do-that.
     subtract 1           from W-count. 
     go to 0100-090         in 0100-WHATEVER. 
  
0100-090.
    EXIT.

Still propagating SECTIONS & PARAGRAPS:

Looks oldfashioned right? But when you have the oppertunity to debug your cobol programs, you will love those EXIT paragraps as a hook for your breakpoints :)
And those INIT paragraps? What's the use of that?
when you are coding you can ask your editor: find "0100-WHATEVER" and you will find ALL the places where that section is performed and the place where the section is coded.
Ask your editor: find "0100-010" and you will jump directly to the section itself.
 
Thank you for the valuable suggestions Truusvlugindewind!

 
It's true that GO TO . . . DEPENDING is fast, in that the logic is pre-distilled by the programmer. I find that performance is still an issue to be surprising, with the ultra-fast processors now available. I replaced a Visual-Basic program with a COBOL program. The COBOL program was over 10,000 times faster.

The COBOL case statement is EVALUATE, which is more powerfull that a simple case structure and is essentially a truth-table compiler. But, as with anything in any language, if you make it too complex it slows things down.
 
Webrabbit:
In a windows/unix environment: you're absolutely right
In a MVS/DB2 environment: you're right
In a MVS/IMS/QSAM/VSAM environment: hmmmmmmmmmmmm this is where they code some pieces of code in assembler to speed up execution. In this gray area (between well structured COBOL and assembler) I would concider GO TO DEPENDING: to fight off assembler a little longer.

 
IBM now has the faster computers in the world (latest news story). When I started in programming, instruction timing was in milliseconds, then microsecons. What usually slows things down now is O/S and application bloat. We were excited when the company's new computer (mainframe) had 512K of main memory.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top