-- MDSubr.Mesa, last edit December 30, 1982 5:58 pm
-- Pilot 5.0/ Mesa 7.0
-- definitions file for subroutines for the modeller

DIRECTORY
  Environment: TYPE USING [wordsPerPage],
  File: TYPE USING [Capability, nullCapability],
  Stream: TYPE USING [Handle],
  Subr: TYPE USING [PackedTime, TTYProcs];

MDSubr: DEFINITIONS = {

-- TYPES and CONSTANTS
versionUnknown: Subr.PackedTime = LONG[0];
versionNil: Subr.PackedTime = LONG[-1];

-- look for this file in the directory
lookNil: CARDINAL = 32767;
Look: TYPE = LONG POINTER TO LookRecord;
LookRecord: TYPE = RECORD[
	name: LONG STRING ← NIL,		-- name of file to look for
	need: BOOL ← FALSE,			-- if false all info below garb.
	presentonlocaldisk: BOOL ← FALSE,	-- is on disk, otherwise FALSE
	cap: File.Capability ← File.nullCapability, -- if presentonlocaldisk, its cap
	localversion: Subr.PackedTime ← versionUnknown,-- for local file
	remoteversion: Subr.PackedTime ← versionUnknown,-- for a remote file
	cardhi: CARDINAL ← 0,
	cardlow: CARDINAL ← 32000,
	remotelength: LONG CARDINAL ← 0,
	locallength: LONG CARDINAL ← 0,
	besttime: Subr.PackedTime ← versionNil	-- the best time from remote&loc
	];
LookSeq: TYPE = LONG POINTER TO LookSeqRecord;
LookSeqRecord: TYPE = RECORD[
	lookzone: UNCOUNTED ZONE ← NIL,
	size: CARDINAL ← 0,		-- current size
	body: SEQUENCE maxsize: CARDINAL OF LookRecord
	];

entNil: CARDINAL = 32767;
Entry: TYPE = LONG POINTER TO EntryRecord;
EntryRecord: TYPE = RECORD[
	name: LONG STRING ← NIL,
	depends: LONG DESCRIPTOR FOR ARRAY OF CARDINAL,
	rule: LONG STRING ← NIL,
	made: BOOL ← FALSE,		-- if true, already made
	visited: BOOL ← FALSE,	-- used by tree walkers
	lookinx: CARDINAL ← lookNil	-- index of "name" in look array
	];
EntrySeq: TYPE = LONG POINTER TO EntrySeqRecord;
EntrySeqRecord: TYPE = RECORD[
	entryzone: UNCOUNTED ZONE ← NIL,
	size: CARDINAL ← 0,		-- current size
	body: SEQUENCE maxsize: CARDINAL OF EntryRecord
	];

SMALLDEPLIST: CARDINAL = 10;
HUGEDEPLIST: CARDINAL = Environment.wordsPerPage - 1;

-- be sure to update array TokString in mdsubrimpl.mesa if you change this
Token: TYPE = {tokBAD, tokEOF, tokLP, tokRP, tokLB, tokRB, tokDOT, tokCOLON,
tokCOMMA, tokEQ, tokAT, tokBANG, tokSEMI, tokGT, tokLT, tokUP, tokIMPLIES,
tokARROW, tokID, tokNUM, tokTYPE, tokPLUS, tokTHEN, tokPROC,
tokRETURNS, tokSTRLIT, tokSTRING, tokSELECT, tokFROM,tokDIR,
tokIMPORTS, tokEXPORTS,tokPROGRAM, tokBEGIN, tokDEFINITIONS,
tokOTHERS, tokCONTROL, tokCONFIG, tokLINKS, tokCODE, tokFRAME, tokPACK,
tokEND, tokUSING, tokSHARES, tokLET, tokOPEN, tokMONITOR};

StringSeq: TYPE = LONG POINTER TO StringSeqRecord;
StringSeqRecord: TYPE = RECORD[
	size: CARDINAL ← 0,
	body: SEQUENCE maxsize: CARDINAL OF StringVarRecord
	];
StringVarRecord: TYPE = RECORD[
	str: LONG STRING ← NIL,
	val: LONG STRING ← NIL
	];

MAXDEP: CARDINAL = 165;	-- biggest is CoPilotDorado.Config
ModType: TYPE = {errortype, imports, exports, directory};
ModInfo: TYPE = LONG POINTER TO ModInfoRecord;
ModInfoRecord: TYPE = RECORD[
	parent: CARDINAL ← entNil,	-- an index into entryse
	modulename: LONG STRING ← NIL,
	sourcefileinx: CARDINAL ← entNil,	-- an index into entryseq
	isdefn, isconfig: BOOL ← FALSE,
	dirinx, impinx, expinx: CARDINAL ← 0,
	dirname, imports, exports: ARRAY [0 .. MAXDEP) OF CARDINAL← ALL[entNil]
	];

-- a more refined Dependency structure
DepSeq: TYPE = LONG POINTER TO DepSeqRecord;
DepSeqRecord: TYPE = RECORD[
	bcdfilename: LONG STRING ← NIL,
	bcdtime: LONG CARDINAL ← 0,
	srcfilename: LONG STRING ← NIL,
	srctime: LONG CARDINAL ← 0,
	modulename: LONG STRING ← NIL,
	FreeString: PROC[LONG STRING] ← NIL,	-- use to free the strings ...
	aflag: BOOL ← FALSE,		-- compiler switch /a
	bflag: BOOL ← TRUE,		-- etc.
	fflag: BOOL ← TRUE,
	jflag: BOOL ← FALSE,
	lflag: BOOL ← FALSE,
	nflag: BOOL ← TRUE,
	sflag: BOOL ← TRUE,
	uflag: BOOL ← FALSE,
	isdefns: BOOL ← FALSE,
	isconfig: BOOL ← FALSE,
	fromsource: BOOL ← FALSE,	-- T => info from source file
	size: CARDINAL ← 0,
	body: SEQUENCE maxsize: CARDINAL OF ADepRecord
	];
ADepRecord: TYPE = RECORD[
	relation: ModType ← errortype,
	modulename: LONG STRING ← NIL,
	bcdfilename: LONG STRING ← NIL,
	bcdtime: LONG CARDINAL ← 0,
	srctime: LONG CARDINAL ← 0
	];

-- GLOBAL VARIABLES
-- defined in MDScanImpl.Mesa
peektok: Token;
peekvalue: LONG UNSPECIFIED;

-- PROGRAMS
MDSubrImpl, MDScanImpl: PROGRAM;

-- PROCS
-- defined in MDSubrImpl.Mesa
-- utilities
StripFirstWord: PROC[str, result:  LONG STRING];

-- having to do with EntrySeq's
PrintEntries: PROC[entryseq: EntrySeq,
	sh: Stream.Handle ← NIL, stringseq: StringSeq, 
	ttyhandle: Subr.TTYProcs];
GetAnEntry: PROC[name: STRING, entryseq: EntrySeq] 
	RETURNS[i: CARDINAL, new: BOOL];
AddToDepends: PROC[parent, child: CARDINAL, entryseq: EntrySeq];
FreeEntrySeq: PROC[pentryseq: LONG POINTER TO EntrySeq];
WalkTheGraph: PROC[firstinx: CARDINAL, entryseq: EntrySeq, proc: PROC[Entry]];

-- having to do with Look's and Entry's together
ThrowAwayLeaves: PROC[firstinx: CARDINAL, entryseq: EntrySeq,
	lookseq: LookSeq, ismodel: BOOL];
CheckNames: PROC[entryseq: EntrySeq, lookseq: LookSeq];
ConvertToLook: PROC[entryseq: EntrySeq, lookseq: LookSeq];
-- having to do with compiler and binder options
InsertOtherSym: PROC[str, val: STRING, stringseq: StringSeq];
LookupOtherSym: PROC[str: LONG STRING, stringseq: StringSeq] 
	RETURNS[LONG STRING];
GetCompilerRule: PROC[stringseq: StringSeq, name: LONG STRING,
	zone: UNCOUNTED ZONE] RETURNS[LONG STRING];
GetBinderRule: PROC[stringseq: StringSeq, name: LONG STRING,
	zone: UNCOUNTED ZONE] RETURNS[LONG STRING];


-- defined in MDScanImpl.Mesa
-- parsing of Mesa source files and .Configs
ParseObject: PROC[sh: Stream.Handle, parent: CARDINAL,
	entryseq: EntrySeq, pmod: ModInfo, depseq: DepSeq, 
	stringseq: StringSeq, sfn: STRING];
ScanInit: PROC[Stream.Handle];
NextTok: PROC[Stream.Handle] RETURNS[Token, LONG UNSPECIFIED];
GetTokString: PROC[tok: Token] RETURNS[LONG STRING];
CheckTok: PROC[Token, Token, STRING];
StopScanner: PROC;
AddToMod: PROC[ModInfo, CARDINAL, ModType];
AddToDep: PROC[depseq: DepSeq, padeprecord: POINTER TO ADepRecord];

-- having to with looks
ReadLocalDirectory: PROC[lookseq: LookSeq];
ReadInLocalDirectoryAll: PROC[lookseq: LookSeq, 
	ThrowAwayThisFile: PROC[name: STRING] RETURNS[BOOL]];
AnalyzeLocalFiles: PROC[oktosort: BOOL, lookseq: LookSeq, 
	getcreatedate: BOOL];
PrintLook: PROC[lookseq: LookSeq];
SortByFileTime: PROC[lookseq: LookSeq, descending: BOOL ← FALSE];
SortByFileName: PROC[lookseq: LookSeq, descending: BOOL ← FALSE];
LookLook: PROC[name: LONG STRING, lookseq: LookSeq]
	 RETURNS[look: Look, lookinx: CARDINAL]; -- index in lookd
FreeLookSeq: PROC[plookseq: LONG POINTER TO LookSeq];
AddToLook: PROC[name: LONG STRING, lookseq: LookSeq] RETURNS[Look];
 
-- Inline Procedures
IsAlpha: PROC[c: CHAR] RETURNS[BOOL] = INLINE { 
RETURN['a <= c AND c <= 'z OR 'A <= c AND c <= 'Z];
};

IsDigit: PROC[c: CHAR] RETURNS[BOOL] = INLINE { 
RETURN['0 <= c AND c <= '9];
};

-- just like StringDefs.LowerCase but INLINE
ToLower: PROC[ch: CHAR] RETURNS[CHAR] = INLINE { 
IF 'A <= ch AND ch <= 'Z THEN ch ← ch + ('a-'A);
RETURN[ch];
};

}.