DIRECTORY Basics, BasicTime USING [GMT, ToNSTime], FileNames, FS, IO, MobDefs, RefText, Rope, VersionMap, VersionMapClassify; VersionMapClassifyImpl: CEDAR PROGRAM IMPORTS BasicTime, FileNames, FS, IO, RefText, Rope, VersionMap EXPORTS VersionMapClassify = BEGIN GMT: TYPE = BasicTime.GMT; Map: TYPE = VersionMap.Map; MapList: TYPE = VersionMap.MapList; ROPE: TYPE = Rope.ROPE; RopeList: TYPE = LIST OF ROPE; STREAM: TYPE = IO.STREAM; VersionStamp: TYPE = VersionMap.VersionStamp; NullVersion: VersionStamp = VersionMapClassify.NullVersion; BadVersion: VersionStamp = VersionMapClassify.BadVersion; KindName: PUBLIC ARRAY VersionMapClassify.KindSet OF ROPE ¬ [ "unknown", "source", "intermediate", "sparc", "sparcOpt", "all" ]; Classify: PUBLIC PROC [name: ROPE] RETURNS [kind: VersionMapClassify.Kind] ~ { nameWithoutVersion: ROPE ~ FileNames.StripVersionNumber[name]; whichMap, other: ATOM; [whichMap, other] ¬ VersionMap.MapAtomForName[nameWithoutVersion]; SELECT TRUE FROM whichMap = $Intermediate => kind ¬ intermediate; whichMap = $Source => kind ¬ source; whichMap = $Executable => IF other = $opt THEN kind ¬ sparcOpt ELSE kind ¬ sparc; ENDCASE => kind ¬ source}; CreatedToMimosaVersionStamp: PUBLIC PROC [created: BasicTime.GMT] RETURNS [VersionStamp] = { RETURN [[BasicTime.ToNSTime[created], 0]]}; ReadVersionStamp: PUBLIC PROC [kind: VersionMapClassify.Kind, fullName: ROPE, created: BasicTime.GMT, rejectServerInaccessible: BOOL] RETURNS [stamp: VersionStamp, whyNot, warning: ROPE] ~ { bangPos: INT ~ fullName.Index[s2: "!"]; verless: ROPE ~ fullName.Substr[len: bangPos]; SELECT kind FROM unknown, source => RETURN [CreatedToMimosaVersionStamp[created], NIL, NIL]; intermediate => SELECT TRUE FROM Rope.Match["*.mob", verless] => RETURN ReadMobStamp[fullName, created, rejectServerInaccessible]; Rope.Match["*.c2c.c", verless] => { [stamp, whyNot] ¬ ReadCOStamp[fullName, created, rejectServerInaccessible]; warning ¬ NIL; RETURN}; ENDCASE => RETURN [CreatedToMimosaVersionStamp[created], NIL, NIL]; sparc, sparcOpt => { [stamp, whyNot] ¬ ReadCOStamp[fullName, created, rejectServerInaccessible]; IF whyNot#NIL AND NOT Rope.Match["*.c2c.o", verless] THEN { stamp ¬ CreatedToMimosaVersionStamp[created]; warning ¬ whyNot.Concat["; create date used for stamp"]; whyNot ¬ NIL} ELSE warning ¬ NIL; RETURN}; ENDCASE => ERROR; }; ReadMobStamp: PROC [fullName: ROPE, created: BasicTime.GMT, rejectServerInaccessible: BOOL] RETURNS [stamp: VersionStamp, whyNot, warning: ROPE ¬ NIL] ~ { from: IO.STREAM; mob: MobDefs.Mob; nRead: INT; from ¬ FS.StreamOpen[fileName: fullName, wantedCreatedTime: created !FS.Error => IF error.code#$serverInaccessible OR NOT rejectServerInaccessible THEN {whyNot ¬ IO.PutFLR["FS.Open[%g of %g] => Error[%g, %g]", LIST[ [rope[fullName]], [time[created]], [atom[error.code]], [rope[error.explanation]]] ]; GOTO Abort} ]; TRUSTED {nRead ¬ from.UnsafeGetBlock[[base: LOOPHOLE[@mob], count: BYTES[MobDefs.Mob]]]}; from.Close[]; IF nRead # BYTES[MobDefs.Mob] THEN RETURN [BadVersion, IO.PutFLR["%g of %g yielded only %g bytes, instead of %g", LIST[ [rope[fullName]], [time[created]], [integer[nRead]], [integer[BYTES[MobDefs.Mob]]]] ]]; {cvi: CARD ~ LOOPHOLE[mob.versionIdent]; SELECT cvi FROM CARD[MobDefs.VersionID] => RETURN [mob.version, NIL]; SwapHWords[MobDefs.VersionID] => RETURN [[SwapHWords[mob.version[0]], SwapHWords[mob.version[1]] ], NIL]; ENDCASE => RETURN[BadVersion, IO.PutFLR["%g of %g has unrecognized versionIdent (%08xH) [expected %08xH]", LIST[ [rope[fullName]], [time[created]], [cardinal[cvi]], [cardinal[MobDefs.VersionID]]] ]]; }; EXITS Abort => stamp ¬ BadVersion}; SwapHWords: PROC [c: CARD] RETURNS [CARD] ~ { n: Basics.LongNumber ~ LOOPHOLE[c]; sn: Basics.LongNumber ~ [pair[hi: n.lo, lo: n.hi]]; RETURN [sn.card]; }; hashMark: ROPE = Rope.Cat["@(", "#)mob", "_version ["]; --broken up to avoid spurrious one sourceStampByteLimit: INT ¬ 8000; headerBytes: INT = 4+4*7; -- size of header for .o files textSizeOffset: INT = 4; -- byte offset of text size field in .o files ReadCOStamp: PROC [fullName: ROPE, created: BasicTime.GMT, rejectServerInaccessible: BOOL] RETURNS [stamp: VersionStamp, whyNot: ROPE ¬ NIL] ~ { hashMarkSize: INT = Rope.Length[hashMark]; hashStartChar: CHAR = Rope.Fetch[hashMark, 0]; buf: REF TEXT = RefText.ObtainScratch[nChars: 512]; smallBuf: REF TEXT = NEW[TEXT[hashMarkSize]]; start: INT ¬ 0; end: INT ¬ sourceStampByteLimit; index: INT ¬ 0; baselen: INT; stream: IO.STREAM; cp: FS.ComponentPositions; base: ROPE; [fullName, cp, ] ¬ FS.ExpandName[fullName]; base ¬ fullName.Substr[start: cp.base.start, len: cp.base.length]; base ¬ base.Substr[len: baselen ¬ base.Index[s2: "."]]; {stream ¬ FS.StreamOpen[fileName: fullName, wantedCreatedTime: created !FS.Error => IF error.code#$serverInaccessible OR NOT rejectServerInaccessible THEN {whyNot ¬ IO.PutFLR["FS.Open[%g of %g] => Error[%g, %g]", LIST[ [rope[fullName]], [time[created]], [atom[error.code]], [rope[error.explanation]]] ]; GOTO NotOpen} ]; {ENABLE { IO.Error => {whyNot ¬ IO.PutFR["IO.Error while trying to find version stamp in %g of %g", [rope[fullName]], [time[created]] ]; GOTO Abort}; IO.EndOfStream => GOTO Alldun}; IF (NOT stream.EndOf[]) AND IO.PeekChar[self: stream].ORD < 2 THEN { ReadBinaryINT: PROC [stream: IO.STREAM] RETURNS [INT] ~ { ln: Basics.LongNumber ¬ [card[0]]; ln.hh ¬ IO.GetByte[stream]; ln.hl ¬ IO.GetByte[stream]; ln.lh ¬ IO.GetByte[stream]; ln.ll ¬ IO.GetByte[stream]; RETURN [ln.int] }; IO.SetIndex[self: stream, index: textSizeOffset]; start ¬ headerBytes + ReadBinaryINT[stream]; end ¬ start + ReadBinaryINT[stream]; IF NOT start IN [0..end) AND end <= IO.GetLength[stream] THEN { start ¬ 0; end ¬ IO.GetLength[stream]; }; }; IO.SetIndex[stream, start]; index ¬ start; WHILE index < end DO bytes: INT ¬ IO.GetBlock[self: stream, block: buf]; i: NAT ¬ 0; needSetIndex: BOOL ¬ FALSE; IsHashMark: PROC [pos: INT] RETURNS [BOOL] ~ { IF pos+hashMarkSize <= bytes THEN { FOR j: INT ¬ 1, j+1 WHILE j < hashMarkSize DO IF hashMark.Fetch[j] # buf[pos+j] THEN RETURN [FALSE]; ENDLOOP; IO.SetIndex[stream, index+pos+hashMarkSize]; needSetIndex ¬ TRUE; RETURN [TRUE]; } ELSE { IO.SetIndex[stream, index+pos]; needSetIndex ¬ TRUE; [] ¬ IO.GetBlock[self: stream, block: smallBuf]; RETURN [Rope.Equal[hashMark, RefText.TrustTextAsRope[smallBuf]]]; } }; IF bytes = 0 THEN EXIT; WHILE i < bytes DO IF buf[i]=hashStartChar AND IsHashMark[pos: i] THEN { moduleName: ROPE; newIndex: INT; vs: VersionStamp ¬ ALL[0]; vs[0] ¬ stream.GetCard[ !IO.Error => IF ec=SyntaxError OR ec=Overflow THEN GOTO NotReally]; IF stream.GetChar[] # ', THEN GOTO NotReally; vs[1] ¬ stream.GetCard[ !IO.Error => IF ec=SyntaxError OR ec=Overflow THEN GOTO NotReally]; IF stream.GetChar[] # '] THEN GOTO NotReally; IF stream.GetChar[] # ' THEN GOTO NotReally; moduleName ¬ IO.GetTokenRope[stream: stream, breakProc: StopOnQuoteOrNull].token; IF base.IsPrefix[moduleName, FALSE] AND (baselen = moduleName.Length[] OR moduleName.EqualSubstrs[start1: baselen, s2: ".config", case: FALSE]) THEN { RefText.ReleaseScratch[buf]; IO.Close[stream]; RETURN [vs]}; newIndex ¬ stream.GetIndex[]; IF newIndex > index + bytes THEN{ index ¬ newIndex; IO.SetIndex[stream, index]; GOTO GetNextBlock; }; i ¬ newIndex - index; EXITS NotReally => i ¬ i}; i ¬ i + 1; REPEAT GetNextBlock => LOOP; -- the enclosing WHILE -- ENDLOOP; index ¬ index + bytes; IF needSetIndex THEN IO.SetIndex[stream, index]; ENDLOOP; GOTO Alldun; EXITS Alldun => whyNot ¬ IO.PutFR["%g of %g has no version stamp", [rope[fullName]], [time[created]] ]; Abort => stamp ¬ BadVersion}; IO.Close[stream]; EXITS NotOpen => stamp ¬ BadVersion}; RefText.ReleaseScratch[buf]; RETURN [BadVersion, whyNot]}; StopOnQuoteOrNull: IO.BreakProc = { RETURN [IF char = '\000 OR char = '" THEN break ELSE other] }; ScanName: PROC [name: ROPE] RETURNS [pos,bang,dot: INT] = { len: INT = Rope.Length[name]; pos ¬ bang ¬ dot ¬ len; WHILE pos > 0 DO posM: INT = pos-1; SELECT Rope.Fetch[name, posM] FROM '! => bang ¬ dot ¬ posM; '. => dot ¬ posM; '>, '/, '] => RETURN; ENDCASE; pos ¬ posM; ENDLOOP; }; MapListLookup: PUBLIC PROC [mapList: MapList, fullName: ROPE, created: BasicTime.GMT, onlyOne, testCreated, testName: BOOL] RETURNS [found: BOOL ¬ FALSE, fromMap: ROPE ¬ NIL, version: VersionStamp ¬ NullVersion] = { IF onlyOne THEN { version ¬ CreatedToMimosaVersionStamp[created]; fromMap ¬ VersionMap.VersionToName[mapList, version].name; {len: INT ¬ fromMap.Length[]; bang: INT ¬ ScanName[fromMap].bang; SELECT Rope.Run[fromMap, 0, fullName, 0, FALSE] FROM =0, RETURN [FALSE]; ENDCASE => RETURN [TRUE, fromMap, version]; }} ELSE { short: ROPE = VersionMap.ShortName[fullName]; rangeList: VersionMap.RangeList ¬ VersionMap.ShortNameToRanges[mapList, short]; WHILE rangeList # NIL DO range: VersionMap.Range ¬ rangeList.first; rangeList ¬ rangeList.rest; WHILE range.len # 0 DO name: ROPE; stamp: VersionStamp; eCreated: BasicTime.GMT; [name, stamp, eCreated, range] ¬ VersionMap.RangeToEntry[range]; IF testCreated AND created#eCreated THEN LOOP; IF testName AND NOT Rope.Equal[fullName, name, FALSE] THEN LOOP; RETURN [TRUE, name, stamp]; ENDLOOP; ENDLOOP; found ¬ FALSE; }; RETURN}; END.  VersionMapClassifyImpl.mesa Copyright Σ 1990, 1992 by Xerox Corporation. All rights reserved. Willie-s, March 23, 1992 6:34 pm PST Spreitze, August 17, 1990 2:55 pm PDT T Y P E S Global variables Single file processing an object file. confusion! search whole file. [char: CHAR] RETURNS [IO.CharClass] Routines to use the old maps for verification of names At this point we did NOT get a match, so flake out! Κ Š–(cedarcode) style•NewlineDelimiter ˜codešœ™Kšœ Οeœ7™BK™$K™%—K˜šΟk ˜ K˜Kšœ žœžœ ˜ K˜ Kšžœ˜Kšžœ˜K˜K˜Kšœ˜Kšœ ˜ K˜K˜—šΟnœžœž˜%Kšžœžœžœ˜?Kšžœ˜Kšœž˜K˜—šœ ™ K˜Kšžœžœ žœ˜Kšœžœ˜Kšœ žœ˜#Kšžœžœžœ˜Kš œ žœžœžœžœ˜Kšžœžœžœžœ˜šœžœ˜-KšŸ œ0˜;KšŸ œ/˜9—˜K˜——šœ™š Ÿœžœžœžœžœ˜=KšœB˜B—K˜—™K™š Ÿœžœžœžœžœ$˜NKšœžœ&˜>Kšœžœ˜K˜Bšžœžœž˜K˜0K˜$šœ˜Kšžœžœžœ˜7—Kšžœ˜—K˜—š Ÿœžœžœžœžœ˜\Kšžœ%˜+K˜—šŸœžœžœ+žœžœžœžœ(žœ˜ΎKšœ žœ˜'Kšœ žœ!˜.šžœž˜Kšœžœ(žœžœ˜Kšœžœžœž˜ Kšœ žœ;˜ašœ#˜#K˜KKšœ žœžœ˜—Kšžœžœ(žœžœ˜C—šœ˜K˜Kš žœžœžœžœ žœ˜;K˜-KšœBžœ˜F—Kšžœ žœ˜Kšžœ˜—Kšžœžœ˜—K˜K˜—šŸ œžœ žœžœžœžœ(žœžœ˜šKšœžœžœ˜K˜Kšœžœ˜ Kšœžœ<žœ žœ žœžœžœ žœ.žœWžœ ˜»Kšžœ%žœžœ˜YK˜ Kšžœ žœžœžœžœ9žœ@žœ˜ΟKšœžœžœ˜(šžœž˜Kšžœžœžœ˜5Kšœ!žœ=žœ˜iKšžœžœ žœKžœX˜Η—Kšœ˜Kšžœ˜#K˜—š Ÿ œžœžœžœžœ˜-Kšœžœ˜#K˜3Kšžœ ˜K˜K˜—Kšœ žœ*Οc"˜ZKšœžœ˜!Kšœ žœ  ˜8Kšœžœ -˜FK˜šŸ œžœ žœžœžœžœžœžœ˜Kšœžœ˜*Kšœžœ˜.K•StartOfExpansion[nChars: NAT]šœžœžœ&˜3Kš œ žœžœžœžœ˜-Kšœžœ˜Kšœžœ˜ K–[self: STREAM]šœžœ˜Kšœ žœ˜ Kšœžœžœ˜Kšœžœ˜Kšœžœ˜ Kšœžœ˜+K˜BK˜7Kšœ žœ<žœ žœ žœžœžœ žœ.žœWžœ ˜ΐšœžœ˜ Kšžœžœgžœ˜‹Kšžœžœ ˜—š žœžœžœžœžœžœ˜DK™š Ÿ œžœ žœžœžœžœ˜9K˜"Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšžœ ˜K˜—Kšžœ/˜1K˜,K˜$š žœžœžœ žœžœžœ˜?K™K˜ Kšœžœ˜Kšœ˜—Kšœ˜—Kšžœ˜K˜šžœ ž˜K–P[self: STREAM, block: REF TEXT, startIndex: NAT _ 0, count: NAT _ 32767]šœžœžœ$˜3Kšœžœ˜ Kšœžœžœ˜š Ÿ œžœžœžœžœ˜.šžœ˜šžœ˜šžœžœ žœž˜-Kšžœ žœžœžœ˜6Kšžœ˜—Kšžœ*˜,Kšœžœ˜Kšžœžœ˜Kšœ˜—šžœ˜Kšžœ˜K–P[self: STREAM, block: REF TEXT, startIndex: NAT _ 0, count: NAT _ 32767]šœžœ˜Kšœžœ)˜0Kšžœ;˜AK˜——K˜—Kšžœ žœžœ˜šžœ ž˜šžœžœžœ˜5Kšœ žœ˜Kšœ žœ˜Kšœžœ˜Kš œžœ žœžœ žœžœ ˜[Kšžœžœžœ ˜-Kš œžœ žœžœ žœžœ ˜[Kšžœžœžœ ˜-Kšžœžœžœ ˜-Kšœ žœB˜Qš žœžœžœ žœ?žœžœ˜–Kšœ˜Kšžœ˜Kšžœ˜ —K˜šžœžœ˜!K˜Kšžœ˜Kšžœ˜Kšœ˜—K˜Kšžœ˜—K˜ šž˜Kšœžœ ˜/—Kšžœ˜—K˜Kšžœžœžœ˜0Kšžœ˜—Kšžœ˜ šž˜KšœžœL˜aK˜—Kšžœ˜Kšžœ ˜%Kšœ˜Kšžœ˜K˜—–' -- [char: CHAR] RETURNS [IO.CharClass]šŸœžœ˜#Kšœžœžœžœ ™#Kš žœžœžœ žœžœ˜;K˜K˜—š Ÿœžœžœžœžœ˜;Kšœžœ˜K˜šžœ ž˜Kšœžœ ˜šžœž˜"K˜K˜Kšœžœ˜Kšžœ˜—K˜ Kšžœ˜—K˜K˜—K˜—šœ6™6K˜—šŸ œžœžœžœžœ"žœžœ žœžœ žœžœ*˜Χšžœ žœ˜K˜/K˜:Kšœžœ˜Kšœžœ˜#šžœ#žœž˜4Kšœ žœžœ˜Kšžœžœžœ˜+—K˜—šžœ˜Kšœžœ"˜-˜!Kšœ-˜-—šžœ žœž˜K˜*K˜šžœž˜Kšœžœ˜ K˜Kšœžœ˜K˜@Kšžœ žœžœžœ˜.Kš žœ žœžœžœžœžœ˜@Kšžœžœ˜Kšžœ˜—Kšžœ˜—Kšœ3™3Kšœžœ˜K˜—Kšžœ˜K˜—K˜Kšžœ˜—…—#ξ2