The ZDVw.d informat does not validate data in z/OS operating environments


The ZDVw.d informat reads and validates zoned decimal data. In z/OS operating environments, the documentation states that ZDVw.d requires an F for all high-order nibbles except the last. The last high-order nibble accepts values ranging from A-F, where A, C, E, and F are positive values, and B and D are negative values.

Although the documentation states these rules, the ZDw.d and ZDVw.d informats behave the same way and validation is not performed. Under z/OS, alphabetic data is treated as valid numeric data by both informats.

To circumvent the problem, use the FCMP procedure to create a function, reference the function in PROC FORMAT to create an informat, and read the data with the new informat. 

On hosts other than z/OS, the ZDw.d and ZDVw.d informats perform the validation so that invalid digits are considered errors. Under z/OS, neither informat performs validation.

The sample code below validates zoned decimal data in z/OS operating environments. The FCMP procedure creates a function and PROC FORMAT uses the function to create a custom informat. The DATA step tests the informat with several values.

proc fcmp outlib=work.functions.smd;
   function myfunc(textin $); 
      l=length(textin)-1; 
      do i=1 to l; 
         if not ('f0'x <= substr(textin,i,1) <= 'f9'x) 
         then return(.); 
      end;
      if not (  'c0'x <= substr(textin,l+1,1) <= 'c9'x
             Or 'd0'x <= substr(textin,l+1,1) <= 'd9'x
             Or 'f0'x <= substr(textin,l+1,1) <= 'f9'x
             ) then return(.);
      return(inputn(textin,'S370FZD.',l+1));
   endsub;
quit;
 
options cmplib=(work.functions);
 
proc format; 
   invalue zdvx(default=16) other=[myfunc()]; 
run;
 
data _null_; 
   x = input('F1F2F3'x,zdvx3.); put x=; 
   x = input('C1C2C3'x,zdvx3.); put x=;
   x = input('F1F2B3'x,zdvx3.); put x=;
run;

This sample code produces the following output:

/* Values written to the SAS log indicate that the first data value was */
/* valid while the last two are invalid.                                */

x=123
x=.
x=.