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

UsingSeq: TYPE = LONG POINTER TO UsingSeqRecord;
-- string entries may be NIL
UsingSeqRecord: TYPE = RECORD[
 zone: UNCOUNTED ZONENIL, -- 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 ZONENIL,
 zoneType: ZoneType ← shared,
 size: CARDINAL ← 0,
 trailingcomment: LONG STRINGNIL,
 ivyHost: LONG STRINGNIL, -- if huge, then "Ivy"
 indigoHost: LONG STRINGNIL, -- 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 STRINGNIL, 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: BOOLFALSE, wrapUsingLists: BOOLTRUE];
FlattenDF: PROC[dfseq: DFSubr.DFSeq, dffilename: LONG STRING,
 h: Subr.TTYProcs, checkForOverwrite, allowForceReadOnly: BOOLTRUE,
 setRecorder, printStatus, skipCameFrom, tryDollars: BOOLFALSE];

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: BOOLFALSE] RETURNS[version: CARDINAL];

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

}.