From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 26-AUG-1989 00:38
To:	MRGATE::"ARISIA::EVERHART"
Subj:	RE: Vax Pascal Question

Message-Id:  <8908260425.AA13507@crdgw1.ge.com>
Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Fri, 25 AUG 89 20:49:41 PDT
Received: from Ruby.VCU.EDU by KL.sri.com with TCP; Fri, 25 Aug 89 20:19:35 PDT
Date: Fri, 25 Aug 89 22:49 EDT
From: FRITZ@Ruby.VCU.EDU
Subject: RE: Vax Pascal Question
To: INFO-VAX@KL.SRI.COM
X-Vms-To: NET%"INFO-VAX@KL.SRI.COM"

   tank!dwayne%rover.bsd.uchicago.edu@HANDIES.UCAR.EDU writes:

>Hey!!!!
>     
>    Does any know the appropriate calling mechanism for an ast parameter.
>     
>I'm declaring the thing like this:
>     
>[ASYNCHRONOUS] PROCEDURE uis$set_pointer_ast (
>        VD_ID0 : UNSIGNED;
>        WD_ID0 : UNSIGNED;
>        %IMMED [UNBOUND, ASYNCHRONOUS] PROCEDURE ASTADR;
>        ASTPRM : UNSIGNED;
>        X1 : SINGLE;
>        Y1 : SINGLE;
>        X2 : SINGLE;
>        Y2 : SINGLE;
>        %IMMED [UNBOUND, ASYNCHRONOUS] PROCEDURE EXITASTADR;
>        EXITASTPRM : UNSIGNED); EXTERNAL;
>     
>I'm declaring my ast's like this:
>     
>[unbound,ASYNCHRONOUS] PROCEDURE ENT_MENU_AST(slot:integer);
>    BEGIN
>        uis$text (VD_ID,1,ITEMS[SLOT],LOCX[SLOT],LOCY[SLOT]);
>    END;
>     
>[unbound,ASYNCHRONOUS] PROCEDURE EXIT_MENU_AST(slot:integer);
>    BEGIN
>        uis$text (VD_ID,0,ITEMS[SLOT],LOCX[SLOT],LOCY[SLOT]);
>    END;

There are two considerations here: persuading Pascal to accept your code, and
getting the code to do the right thing. The first may be accomplished in two
ways:

   1) Declaring the procedure parameters as follows:

      %IMMED [UNBOUND, ASYNCHRONOUS] PROCEDURE Astadr(Slot: [volatile] integer);
      Astprm : [volatile] integer;

or
   2) Putting `%immed' and '%ref' in the call:

      uis$set_pointer_ast(vd_id,wd_id,%immed Astadr,%ref Slot,
                          x1,y1,x2,y2,%immed Exitastadr,%ref Slot);

In your case this will probably not work. Both ways wind up passing the
*address* of Slot to uis$set_pointer_ast and thence to the ASTs themselves; if
you do something like

      for j:=0 to max do uis$set_pointer_ast(...,j,...,j);

you will wind up with each AST being passed j's address, so each will have the
same value of Slot--and that value will be garbage!

One way of getting around this is to pass the AST parameter by immediate value:

      %immed [unbound, asynchronous] procedure Astadr(%immed Slot: integer);
      %immed Astprm : integer;

Unfortunately Pascal does not like you to write procedures that receive
parameters by immediate value. You can trick Pascal like so:

   [unbound,asynchronous] procedure Ent_menu_ast(var fake: [volatile] char);
       var Slot: integer;
       begin
           Slot:=iaddress(fake);
           uis$text (VD_ID,1,ITEMS[SLOT],LOCX[SLOT],LOCY[SLOT]);
       end;     

This pretends that the integer passed by immediate value is the address of a
char, then uses iaddress to change this `address' back into the integer it
always was. The volatile var parameter discourages Pascal from trying to copy
its value to the local stack frame. You would need to pass Ent_menu_ast to to
uis$set_pointer_ast with an explicit %immed to override type checking. All of
this is of course very unsupported.

The other way to do it requires some change in the rest of your program,
something like this:

   type
      shelf_type = record items: item_type; locX,locY: loc_type end;
   ...
   [asynchronous] procedure uis$set_pointer_ast (
      ...
      %immed [unbound, asynchronous] procedure Astadr
         (var Shelf: [volatile] shelf_type);
      var Astprm : [volatile] shelf_type;
      ...); external;
   ...
   [unbound,asynchronous] procedure ent_menu_ast(
       var Shelf: [volatile] shelf_type);
       begin
           with Shelf do uis$text(vd_id,1,items,locX,locY);
       end;
    ...
    var stuff: array[0..max] of shelf_type;
    ...
    for j:=0 to max do uis$set_pointer_ast(...,stuff[j],...,stuff[j]);

Now the address of Stuff[j] is passed to the AST routine, so each AST looks at
a different shelf. If uis$text does not change its arguments then Shelf need not
be declared var; but it should always be declared volatile, since it will be
accessed by an AST routine.