Overview
One of the problems we have with packed decimal numbers is that we would like to print their values. While zoned decimal numbers are (mostly) printable, decimal numbers are not. If you take a value such as X'456F' and copy it onto a line and print it with XPRNT, you will not get the number 456 or anything useful. X'45' is not a printable character in EBCDIC, and X'6F' is a question mark.
We want to be able to print numbers, and we are sometimes rather fussy about it. We would like to be able to:
We can do most of these with the Edit command. Its format looks like this:
ED D1(L,B1),D2(B2)
D1(B1) is the address of a character field L bytes long. This is the destination where we want to have the printable value.
D2(B2) is the address of a packed decimal variable. Notice we do not have a length for it.
Before we use ED, we put an "edit pattern" in the character field at D1(B1). This is often done using MVC and a literal expressed in hexadeccimal. The edit pattern contains special byte values which tell ED how to do its work.
We also have a "significance switch" as part of ED. It is either on of off at any point.
What is in the edit pattern and how is it used?
The first byte of the edit pattern is the fill character. This is similar to the idea of a fill character in C++. It is often a blank (X'40') and is always printable.
Other bytes of the edit pattern are:
ED will work its way through the edit pattern one byte at a time and through the packed decimal number one digit at a time. As it does so, it replaces the edit pattern bytes in the destination with printable characters. The sequence of events is:
If the digit is not 0 or significance is on, replace the X'20' by the printable version of the digit (such as X'F3' for 3) and switch significance on Else replace the X'20' with the fill character.
If significance is on, leave the inserted character in place Else replace the inserted character with the fill character.
If the sign is positive, significance is switched off Else significance is switched on.
In this case, there may be more inserted characters left in the pattern, which may be printed (on) or replaced with the fill character (off).
ED will set the condition code to 0 for a zero value, 1 for a negative value or 2 for a positive value.
What happens with the significance switch?
Examples
For each example, it may be helpful to write out the packed decimal values in hexadecimal (as they are stored) and work through the example by hand.
Suppose we have these variables:
PNUM1 DC PL2'123' PNUM2 DC PL2'23' PNUM3 DC PL3'3' PNUM4 DC PL2'0' NUMOUT DS CL4
Suppose we now have these instructions:
MVC NUMOUT(2),=XL2'40202120' ED NUMOUT(2),PNUM1
The result is that NUMOUT will contain X'40F1F2F3'.
Instead suppose we have:
MVC NUMOUT(2),=XL2'40202120' ED NUMOUT(2),PNUM2
The result is that NUMOUT will contain X'4040F2F3'.
Instead suppose we have:
MVC NUMOUT(2),=XL2'40202120' ED NUMOUT(2),PNUM3
The result is that NUMOUT will contain X'404040F3'.
Instead suppose we have:
MVC NUMOUT(2),=XL2'40202120' ED NUMOUT(2),PNUM4
The result is that NUMOUT will contain X'404040F0'.
In this last case, the X'F0' appears because sigificance was turned on by the X'21'.
Instead suppose we have:
MVC NUMOUT(2),=XL2'40202020' ED NUMOUT(2),PNUM4
The result is that NUMOUT will contain X'40404040'.
This last result is not desirable. Our task is to print the value of PNUM4, and if the value is 0, we should print a 0, not just spaces. (Imagine your boss saying "You forgot to print that number!" You say "I did print it but it was 0, so it was printed as spaces." Who is going to win that argument?)
Suppose we have an amount of money. We will want to put in a decimal point (X'4B') and have two digits to the right of it. We might have:
COST DC PL3'4567' COSTOUT DS CL7
Now we have:
MVC COSTOUT(7),=X'402021204B2020' ED COSTOUT(7),COST
The result is that COSTOUT will contain X'4040F4F54BF6F7'.
On the other hand, if COST instead contains X'67', the result is that COSTOUT will contain X'404040F04BF6F7'.
If we are printing an amount of money, it is customary to print one digit to the left of the decimal point even if it is 0. (Suppose we put in a dollar sign; it is much easier to be mistaken about the value of '$.67' than about '$0.67'.)
Suppose we have a large integer. It is customary (in the U.S.) to insert a comma (X'6B') between groups of 3 digits. We might have:
BIGNUM DC PL5'87654321' BIGOUT DS CL12
Now we have:
MVC BIGOUT(12),=X'402020206B2020206B202120' ED BIGOUT(12),BIGNUM
The result is that BIGOUT will contain X'4040F8F76BF6F5F46BF3F3F2F1'.
Suppose BIGNUM has a smaller value such as 54321. The result is that BIGOUT will contain X'404040404040F5F46BF3F2F1', where the first comma did not print as a comma because the significance was still off.
How do we handle negative values? There are several ways this is done in business documents:
Suppose we have:
NEGNUM DC PL3'-2650' NEGOUT DS CL8
Now we have:
MVC NEGOUT(8),=X'402021204B202060' ED NEGOUT(8),NEGNUM
The result is that NEGNUM will contain X'4040F2F64BF5F060'. When ED reached the sign digit of NEGNUM, it found that it had a negative number and it left the significance on, so the X'60' printed as itself and not as a fill character.
If NEGNUM contained a positive value, the significance would have been switched off and the X'60' would have been replaced by the fill character.
The same mechanism can be used to print CR or DB at the right hand side.