DIRECTORY Atom, BasicTime, Buttons, Commander, CommandTool, FS, IO, IOClasses, List, Process, Rope, TapeToolInternal, TIPUser, ViewerClasses; MebesDirectory: CEDAR PROGRAM IMPORTS Atom, BasicTime, Commander, CommandTool, FS, IO, IOClasses, List, Process, Rope = BEGIN RunID: Rope.ROPE; log: IO.STREAM; favoriteDirectory: Rope.ROPE _ "/Cherry/MPChip/"; directoryPrefix: Rope.ROPE; Letter: PROCEDURE [c: CHARACTER] RETURNS [BOOLEAN] = BEGIN RETURN[c IN ['A..'Z]]; END; Digit: PROCEDURE [c: CHARACTER] RETURNS [BOOLEAN] = BEGIN RETURN[c IN ['0..'9]]; END; AlphaNum: PROCEDURE [c: CHARACTER] RETURNS [BOOLEAN] = BEGIN RETURN[Digit[c] OR Letter[c]]; END; IsRun: PROC [ rope: Rope.ROPE ] RETURNS [ BOOL ] = {RETURN[(rope.Length = 3) AND Digit[rope.Fetch[0]] AND AlphaNum[rope.Fetch[1]] AND Letter[rope.Fetch[2]]]}; IsLayer: PROC [ rope: Rope.ROPE ] RETURNS [ BOOL ] = {RETURN[(rope.Length = 5) AND Digit[rope.Fetch[0]] AND Digit[rope.Fetch[1]] AND (rope.Fetch[2] = '-) AND Letter[rope.Fetch[3]] AND AlphaNum[rope.Fetch[4]]]}; IsDie: PROC [ rope: Rope.ROPE ] RETURNS [ BOOL ] = {RETURN[(rope.Length = 1) AND Letter[rope.Fetch[0]]]}; Abort: PROCEDURE [name: Rope.ROPE] = BEGIN log.PutF["... %g", IO.rope[name]]; ERROR ABORTED; END; FileServerName: PROCEDURE [die, layer: Rope.ROPE] RETURNS [ Rope.ROPE ] = BEGIN RETURN[IO.PutFR["%gMPC%g%g%g.mebes", IO.rope[directoryPrefix], IO.rope[RunID], IO.rope[die], IO.rope[IF layer.Length = 0 THEN "" ELSE Rope.Cat["-", layer]]]]; END; LocalName: PROCEDURE [die, layer: Rope.ROPE] RETURNS [ Rope.ROPE ] = BEGIN RETURN[IO.PutFR["MPC%g%g%g.mebes", IO.rope[RunID], IO.rope[die], IO.rope[IF layer.Length = 0 THEN "" ELSE Rope.Cat["-", layer]]]]; END; TapeHeaderName: PROCEDURE [die, layer: Rope.ROPE] RETURNS [ Rope.ROPE ] = BEGIN RETURN[IO.PutFR["MPC%g%g%g.%g ", IO.rope[RunID], IO.rope[die], IO.rope[layer.Substr[len: 2]], IO.rope[layer.Substr[start: 3]]]]; -- hyphen in layer becomes period END; Compare: PROC [ from, to: IO.STREAM, closeFrom, closeTo: BOOL _ TRUE ] RETURNS [ different: BOOL ] = BEGIN DO IF from.GetChar[ ! IO.EndOfStream => GOTO CheckToLength ] # to.GetChar[ ! IO.EndOfStream => GOTO FoundDifference ] THEN GOTO FoundDifference; REPEAT CheckToLength => different _ NOT to.EndOf[]; FoundDifference => different _ TRUE; ENDLOOP; IF closeTo THEN to.Close[]; IF closeFrom THEN from.Close[]; END; CopyToServer: PROC [localName, serverName: Rope.ROPE _ NIL, fromStream: IO.STREAM _ NIL] = BEGIN serverPresent: BOOL _ FALSE; localPresent: BOOL _ FALSE; serverCreated, localCreated: BasicTime.GMT; IF serverName # NIL THEN BEGIN serverPresent _ TRUE; serverCreated _ FS.FileInfo[serverName ! FS.Error => IF error.code = $unknownFile THEN {serverPresent _ FALSE; CONTINUE} ELSE REJECT ].created; END; IF localName # NIL THEN BEGIN localPresent _ TRUE; localCreated _ FS.FileInfo[localName ! FS.Error => IF error.code = $unknownFile THEN {localPresent _ FALSE; CONTINUE} ELSE REJECT ].created; END; IF fromStream # NIL THEN BEGIN different: BOOL _ TRUE; fromStream.SetIndex[0]; IF localPresent THEN BEGIN different _ Compare[to: FS.StreamOpen[localName], from: fromStream, closeFrom: FALSE]; fromStream.SetIndex[0]; END; IF different THEN BEGIN log.PutF["... creating local file %g", IO.rope[localName]]; IOClasses.Copy[from: fromStream, to: FS.StreamOpen[localName, $create], closeFrom: FALSE]; localPresent _ TRUE; localCreated _ FS.FileInfo[localName].created; END; END; SELECT TRUE FROM localPresent AND serverName # NIL AND (NOT serverPresent OR BasicTime.Period[from: serverCreated, to: localCreated]>0) => BEGIN log.PutF["... copying local file to %g", IO.rope[serverName]]; [] _ FS.Copy[ from: localName, to: serverName, wantedCreatedTime: localCreated ! FS.Error => {log.PutF[" ... copy failed because %g", IO.rope[error.explanation]]; GOTO Abort} ]; END; ENDCASE => NULL; EXITS Abort => ERROR ABORTED; END; DoMebesDirectory: PROC [cmd: Commander.Handle] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] -- Commander.CommandProc -- = BEGIN MPCTokenProc: PROC [char: CHAR] RETURNS [IO.CharClass] -- IO.BreakProc -- = {RETURN[SELECT char FROM IN [IO.NUL .. IO.SP], ',, ':, '; => sepr, '[, '], '(, '), '{, '}, '", '+, '*, '/, '@, '_ => break, '- => other, ENDCASE => other]}; mebesTapeHeaderFile, filesToTape: IO.STREAM; tech: Rope.ROPE; dice: LIST OF Rope.ROPE _ NIL; layers: LIST OF Rope.ROPE _ NIL; now: BasicTime.Unpacked = BasicTime.Unpack[BasicTime.Now[]]; r: REF ANY; tapeTool: TapeToolInternal.TapeTool _ NIL; args: CommandTool.ArgumentVector = CommandTool.Parse[cmd]; updateServer: BOOL _ FALSE; makeTape: BOOL _ FALSE; log _ cmd.out; BEGIN ENABLE ABORTED => GOTO Punt; log.PutRope["\nMebesDirectory 6.0 --- July 31, 1985 ..."]; RunID _ NIL; IF args.argc<2 THEN BEGIN log.PutRope[cmd.procData.doc]; RETURN; END; FOR i: NAT IN [1..args.argc) DO SELECT TRUE FROM args[i].Equal["-updateServer", FALSE] => updateServer _ TRUE; args[i].Equal["-makeTape", FALSE] => makeTape _ TRUE; RunID = NIL AND IsRun[args[i]] => RunID _ args[i]; IsDie[args[i]] => dice _ CONS[args[i], dice]; IsLayer[args[i]] => layers _ CONS[args[i], layers]; ENDCASE => {log.PutF["... illegal argument \"%g\"...aborted", IO.rope[args[i]]]; RETURN}; ENDLOOP; IF RunID = NIL THEN {log.PutRope["... no run id (e.g. 49A) ... aborted"]; RETURN}; directoryPrefix _ Rope.Cat[favoriteDirectory, RunID, "/"]; IF dice = NIL THEN BEGIN otherInput: IO.STREAM = FS.StreamOpen[IO.PutFR["%gDice.cm", IO.rope[directoryPrefix]]]; DO t: Rope.ROPE = otherInput.GetTokenRope[MPCTokenProc ! IO.EndOfStream => EXIT].token; IF NOT IsDie[t] THEN Abort[IO.PutFR["\"%g\" is improper die code, should be single capital letter", IO.rope[t]]]; dice _ CONS[t, dice]; ENDLOOP; otherInput.Close[]; END; TRUSTED {dice _ LOOPHOLE[List.Reverse[LOOPHOLE[dice]]]}; IF layers = NIL THEN BEGIN otherInput: IO.STREAM _ FS.StreamOpen[IO.PutFR["%gTech.cm", IO.rope[directoryPrefix]]]; tech _ otherInput.GetTokenRope[MPCTokenProc].token; otherInput.Close[]; otherInput _ FS.StreamOpen[IO.PutFR["%gTechnology/%g-TapeLayers.cm", IO.rope[favoriteDirectory], IO.rope[tech]]]; DO t: Rope.ROPE = otherInput.GetTokenRope[MPCTokenProc ! IO.EndOfStream => EXIT].token; IF NOT IsLayer[t] THEN Abort[IO.PutFR["\"%g\" is improper Mebes layer code, should be of form DD-AA", IO.rope[t]]]; layers _ CONS[t, layers]; ENDLOOP; otherInput.Close[]; END; TRUSTED {layers _ LOOPHOLE[List.Reverse[LOOPHOLE[layers]]]}; mebesTapeHeaderFile _ IO.ROS[]; mebesTapeHeaderFile.PutRope["\000\002\000"]; -- 2 is Cedar version, was 1 before TRUSTED {nFiles: [0..99] _ List.Length[LOOPHOLE[dice]]*List.Length[LOOPHOLE[layers]]; mebesTapeHeaderFile.PutChar[LOOPHOLE[nFiles]] }; FOR i: LIST OF Rope.ROPE _ dice, i.rest WHILE i#NIL DO FOR j: LIST OF Rope.ROPE _ layers, j.rest WHILE j#NIL DO mebesTapeHeaderFile.PutRope[TapeHeaderName[i.first, j.first]]; ENDLOOP; ENDLOOP; mebesTapeHeaderFile.PutF["%02d%02d%02d\011", IO.int[LOOPHOLE[now.month, CARDINAL] + 1], IO.int[now.day], IO.int[now.year MOD 100]]; FOR Bytecount: INT IN [mebesTapeHeaderFile.GetIndex..2048) DO TRUSTED {mebesTapeHeaderFile.PutChar[LOOPHOLE[0, CHAR]]}; ENDLOOP; CopyToServer[localName: IO.PutFR["MPC%g.mebes", IO.rope[RunID]], fromStream: IO.RIS[IO.RopeFromROS[mebesTapeHeaderFile]]]; filesToTape _ IO.ROS[]; filesToTape.PutRope[FileServerName["", ""]]; -- of the header file FOR i: LIST OF Rope.ROPE _ dice, i.rest WHILE i#NIL DO FOR j: LIST OF Rope.ROPE _ layers, j.rest WHILE j#NIL DO filesToTape.PutF[" %g", IO.rope[FileServerName[i.first, j.first]]]; ENDLOOP; ENDLOOP; CopyToServer[localName: IO.PutFR["MPC%g.cedarTape", IO.rope[RunID]], fromStream: IO.RIS[IO.RopeFromROS[filesToTape]]]; IF updateServer THEN BEGIN CopyToServer[ localName: IO.PutFR["MPC%g.cedarTape", IO.rope[RunID]], serverName: IO.PutFR["%g/MPC%g.cedarTape", IO.rope[directoryPrefix], IO.rope[RunID]]]; CopyToServer[ localName: IO.PutFR["MPC%g.mebes", IO.rope[RunID]], serverName: FileServerName["", ""]]; FOR i: LIST OF Rope.ROPE _ dice, i.rest WHILE i#NIL DO FOR j: LIST OF Rope.ROPE _ layers, j.rest WHILE j#NIL DO CopyToServer[localName: LocalName[i.first, j.first], serverName: FileServerName[i.first, j.first]]; ENDLOOP; ENDLOOP; END; IF makeTape AND (r _ Atom.GetProp[$TapeTool, $state]) # NIL AND (tapeTool _ NARROW[r]).open THEN BEGIN SetRope: PROC [ textViewer: ViewerClasses.Viewer, text: Rope.ROPE ] = BEGIN textViewer.class.set[textViewer, text, TRUE]; Process.Pause[Process.MsecToTicks[500]]; END; PushButton: PROC [button: Buttons.Button] = BEGIN button.class.notify[button, LIST[ NEW[TIPUser.TIPScreenCoordsRec _ [mouseX: 1, mouseY: 1, color: button.column = color]], $Mark, $Hit ]]; END; fileNames: IO.STREAM = IO.ROS[]; log.PutRope[".... generating tape"]; SetRope[tapeTool.blockingViewer, "2048"]; PushButton[tapeTool.RewindButton]; IOClasses.Copy[from: FS.StreamOpen[IO.PutFR["%gMPC%g.cedarTape", IO.rope[directoryPrefix], IO.rope[RunID]]], to: fileNames, closeTo: FALSE]; SetRope[tapeTool.fileNameViewer, IO.RopeFromROS[fileNames]]; PushButton[tapeTool.WriteButton]; Process.Pause[Process.SecondsToTicks[1]]; WHILE tapeTool.active DO Process.Pause[Process.SecondsToTicks[1]] ENDLOOP; log.PutRope[".... done (you can unload tape now)"]; END ELSE log.PutRope[".... tape not generated... done"]; EXITS Punt => log.PutF[" ... aborted"]; END; END; Commander.Register["MebesDirectory", DoMebesDirectory, "\n.. makes a list of Mebes files, creates a Mebes tape label file, can write Mebes files to a file server, and can (with a cooperating TapeTool) write a Mebes tape. The format is\n\nMebesDirectory [-UpdateServer] [-MakeTape] [Die*] [Layer*] RunID\n\n where the items in [] are optional, and [x*] means any number of x's separated by spaces. Die takes the form of a single capital letter, Layer takes the form DD-AA (e.g., 20-PO), and RunId takes a form like 49A or 8BB. If any Die or Layer appears explicitly, the list in the command line overrides the MPC defaults.\n"]; END.-- of MebesDirectory ØMebesDirectory.mesa Permute input text into MebesDirectory file, and command file Created by Alan Paeth, PARC, August 2, 1982 Last Edited by: McCreight, July 31, 1985 6:15:26 pm PDT variables procedures/code open typescript, look for a command line, herald Create the Mebes tape header file ... pad 2048-byte block with 0's Make a list of files to be transferred to the tape Copy relevant local files to the server... Copy files from the server to the tape... ʘJšœ™Jšœ>™>Jšœ+™+Jšœ7™7J˜šÏk ˜ Jšœ2œœK˜ƒJ˜—šœœ˜Jšœ*œœ#˜ZJš˜J˜Jšœ ™ J˜Jšœ œ˜Jšœœœ˜Jšœœ˜1Jšœœ˜J™Jšœ™J˜š Ïnœ œ œœœ˜4Jšœœœ œ˜!J˜—š žœ œ œœœ˜3Jšœœœ œ˜!J˜—š žœ œ œœœ˜6Jšœœ œ œ˜)J˜—š žœœœœœ˜2šœœœœ˜NJšœ˜—J˜—š žœœœœœ˜4šœœœœ˜KJšœœ˜2Jšœ˜—J˜—š žœœœœœ˜2Jšœœœ˜6J˜—šžœ œ œ˜$Jš˜Jšœœ ˜"Jšœœ˜Jšœ˜J˜—š žœ œœœœ˜IJš˜Jšœœœœœ œœœœ˜žJšœ˜J˜—š ž œ œœœœ˜DJš˜Jšœœœœ œœœœ˜‚Jšœ˜J˜—š žœ œœœœ˜IJš˜Jš œœœœ œœ"Ïc!˜¦Jšœ˜J˜—šžœœ œœœœœœ˜dJš˜š˜Jšœœœ!œœœœ˜š˜Jšœœ ˜,Jšœœ˜$—Jšœ˜—Jšœ œ ˜Jšœ œ˜Jšœ˜J˜J˜—šž œœœœœœœ˜ZJš˜J˜Jšœœœ˜Jšœœœ˜Jšœ'œ˜+J˜šœœ˜Jš˜Jšœœ˜šœœ˜&šœœ ˜ Jš œœœœœ˜O—Jšœ ˜ —Jšœ˜J˜—šœ œ˜Jš˜Jšœœ˜šœœ˜$šœœ ˜ Jš œœœœœ˜N—Jšœ ˜ —Jšœ˜J˜—šœœ˜Jš˜Jšœ œœ˜Jšœ˜J˜šœ˜Jš˜Jšœœ5œ˜VJšœ˜Jšœ˜J˜—šœ ˜Jš˜Jšœ'œ˜;Jšœ%œ,œ˜ZJšœœ˜Jšœœ˜.Jšœ˜—Jšœ˜J˜—šœœ˜š œ œœœœœ>˜yJš˜Jšœ)œ˜>šœœ˜ Jšœ˜Jšœ˜Jšœ˜šœœ ˜ Jšœ)œœ˜Q—Jšœ˜—Jšœ˜—Jšœœ˜—š˜Jšœ œœ˜—Jšœ˜J˜J˜—šžœœœ œœ œœŸœ˜Jš˜J˜š ž œœœœœ Ÿœ˜Kšœœœ˜Jš œœœœœ˜*Jšœ8˜8Jšœ ˜ Jšœ ˜—J™—Jšœ"œœ˜,Jšœ œ˜Jš œœœœœ˜Jš œœœœœ˜ Jšœ<˜Jšœ˜—Jšœ˜—šœ,˜,Jšœœ œ˜*Jšœ˜Jšœœ˜—J™šœ œœ&˜=Jšœœœ˜9Jšœ˜—Jš œœœœœœ$˜zJ˜J˜Jšœ2™2J˜Jšœœœ˜Jšœ-Ÿ˜Bš œœœœœœ˜6š œœœœœœ˜8Jšœœ)˜CJšœ˜—Jšœ˜—Jš œœœœœœ˜vJ˜J˜Jšœ*™*J˜šœ˜Jš˜šœ ˜ Jšœ œœ˜7Jšœ œœœ˜V—šœ ˜ Jšœ œœ˜3Jšœ$˜$—š œœœœœœ˜6š œœœœœœ˜8J˜cJšœ˜—Jšœ˜—šœ˜J˜J˜——Jšœ)™)J™š œ œ)œœ œ ˜`Jš˜J˜šžœœ0œ˜EJš˜Jšœ'œ˜-Jšœ(˜(Jšœ˜J˜—šž œœ˜+Jš˜Jšœœœd˜‰Jšœ˜J˜—Jš œ œœœœ˜ Jšœ$˜$Jšœ)˜)Jšœ"˜"š œœ œœœ˜lJšœœ˜—Jšœ!œ˜