[futurebasic] Re: XREF

Message: < previous - next > : Reply : Subscribe : Cleanse
Home   : November 1997 : Group Archive : Group : All Groups

From: Rick Brown <rbrown@...>
Date: Wed, 12 Nov 1997 22:39:11 -0600
I wrote:

> > At any rate, the "XREF @ gList.MyRec(_bazillion)" statement does
> > nothing, because it's only meaningful if there's a "DIM gList&" or a
> > "DIM gList%;4" statement somewhere along with it, to define gList& (or
> > gList%) as a global variable, which is to contain the handle.  In
> > particular, XREF@ doesn't reserve any space for anything.

David replied:
> I have no idea if my solution has got through, but I'd like to comment on
> Rick's answer to this non-functioning solution.
> 
> I can follow your logic here, but I have a bit of a problem with the fact
> that the code for XREF@ #1.BAS which explains the .Top& workaround does not
> do what you suggest.  It seems to work - why?
> 
> Iive attempted to post a solution - which seems to bounce - which does work
> but does not use the .top& workaround. Now I'm really confused!

Okay, I've done some experimenting, and I now have another asessment of
what's happening:

It looks like the statement "XREF@ myArray.myRecSize(_maxIndex)" does in
fact reserve some space (even though it's not _supposed_ to.  This is a
bug.)  It reserves one record of size _myRecSize, and calls that record
myArray.  So, if _myRecSize is 20, the XREF@ statement reserves 20 bytes
on the stack, and VARPTR(myArray) will return the address of the first
of those 20 bytes.

When you then execute a statement like, "myArray.Top& = FN
NEWHANDLE(...)," the handle to the block is stored into the first 4 of
those bytes.  The remaining 16 bytes (to use my example numbers) are not
used.  It is _not_ necessary to have a separate "DIM myArray;4"
statement to reserve 4 bytes for the handle, as I had previously
thought.

When you subsequently make references to the _array_ called myArray, FB
looks into the (non-array) _record_ called myArray, expecting to find a
handle in the first 4 bytes.  It uses that handle to figure out where
the array's elements are.

To make things more confusing: if you happen to explicitly DIM a long
integer called myArray& _before_ the XREF@ statement, then FB assigns
the _same_location_ in memory to the 4-byte myArray& variable and the
20-byte (or whatever) myArray _record_.  You can verify this by printing
VARPTR(myArray&) and VARPTR(myArray).  That means that, in this case,
you can assign the handle either to myArray& (the long int) or to
myArray.Top& (the first 4 bytes of the record).  Since they both occupy
the same memory, the effect is the same.

On the other hand, if you say "DIM myArray&" _after_ the XREF@ statement
(or if you omit the "DIM myArray&" altogether), then FB assigns two
_different_ locations to the long int myArray& and the 20-byte record
myArray.  In this case, you _must_ assign the handle to myArray.Top&; it
won't work if you assign in to myArray&.

As far as I can tell, all of the above applies only to arrays of
_records_ defined with XREF@.  If you use XREF@ to define an array of a
"simple" type, as in "XREF@ myArray%(32)", then FB does not create that
phantom record.  In this case, you should assign the handle to the long
int variable (i.e. to myArray&).

All of the above applies to XREF as well as to XREF@.  However, there is
an additional problem with XREF which doesn't occur with XREF@.  If XREF
defines an array of records where each record has multiple fields, then
FB does not correctly calculate the addresses of the 2nd and subsequent
fields in each element.  A reference to "myArray.field2&(n)" in this
case likely to cause a crash.