× 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.



Hi Rob,

I already changed my mind about that last night. I said it wouldn't be an issue.

The issue I was worried about is a complex one that isn't easy to explain. I can give an example, but I'm worried you'd just look at it and say "nobody would ever do that" simply because my example is too contrived. But writing a real example that illustrates the benefit would take too long...

Also bear in mind that I already determined that I was wrong and that this is a non-issue.

But, I'll explain anyway... here's a bad example to start with:


D Blah s 10a
/free
MyProc( Blah: %size(Blah) );


P MyProc B
D MyProc pi
D SomeParm 1a
D Length 10i 0 value

D Whatever s 10a based(p_Whatever)

/free

if Length >= %size(Whatever);
p_Whatever = %addr(SomeParm);
Whatever = *ALL'x';
else;
// field is too short
endif;

/end-free
P E

The point here is that the compiler doesn't check the UPPER bounds of the length of a variable. It makes sure the variable is LONG ENOUGH, but it doesn't look at whether it's LONGER than the procedure wants.

In the above example, the prototype defines 1A, even though I can pass longer values. In this example, the caller provides a 10A, even though the procedure defines a 1A. This doesn't matter, because I know the variable will be passed by reference, so I can refer to a longer value.

I know, I know... you're thinking "but that's not the PROPER way to do that... you should use *VARSIZE instead" like this:

D MyProc pi
D SomeParm 65535A options(*varsize)
D Length 10i 0 value

That's true -- but again, this is a contrived example because a real one would take too much work to code, and I'd rather not spend 2 hours explaining the situation :)

But a real situation where I might do this is if I needed a field that's larger than 64k (I'm still at v5r4 -- but even if I weren't, I'd still have lots of code around from when I was!) In that situation, I might be using pointer logic to call a procedure, and I might have one BASED 65535 field that that's in a dynamically allocated buffer that's millions of bytes long. (Even with 6.1 I'd have to use that technique if I wanted to exceed 16 MB)

However, if the compiler copied my field to a temporary, and copied it back, it'd only copy 65535 of the field, because that's all I had defined on the prototype. Thus, breaking backward compatibility -- or so I was thinking at the time.

I've also seen quite a lot of code from people who don't understand the *VARSIZE keyword. Those people code 1A when their field varies. For example, i've seen this example quite a lot on the Internet:

D RunCmd PR ExtPgm('QCMDEXC')
D cmd 1a
D len 15p 5 const

They don't worry about the fact that 'cmd' is only 1A, because they know it's passed by reference, and the QCMDEXC API will pick up the full length they pass in the 2nd parameter. If RPG copies it to a temporary, it'll only copy 1 byte however, and that will truncate the string.

So I was thinking that this would break compatility -- but I changed my mind. why did I change my mind?

Because there's no reason for RPG to use a temporary variable in these cases. It'll just pass the field as-is. So the behavior won't change...

I was thinking that you might decide to pass a VARYING or Unicode field or something like that. When it did that, it'd only copy the shorter length defined on the prototype. But for existing code, you can't do that, it wouldn't compile... so no backward compatibility issue there. The procedure might have to be rewritten to make the new "autoconvert" feature work properly in the future, but for existing code it wouldn't break anything.

Again, I changed my mind about this last night already (and posted that). I was wrong.


rob@xxxxxxxxx wrote:
Why would there have to be some sort of keyword or it would break backward compatibility? Default is I pass in a variable, called program may, or may not, change it, and passes it back to me. We're requesting the same behavior. Only difference is variable casting. If there's a danger of truncation then it should be handled in the called program. For example I pass in a filled 5i and the called program is 2p. Why should every program that uses the subprocedure have to handle the truncation? Takes away from storing the logic in one place.


Rob Berendt


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.