-- PilotSegments.mesa  Edited by Johnsson on February 3, 1981  4:33 PM

DIRECTORY
  Environment USING [PageCount, PageNumber],
  File USING [
    Capability, delete, grow, nullCapability, Permissions, read, shrink, Unknown, write],
  Space USING [Handle, InsufficientSpace],
  Time USING [Packed];


Segments: DEFINITIONS IMPORTS File, Space =
  BEGIN

  Address: TYPE = LONG POINTER;

  FP: TYPE = File.Capability;

  FPHandle: TYPE = POINTER TO FP;

  FHandle: TYPE = POINTER TO FObject;

  SHandle: TYPE = POINTER TO SObject;

  -- Assert: The word POINTER does not appear below here.

  PageCount: TYPE = Environment.PageCount;
  PageNumber: TYPE = Environment.PageNumber;

  NullFP: FP = File.nullCapability;

  FObject: TYPE = PRIVATE RECORD [
    cap: Segments.FP,
    inuse: BOOLEAN,
    spare1, spare2, spare3: BOOLEAN,
    lock: [0..MaxFileLocks],
    link: FHandle];

  MaxFileLocks: PRIVATE CARDINAL = 7777B;

  SObject: TYPE = PRIVATE RECORD [
    file: FHandle,
    base: Segments.PageNumber,
    pages: Segments.PageCount,
    space: Space.Handle,
    inuse: BOOLEAN,
    mapped: BOOLEAN,
    killed: BOOLEAN,
    write: BOOLEAN,
    spare1, spare2, spare3: BOOLEAN,
    lock: [0..MaxSegLocks],
    link: SHandle];

  MaxSegLocks: PRIVATE CARDINAL = 777B;

  -- S E G M E N T S

  AllocInfo: TYPE = PRIVATE CARDINAL;
  EasyUp: AllocInfo = 0;
  EasyDown: AllocInfo = 0;
  HardUp: AllocInfo = 0;
  HardDown: AllocInfo = 0;

  DefaultBase: Segments.PageNumber = LAST[Segments.PageNumber];
  DefaultMDSBase: Segments.PageNumber = DefaultBase - 1;
  DefaultXMBase: Segments.PageNumber = DefaultMDSBase - 1;
  DefaultANYBase: Segments.PageNumber = DefaultXMBase - 1;

  SwapError: PRIVATE SIGNAL [seg: SHandle];
  InvalidSegment: PRIVATE SIGNAL [s: UNSPECIFIED];

  SwapProblem: PROC RETURNS [SIGNAL [seg: SHandle]] = INLINE {RETURN[SwapError]};

  OutOfMemory: PROC RETURNS [SIGNAL [x: CARDINAL]] = INLINE {
    RETURN[LOOPHOLE[Space.InsufficientSpace]]};

  DeleteSegment: PROCEDURE [seg: SHandle];
  EnumerateSegments: PROCEDURE [proc: PROCEDURE [SHandle] RETURNS [BOOLEAN]]
    RETURNS [SHandle];
  FlushSegmentCache: PROCEDURE;
  Kill: PROCEDURE [seg: SHandle, base: PageNumber ← DefaultBase];
  MakeReadOnly: PROCEDURE [seg: SHandle];
  MoveSegment: PROCEDURE [seg: SHandle, base: PageNumber, pages: PageCount];
  NewSegment: PROCEDURE [file: FHandle, base: PageNumber, pages: PageCount,
    access: Access ← DefaultAccess] RETURNS [SHandle];
  SegmentAddress: PROCEDURE [seg: SHandle] RETURNS [Segments.Address];
  SwapIn: PROCEDURE [
    seg: SHandle, base: PageNumber ← DefaultANYBase, info: AllocInfo ← EasyUp];
  SwapOut: PROCEDURE [seg: SHandle];
  SwapUp: PROCEDURE [seg: SHandle];
  Unlock: PROCEDURE [seg: SHandle];
  VMtoSegment: PROCEDURE [a: Segments.Address] RETURNS [SHandle];


  FileFromSegment: PROC [seg: SHandle] RETURNS [FHandle] = INLINE {
    RETURN[seg.file]};

  BaseFromSegment: PROC [seg: SHandle] RETURNS [PageNumber] = INLINE {
    RETURN[seg.base]};

  IsSwappedIn: PROC [seg: SHandle] RETURNS [BOOLEAN] = INLINE {
    RETURN[seg.mapped]};

  PagesFromSegment: PROC [seg: SHandle] RETURNS [PageCount] = INLINE {
    RETURN[seg.pages]};

  LockFromSegment: PROC [seg: SHandle] RETURNS [CARDINAL] = INLINE {
    RETURN[seg.lock]};

  UpdateUsageHint: PROC [seg: SHandle] = INLINE {};

  -- F I L E S: 

  VersionOptions: TYPE = PRIVATE [0..3];
  DefaultVersion: VersionOptions = 0;
  NewFileOnly: VersionOptions = 1;
  OldFileOnly: VersionOptions = 2;

  Access: TYPE = PRIVATE File.Permissions;
  AllAccess: Segments.Access =
    File.read + File.write + File.grow + File.shrink + File.delete;
  DefaultAccess: Segments.Access = 0;
  Read: Segments.Access = File.read;
  ReadWrite: Segments.Access = AllAccess;
  Write: Segments.Access = File.write + File.grow + File.shrink + File.delete;

  FileNameError: PRIVATE SIGNAL [name: STRING];
  FileError: PRIVATE SIGNAL [f: FHandle];
  InvalidFile: PRIVATE SIGNAL [f: UNSPECIFIED];

  FileNameProblem: PROC RETURNS [SIGNAL [name: STRING]] = INLINE {
    RETURN[FileNameError]};

  FileProblem: PROC RETURNS [SIGNAL [f: FHandle]] = INLINE {RETURN[FileError]};

  FileUnknown: PROCEDURE RETURNS [SIGNAL] = INLINE {RETURN[LOOPHOLE[File.Unknown]]};

  DestroyFile: PROCEDURE [file: FHandle];
  EnumerateFiles: PROCEDURE [proc: PROCEDURE [FHandle] RETURNS [BOOLEAN]]
    RETURNS [file: FHandle];
  FPFromFile: PROCEDURE [file: FHandle, fp: FPHandle] = INLINE {fp↑ ← file.cap};
  GetFileProperties: PROCEDURE [file: FHandle]
    RETURNS [create, write, read: Time.Packed, length: LONG CARDINAL];
  GetFileTimes: PROCEDURE [file: FHandle]
    RETURNS [create, write, read: Time.Packed];
  GetFileLength: PROCEDURE [file: FHandle] RETURNS [LONG CARDINAL];
  InsertFile: PROCEDURE [
    file: Segments.FPHandle, access: Segments.Access ← DefaultAccess]
    RETURNS [FHandle];
  NewFile: PROCEDURE [
    name: STRING, access: Segments.Access ← DefaultAccess,
    version: VersionOptions ← DefaultVersion] RETURNS [FHandle];
  LockFile: PROCEDURE [file: FHandle];

  ReleasableFile: PROC [file: FHandle] RETURNS [BOOLEAN] = INLINE {
    RETURN[file.lock = 0]};

  ReleaseFile: PROCEDURE [file: FHandle];
  SetFileLength: PROCEDURE [file: FHandle, length: LONG CARDINAL];
  SetFileTimes: PROCEDURE [file: FHandle, create, write, read: Time.Packed ← [0]];
  UnlockFile: PROCEDURE [file: FHandle];

  -- D I R E C T O R Y: 

  EnumerateDirectory: PROC [
    proc: PROC [Segments.FPHandle, STRING] RETURNS [BOOLEAN],
    files: STRING ← NIL,
    wantWholeName: BOOLEAN ← FALSE];

  -- for Debugger Only: 

  NameForFile: PROCEDURE [name: STRING, file: FHandle];
  ModifyFile: PROCEDURE [name: STRING] RETURNS [BOOLEAN];
  AddModifyProc: PROC [PROC [STRING, FHandle] RETURNS [BOOLEAN]];
  InvalidateFileCache: PROCEDURE;
  FlushFileCache: PROCEDURE;

  END.