-- DFSubr.Mesa
-- last edit January 3, 1983 6:01 pm
-- last edit May 22, 1983 1:04 pm by Russ Atkinson
-- (changed STRING to LONG STRING in WriteOut)
-- Pilot 6.0 / Mesa 7.0

DIRECTORY
File: TYPE USING [Capability, nullCapability],
Stream: TYPE USING [Handle],
Subr: TYPE USING[TTYProcs],
TimeStamp: TYPE USING[Null, Stamp];

DFSubr: DEFINITIONS = {

Criterion: TYPE = {none, update, notequal};

DF: TYPE = LONG POINTER TO DFFileRecord;
DFFileRecord: TYPE = RECORD[
 host: LONG STRING ← NIL,  -- ivy
 directory: LONG STRING ← NIL, -- schmidt>model
 shortname: LONG STRING ← NIL, -- junk.mesa
 version: CARDINAL ← 0,  -- 23
 createtime: LONG CARDINAL ← 0, -- > 0 is create time from leader pg.
 comment: LONG STRING ← NIL, -- comment before this line
 recorder: LONG STRING ← NIL, -- describebcd, verifydf, releasetool
 releaseHost: LONG STRING ← NIL, -- release on Ivy
 releaseDirectory: LONG STRING ← NIL, -- release as Cedar>Top
 atsign: BOOL ← FALSE, -- indirect this df file
 criterion: Criterion ← none,
     -- none, notequal => xfer if ~= dates
     -- update => like retrieve/U
 topmark: BOOL ← FALSE, -- if T then this is top bcd in DF
 newOnly: BOOL ← FALSE, -- filename preceded by ~,
    -- indicating retrieve only if not already on disk
 public: BOOL ← FALSE, -- if T then directory was Public
 publicOnly: BOOL ← FALSE, -- if T then {PublicOnly} in filename
 readonly: BOOL ← FALSE, -- readonly directory
 cameFrom: BOOL ← FALSE, -- T => CameFrom, F=> ReleaseAs
 parentCameFrom: BOOL ← FALSE, -- used by ReleaseTool
 versionstamp: TimeStamp.Stamp ← TimeStamp.Null, -- used by DescribeBcd & VerifyDF
 presentonlocaldisk: BOOL ← FALSE,-- file is on local disk
 cap: File.Capability ← File.nullCapability,
 using: UsingSeq ← NIL,  -- using list for df file
 isdefns: BOOL ← FALSE, -- used by describebcd
 systemfile: BOOL ← FALSE, -- is a Mesa system file
 eval: BOOL ← FALSE,  -- has been evaluated in EvalBcds
 need: BOOL ← FALSE,  -- need to retrieve this file
 exportsAnalyzed: BOOL ← FALSE, -- used by FlattenDF
 includeAnalyzed: BOOL ← FALSE -- used by FlattenDF
 ];

UsingSeq: TYPE = LONG POINTER TO UsingSeqRecord;
-- string entries may be NIL
UsingSeqRecord: TYPE = RECORD[
 zone: UNCOUNTED ZONE ← NIL, -- the zone the strings are in
 size: CARDINAL ← 0,
 body: SEQUENCE maxsize: CARDINAL OF LONG STRING -- the strings
 ];
 
ZoneType: TYPE = {shared, single, huge};

DFSeq: TYPE = LONG POINTER TO DFSeqRecord;
-- don't change this record without looking at AllocSpecialSeq in DFSubrImpl
DFSeqRecord: TYPE = RECORD[
 dfzone: UNCOUNTED ZONE ← NIL,
 zoneType: ZoneType ← shared,
 size: CARDINAL ← 0,
 trailingcomment: LONG STRING ← NIL,
 ivyHost: LONG STRING ← NIL, -- if huge, then "Ivy"
 indigoHost: LONG STRING ← NIL, -- if huge then "Indigo"
 body: SEQUENCE maxsize: CARDINAL OF DFFileRecord
 ];
 
-- PROGRAMS (does NOT need to be started explicitly)
DFSubrImpl, DFParserImpl: PROGRAM;

-- PROCS (defined in DFParserImpl.Mesa)
DFEntryProcType: TYPE = PROC[dfEntry: DF];

-- be sure to check version >0, createtime = 0, and criterion = none
-- to determine if wants explicit version
InterestingNestedDFProcType: TYPE = PROC[
 host, directory, shortname, ancestor, immediateParent: LONG STRING,
 version, nLevel: CARDINAL, createtime: LONG CARDINAL,
 driverUsingSeq, innerUsingSeq: UsingSeq, dfEntry: DF,
 entryIsReadonly, publicOnly: BOOL, criterion: Criterion];

-- if noremoteerrors is true, don't complain if a file doesn't
-- appear to have a remote place
-- if forceReadonly then make every entry in this DF file be ReadOnly
-- if omitNonPublic, then don't parse them into dfseq
-- dffilename is for error messages
ParseStream: PROC[sh: Stream.Handle, dfseq: DFSeq, dffilename: LONG STRING,
 using: UsingSeq, noremoteerrors, forceReadonly, omitNonPublic: BOOL,
 h: Subr.TTYProcs, interestingNestedDF: InterestingNestedDFProcType ← NIL,
 dfEntryProc: DFEntryProcType ← NIL,
 ancestor: LONG STRING ← NIL, nLevel: CARDINAL ← 0];

-- PROCS (defined in DFSubrImpl)
-- remember this stuff uses its own HugeZone
-- allocation
-- if useHugeZone then only uses HugeZone
AllocateDFSeq: PROC[maxEntries: CARDINAL, zoneType: ZoneType]
 RETURNS[dfseq: DFSeq];
NextDF: PROC[dfseq: DFSeq] RETURNS[df: DF];
FreeDFSeq: PROC[pdfseq: POINTER TO DFSeq];
 
-- input/output

WriteOut: PROC[dfseq: DFSeq, topLevelFile: LONG STRING, outputStream: Stream.Handle,
 print, altoCompatibility: BOOL ← FALSE, wrapUsingLists: BOOL ← TRUE];
FlattenDF: PROC[dfseq: DFSubr.DFSeq, dffilename: LONG STRING,
 h: Subr.TTYProcs, checkForOverwrite, allowForceReadOnly: BOOL ← TRUE,
 setRecorder, printStatus, skipCameFrom, tryDollars: BOOL ← FALSE];

TooManyEntries: ERROR; -- raised by FlattenDF when dfseq fills up

-- UsingSeq procedures
-- oldusing may be NIL
AppendToUsingSeq: PROC[oldusing: UsingSeq, shortname: LONG STRING, zone: UNCOUNTED ZONE]
 RETURNS[newusing: UsingSeq];
UsingEmpty: PROC[usingseq: UsingSeq] RETURNS[empty: BOOL];
IntersectUsing: PROC[driver, limiter: UsingSeq] RETURNS[newusing: UsingSeq];
CopyUsing: PROC[limiter: UsingSeq] RETURNS[newusing: UsingSeq];
FreeUsingSeq: PROC[using: UsingSeq];
 
-- utilities
ReadInDir: PROC[dfseq: DFSeq];
LookupDF: PROC[dfseq: DFSeq, shortname: LONG STRING] RETURNS[df: DF];

-- fullname is readonly
-- any of host, directory, short may be NIL
-- if mustbedir is TRUE then if long does not end in a '>
-- the tail is assumed to be part of the directory, not the short,
-- e.g. "schmidt>pilot" is all a directory if mustbedir is TRUE
StripLongName: PROC[fullname, host, directory, short: LONG STRING,
 mustbedir: BOOL ← FALSE] RETURNS[version: CARDINAL];

SortByFileName, SortByCap: PROC[dfseq: DFSeq, min, max: CARDINAL,
 ignorehostanddir: BOOL ← FALSE];
CompareDFs: PROC[dfleft, dfright: DF, ignorehostanddir: BOOL ← FALSE]
 RETURNS[res: INTEGER];
InsertCRs: PROC[dfseq: DFSeq];

}.