Interesting stuff. Good for you!

> In contrast to C, PTRADD adds byte addresses, not elements.

Yes, in C, given foo *bar = &someFoo; then bar+1 is (counter-intuitively for 
those of us who came up through HLASM) not the address of someFoo plus one; it 
is the address of someFoo plus the length of a foo -- in other words, adding 
one to bar increments bar by the length of a foo, not by absolute 1. Adding 2 
increments by twice the length of a foo, and so forth.

That works well for fixed-element-length arrays -- if you have a pointer to an 
element in an array of integers then pointer+1 is the address of the next 
integer -- but it is inconvenient for certain z/OS tables -- e.g. the TIOT -- 
where each variable-length element contains its absolute length, i.e. the 
offset to the next element. Given tiot* tiot_p = &someTIOT, then adding 
tiot_p->tioelngh to tiot_p gives you an address somewhere out in the distant 
weeds, not the address of the next TIOT. The solution is a local function -- 
mine is called AddressIncrement -- that casts the address to an integer and 
adds the length algebraically. (Alternatively you can cast the address to a 
char* -- the elements of a char* have a length of 1, so the address of the next 
element is the address of the next byte, QED.)

Charles


-----Original Message-----
From: IBM Mainframe Assembler List [mailto:[email protected]] On 
Behalf Of Bernd Oppolzer
Sent: Sunday, September 13, 2020 10:54 AM
To: [email protected]
Subject: Re: Deep Cuts

This is a very interesting discussion for me, as I am the current 
maintainer of "New Stanford Pascal".
I am trying to extend the language to make it more usable, while not 
violating the Pascal spirit.
Inspiration and motivation are the different versions of IBM's Pascal 
(Pascal/VS and VS/Pascal),
available for MVS and VM/CMS starting from ca. 1980 on.

I recently added MEMCPY, MEMSET and MEMCMP; I allowed to take the ADDR 
of every object
(that is, pointers do not only exist for dynamically created variables, 
via NEW), and I added new functions
ALLOC and FREE, which do a better job in storage allocating than NEW and 
DISPOSE (DISPOSE,
in fact, was never implemented in the "old" Stanford compiler; it only 
had some global heap
freeing mechanism using MARK and RELEASE).

The NULL pointer (called NIL in Pascal) is implemented as 0xFFFFFFFF 
(minus one), so that
MEMSETting a struct containing pointers indeed will not yield NIL 
pointers; you have to
set the pointers explicitly to NIL after the MEMSET. Dereferencing a NIL 
pointer will give
a 0C4 abend on the mainframe; if you want, you can create a DEBUG 
version of the program
which checks for NIL before dereferencing and throws a Pascal runtime 
error.

Regarding pointer arithmetic:

it is not allowed to add an integer value to a pointer directly, but

there is a function called PTRADD (p, i), which adds an integer value i 
to a pointer p.
i may be positive or negative.
The pointer p is of type ANYPTR (or VOIDPTR), which is a ptr type 
compatible to all
other pointer types. The result of PTRADD is of type ANYPTR, too.
In contrast to C, PTRADD adds byte addresses, not elements.

PTRADD (p, 0) is used to cast pointer types (pointers are typed pointers 
in Pascal);
it can be coded as PTRCAST (p), too.

PTRDIFF (p1, p2) with integer result is the distance between two pointers.

Reply via email to