× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



Just to make the record clear <g> I never said "Varying Data Structure".
:)

-Bob Cozzi
www.RPGxTools.com
RPG xTools - Enjoy programming again.

-----Original Message-----
From: rpg400-l-bounces+cozzi=rpgiv.com@xxxxxxxxxxxx
[mailto:rpg400-l-bounces+cozzi=rpgiv.com@xxxxxxxxxxxx] On Behalf Of Scott
Klement
Sent: Thursday, February 09, 2006 5:21 PM
To: RPG programming on the AS400 / iSeries
Subject: RE: RNX0115 message / %SubArr


> After filling 'Dlr', I wanted to remove any 'empty' elements so that when it
> was sorted using 'sorta' there would not be a bunch of empty elements at the
> start.

VARYING won't help you here. VARYING only applies to character strings, it 
doesn't apply to arrays.

I've worked with that same problem many times.  There are two solutions to 
it...  one is to use the QSort() API (or another API) to do the sorting, 
and the second is to use the %SubArr() BIF that was introduced in V5R3.

Both solutions require you to declare a variable that your code uses to 
keep track of how many elements are in the array.


> I made 'Dlr1' varying because when it was not, and 'Dlr' was varying,
> executing:
> %SubArr(Dlr:1:Idx) = %SubArr(Dlr1:1:Idx);
> caused each sub-field in 'Dlr' to be 'mis-positioned' by 2 characters.

yes, but I think you're misinterpreting what VARYING does.  VARYING 
doesn't make your array variable-sized.  It makes a character string 
variable sized.



> Bob Cozzi indicated that this was (probably) caused by the 'hidden' 
> index to the varying data structure.

There's no such thing as a varying data structure.  Just a varying field 
-- and, of course, Bob is absolutely correct that the first 2 bytes 
contain the length of the string.  This does not affect the length of the 
data structure, just the character string.

I really hate the fact that IBM implemented VARYING as a keyword. I think 
that all of the confusion surrounding VARYING is because it's really a 
data type, but you define in on a D-spec with a keyword. (and if the 
number of questions I get is any indication, there's a lot of confusion 
indeed)

But really, VARYING is a data type.  Just as packed, zoned, binary and 
integer are all different data types that store numbers, alphanumeric and 
varying are both data types that store character strings.

Consider a simple example:

      D Test            s            100A
      D Dlr             s            100A   varying


Test occupies 100 bytes of memory.  No matter what you do with Test, it 
always occupies 100 bytes of memory, and the opcodes will always think 
that there's 100 bytes of data in it.  If I type this:

      Test = 'Hello Tim';

Do you think that I've just assigned 9 bytes to Test?  Nope.  I've 
assigned 100 bytes. The characters 'Hello Tim' plus 91 blanks. The CPU 
will write every single character position every time I assign a value to 
"test".  There's no way to make it be anyting other than 100 bytes long.

On the other hand:

      Dlr = 'Hello Tim';

This Dlr variable is VARYING. It occupies 102 bytes of memory (100 bytes 
are reserved for data, and 2 bytes are reserved to keep track of the 
current length).  It will always take up 102 bytes of physical memory, but 
when I use it, it only changes 11 bytes of memory.  It first assigns the 
length of 9 (in the format x'0009') in the first 2 bytes, and then sets 
bytes 3-11 to the string 'Hello Tim'.  The remaining 91 bytes are not 
changed, and if you use this string with RPG opcodes and BIFs they won't 
try to look at those 91 bytes, they'll only use the first 9 because they 
ignore anything after the length that was stored in the first 2 bytes.

So, IMHO, it's just a different type of variable for storing alpanumeric 
data.  And a very useful one too... I rarely use fixed with strings 
anymore, to be honest.

VARYING doesn't have anything to do with data structures or arrays.

consider this array:

      D Dlr             s            100A   varying dim(2500)

That array isn't varying.  Just as the following array isn't packed:

      D Test            s              9P 2  dim(2500)

The array isn't packed...  rather it's a collection of 2500 fields, and 
each field contains a packed number.  The same is true of the VARYING data 
type.  In the first example, I don't have one varying-length array, I have 
2500 varying-length character fields.

here's another example:

      D MyStruct        ds
      D    first                      20A   varying
      D    last                       20A   varying

This data structure isn't varying.  However, it does contain two varying 
fields.  The one called "first" occupies positions 1-22 of the DS, and 
the one called "last" occupies positions 23-44 of the DS.

IMHO, it would've been clearer if instead of making a "varying" keyword, 
they simply made a "V" data type.

      D Dlr             s            100v   dim(2500)

or
      D MyStruct        ds
      D    first                      20v
      D    last                       20v

In my mind, anyway, that syntax is easier to follow.  However, that's not 
the way IBM did it, so the above syntax won't work.

If they had done it that way, it also would've put an end to the 
continual questions and confusion abotu the difference between "varying" 
and "options(*varsize)" on a prototype.  I get that question a lot. People 
don't udnerstand that VARYING is telling you the data type of the 
parameter, whereas options(*varsize) is telling the compiler not to do 
validity checking on the length.

But anyway... enough complaining about IBM for the moment. (The people in 
Toronto already hate me, why exacerbate it, right...)

    D                 Ds                  Based(DlrBase)
    D  Dlr                         100A   Varying
    D                                     Dim(2500)
    D                                     Ascend
    D  DlrIdx                             Like(DlrDs.Idx)
    D                                     Overlay(Dlr : 1)
    D  DlrCode                            Like(DlrDs.Code)
    D                                     Overlay(Dlr : *Next)
    D  DlrType                            Like(DlrDs.Type)
    D                                     Overlay(Dlr : *Next)
[snip]

So what do we have here?  You've declared a character string that's 100A 
VARYING.  Again, the VARYING doesn't apply to the array or the DS, ti 
applies to the length of each field in the Dlr array. Each field will be 
102 bytes long. The first 2 bytes specify the length, the remaining 100 
bytes are a character string.

DlrIdx, overlaying from position 1 of Dlr.  Remember, the first two bytes 
of Dlr are that hidden length field -- so you've overlaid that field. 
Anything you assign to DlrIdx will change the length of Dlr. If the binary 
value of the first 2 bytes of DlrIdx happens to be higher than x'0064' 
(which in decimal is 100) then you'll get a "Length of varying length 
variable is out of range" error.

Since Dlr's only purpose (as far as I can tell) is to make it possible for 
all of the subfields to be stuck in the same array, there's absolutely no 
sense in making it VARYING.  You aren't using it as an alphanumeric field, 
anyway, it's just a holding space for the array.  Since the subfields are 
a fixed-length, it doesn't make sense for the field their defined on to be 
VARYING, does it?

Instead, I'd declare your DS as follows:

    D                 Ds                  Based(DlrBase)
    D  Dlr                                Dim(2500)
    D                                     Ascend
    D  DlrIdx                             Like(DlrDs.Idx)
    D                                     Overlay(Dlr : 1)
    D  DlrCode                            Like(DlrDs.Code)
    D                                     Overlay(Dlr : *Next)
    D  DlrType                            Like(DlrDs.Type)
    D                                     Overlay(Dlr : *Next)
    ... additional fields here...

What did I change?  I removed the word VARYING because, as I (hopefully) 
explained well enough, it doesn't make sense.

I also removed the 100A definition.  There's no reason to hard-code the 
length of Dlr, because the compiler will figure it out for you based on 
the length of the subfields.

When you add elements to this array, have another field called "Dlr_Count" 
or something like that.

      D Dlr_Count       s             10I 0

Each time you add a new element to Dlr (or Dlr1 or whatever) do this:

          Dlr_Count = Dlr_Count + 1;

The idea is, Dlr_Count will always have a count of what's stored in the 
Dlr_Array.

When it's time to sort it, if you don't want the blanks, do this:

      sorta %subarr(Dlr:1:Dlr_Count);

Simple enough, eh?

If you're not on V5R3, or would prefer to use an array of qualified data 
structures rather than an (ugly) overlay array, use the qsort() API 
instead of sorta.

      qsort( %addr(Dlr): Dlr_Count: %size(Dlr): %paddr(CompProc) );


>> Because I had previously received the RNX0115 message, I evalled
> Dlr1(2501)
>> and it was displayed as empty.

That's the way the debugger has always worked, and has nothing to do with 
the VARYING keyword or anything else in your code.  It doesn't verify that 
the number you type for an index is within the bounds of the array.  If 
you specify a higher number, it'll calculate the spot in memory that WOULD 
be used if your array was large enough, and it'll look in that spot (very 
possibly viewing memory that's used for something else entirely.)

But that's a "bug" in the debugger -- not the RPG compiler or language.

>>
>> The next statement: %SubArr( Dlr : 1 : Idx ) = %SubArr ( Dlr1 : 1 : Idx );
>>
>> Resulted in the following error:
>> Message ID . . . . . . :   RNX0115       Severity . . . . . . . :   50
[SNIP]

Hopefully you now understand why you got that error.

I don't understand why you're doing this, however... if Dlr is based on a 
pointer, why not just point it to the memory where Dlr1 is sitting? 
Copying the data from one array to the other seems like an awful waste of 
CPU cycles.

Of course,I don't know where the pointer points to.  If you need it to 
point to some other area of memory for some reason, I guess copying the 
data might be the right thing to do.


>> Why does Dlr1 now have 9834 elements?

It doesn't...  the debugger just didn't try to stop you.  Your code won't 
be able to access any data beyond the 2500th element.

>> Does DIMming an array not limit the maximum number of elements it can
> have?

The debugger is just looking at the underlying memory for your variable. 
Remember, variables are an illusion!  The computer doesn't understand 
variables, they're just for human convienience.  At run time, everything 
is just space in the system's "main storage".  Since the debugger has to 
display the contents of your variable at runtime, it looks at the memory 
behind the variable and reformats it to display it on the screen so you 
can read it.

Although RPG forces you to stay between 1 - 2500 when referencing indexes 
in your array, the debugger has no such safeguards (probably because there 
are other programming languages that don't have these safeguards) and will 
display elements that don't exist.

But, that's just an aspect of the debugger, it's not an aspect of your 
program or the RPG language.


As an Amazon Associate we earn from qualifying purchases.

This thread ...

Follow-Ups:
Replies:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.