Variable-Length Character Data
RPG supports two types of variable-length string variables. One is defined with the %STR function, the other with the VARYING keyword. Can you explain the difference?
The VARYING keyword tells the system to store the length of the variable's value in a 2-byte binary prefix. Because of this prefix, the variable occupies two more bytes of storage than its defined length. Here's a short example that will show you this structure.
D Structure ds 24 D VarString 12a varying D Length 1 2u 0 D Data 3 24 C eval VarString = 'RPG RULZ!' C eval *inlr = *on
I overlayed the VARYING field, VarString, with two other fields so that I could use the debugger to inspect the contents of the varying-length variable. Notice what happened when I ran the program.
> EVAL structure VARSTRING OF STRUCTURE = 'RPG RULZ! ' LENGTH OF STRUCTURE = 9 DATA OF STRUCTURE = 'RPG RULZ! '
The debugger showed me that LENGTH has a value of 9. This is the length of the literal that I had assigned to VARSTRING in the RPG program. But notice that LENGTH is just another name for the first two bytes of VARSTRING. The remainder of VARSTRING is included in the DATA subfield. The debugger showed that the literal was stored in the third and subsequent bytes of VARSTRING.
Now look at the data in hex.
> EVAL structure :x 00000 0009D9D7 C740D9E4 D3E95A40 40404040 - ..RPG RULZ! 00010 40404040 40404040
Do you see the 0009 that begins the hex constant? I've colored it red. That's the length of the variable's value, which I've colored green.
Null-terminated strings come from the Unix world, or, more properly, from the C language. A null-terminated string is a group of bytes that ends with a hex zero, similar to the way that declarative sentences in English end with a period, except that the hex zero is not part of the string. Since so much OS/400 software (especially APIs) is written in C, the %STR function provides a way for RPG to exchange null-terminated strings with C programs.
Here's an example, in which an RPG program binds to C's printf function.
DShowTemperature pr extproc('printf') D Format * value options(*string) D Temperature * value options(*string) D Place * value options(*string) D Temperature s 10i 0 D Place s 12a /free ShowTemperature ('The temperature is %s in %s.': %char(Temperature):Place); *inlr = *on; /end-free
All arguments are passed to printf as pointers to null-terminated strings. If TEMPERATURE has a value of 105 and PLACE has a value of Lost Angeles, the program produces the following output.
The temperature is 105 in Lost Angeles.
Here's another example. When you run a program within Qshell, parameters are passed as null-terminated strings. That is, if the first parameter is A, the program receives an A character and a null character. Everything after the null is garbage. You can use the %STR function to extract the parameter value--up to, but not including, the null--into another variable, which I recommend be a character variable with the varying attribute.
The following program, which I cleverly named STRING7, accepts up to four parameters from Qshell.
* to compile: * CRTBNDRPG PGM(MYLIB/STRING7) + * SRCFILE(MYLIB/QRPGLESRC) + * SRCMBR(STRING7) H dftactgrp(*no) actgrp(*new) Fqsysprt o f 132 printer D Main pr extpgm('STRING7') D Parm01 64 D Parm02 64 D Parm03 64 D Parm04 64 D D Main pi D Parm01 64 D Parm02 64 D Parm03 64 D Parm04 64 D ProcessParm pr D Parm 64a D count s 1p 0 D val s 64a varying D length s 3p 0 /free if %parms >= 1; ProcessParm (Parm01); endif; if %parms >= 2; ProcessParm (Parm02); endif; if %parms >= 3; ProcessParm (Parm03); endif; if %parms >= 4; ProcessParm (Parm04); endif; *inlr = *on; /end-free Oqsysprt e pline 1 O count 4 O length 1 +0001 O +0001 '/' O val O '/' P ProcessParm b D pi D Parm 64a /free val = %str(%addr(Parm):64); length = %len(val); count += 1; except pline; /end-free P e
The %STR function requires a pointer to a variable. In this case, %STR points to the address of the parameter that was passed by reference to the subprocedure.
Run STRING7 from Qshell, passing one to four parameters of your preference. In the following example, I passed three parameters.
/qsys.lib/mylib.lib/string7.pgm Unix "-- the full employment operating system." 'RPG Rulz!'
This is the output I received.
1 4 /Unix / 2 40 /-- the full employment operating system. / 3 9 /RPG Rulz! /
Use OPTIONS(*STRING) only when exchanging data with programs that require null-terminated strings. For work variables within RPG programs, always use VARYING.
Contact the Editors
|Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved.|