-- File: Leaf.mesa
-- Last edited by Levin:   5-Feb-81 15:38:47
-- Last edited by Gobbel: 27-Jul-81 19:16:00
-- Loosely derived (after extensive discussions with Wobber) from Butterfield's
--   LeafDefs of July 27, 1979  2:11 PM.
-- last edited by Hankins:  24-Jul-84 14:42:15	Klamath conversion (op => o)

DIRECTORY
  Environment USING [Byte],
  PupTypes USING [PupSocketID, PupType];

Leaf: DEFINITIONS =
  BEGIN


  -- Types and Related Constants --

  LeafType: TYPE = MACHINE DEPENDENT{
    error(0), open(1), close(2), delete(3), length(4), truncate(5), read(6),
    write(7), reset(8), noop(9), telnet(10), params(11), (31)};

  LeafOp: TYPE = MACHINE DEPENDENT RECORD [
    type(0:0..4): LeafType,
    sense(0:5..5): {request, reply} ← request,
    length(0:6..15): CARDINAL [0..532]];

  openOp: LeafOp = [type: open, length: 2 * SIZE[open RequestObject]];
  closeOp: LeafOp = [type: close, length: 2 * SIZE[close RequestObject]];
  deleteOp: LeafOp = [type: delete, length: 2 * SIZE[delete RequestObject]];
  lengthOp: LeafOp = [type: length, length: 2 * SIZE[length RequestObject]];
  truncateOp: LeafOp = [type: truncate, length: 2 * SIZE[truncate RequestObject]];
  readOp: LeafOp = [type: read, length: 2 * SIZE[read RequestObject]];
  writeOp: LeafOp = [type: write, length: 2 * SIZE[write RequestObject]];
  resetOp: LeafOp = [type: reset, length: 2 * SIZE[reset RequestObject]];
  paramsOp: LeafOp = [type: params, length: 2 * SIZE[params RequestObject]];

  -- All strings in the reset and open ops have the form:
  -- LeafString: TYPE = MACHINE DEPENDENT RECORD [
  --   length: CARDINAL, text: ARRAY [0..0) OF CHARACTER];

  -- Note:  the op.length field for reset, open, and write must include the entire
  -- opSpecific body, including the variable length data that follows the fixed parts
  -- declared below.

  Request: TYPE = LONG POINTER TO RequestObject;
  OpenRequest: TYPE = LONG POINTER TO open RequestObject;
  CloseRequest: TYPE = LONG POINTER TO close RequestObject;
  DeleteRequest: TYPE = LONG POINTER TO delete RequestObject;
  TruncateRequest: TYPE = LONG POINTER TO truncate RequestObject;
  ReadRequest: TYPE = LONG POINTER TO read RequestObject;
  WriteRequest: TYPE = LONG POINTER TO write RequestObject;
  ResetRequest: TYPE = LONG POINTER TO reset RequestObject;
  ParamsRequest: TYPE = LONG POINTER TO params RequestObject;

  RequestObject: TYPE = MACHINE DEPENDENT RECORD [
    op: LeafOp,
    opSpecific: SELECT COMPUTED LeafType FROM
      params => [
        packetDataBytes: CARDINAL,  -- server's default is 532
        fileLockTimeout: FiveSeconds ← 0,  -- server's default is 10 minutes
        connectionTimeout: FiveSeconds ← 0],  -- server's default is 12 hours
      reset => [
        which: Resetee ← thisHost
        -- primaryUserName string
        -- primaryPassword string
        ],
      open => [
        handle: Handle ← noHandle,
        read: BOOLEAN ← TRUE,
        write, extend, multiple, create: BOOLEAN ← FALSE,
        vExplicit: {no, old, nextOrOld, any} ← any,
        vDefault: {no, lowest, highest, next} ← highest,
        leaderInfo, listMultiple: BOOLEAN ← FALSE,
        fill: [0..31] ← 0
        -- primaryUserName string
        -- primaryPassword string
        -- secondaryUserName string
        -- secondaryPassword string
        -- fileName string
        ],
      close, delete => [handle: Handle],
      truncate => [handle: Handle, eofAddress: FileAddress],
      read => [
        handle: Handle,
        address: FileAddress,
        length: ByteCount,
        rate: Rate ← anyRate],
      write => [
        handle: Handle,
        address: FileAddress,
        length: ByteCount,
        writeBody: SELECT OVERLAID * FROM
          writeWords => [writeWords: ARRAY [0..0) OF WORD],
          writeBytes => [writeBytes: PACKED ARRAY [0..0) OF Environment.Byte],
          writeChars => [writeChars: PACKED ARRAY [0..0) OF CHARACTER],
          ENDCASE],
      -- not presently used --
      error => NULL,
      noop => NULL,
      -- not presently implemented --
      length => [handle: Handle],
      telnet => NULL,
      ENDCASE];

  openAns: LeafOp = [
    type: open, sense: reply, length: 2 * SIZE[open AnswerObject]];
  closeAns: LeafOp = [
    type: close, sense: reply, length: 2 * SIZE[close AnswerObject]];
  deleteAns: LeafOp = [
    type: delete, sense: reply, length: 2 * SIZE[delete AnswerObject]];
  lengthAns: LeafOp = [
    type: length, sense: reply, length: 2 * SIZE[length AnswerObject]];
  truncateAns: LeafOp = [
    type: truncate, sense: reply, length: 2 * SIZE[truncate AnswerObject]];
  readAns: LeafOp = [
    type: read, sense: reply, length: 2 * SIZE[read AnswerObject]];
  writeAns: LeafOp = [
    type: write, sense: reply, length: 2 * SIZE[write AnswerObject]];
  resetAns: LeafOp = [
    type: reset, sense: reply, length: 2 * SIZE[reset AnswerObject]];
  paramsAns: LeafOp = [
    type: params, sense: reply, length: 2 * SIZE[params AnswerObject]];

  Answer: TYPE = LONG POINTER TO AnswerObject;
  OpenAnswer: TYPE = LONG POINTER TO open AnswerObject;
  CloseAnswer: TYPE = LONG POINTER TO close AnswerObject;
  DeleteAnswer: TYPE = LONG POINTER TO delete AnswerObject;
  TruncateAnswer: TYPE = LONG POINTER TO truncate AnswerObject;
  ReadAnswer: TYPE = LONG POINTER TO read AnswerObject;
  WriteAnswer: TYPE = LONG POINTER TO write AnswerObject;
  ResetAnswer: TYPE = LONG POINTER TO reset AnswerObject;
  ParamsAnswer: TYPE = LONG POINTER TO params AnswerObject;

  AnswerObject: TYPE = MACHINE DEPENDENT RECORD [
    op: LeafOp,
    opSpecific: SELECT COMPUTED LeafType FROM
      error => [error: IfsError, errorOp: LeafOp, handle: Handle],
      reset => NULL,
      params => [o: CARDINAL, undefined: CARDINAL],
      open => [handle: Handle, eofAddress: FileAddress],
      close, delete, truncate => [handle: Handle],
      read => [
        handle: Handle,
        address: FileAddress,
        length: ByteCount,
        readBody: SELECT OVERLAID * FROM
          readWords => [readWords: ARRAY [0..0) OF WORD],
          readBytes => [readBytes: PACKED ARRAY [0..0) OF Environment.Byte],
          readChars => [readChars: PACKED ARRAY [0..0) OF CHARACTER],
          ENDCASE],
      write => [
        handle: Handle, address: FileAddress, length: ByteCount, rate: Rate],
      -- not presently expected --
      noop => NULL,
      -- not presently implemented --
      length => [handle: Handle, eofAddress: FileAddress],
      telnet => NULL,
      ENDCASE];

  FiveSeconds: TYPE = CARDINAL;  -- units of five seconds; zero means server default

  FileAddress: TYPE = MACHINE DEPENDENT RECORD [
    opSpecific(0:0..4): OpSpecificFileAddress ← [read[]],
    high(0:5..15): [0..2047],
    low(1:0..15): CARDINAL];

  OpSpecificFileAddress: TYPE = MACHINE DEPENDENT RECORD [
    SELECT COMPUTED LeafType FROM
    open, length, truncate => [fill: [0..31] ← 0],
    read, write => [
      mode: {anywhere, noHoles, dontExtend, checkExtend} ← anywhere,
      newEOF: BOOLEAN ← FALSE,
      fill: [0..3] ← 0],
    ENDCASE];

  ByteCount: TYPE = CARDINAL;

  Rate: TYPE = CARDINAL;
  anyRate: Rate = 0;

  Handle: TYPE = CARDINAL;
  noHandle: CARDINAL = 0;

  Resetee: TYPE = MACHINE DEPENDENT{thisHost(0), fileLocks(1), allHosts(177777B)};

  IfsError: TYPE = MACHINE DEPENDENT{
    ok(0), nameMalformed(201), illegalChar(202), illegalStar(203),
    illegalVersion(204), nameTooLong(205), illegalDIFAccess(206),
    fileNotFound(207), accessDenied(208), fileBusy(209), dirNotFound(210),
    allocExceeded(211), fileSystemFull(212), createStreamFailed(213),
    fileAlreadyExists(214), fileUndeletable(215), userName(216),
    userPassword(217), filesOnly(218), connectName(219), connectPassword(220),
    brokenLeaf(1001), unimplementedOp(1010), badHandle(1011), fileTooLong(1012),
    illegalTruncate(1013), illegalRead(1015), illegalWrite(1016), (177777B)};


  -- Miscellaneous Declarations --

  leafSocket: PupTypes.PupSocketID = [0, 43B];
  ptLeaf: PupTypes.PupType = LOOPHOLE[260B];


  END.