-- File: AltoDirList.mesa
-- Last edited by Levin:  28-Jan-81 19:33:31

DIRECTORY
  AltoFile USING [FP, sysDirFP],
  AltoFilePrivate USING [
    DirHandle, DirObject, FlushDirectoryBuffer, ResetDirectoryLength, sysDir],
  VMDefs USING [CloseFile, FileHandle, PageNumber],
  VMSpecial USING [OpenAltoFileFromFP],
  VMStorage USING [shortTerm];

AltoDirList: MONITOR
  IMPORTS AltoFilePrivate, VMDefs, VMSpecial, VMStorage
  EXPORTS AltoFile, AltoFilePrivate =

  BEGIN OPEN AltoFilePrivate;

  -- Global Variables --

  dirList: DirHandle;

  -- Miscellaneous Declarations --

  BadDirectoryList: ERROR = CODE;

  -- Procedures and Signals Exported to AltoFile --

  DirObject: PUBLIC TYPE = AltoFilePrivate.DirObject;

  OpenDirectory: PUBLIC ENTRY PROCEDURE [fp: AltoFile.FP]
    RETURNS [dir: DirHandle] =
    BEGIN
    FOR dir ← dirList, dir.link UNTIL dir = NIL DO
      IF dir.fp = fp THEN BEGIN dir.useCount ← dir.useCount + 1; EXIT END;
      REPEAT FINISHED => dir ← AddDirectory[fp ! UNWIND => NULL];
      ENDLOOP;
    END;
    
  CloseDirectory: PUBLIC ENTRY PROCEDURE [dir: DirHandle] =
    BEGIN
    IF (dir.useCount ← dir.useCount - 1) = 0 THEN
      BEGIN
      IF dir = dirList THEN dirList ← dir.link
      ELSE
	FOR prev: DirHandle ← dirList, prev.link UNTIL prev.link = NIL DO
	  IF prev.link = dir THEN BEGIN prev.link ← dir.link; EXIT END;
	  REPEAT FINISHED => ERROR BadDirectoryList;
	  ENDLOOP;
      FlushDirectoryBuffer[dir ! UNWIND => NULL];
      VMDefs.CloseFile[dir.file];
      VMStorage.shortTerm.FREE[@dir];
      END;
    END;
    
  -- Procedures and Signals Exported to FilePrivateDefs --

  InitializeDirectory: PUBLIC PROCEDURE =
    BEGIN
    dirList ← NIL;
    sysDir ← AddDirectory[AltoFile.sysDirFP];
    END;

  FinalizeDirectory: PUBLIC PROCEDURE =
    {CloseDirectory[sysDir]};


  -- Internal Procedures --

  AddDirectory: PROCEDURE [fp: AltoFile.FP] RETURNS [dir: DirHandle] =
    -- creates a new directory entry, initializes it, and adds it to the directory list.
    BEGIN
    dir ← VMStorage.shortTerm.NEW[DirObject ← DirObject[
      file:, length:, buffer: NIL, page: LAST[VMDefs.PageNumber], fp: fp,
      spacePos:, spaceNeeded:, spaceFound: 0, link: dirList, useCount: 1]];
    BEGIN
    ENABLE UNWIND => VMStorage.shortTerm.FREE[@dir];
    dir.file ← VMSpecial.OpenAltoFileFromFP[fp: fp, writable: TRUE, cacheFraction: 1];
    ResetDirectoryLength[dir ! UNWIND => VMDefs.CloseFile[dir.file]];
    END;
    dirList ← dir;
    END;

  END.