-- RapunzelServerImpl.mesa
-- Demo	 9-Jan-87 14:02:33 PST

DIRECTORY Courier, Heap, System, Rapunzel, RapunzelCourier;

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

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


  Dispatcher: Courier.Dispatcher = {
    ENABLE {
      Rapunzel.Fault => {
        args: RapunzelCourier.FaultArgs ← [code, address];
        Courier.SignalRemoteError[0, [@args, RapunzelCourier.DescribeFaultArgs]];
        };
      };
    SELECT procedureNumber FROM
      1 => DoPeekShort[cH, arguments, results];
      2 => DoPokeShort[cH, arguments, results];
      3 => DoPeekSeqShort[cH, arguments, results];
      4 => DoPokeSeqShort[cH, arguments, results];
      5 => DoPeekLong[cH, arguments, results];
      6 => DoPokeLong[cH, arguments, results];
      7 => DoDoCmds[cH, arguments, results];
      8 => DoSetShftAddrs[cH, arguments, results];
      ENDCASE => ERROR Courier.NoSuchProcedureNumber;
    };

  DoPeekShort: PROCEDURE[
    cH: Courier.Handle, arguments: Courier.Arguments, results: Courier.Results] = {
    args: RapunzelCourier.PeekShortArgs;
    res: RapunzelCourier.PeekShortRes;
    arguments[[@args, RapunzelCourier.DescribePeekShortArgs]];
    [res.result] ← Rapunzel.PeekShort[NIL, args.address];
    [] ← results[[@res, RapunzelCourier.DescribePeekShortRes]];
    Courier.Free[[@args, RapunzelCourier.DescribePeekShortArgs], cH.zone];
    };

  DoPokeShort: PROCEDURE[
    cH: Courier.Handle, arguments: Courier.Arguments, results: Courier.Results] = {
    args: RapunzelCourier.PokeShortArgs;
    arguments[[@args, RapunzelCourier.DescribePokeShortArgs]];
    Rapunzel.PokeShort[NIL, args.address, args.value];
    [] ← results[];
    Courier.Free[[@args, RapunzelCourier.DescribePokeShortArgs], cH.zone];
    };

  DoPeekSeqShort: PROCEDURE[
    cH: Courier.Handle, arguments: Courier.Arguments, results: Courier.Results] = {
    args: RapunzelCourier.PeekSeqShortArgs;
    res: RapunzelCourier.PeekSeqShortRes;
    arguments[[@args, RapunzelCourier.DescribePeekSeqShortArgs]];
    [res.resultSeq] ← Rapunzel.PeekSeqShort[NIL, args.address, args.count];
    [] ← results[[@res, RapunzelCourier.DescribePeekSeqShortRes]];
    Courier.Free[[@args, RapunzelCourier.DescribePeekSeqShortArgs], cH.zone];
    Rapunzel.FreePeekSeqShortResults[bH: NIL, resultSeq: res.resultSeq];
    };

  DoPokeSeqShort: PROCEDURE[
    cH: Courier.Handle, arguments: Courier.Arguments, results: Courier.Results] = {
    args: RapunzelCourier.PokeSeqShortArgs;
    arguments[[@args, RapunzelCourier.DescribePokeSeqShortArgs]];
    Rapunzel.PokeSeqShort[NIL, args.address, args.valueSeq];
    [] ← results[];
    Courier.Free[[@args, RapunzelCourier.DescribePokeSeqShortArgs], cH.zone];
    };

  DoPeekLong: PROCEDURE[
    cH: Courier.Handle, arguments: Courier.Arguments, results: Courier.Results] = {
    args: RapunzelCourier.PeekLongArgs;
    res: RapunzelCourier.PeekLongRes;
    arguments[[@args, RapunzelCourier.DescribePeekLongArgs]];
    [res.result] ← Rapunzel.PeekLong[NIL, args.address];
    [] ← results[[@res, RapunzelCourier.DescribePeekLongRes]];
    Courier.Free[[@args, RapunzelCourier.DescribePeekLongArgs], cH.zone];
    };

  DoPokeLong: PROCEDURE[
    cH: Courier.Handle, arguments: Courier.Arguments, results: Courier.Results] = {
    args: RapunzelCourier.PokeLongArgs;
    arguments[[@args, RapunzelCourier.DescribePokeLongArgs]];
    Rapunzel.PokeLong[NIL, args.address, args.value];
    [] ← results[];
    Courier.Free[[@args, RapunzelCourier.DescribePokeLongArgs], cH.zone];
    };

  DoDoCmds: PROCEDURE[
    cH: Courier.Handle, arguments: Courier.Arguments, results: Courier.Results] = {
    args: RapunzelCourier.DoCmdsArgs;
    res: RapunzelCourier.DoCmdsRes;
    arguments[[@args, RapunzelCourier.DescribeDoCmdsArgs]];
    [res.resultSeq] ← Rapunzel.DoCmds[NIL, args.cmdSeq];
    [] ← results[[@res, RapunzelCourier.DescribeDoCmdsRes]];
    Courier.Free[[@args, RapunzelCourier.DescribeDoCmdsArgs], cH.zone];
    Rapunzel.FreeDoCmdsResults[bH: NIL, resultSeq: res.resultSeq];
    };

  DoSetShftAddrs: PROCEDURE[
    cH: Courier.Handle, arguments: Courier.Arguments, results: Courier.Results] = {
    args: RapunzelCourier.SetShftAddrsArgs;
    arguments[[@args, RapunzelCourier.DescribeSetShftAddrsArgs]];
    Rapunzel.SetShftAddrs[NIL, args.shftA, args.shftB];
    [] ← results[];
    Courier.Free[[@args, RapunzelCourier.DescribeSetShftAddrsArgs], cH.zone];
    };


  started: BOOLEAN ← FALSE;
  RemoteBind: PUBLIC PROCEDURE [
    host: System.NetworkAddress, zone: UNCOUNTED ZONE ← NIL]
    RETURNS[bH: BindHandle] = {
    bH ← NIL;
    IF zone = NIL THEN zone ← Heap.systemZone;
    IF started THEN RETURN;
    Courier.ExportRemoteProgram[
      programNumber: RapunzelCourier.programNumber,
      versionRange: [RapunzelCourier.version,RapunzelCourier.version],
      dispatcher: Dispatcher, serviceName: "Rapunzel"L,
      zone: zone, classOfService: transactional];
    started ← TRUE;
  };

  RemoteUnbind: PUBLIC PROCEDURE[
    bH: BindHandle] RETURNS [nil: BindHandle] = {
    nil ← NIL;
    IF ~started THEN RETURN;
    Courier.UnexportRemoteProgram[
      programNumber: RapunzelCourier.programNumber,
      versionRange: [RapunzelCourier.version,RapunzelCourier.version]];
    started ← FALSE;
    };



  }.