-- RapunzelClientImpl.mesa
-- BJackson	11-Jan-88 11:13:00 PST

DIRECTORY Courier, Heap, System, Rapunzel, RapunzelCourier;

RapunzelClientImpl: PROGRAM
  IMPORTS Heap, Courier, RapunzelCourier  EXPORTS Rapunzel = {

  BindHandle: TYPE = LONG POINTER TO READONLY BindObject;
  BindObject: PUBLIC TYPE = Courier.Object;

  Fault: PUBLIC ERROR [
    bH: BindHandle, code: Rapunzel.FaultCode, address: Rapunzel.Address]= CODE;

  PeekShort: PUBLIC PROCEDURE [
    bH: BindHandle, address: Rapunzel.Address]
    RETURNS [result: Rapunzel.Short]= {
    args: RapunzelCourier.PeekShortArgs ← [address];
    res: RapunzelCourier.PeekShortRes;
    DoCourierCall[
      cH: bH, procedureNumber: RapunzelCourier.PeekShort,
      arguments: [@args, RapunzelCourier.DescribePeekShortArgs],
      results: [@res, RapunzelCourier.DescribePeekShortRes]];
    [result] ← res;
};

  PokeShort: PUBLIC PROCEDURE [
    bH: BindHandle, address: Rapunzel.Address, value: Rapunzel.Short]= {
    args: RapunzelCourier.PokeShortArgs ← [address, value];
    DoCourierCall[
      cH: bH, procedureNumber: RapunzelCourier.PokeShort,
      arguments: [@args, RapunzelCourier.DescribePokeShortArgs]];
};

  PeekSeqShort: PUBLIC PROCEDURE [
    bH: BindHandle, address: Rapunzel.Address, count: CARDINAL]
    RETURNS [resultSeq: LONG POINTER TO Rapunzel.SeqShort]= {
    args: RapunzelCourier.PeekSeqShortArgs ← [address, count];
    res: RapunzelCourier.PeekSeqShortRes;
    DoCourierCall[
      cH: bH, procedureNumber: RapunzelCourier.PeekSeqShort,
      arguments: [@args, RapunzelCourier.DescribePeekSeqShortArgs],
      results: [@res, RapunzelCourier.DescribePeekSeqShortRes]];
    [resultSeq] ← res;
};

  FreePeekSeqShortResults: PUBLIC PROCEDURE[
    bH: BindHandle, resultSeq: LONG POINTER TO Rapunzel.SeqShort] = {
    res: RapunzelCourier.PeekSeqShortRes;
    res.resultSeq ← resultSeq;
    Courier.Free[[@res, RapunzelCourier.DescribePeekSeqShortRes], bH.zone];
    };

  PeekSeqLong: PUBLIC PROCEDURE [
    bH: BindHandle, address: Rapunzel.Address, count: CARDINAL]
    RETURNS [resultSeq: LONG POINTER TO Rapunzel.SeqLong]= {
    args: RapunzelCourier.PeekSeqLongArgs ← [address, count];
    res: RapunzelCourier.PeekSeqLongRes;
    DoCourierCall[
      cH: bH, procedureNumber: RapunzelCourier.PeekSeqLong,
      arguments: [@args, RapunzelCourier.DescribePeekSeqLongArgs],
      results: [@res, RapunzelCourier.DescribePeekSeqLongRes]];
    [resultSeq] ← res;
};

  FreePeekSeqLongResults: PUBLIC PROCEDURE[
    bH: BindHandle, resultSeq: LONG POINTER TO Rapunzel.SeqLong] = {
    res: RapunzelCourier.PeekSeqLongRes;
    res.resultSeq ← resultSeq;
    Courier.Free[[@res, RapunzelCourier.DescribePeekSeqLongRes], bH.zone];
    };

  PokeSeqShort: PUBLIC PROCEDURE [
    bH: BindHandle, address: Rapunzel.Address, valueSeq: LONG POINTER TO Rapunzel.SeqShort]= {
    args: RapunzelCourier.PokeSeqShortArgs ← [address, valueSeq];
    DoCourierCall[
      cH: bH, procedureNumber: RapunzelCourier.PokeSeqShort,
      arguments: [@args, RapunzelCourier.DescribePokeSeqShortArgs]];
};

  PeekLong: PUBLIC PROCEDURE [
    bH: BindHandle, address: Rapunzel.Address]
    RETURNS [result: Rapunzel.Long]= {
    args: RapunzelCourier.PeekLongArgs ← [address];
    res: RapunzelCourier.PeekLongRes;
    DoCourierCall[
      cH: bH, procedureNumber: RapunzelCourier.PeekLong,
      arguments: [@args, RapunzelCourier.DescribePeekLongArgs],
      results: [@res, RapunzelCourier.DescribePeekLongRes]];
    [result] ← res;
};

  PokeLong: PUBLIC PROCEDURE [
    bH: BindHandle, address: Rapunzel.Address, value: Rapunzel.Long]= {
    args: RapunzelCourier.PokeLongArgs ← [address, value];
    DoCourierCall[
      cH: bH, procedureNumber: RapunzelCourier.PokeLong,
      arguments: [@args, RapunzelCourier.DescribePokeLongArgs]];
};

  DoCmds: PUBLIC PROCEDURE [
    bH: BindHandle, cmdSeq: LONG POINTER TO Rapunzel.SeqCmd]
    RETURNS [resultSeq: LONG POINTER TO Rapunzel.SeqResult]= {
    args: RapunzelCourier.DoCmdsArgs ← [cmdSeq];
    res: RapunzelCourier.DoCmdsRes;
    DoCourierCall[
      cH: bH, procedureNumber: RapunzelCourier.DoCmds,
      arguments: [@args, RapunzelCourier.DescribeDoCmdsArgs],
      results: [@res, RapunzelCourier.DescribeDoCmdsRes]];
    [resultSeq] ← res;
};

  FreeDoCmdsResults: PUBLIC PROCEDURE[
    bH: BindHandle, resultSeq: LONG POINTER TO Rapunzel.SeqResult] = {
    res: RapunzelCourier.DoCmdsRes;
    res.resultSeq ← resultSeq;
    Courier.Free[[@res, RapunzelCourier.DescribeDoCmdsRes], bH.zone];
    };

  SetShftAddrs: PUBLIC PROCEDURE [
    bH: BindHandle, shftA, shftB: Rapunzel.Address]= {
    args: RapunzelCourier.SetShftAddrsArgs ← [shftA, shftB];
    DoCourierCall[
      cH: bH, procedureNumber: RapunzelCourier.SetShftAddrs,
      arguments: [@args, RapunzelCourier.DescribeSetShftAddrsArgs]];
};

  WriteSequential: PUBLIC PROCEDURE [
    bH: BindHandle, startingAddress: Rapunzel.Address, count: CARDINAL, seq: LONG POINTER TO Rapunzel.SeqLong]= {
    args: RapunzelCourier.WriteSequentialArgs ← [startingAddress, count, seq];
    DoCourierCall[
      cH: bH, procedureNumber: RapunzelCourier.WriteSequential,
      arguments: [@args, RapunzelCourier.DescribeWriteSequentialArgs]];
};


  RemoteBind: PUBLIC PROCEDURE[
    host: System.NetworkAddress, zone: UNCOUNTED ZONE ← NIL]
    RETURNS[bH: BindHandle] = {
    IF zone = NIL THEN zone ← Heap.systemZone;
    bH ← Courier.Create[
      remote: host, programNumber: RapunzelCourier.programNumber, 
    versionNumber: RapunzelCourier.version, zone: zone, classOfService: transactional];
    };

  RemoteUnbind: PUBLIC PROCEDURE[
    bH: BindHandle] RETURNS [nil: BindHandle] = {
    nil ← NIL;
    IF bH # NIL THEN Courier.Delete[bH];
    };


  DoCourierCall: PROCEDURE[
    cH: Courier.Handle, procedureNumber: CARDINAL,
    arguments: Courier.Parameters ← Courier.nullParameters, 
    results: Courier.Parameters ← Courier.nullParameters,
    streamCheckoutProc: PROCEDURE [cH: Courier.Handle] ← NIL] = {
    ENABLE {
      Courier.RemoteErrorSignalled => {
        SELECT errorNumber FROM
          0 => DoFault[cH, arguments];
          ENDCASE;
        };
      Courier.Error => NULL;
      };
    [] ← Courier.Call[
      cH: cH, procedureNumber: procedureNumber, arguments: arguments, 
      results: results, streamCheckoutProc: streamCheckoutProc];
    };

  DoFault: PROCEDURE[
    bH: BindHandle, arguments: Courier.Arguments] = {
    args: RapunzelCourier.FaultArgs;
    arguments[[@args, RapunzelCourier.DescribeFaultArgs]];
    ERROR Fault[bH, args.code, args.address];
    };



  }.