IBM i offers some new CL built-ins in 7.2.
You may or may not have noticed that with the 7.2 release of the i operating system IBM has continued to enhance CL in order to make our lives, as developers, easier. With 7.2, we have eight new CL built-ins available to us.
This month, we'll look at four of the new CL built-ins: %char, %dec, %int, and %uint. In the next article, we'll review the other four: %upper, %lower, %size, and %len.
%char
The first built-in we'll look at, %char, is defined with one parameter and is by far my favorite of the built-ins we'll review this month. The %char built-in, as you might guess if you're familiar with the ILE RPG %char built-in, converts data from one format to character format. The one parameter is required and can be of type decimal (*Dec), integer (*Int), unsigned integer (*UInt), or logical (*Lgl). The returned character value can be used anywhere that CL supports the use of a character expression. That is, it can be assigned to a CL variable (type *Char), passed as a character constant to another program, or used within the context of a more complex character expression.
This last capability, used within the context of a more complex character expression, is the item I like most. Have you ever tried to construct a message in CL from a combination of character and numeric values as in the following?
Dcl Var(&Text) Type(*Char) Len(50)
Dcl Var(&Answer) Type(*Int) Value(13)
ChgVar Var(&Text) +
Value('The answer is' *BCat &Answer)
If so, then you have also had the opportunity to give yourself a head slap when the compile fails with CPD0712 (Operand does not have valid type of operator) and CPF0711 (Operands in expression not same type). One workaround, shown below, is to convert the value of &Answer to character form prior to constructing the message.
Dcl Var(&Text) Type(*Char) Len(50)
Dcl Var(&Answer) Type(*Int) Value(13)
Dcl Var(&Temp) Type(*Char) Len(5)
ChgVar Var(&Temp) Value(&Answer)
ChgVar Var(&Text) +
Value('The answer is' *BCat &Temp)
This workaround is easy enough to code but does have some considerations:
- You need to declare the variable (&Temp in the example) to hold the character value of &Answer.
- As part of declaring &Temp, you need to consider the length (LEN) of the temporary variable since this length will impact the result of the &Text variable due to the CHGVAR of &Temp including leading zeros.
- a.With Len(5), you end up with a &Text value of 'The answer is 00013' (though with the %triml built-in you could get rid of the leading zeros).
- b.With Len(2), you end up with a &Text value of 'The answer is 13', but the program will also fail (CPF0819 – Variable or substring of variable too small to hold result) if the value of &Answer happens to be 113.
- The CHGVAR of &Text now references &Temp as opposed to &Answer (giving later reviewers of the program a bit more to look at).
Using the %char built-in, as shown below, addresses all of these concerns.
Dcl Var(&Text) Type(*Char) Len(50)
Dcl Var(&Answer) Type(*Int) Value(13)
ChgVar Var(&Text) +
Value('The answer is' *BCat %char(&Answer))
When working with numeric data, the %char built-in returns the result as a left-adjusted (with a leading negative sign if needed) decimal format with leading zeros removed so you end up with a &Text value of 'The answer is 13'. Did I mention that I really like this built-in? Though I don't envision too many developers using this built-in in the context of expressions such as the COND parameter of IF and WHEN commands, you can do this, demonstrating that the %char built-in is quite general-purpose.
With that introduction to %char, you can most likely anticipate the usage of the built-ins %dec, %int, and %uint.
%dec
The %dec built-in converts data from one format to decimal format and has three parameters. The first parameter is required and represents the data to be converted. The format of this data can be *Char, *Dec, *Int, *UInt, or *Lgl. In the case of converting *Char data to decimal format, the character data can have a leading or following negative sign and leading or trailing blanks. If a value of all blanks is found, then the resulting decimal value is 0.
The second and third parameters for %dec are optional and represent the desired number of total digits and number of decimal places, respectively, for the returned result. If the first parameter is *Char, the default for total digits is fifteen and the default for decimal places is five. If the first parameter is *Lgl, the default for total digits is one and the default for decimal places is zero. If the first parameter is numeric, the default for total digits and decimal places is the same as the attributes defined for the first parameter. Total digits can be a value from one to fifteen while decimal places can be from zero to nine (but not greater than total digits).
The %dec built-in can be used anywhere CL supports an arithmetic expression.
%int and %uint
The %int and %uint built-ins convert data from one format to 4-byte integer and 4-byte unsigned integer formats, respectively. Both define one required parameter representing the data to be converted. For the %int built-in, the parameter can be *Char, *Dec, *UInt, or *Lgl; for %uint, the parameter can be *Char, *Dec, *Int, or *Lgl.
As the *Int and *UInt data types can represent only whole numbers, any decimal digits (when converting from *Char or *Dec) will be truncated without rounding. And as *UInt can represent only unsigned numeric values, any negative values (when converting from *Char, *Dec, or *Int) will result in an error.
But Wait, There's More
The new built-ins discussed in today's article provide productivity enhancements that you should definitely consider adding to your development toolkit. In the next article, we'll look at additional built-ins that IBM has introduced to the CL language.
More CL Questions?
Wondering how to accomplish a function in CL? Send your CL-related questions to me at
LATEST COMMENTS
MC Press Online