docd...@panix.com wrote:
> In article <
x7Kdne_W6JRDfp_L...@giganews.com>,
> Arnold Trembley <
arnold....@att.net> wrote:
>> If I need to change all the trailing spaces in a PIC X field to nulls
>> (LOW-VALUES), I would like to be able to code it this way:
>>
>> 05 destination-field PIC X(100) VALUE SPACES.
>>
>> MOVE "This is a null-terminated string" TO destination-field
>>
>> INSPECT destination-field REPLACING TRAILING SPACES BY LOW-VALUES.
>>
>> But when I look in the IBM Enterprise COBOL manual for z/OS, there
>> is no TRAILING option for INSPECT..REPLACING.
>
> How about:
Doc,
This cannot work as posted.
WS-SOURCE-FIELD is imaginary... it is defined nowhere.
WS-DESINATION-FIELD is spelled incorrectly.
These days, with the interaction going on between workstations and
mainframes, the need to deal with null terminated strings is becoming more
prevalent.
The words 'ASCIIZ and 'EBCDICZ' are shorthand ways to write "a
null-terminated string in either of these two encoding systems".
Here's some more background:
https://msdn.microsoft.com/en-us/library/ee267399(v=bts.10).aspx
The specific stated problem:
The original requirement works on a single field; it has had an
EBCDICZ/ASCIIZ string moved to it and the requirement is to force the
padding spaces generated by the COBOL compiler when it made this move, to be
set to hex '00'. (In other words, to propagate the terminating X'00' to the
end of the destination field, which was padded with spaces by COBOL.)
(Did you actually look at any of the other code examples posted in this
thread?)
On the (necessary because you haven't defined or mentioned it) assumption
that WS-SOURCE-FIELD is representing the EBCDICZ/ASCIIZ field (e.g.
'ABCDE#', where # is X'00', note that the 88 level "validation" of these
characters is irrelevant because the string can contain ANY valid EBCDIC
character; although this will work as a 'filter' if there was a pressing
need to filter and the string had not been already validated. Normally, the
string would be "validated" at the point where the terminator was appended
to it; the terminator marks the characters that are required for the
process.)
I would make the following observations:
>
> 05 WS-CHAR-TSTFLD PIC X VALUE LOW-VALUES.
> 88 VALID-CHAR VALUES 'A' THRU 'I', 'J' THRU 'R', 'S' THRU 'Z',
> 'a' THRU 'i', 'j' THRU 'r', 's' THRU 'z',
> '0' THRU '9', (etc. as needed)
>
This is an effective and flexible "filter" but it will cause more problems
than it will solve. It will cause the source string to be truncated to the
length of the last "valid character" as defined here. (It may still contain
other "invalid characters"...) That completely invalidates the whole point
of null termination. (A way to define valid variable length strings without
having to use count fields.)
> MOVE LOW-VALUES TO WS-CHAR-TSTFLD
> WS-DESINATION-FIELD
> PERFORM VARYING SUB1 FROM (LENGTH OF WS-SOURCE-FIELD)
> BY -1
> UNTIL VALID-CHAR OR SUB1 = 0
> MOVE WS-SOURCE-FIELD(SUB1:1) TO WS-CHAR-TSTFLD
> END-PERFORM
This PERFORM is unnecessary because it will ALWAYS stop on the penultimate
character of WS-SOURCE-FIELD... UNLESS it is a character which fails the 88
level filter. If that happens, it declares the character invalid and it will
not be part of the final string transferred to WS-DESTINATION-FIELD. But the
process which "packaged" the string by null-terminating it, has indicated
that everything before the null terminator is required (that's why it is
null terminated...) You end up with two different views of what is valid and
a process which stops.
If you are not satisfied that the null terminated string is valid, then keep
the PERFORM, but in reality that string will contain valid characters for
the process which it is intended.
If you are satisfied that is the case, then you might as well say:
SET SUB1 to LENGTH OF WS-SOURCE-FIELD - 1 ...and avoid all the PERFORM
overheads...
(As already noted, the string would be validated before having the
terminator appended to it. If this is an "invalid character", then it is a
wanted one...If it is a "valid character" - which it should be... - then the
perform will stop. If there are other "invalid characters" in the string
(before the valid character), THEY won't be found, so why would you pick on
the penultimate one only... :-)
> IF SUB1 = 0
> PERFORM A315712-INVALID-INPUT THRU A315712-EXIT
(This only happens if the entire source string fails the 88 filter.
Otherwise, the string has its length changed, but it may still contain
"invalid characters", so what was the point?. It contradicts the null
termination. Adding a null terminator to a specifc position in a string says
that the characters up to that terminator are required. Even if it contains
characters that fail the 88 level, those characters were in it before it was
terminated, so those characters are required. In effect, this will bomb out
a "false positive" if it doesn't like a character in the string...)
> ELSE
> MOVE WS-SOURCE-FIELD(1:SUB1) TO WS-DESTINATION-FIELD
> END-IF
And (I think, memory may be incorrect here...) WS-DESTINATION-FIELD will be
padded with blanks (I believe it needs refmod on the target as well as the
source to prevent padding.) which is not what is wanted. All that has
happened is that the code has successfully removed the terminating Hex '00"
from the EBCDICZ/ASCIIZ string...
As they say in Japan:
"Please, look again..."