If any of the below parameters are not present then need to find for keyword Keys and add the required parameters.
NONINDEXED,
NIXD,
INDEXED,
IXD,
NUMBERED,
NUMD
To overcome this scenarios i have added "Keyp?" & "Defines?" to your code.
Code:
Defines? = Pos( ' DEFINE', LINE ) > 0
NoIndex? = Pos( ' NONINDEXED', LINE ) > 0 ,
| Pos( ' NIXD', LINE ) > 0
Index? = Pos( ' INDEXED', LINE ) > 0 ,
| Pos( ' IXD', LINE ) > 0
Number? = Pos( ' NUMBERED', LINE ) > 0 ,
| Pos( ' NUMD', LINE ) > 0
Keysp? = Pos( ' KEYS', LINE ) > 0
. . . . . . . . . . . . .
SELECT
WHEN Defines? THEN DO
ADDPERM = 'N'
END
WHEN NoIndex? & ADDPERM = 'N' THEN DO
PRMT3 = "LOG(NONE)"||' '||"-"
CALL ADD_ATTRIBUTES
ADDPERM = 'Y'
END
WHEN Index? & ADDPERM = 'N' THEN DO
PRMT3 = "LOG(UNDO)"||' '||"-"
P1=POS(VAR1,LINE)
CALL ADD_ATTRIBUTES
ADDPERM = 'Y'
END
WHEN Number? & ADDPERM = 'N' THEN DO
PRMT3 = "LOG(UNDO)"||' '||"-"
P1=POS(VAR1,LINE)
CALL ADD_ATTRIBUTES
ADDPERM = 'Y'
END
WHEN Keysp? & ADDPERM = 'N' THEN DO
ATTR3 = "LOG(UNDO)"||' '||"-"
CALL ADD_ATTRIBUTES
ADDPERM = 'Y'
END
. . . . . . . . .
It's adding parameters in below scenarios:
1. When there is space between Keys and '(" ex: "KEYS (09 00)" .
2. If parameter is ending with ')' i.e., last parameter ex: INDEXED)
"(CURRLN) = LINENUM .ZCSR" /* CURRENT LINE */
"(LASTLN) = LINENUM .ZLAST" /* LAST LINE NUMBER */
I = 0
DO FOREVER
I = I + 1
IF I > LASTLN THEN LEAVE
"(LINE) = LINE " I
LINE = SUBSTR(LINE,1,80)
IF SUBSTR(LINE,1,3) = "//*" | SUBSTR(LINE,1,3) = " /*" THEN ITERATE
VAR1 = SUBWORD(LINE,1,1)
UPPER VAR1
PRMT1 = "RLSQUIESCE"||' '||"-"
Defines? = Pos( ' DEFINE', LINE ) > 0,
| Pos( ' DEFINE ', LINE ) > 0
stringa? = Pos( ' STRINGA', LINE ) > 0,
| Pos( ' STRINGA ', LINE ) > 0,
| Pos( ' STRINGA)', LINE ) > 0,
| Pos( ' STRINGA )', LINE ) > 0
stringb? = Pos( ' STRINGb', LINE ) > 0,
| Pos( ' STRINGb ', LINE ) > 0,
| Pos( ' STRINGb)', LINE ) > 0,
| Pos( ' STRINGb )', LINE ) > 0
NoIndex? = Pos( ' NONINDEXED', LINE ) > 0 ,
| Pos( ' NIXD', LINE ) > 0
Index? = Pos( ' INDEXED', LINE ) > 0 ,
| Pos( ' IXD', LINE ) > 0
Number? = Pos( ' NUMBERED', LINE ) > 0 ,
| Pos( ' NUMD', LINE ) > 0
Keysp? = Pos( ' KEYS', LINE ) > 0,
| Pos( ' KEYS ', LINE ) > 0
SELECT
WHEN Defines? THEN DO
ADDATTR = 'N'
END
WHEN stringa? & ADDATTR = 'N' THEN DO
PRMT2 = "LOG(UNDO)"||' '||"-"
CALL ADD_ATTRB
ADDATTR = 'Y'
END
WHEN stringb? & ADDATTR = 'N' THEN DO
PRMT2 = "LOG(NONE)"||' '||"-"
CALL ADD_ATTRB
ADDATTR = 'Y'
END
WHEN NoIndex? & ADDATTR = 'N' THEN DO
PRMT2 = "LOG(NONE)"||' '||"-"
CALL ADD_ATTRA
ADDATTR = 'Y'
END
WHEN Index? & ADDATTR = 'N' THEN DO
PRMT2 = "LOG(UNDO)"||' '||"-"
CALL ADD_ATTRA
ADDATTR = 'Y'
END
WHEN Number? & ADDATTR = 'N' THEN DO
PRMT2 = "LOG(UNDO)"||' '||"-"
CALL ADD_ATTRA
ADDATTR = 'Y'
END
WHEN Keysp? & ADDATTR = 'N' THEN DO
PRMT2 = "LOG(UNDO)"||' '||"-"
CALL ADD_ATTRA
ADDATTR = 'Y'
END
OTHERWISE
NOP
END
END
/* EXIT(RC) */
NoIndex? = Pos( ' NONINDEXED', LINE ) > 0 ,
| Pos( ' NIXD', LINE ) > 0
Index? = Pos( ' INDEXED', LINE ) > 0 ,
| Pos( ' IXD', LINE ) > 0
So every time you set NoIndex? you also set Index? SIASD!
The flags are used ONLY to indicate the presence of each specific keyword in the current line.
Alternate way is - explicit reset of all flags before every new line, and/or conditional verification of each flag depending on those previously set.
This approach would be really SIASD - if only you thought a little about this.
The most primitive fix is: insert your new line(s) not after, but before the current line; either it ends with ')' or not.
The whole REXX code could also be re-arranged in a more simple and clear way; I'm busy now for this exercise. Maybe later I'll return to it.
I tried to add before but my code is overwriting. I will try again and post the results.
I also will test with trace option and try to figure out.
I can understand. Thanks for your time and help.
I spent about 40 minutes to fix the bugs, to adjust the style of coding, and to remove absolutely unneeded garbage from the code.
It seems to be working correctly.
I am against using too complicated methods to reach simple goals, that's why I always do everything in the most simple way.
Code:
/* REXX */
Address ISREDIT
"MACRO"
"(CURRLN) = LINENUM .ZCSR" /* CURRENT LINE */
"(LASTLN) = LINENUM .ZLAST" /* LAST LINE NUMBER */
I = 0
Defines? = 0
AttrAdded? = 0
Do Forever
I = I + 1
If I > LASTLN Then Leave /* stop at the end of text */
"(LINE) = LINE " I /* read whole line */
Parse Var Line Line '/*' Comments /* separate comment part */
If Line = '' Then /* nothing but comments? */
Iterate /* continue to next line */
If ¬Defines? Then Do /* look for first DEFINE */
Defines? = Pos( ' DEFINE', LINE ) > 0 /* mark "DEFINE clause" */
If Defines? Then
AttrAdded? = 0 /* reset flag when first in DEFINE */
End
Else If Pos( ' DATA', LINE ) > 0 Then /* look for end DEFINE */
Defines? = 0 /* mark "out of DEFINE clause */
If ¬Defines? , /* while not within DEFINE */
| AttrAdded? Then /* or all done already */
Iterate /* continue to next line */
/* Detect all keywords we are interested in */
NoIndex? = Pos( ' NONINDEXED', LINE ) > 0 ,
| Pos( ' NIXD', LINE ) > 0
Index? = Pos( ' INDEXED', LINE ) > 0 ,
| Pos( ' IXD', LINE ) > 0
Number? = Pos( ' NUMBERED', LINE ) > 0 ,
| Pos( ' NUMD', LINE ) > 0
Keysp? = Pos( ' KEYS', LINE ) > 0
Select
When NoIndex? Then
CALL ADD_ATTRB I "LOG(NONE) -"
When Index? ,
| Number? ,
| Keysp? Then
CALL ADD_ATTRB I "LOG(UNDO) -"
Otherwise
Nop
End
End
Return 0
/* ------------------------------------------------------------ */
ADD_ATTRB:
/* ------------------------------------------------------------ */
Arg LN PRMT2 /* variable parts passed as parameters */
Address ISREDIT
PRMT1 = "RLSQUIESCE -" /* constant part defined as local */
P1 = Verify( LINE, ' ' ) /* calculate current indentation */
Blanks = Copies( ' ', P1 - 2 ) /* prepare string of blanks */
"ISREDIT LINE_BEFORE " LN "= DATALINE '" Blanks || PRMT1"'"
"ISREDIT LINE_BEFORE " LN "= DATALINE '" Blanks || PRMT2"'"
LASTLN = LASTLN + 2 /* new last line now moved by 2 */
AttrAdded? = 1 /* flag "this clause done" */
Return
I hope when more special cases need to be considered, it would be much easier to update a short and clear code, rather than a sophisticated and long one.
The most primitive fix is: insert your new line(s) not after, but before the current line; either it ends with ')' or not.
The whole REXX code could also be re-arranged in a more simple and clear way; I'm busy now for this exercise. Maybe later I'll return to it.
I tried to add before but my code is overwriting. I will try again and post the results.
I also will test with trace option and try to figure out.
I can understand. Thanks for your time and help.
I spent about 40 minutes to fix the bugs, to adjust the style of coding, and to remove absolutely unneeded garbage from the code.
It seems to be working correctly.
I am against using too complicated methods to reach simple goals, that's why I always do everything in the most simple way.
Code:
/* REXX */
Address ISREDIT
"MACRO"
"(CURRLN) = LINENUM .ZCSR" /* CURRENT LINE */
"(LASTLN) = LINENUM .ZLAST" /* LAST LINE NUMBER */
I = 0
Defines? = 0
AttrAdded? = 0
Do Forever
I = I + 1
If I > LASTLN Then Leave /* stop at the end of text */
"(LINE) = LINE " I /* read whole line */
Parse Var Line Line '/*' Comments /* separate comment part */
If Line = '' Then /* nothing but comments? */
Iterate /* continue to next line */
If ¬Defines? Then Do /* look for first DEFINE */
Defines? = Pos( ' DEFINE', LINE ) > 0 /* mark "DEFINE clause" */
If Defines? Then
AttrAdded? = 0 /* reset flag when first in DEFINE */
End
Else If Pos( ' DATA', LINE ) > 0 Then /* look for end DEFINE */
Defines? = 0 /* mark "out of DEFINE clause */
If ¬Defines? , /* while not within DEFINE */
| AttrAdded? Then /* or all done already */
Iterate /* continue to next line */
/* Detect all keywords we are interested in */
NoIndex? = Pos( ' NONINDEXED', LINE ) > 0 ,
| Pos( ' NIXD', LINE ) > 0
Index? = Pos( ' INDEXED', LINE ) > 0 ,
| Pos( ' IXD', LINE ) > 0
Number? = Pos( ' NUMBERED', LINE ) > 0 ,
| Pos( ' NUMD', LINE ) > 0
Keysp? = Pos( ' KEYS', LINE ) > 0
Select
When NoIndex? Then
CALL ADD_ATTRB I "LOG(NONE) -"
When Index? ,
| Number? ,
| Keysp? Then
CALL ADD_ATTRB I "LOG(UNDO) -"
Otherwise
Nop
End
End
Return 0
/* ------------------------------------------------------------ */
ADD_ATTRB:
/* ------------------------------------------------------------ */
Arg LN PRMT2 /* variable parts passed as parameters */
Address ISREDIT
PRMT1 = "RLSQUIESCE -" /* constant part defined as local */
P1 = Verify( LINE, ' ' ) /* calculate current indentation */
Blanks = Copies( ' ', P1 - 2 ) /* prepare string of blanks */
"ISREDIT LINE_BEFORE " LN "= DATALINE '" Blanks || PRMT1"'"
"ISREDIT LINE_BEFORE " LN "= DATALINE '" Blanks || PRMT2"'"
LASTLN = LASTLN + 2 /* new last line now moved by 2 */
AttrAdded? = 1 /* flag "this clause done" */
Return
I hope when more special cases need to be considered, it would be much easier to update a short and clear code, rather than a sophisticated and long one.
I am so thankful for what you did.
I just added one more line since i saw some statement "DEF CLUSTER" instead of DEFINE CLUSTER.
Code:
Defines? = Pos( ' DEFINE', LINE ) > 0,
| Pos( ' DEF ', LINE ) > 0
Thanks again for helping me with this requirement.
1) The alternate solution is supposed mainly to resolve another issue: standardized alignment/arrangement of the source statement(s). Logically it is a separate task from adding missing parameters. Those two could be implemented separately from each other, and also applied separately, which makes sense in most cases.
2) Partial syntax check algorithm could be implemented in a less chaotic way, by using the existing REXX operations. Long time ago I did such exercises; maybe I'll present some parsing examples in a separate topic.
3) In all presented examples we did not consider important case(s): what if the parameters to be added do exist already in the source code? (For instance, if this macro has been applied twice to the same library member???)
This case is much more important than re-alignment of the source code, but it requires a changed scan/parse approach.
1) The alternate solution is supposed mainly to resolve another issue: standardized alignment/arrangement of the source statement(s). Logically it is a separate task from adding missing parameters. Those two could be implemented separately from each other, and also applied separately, which makes sense in most cases.
2) Partial syntax check algorithm could be implemented in a less chaotic way, by using the existing REXX operations. Long time ago I did such exercises; maybe I'll present some parsing examples in a separate topic.
3) In all presented examples we did not consider important case(s): what if the parameters to be added do exist already in the source code? (For instance, if this macro has been applied twice to the same library member???)
This case is much more important than re-alignment of the source code, but it requires a changed scan/parse approach.
Thanks for your suggestions and which are valid scenarios.
I already faced the similar example with respect to your third point.
Some other team already added these parameters couple of months ago but by mistakenly client had given same members to us again.
currently we are doing srchfor with keyword in the PDS before running this rexx code.
My idea is to find for string "RSLQUIESCE" and the logic if found.