<<>> <> <> <> <> <> <<>> <> <> <<>> DIRECTORY Args USING [ Arg, ArgRope, Error, GetRope, NArgs ], Ascii, BasicTime USING [ GMT ], Commander USING [ CommandProc, Register ], CommandTool USING [ CurrentWorkingDirectory ], Convert, ExtendADotOut USING [ ActionID, ActionIDFromAction, DependencyInfo, DependencyInfoRep, ObjectClassFromFileName, ObjectIDFromFile, ObjectID, PutDependencyInfo, StampFromIDs, VersionStamp ], FS USING [ ComponentPositions, Delete, Error, ExpandName, Rename, StreamOpen ], IO USING [ card, Close, Flush, GetRope, int, PutF, PutFR, PutRope, rope, STREAM ], PBasics USING [LowHalf, LowByte, HighByte, BITAND, endianBitsInBytes], PFS, PFSNames, PFSPrefixMap, Process USING [ CheckForAbort, EnableAborts, InitializeCondition, SecondsToTicks ], Rope USING [ Cat, Concat, Equal, Fetch, FindBackward, Flatten, Length, ROPE, Substr, Translate], SymTab, SystemVersion USING [machineType, MachineType], ThisMachine USING [ ProcessorID ], UnixErrno, UnixStat, UnixSysCalls USING [ GetPID, SymLink, Unlink ], UnixSysCallExtensions USING [Spawn], UnixTypes USING [CHARPtr, SysCallResult], UserProfile USING [Token], UXStrings; CcCommandsImpl: CEDAR MONITOR IMPORTS Args, Ascii, Commander, CommandTool, Convert, ExtendADotOut, FS, IO, PBasics, PFS, PFSNames, PFSPrefixMap, Process, Rope, SymTab, SystemVersion, ThisMachine, UnixErrno, UnixSysCalls, UnixSysCallExtensions, UserProfile, UXStrings ~ { ROPE: TYPE ~ Rope.ROPE; LOR: TYPE ~ LIST OF ROPE; ShouldNotHappen: ERROR [message: ROPE] ~ CODE; ForkTrouble: ERROR ~ CODE; NYI: ERROR ~ CODE; DeleteFiles: BOOL ~ TRUE; <> <> amd29000: SystemVersion.MachineType ~ LOOPHOLE[20, SystemVersion.MachineType]; <> <> <> <> <> <> <> uid: CARD32 ¬ 0; processID: INT ~ UnixSysCalls.GetPID[]; processorID: ROPE ~ ThisMachine.ProcessorID[$Octal]; CshCommandString: UXStrings.UnixString ~ UXStrings.Create[from: "/bin/csh -s"]; MACHINECLASS: ROPE ~ "ComplexCc.MachineClass"; NewName: ENTRY PROC [suffix: ROPE ¬ ".o", wDir: ROPE] RETURNS [ fName: ROPE ] ~ { ENABLE { UNWIND => NULL }; fName ¬ IO.PutFR["cedarCc%gFrom%g%g", IO.card[uid], IO.int[processID], IO.rope[processorID], IO.rope[suffix]]; IF NOT Rope.Equal[wDir, NIL] THEN { IF wDir.Fetch[wDir.Length[]-1] # '/ THEN wDir ¬ wDir.Cat["/"]; fName ¬ wDir.Cat[fName]; }; uid ¬ uid.SUCC; }; <> ViewFix: PROC [cedar, insert: ROPE, isDir, simpleExt, create: BOOL, otherUnlink: LOR] RETURNS [unix: ROPE ¬ NIL, unlink: LOR ¬ NIL] ~ { ENABLE PFS.Error => ERROR ShouldNotHappen[IO.PutFR["Got PFS.Error[%g, %g] while UXifying %g", [atom[error.code]], [rope[error.explanation]], [rope[cedar]] ]]; given: PFS.PATH ~ PFS.PathFromRope[cedar]; translated: PFS.PATH ~ PFSPrefixMap.Translate[ PFS.AbsoluteName[given]]; cedarPath: PFS.PATH ~ IF isDir THEN PFSNames.EnsureDirectory[translated] ELSE translated; --EnsureDirectory only required because Translate bogusly drops that bit (MJS March 13, 1990) rawRope: ROPE ~ PFS.RopeFromPath[cedarPath].Flatten[]; --for debugging viewComp: PFSNames.Component ~ cedarPath.Fetch[0]; view: ROPE ~ viewComp.ComponentRope[]; IF isDir # given.IsADirectory[] THEN ERROR ShouldNotHappen[IO.PutFR[IF isDir THEN "%g not a directory" ELSE "%g is a directory", [rope[cedar]] ]]; IF isDir AND (insert#NIL OR create OR simpleExt) THEN ERROR--not implemented because not needed--; SELECT TRUE FROM view.Equal["-ux", FALSE] => { viewless: PFS.PATH ~ cedarPath.ReplaceComponent[0, emptyComponent]; parent: PFS.PATH ~ viewless.Parent[]; parentRope: ROPE ~ PFS.RopeFromPath[parent]; last: PFSNames.Component ~ viewless.ShortName[]; lastRope: ROPE ~ last.ComponentRope[--PFS doesn't put in version info--]; original: ROPE ~ parentRope.Concat[lastRope]; IF insert#NIL THEN { new: ROPE ~ parentRope.Cat[insert, lastRope]; GetLink[original, new]; RETURN [new, CONS[new, otherUnlink]]}; RETURN [original, otherUnlink]}; view.Equal["-vux", FALSE] => { full, parent: PFS.PATH; fullLast: PFSNames.Component; fullRope, parentRope, verfulLast, verlessLast, vuxrepRope, uxishRope: ROPE; IF create THEN { out: IO.STREAM ~ PFS.StreamOpen[fileName: cedarPath, accessOptions: create]; file: PFS.OpenFile ~ PFS.OpenFileFromStream[out]; modeProp: ROPE; dm: UnixStat.Mode; full ¬ PFS.GetInfo[file].fullFName; modeProp ¬ PFS.GetClientProperty[file, "UnixMode"]; dm ¬ LOOPHOLE[Convert.CardFromRope[modeProp]]; dm.owner.write ¬ true; PFS.SetClientProperty[file, "UnixMode", Convert.RopeFromCard[LOOPHOLE[dm, CARD16], 8]]; out.Close[]} ELSE IF isDir THEN { full ¬ cedarPath.ReplaceComponent[0, emptyComponent]; unix ¬ PFS.RopeFromPath[full].Translate[translator: Lower]; RETURN [unix, otherUnlink]} ELSE full ¬ PFS.FileInfo[cedarPath].fullFName; fullRope ¬ PFS.RopeFromPath[full].Flatten[]; --for debugging fullLast ¬ full.ShortName[]; parent ¬ full.Parent[].ReplaceComponent[0, emptyComponent]; parentRope ¬ PFS.RopeFromPath[parent].Translate[translator: Lower]; IF NOT parent.IsADirectory[] THEN ERROR ShouldNotHappen["PFS shouldn't be crocky!"]; IF fullLast.version.versionKind # numeric THEN ERROR ShouldNotHappen[ IO.PutFR["Didn't expect to find %g in file system (note version!)", [rope[PFS.RopeFromPath[full]]] ]]; verlessLast ¬ fullLast.ComponentRope[--PFS doesn't put in version info--]; verfulLast ¬ IO.PutFR["%g.~%g~", [rope[verlessLast.Translate[translator: Lower]]], [integer[fullLast.version.version]]]; vuxrepRope ¬ parentRope.Cat[verfulLast]; IF simpleExt OR insert#NIL THEN { uxishRope ¬ parentRope.Cat[insert, verlessLast]; GetLink[vuxrepRope, uxishRope]; RETURN [uxishRope, CONS[uxishRope, otherUnlink]]} ELSE RETURN [vuxrepRope, otherUnlink]; }; ENDCASE => ERROR ShouldNotHappen[ IO.PutFR["Can't apply UNIX tools to %g because of its view", IO.rope[PFS.RopeFromPath[cedarPath]] ]]; }; emptyComponent: PFSNames.Component ~ []; Lower: PROC [old: CHAR] RETURNS [CHAR] ~ {RETURN Ascii.Lower[old]}; LinkData: TYPE ~ REF LinkDataRec; LinkDataRec: TYPE ~ RECORD [ from: ROPE, count: NAT, toCP: UnixTypes.CHARPtr ¬ [], change: CONDITION]; GetLink: ENTRY PROC [from, to: ROPE] ~ { ENABLE UNWIND => NULL; ld: LinkData ¬ NARROW[linkTab.Fetch[to].val]; IF ld=NIL THEN { ld ¬ NEW [LinkDataRec ¬ [NIL, 0]]; TRUSTED { Process.InitializeCondition[@ld.change, Process.SecondsToTicks[10]]; Process.EnableAborts[@ld.change]}; IF NOT linkTab.Insert[to, ld] THEN ERROR}; DO SELECT TRUE FROM ld.count=0 => { fromCP: UnixTypes.CHARPtr ~ UXStrings.Create[from]; toCP: UnixTypes.CHARPtr ¬ ld.toCP ¬ UXStrings.Create[to]; res: UnixTypes.SysCallResult ¬ UnixSysCalls.SymLink[fromCP, toCP]; IF res=failure THEN RETURN WITH ERROR ShouldNotHappen[ IO.PutFR["Link from %g to %g failed; errno is %g", IO.rope[from], IO.rope[to], IO.card[LOOPHOLE[UnixErrno.GetErrno[], CARD]]]]; ld.count ¬ ld.count.SUCC; ld.from ¬ ld.from; RETURN}; ld.from.Equal[from] => {ld.count ¬ ld.count.SUCC; RETURN}; ENDCASE => WAIT ld.change ENDLOOP; }; linkTab: SymTab.Ref ~ SymTab.Create[case: TRUE]; DropLink: ENTRY PROC [to: ROPE] ~ { ENABLE UNWIND => NULL; ld: LinkData ¬ NARROW[linkTab.Fetch[to].val]; IF ld=NIL OR ld.count=0 THEN RETURN WITH ERROR ShouldNotHappen[IO.PutFR["Excess dropping of link to %g", [rope[to]] ]]; ld.count ¬ ld.count.PRED; BROADCAST ld.change; IF ld.count=0 THEN { res: UnixTypes.SysCallResult ~ UnixSysCalls.Unlink[ld.toCP]; IF NOT linkTab.Delete[to] THEN ERROR; IF res = failure THEN RETURN WITH ERROR ShouldNotHappen[ IO.PutFR["Unlink failed for %g; errno is %g", IO.rope[to], IO.card[LOOPHOLE[UnixErrno.GetErrno[], CARD]]]]; }; RETURN}; UnlinkList: PROC [list: LOR] ~ { FOR list ¬ list, list.rest WHILE list#NIL DO DropLink[list.first]; ENDLOOP; RETURN}; ConsComponent: PROC [name: ROPE, version: PFSNames.Version] RETURNS [PFSNames.Component] ~ { RETURN [[name: [base: name, start: 0, len: name.Length[]], version: version]]}; <> MachineTypeFromMachineClass: PROC [ machineClass: ROPE ] RETURNS [ machineType: SystemVersion.MachineType ] ~ { SELECT TRUE FROM Rope.Equal[machineClass, "sparc", FALSE] => machineType ¬ sun4; Rope.Equal[machineClass, "mc68020", FALSE] => machineType ¬ sun3; Rope.Equal[machineClass, "sun4", FALSE] => machineType ¬ sun4; Rope.Equal[machineClass, "sun3", FALSE] => machineType ¬ sun3; Rope.Equal[machineClass, "amd29000", FALSE] => machineType ¬ amd29000; ENDCASE => ERROR; }; MachineClassFromMachineType: PROC [ machineType: SystemVersion.MachineType ] RETURNS [ machineClass: ROPE ] ~ { SELECT machineType FROM sun4 => machineClass ¬ "sun4"; sun3 => machineClass ¬ "sun3"; amd29000 => machineClass ¬ "amd29000"; ENDCASE => machineClass ¬ "I don't know"; }; GetCommandNames: PROC [host, target: SystemVersion.MachineType] RETURNS [compiler, loader, move, csh: ROPE ¬ NIL] ~ { CompilerDefault: ROPE ~ "/usr/local/bin/ccc"; MoveDefault: ROPE ~ "/bin/mv"; LoadDefault: ROPE ~ "/bin/ld"; CshDefault: ROPE ~ "/bin/csh -s"; targetName: ROPE ~ MachineClassFromMachineType[ target ]; IF host # sun4 THEN ERROR ShouldNotHappen ["host is not a sun4"]; compiler ¬ UserProfile.Token["ComplexCc.cc", CompilerDefault]; loader ¬ UserProfile.Token["ComplexCc.ld", LoadDefault]; move ¬ UserProfile.Token["ComplexCc.mv", MoveDefault]; csh ¬ UserProfile.Token["ComplexCc.csh", CshDefault]; compiler ¬ UserProfile.Token[Rope.Cat["ComplexCc.", targetName, ".cc"], compiler]; loader ¬ UserProfile.Token[Rope.Cat["ComplexCc.", targetName, ".ld"], loader]; move ¬ UserProfile.Token[Rope.Cat["ComplexCc.", targetName, ".mv"], move]; csh ¬ UserProfile.Token[Rope.Cat["ComplexCc.", targetName, ".csh"], csh]; }; UnixNil: UnixTypes.CHARPtr ~ LOOPHOLE[NIL]; MsgFromExitError: PROC [status: INT, command: ROPE] RETURNS [msg: ROPE] ~ { lowHalf: CARD16 ~ PBasics.LowHalf[LOOPHOLE[status, CARD32]]; lowByte: BYTE ~ PBasics.LowByte[lowHalf]; nextLowByte: BYTE ~ PBasics.HighByte[lowHalf]; low7: BYTE; IF lowByte = 177B THEN { msg ¬ IO.PutFR["execution of %g stopped by signal %g\n", IO.rope[command], IO.int[nextLowByte]]; RETURN [msg]; }; IF lowByte = 0 THEN { msg ¬ IO.PutFR["execution of %g exited with %g\n", IO.rope[command], IO.int[nextLowByte]]; RETURN [msg]; }; SELECT PBasics.endianBitsInBytes FROM big => low7 ¬ PBasics.BITAND[lowByte, 077B]; little => low7 ¬ PBasics.BITAND[lowByte, 176B]; ENDCASE => ERROR; msg ¬ IO.PutFR["execution of %g terminated due to signal %g\n", IO.rope[command], IO.int[low7]]; }; MsgFromFile: PROC [fileName: ROPE, delete: BOOL ¬ TRUE] RETURNS [msg: ROPE] ~ { stream: IO.STREAM; stream ¬ FS.StreamOpen[fileName: fileName !FS.Error => { stream ¬ NIL; CONTINUE }]; IF stream # NIL THEN { msg ¬ stream.GetRope[]; stream.Close[]; IF delete THEN FS.Delete[name: fileName !FS.Error => CONTINUE]; }; }; <> FOR list: LIST OF ROPE ¬ files, list.rest WHILE list # NIL DO file: ROPE ~ list.first; sourceRope: ROPE ~ Rope.Cat[dir, file]; destinationRope: ROPE ~ Rope.Cat[dir, "FILE-", file]; source: UnixTypes.CHARPtr ~ UXStrings.Create[sourceRope]; destination: UnixTypes.CHARPtr ~ UXStrings.Create[destinationRope]; res: UnixTypes.SysCallResult ~ UnixSysCalls.SymLink[source, destination]; IF res = failure THEN ERROR ShouldNotHappen[ IO.PutFR["Link from %g to %g failed; errno is %g", IO.rope[destinationRope], IO.rope[sourceRope], IO.card[LOOPHOLE[UnixErrno.GetErrno[], CARD]]]]; ENDLOOP; }; UnlinkNames: PROC [dir: ROPE, files: LIST OF ROPE] ~ { FOR list: LIST OF ROPE ¬ files, list.rest WHILE list # NIL DO file: ROPE ~ list.first; sourceRope: ROPE ~ Rope.Cat[dir, "FILE-", file]; source: UnixTypes.CHARPtr ~ UXStrings.Create[sourceRope]; res: UnixTypes.SysCallResult ~ UnixSysCalls.Unlink[source]; IF res = failure THEN ERROR ShouldNotHappen[ IO.PutFR["Unlink failed for %g; errno is %g", IO.rope[sourceRope], IO.card[LOOPHOLE[UnixErrno.GetErrno[], CARD]]]]; ENDLOOP; };>> Execute: PROC [command: ROPE, wDir: ROPE ¬ NIL] RETURNS [status: INT, msg: ROPE ¬ NIL] ~ { newCommand: ROPE ~ IF wDir.Equal[NIL] THEN command ELSE Rope.Cat["cd ", wDir, " ; ", command]; string: UXStrings.UnixString ~ UXStrings.Create[from: newCommand]; ropeStdErr: ROPE ~ NewName[".stderr", wDir]; stringStdErr: UXStrings.UnixString ~ UXStrings.Create[from: ropeStdErr]; ropeStdOut: ROPE ~ NewName[".stdout",wDir]; stringStdOut: UXStrings.UnixString ~ UXStrings.Create[from: ropeStdOut]; status ¬ UnixSysCallExtensions.Spawn[string, UnixNil, stringStdOut, stringStdErr]; IF status # 0 THEN msg ¬ MsgFromExitError[status: status, command: command]; msg ¬ Rope.Cat[msg, MsgFromFile[fileName: ropeStdErr, delete: DeleteFiles]]; msg ¬ Rope.Cat[msg, MsgFromFile[fileName: ropeStdOut, delete: DeleteFiles]]; }; ExecuteCsh: PROC [hostType, targetType: SystemVersion.MachineType, commandLines: ROPE, wDir: ROPE ¬ NIL] RETURNS [status: INT, msg: ROPE ¬ NIL] ~ { cshCommandRope: ROPE ~ GetCommandNames[ host: hostType, target: targetType].csh; cshCommandString: UnixTypes.CHARPtr ~ UXStrings.Create[cshCommandRope].string; IF cshCommandRope = NIL THEN ERROR ShouldNotHappen[IO.PutFR[ "Cshell execution on target of class %g cannot be done from host of class %g", IO.rope[MachineClassFromMachineType[targetType]], IO.rope[MachineClassFromMachineType[hostType]], ]]; { ropeStdIn: ROPE ~ NewName[".stdin", wDir]; stringStdIn: UXStrings.UnixString ~ UXStrings.Create[from: ropeStdIn]; ropeStdErr: ROPE ~ NewName[".stderr", wDir]; stringStdErr: UXStrings.UnixString ~ UXStrings.Create[from: ropeStdErr]; ropeStdOut: ROPE ~ NewName[".stdout", wDir]; stringStdOut: UXStrings.UnixString ~ UXStrings.Create[from: ropeStdOut]; streamIn: IO.STREAM ~ FS.StreamOpen[fileName: ropeStdIn, accessOptions: $create]; IF NOT wDir.Equal[NIL] THEN streamIn.PutF["cd %g\n", IO.rope[wDir]]; streamIn.PutF["%g\n", IO.rope[commandLines]]; streamIn.Close[]; status ¬ UnixSysCallExtensions.Spawn[cshCommandString, stringStdIn, stringStdOut, stringStdErr]; IF status # 0 THEN msg ¬ MsgFromExitError[status: status, command: cshCommandRope]; msg ¬ Rope.Cat[msg, MsgFromFile[fileName: ropeStdErr, delete: DeleteFiles]]; msg ¬ Rope.Cat[msg, MsgFromFile[fileName: ropeStdOut, delete: DeleteFiles]]; FS.Delete[name: ropeStdIn !FS.Error => CONTINUE]; } }; OutFilename: PROC [ template: ROPE ] RETURNS [ name: ROPE ] ~ { fullName: ROPE; cp: FS.ComponentPositions; [fullFName: fullName, cp: cp] ¬ FS.ExpandName[template]; { shortName: ROPE ~ fullName.Substr[cp.base.start, cp.base.length]; name ¬ shortName.Cat[".o"]; }; }; FixPath: PROC [ origName: ROPE ] RETURNS [ newName: ROPE ¬ NIL ] ~ { IF Rope.Equal[origName, NIL] THEN RETURN; newName ¬ origName.Translate[translator: BrackToSlash]; }; BrackToSlash: PROC [old: CHAR] RETURNS [new: CHAR] ~ { new ¬ IF ( old = '> ) THEN '/ ELSE old}; FixDirectory: PROC [ origName: ROPE ] RETURNS [ newName: ROPE ¬ NIL ] ~ { length: INT ~ Rope.Length[origName]; IF length = 0 THEN RETURN; newName ¬ FixPath[origName]; IF newName.Fetch[length-1] # '/ THEN newName ¬ newName.Cat["/"]; RETURN [newName]; }; GetDirAndFixPath: PROC [ origDir, origName: ROPE ] RETURNS [ dir, basename: ROPE ¬ NIL ] ~ { <> <> dir ¬ origDir; IF Rope.Equal[origName, NIL] THEN RETURN; basename ¬ FixPath[origName]; { pos: INT32 ~ basename.FindBackward["/"].SUCC; IF ( pos # 0 ) THEN { dir ¬ origDir.Concat[basename.Substr[0, pos]]; basename ¬ basename.Substr[pos]; RETURN}; }; }; <> CommandSyntaxError: ERROR ~ CODE; ComplexCCProc: Commander.CommandProc ~ { ENABLE { Args.Error => { msg ¬ ComplexCCUsage; GOTO Failed }; ShouldNotHappen => { msg ¬ message; GOTO Failed }; CommandSyntaxError => { msg ¬ ComplexCCUsage; GOTO Failed }; FS.Error => { msg ¬ error.explanation; GOTO Failed }; }; binDir: ROPE ¬ NIL; srcDir: ROPE ¬ NIL; ccSwitches: ROPE; ldSwitches: ROPE; libSwitches: ROPE; doALoad: BOOL ¬ FALSE; xFlag: BOOL ¬ FALSE; inFilename: ROPE; intFileList: LIST OF ROPE; -- list of file names for intermediate files loadFileList: LIST OF ROPE; -- list of file names for loading outFilename: ROPE; currentDir: ROPE ~ ViewFix[CommandTool.CurrentWorkingDirectory[], NIL, TRUE, FALSE, FALSE, NIL].unix; --a UXIO name InnerDoIt: PROC [hostType, targetType: SystemVersion.MachineType] ~ { <> ENABLE { FS.Error => { msg ¬ error.explanation; GOTO Failed; }; ABORTED => { msg ¬ "-- Aborted!"; GOTO Failed; } }; compilerName: ROPE; loaderName: ROPE; moveName: ROPE; links: LOR ¬ NIL; ccSrc, ccOut, intFudge, ldOut, ldOutUX: ROPE; ldCommand: ROPE ¬ NIL; [compiler: compilerName, loader: loaderName] ¬ GetCommandNames[host: hostType, target: targetType]; IF compilerName.Equal[NIL] OR loaderName.Equal[NIL] THEN { msg ¬ IO.PutFR["Compilation from host type %g to target type %g is not valid", IO.rope[MachineClassFromMachineType[hostType]], IO.rope[MachineClassFromMachineType[targetType]], ]; GOTO Failed; }; <> <<>> {ENABLE UNWIND => UnlinkList[links]; [ccSrc, links] ¬ ViewFix[srcDir.Concat[inFilename], NIL, FALSE, TRUE, FALSE, links]; [ccOut, links] ¬ ViewFix[binDir.Cat[outFilename], NIL, FALSE, TRUE, TRUE, links]; IF doALoad THEN { inputDir: ROPE ~ currentDir.Cat[binDir]; ldOut ¬ binDir.Concat[NewName[".o", NIL]]; [ldOutUX, links] ¬ ViewFix[ldOut, NIL, FALSE, FALSE, TRUE, links]; FOR tail: LIST OF ROPE ¬ loadFileList, tail.rest WHILE ( tail # NIL ) DO renamed: ROPE; [renamed, links] ¬ ViewFix[binDir.Concat[tail.first], "FILE-", FALSE, FALSE, FALSE, links]; ldCommand ¬ ldCommand.Cat[" ", renamed]; ENDLOOP; ldCommand ¬ ldCommand.Cat[" ", libSwitches]; }; <> <<>> { status: INT; localMsg, command: ROPE ¬ NIL; command ¬ IO.PutFR["%g %g -o %g %g -I./%g", IO.rope[compilerName], IO.rope[ccSwitches], IO.rope[ccOut], IO.rope[ccSrc], IO.rope[srcDir]]; [status: status, msg: localMsg] ¬ Execute[command: command, wDir: currentDir]; IF ( NOT localMsg.Equal[NIL] ) THEN { IF ( status # 0 ) THEN { msg ¬ IO.PutFR["Compilation failed; error: %g, msg: %g", IO.int[status], IO.rope[localMsg]]; UnlinkList[links]; GOTO Failed; }; msg ¬ IO.PutFR[".\nCompilation warnings: %g\n", IO.rope[localMsg]]; } ELSE { msg ¬ "."; }; cmd.err.PutRope[msg]; cmd.err.Flush[]; }; Process.CheckForAbort[]; <> IF ( doALoad ) THEN { status: INT; localMsg: ROPE; [intFudge, links] ¬ ViewFix[binDir.Cat[outFilename], "FILE-", FALSE, TRUE, FALSE, links]; ldCommand ¬ IO.PutFR["%g %g -o %g %g %g", IO.rope[loaderName], IO.rope[ldSwitches], IO.rope[ldOutUX], IO.rope[intFudge], IO.rope[ldCommand] ]; [status: status, msg: localMsg] ¬ Execute[command: ldCommand, wDir: currentDir]; IF ( NOT localMsg.Equal[NIL] ) THEN { IF ( status # 0 ) THEN { msg ¬ IO.PutFR["Load failed; error: %g, msg: %g", IO.int[status], IO.rope[localMsg]]; UnlinkList[links]; GOTO Failed; }; msg ¬ IO.PutFR[".\nLoad warnings: %g\n", IO.rope[localMsg]]; } ELSE { msg ¬ "."; }; cmd.err.PutRope[msg]; cmd.err.Flush[]; Process.CheckForAbort[]; }; }; UnlinkList[links]; IF ( doALoad ) THEN { FS.Rename[from: ldOut, to: binDir.Concat[outFilename] !FS.Error => { msg ¬ IO.PutFR["FS.Error[%g, %g] while trying to rename %g to %g", [atom[error.code]], [rope[error.explanation]], [rope[ldOut]], [rope[binDir.Concat[outFilename]]]]; GOTO Failed}]; }; Process.CheckForAbort[]; <> IF ( xFlag ) THEN { self: ExtendADotOut.ObjectID; action: ExtendADotOut.ActionID ~ ExtendADotOut.ActionIDFromAction["CC"]; dependList: LIST OF ExtendADotOut.ObjectID ¬ NIL; deps: ExtendADotOut.DependencyInfo; depFileList: LIST OF ROPE ¬ NIL; depFileList ¬ CONS[Rope.Cat[srcDir, inFilename], depFileList]; FOR list: LIST OF ROPE ¬ intFileList, list.rest WHILE list # NIL DO fileName: ROPE ~ list.first; depFileList ¬ CONS[Rope.Cat[srcDir, fileName], depFileList]; ENDLOOP; FOR list: LIST OF ROPE ¬ loadFileList, list.rest WHILE list # NIL DO fileName: ROPE ~ list.first; depFileList ¬ CONS[Rope.Cat[binDir, fileName], depFileList]; ENDLOOP; FOR list: LIST OF ROPE ¬ depFileList, list.rest WHILE list # NIL DO fileName: ROPE ~ list.first; dependList ¬ CONS[ExtendADotOut.ObjectIDFromFile[fileName], dependList]; ENDLOOP; self.class ¬ ExtendADotOut.ObjectClassFromFileName[outFilename]; self.name ¬ Rope.Cat[binDir, outFilename]; self.stamp ¬ ExtendADotOut.StampFromIDs[action, dependList]; deps ¬ NEW [ExtendADotOut.DependencyInfoRep ¬ [ self: self, action: action, dependList: dependList ]]; ExtendADotOut.PutDependencyInfo[Rope.Cat[binDir, outFilename], deps]; }; msg ¬ " no errors."; EXITS Failed => { result ¬ $Failure }; }; targetClass: ROPE ¬ UserProfile.Token[key: MACHINECLASS, default: "sun4"]; hostClass: ROPE ¬ MachineClassFromMachineType[ SystemVersion.machineType ]; <> ProcessCommandLine: PROC ~ { nArgs: INT32 ~ Args.NArgs[cmd]; i: NAT; FOR i ¬ 0, i.SUCC WHILE ( i < nArgs ) DO NextRope: PROC RETURNS [ r: ROPE ] ~ INLINE { ropeArg: Args.Arg ~ Args.ArgRope[cmd, i.SUCC]; r ¬ ropeArg.rope; i ¬ i.SUCC; }; NextList: PROC RETURNS [ l: LIST OF ROPE ¬ NIL ] ~ INLINE { FOR j: INT32 ¬ i.SUCC, j.SUCC WHILE ( j < nArgs ) DO anArg: ROPE ~ Args.GetRope[cmd, j]; IF ( anArg.Fetch[0] = '- ) THEN { i ¬ j.PRED; EXIT} ; l ¬ CONS[anArg, l]; REPEAT FINISHED => { i ¬ nArgs } ENDLOOP; }; anArg: ROPE ~ Args.GetRope[cmd, i]; SELECT TRUE FROM anArg.Equal[s2: "-in", case: FALSE] => { inFilename ¬ NextRope[] }; anArg.Equal[s2: "-out", case: FALSE] => { outFilename ¬ NextRope[] }; anArg.Equal[s2: "-binDir", case: FALSE] => { binDir ¬ NextRope[] }; anArg.Equal[s2: "-srcDir", case: FALSE] => { srcDir ¬ NextRope[] }; anArg.Equal[s2: "-lSwitch", case: FALSE] => { ldSwitches ¬ NextRope[] }; anArg.Equal[s2: "-cSwitch", case: FALSE] => { ccSwitches ¬ NextRope[] }; < { userHost _ NextRope[] };>> anArg.Equal[s2: "-class", case: FALSE] => { targetClass ¬ NextRope[] }; anArg.Equal[s2: "-lib", case: FALSE] => { libSwitches ¬ NextRope[] }; anArg.Equal[s2: "-int", case: FALSE] => { intFileList ¬ NextList[] }; anArg.Equal[s2: "-X", case: FALSE] => { xFlag ¬ TRUE }; anArg.Equal[s2: "-load", case: FALSE] => { doALoad ¬ TRUE; loadFileList ¬ NextList[] }; ENDCASE => ERROR CommandSyntaxError; ENDLOOP; }; ProcessCommandLine[]; binDir ¬ FixDirectory[binDir]; srcDir ¬ FixDirectory[srcDir]; inFilename ¬ FixPath[inFilename]; IF ( outFilename = NIL ) THEN outFilename ¬ OutFilename[inFilename]; [binDir, outFilename] ¬ GetDirAndFixPath[binDir, outFilename]; cmd.err.PutF[" [localhost] "]; cmd.err.PutRope["C compiling "]; cmd.err.Flush[]; InnerDoIt[ hostType: MachineTypeFromMachineClass[hostClass], targetType: MachineTypeFromMachineClass[targetClass]]; <> EXITS Failed => { result ¬ $Failure }; }; ComplexRshProc: Commander.CommandProc ~ { ENABLE { Args.Error => { msg ¬ ComplexRshUsage; GOTO Failed }; ShouldNotHappen => { msg ¬ message; GOTO Failed }; CommandSyntaxError => { msg ¬ ComplexRshUsage; GOTO Failed }; FS.Error => { msg ¬ error.explanation; GOTO Failed }; }; xFlag: BOOL ¬ FALSE; xClassName: ROPE ¬ NIL; -- The name of the class for this action srcDir: ROPE; binDir: ROPE ¬ NIL; srcInFileList: LIST OF ROPE; -- Source files that will be transfered FROM Cedar binInFileList: LIST OF ROPE; -- Binary files that will be transfered FROM Cedar srcOutFileList: LIST OF ROPE; -- Source files that will be copied TO Cedar back binOutFileList: LIST OF ROPE; -- Binary files that will be copied TO Cedar back unlinkList: LOR ¬ NIL; --files to unlink later rshCmd: ROPE; currentDir: ROPE ~ CommandTool.CurrentWorkingDirectory[]; InnerDoIt: PROC [hostType, targetType: SystemVersion.MachineType] ~ { <> ENABLE { FS.Error => { msg ¬ error.explanation; GOTO Failed; }; ABORTED => { msg ¬ "-- Aborted!"; GOTO Failed; } }; <> <> <<>> {ENABLE UNWIND => UnlinkList[unlinkList]; FOR list: LIST OF ROPE ¬ srcInFileList, list.rest WHILE list # NIL DO fileName: ROPE ~ list.first; [, unlinkList] ¬ ViewFix[srcDir.Cat[fileName], NIL, FALSE, TRUE, FALSE, unlinkList]; ENDLOOP; FOR list: LIST OF ROPE ¬ binInFileList, list.rest WHILE list # NIL DO fileName: ROPE ~ list.first; [, unlinkList] ¬ ViewFix[binDir.Cat[fileName], NIL, FALSE, TRUE, FALSE, unlinkList]; ENDLOOP; FOR list: LIST OF ROPE ¬ srcInFileList, list.rest WHILE list # NIL DO fileName: ROPE ~ list.first; [, unlinkList] ¬ ViewFix[srcDir.Cat[fileName], NIL, FALSE, TRUE, TRUE, unlinkList]; ENDLOOP; FOR list: LIST OF ROPE ¬ binInFileList, list.rest WHILE list # NIL DO fileName: ROPE ~ list.first; [, unlinkList] ¬ ViewFix[binDir.Cat[fileName], NIL, FALSE, TRUE, TRUE, unlinkList]; ENDLOOP; <> <<>> { status: INT; localMsg: ROPE ¬ NIL; realDir: ROPE ¬ currentDir; IF NOT srcDir.Equal[NIL] THEN IF srcDir.Fetch[0] = '/ THEN realDir ¬ srcDir ELSE realDir ¬ currentDir.Cat["/", srcDir] ELSE realDir ¬ currentDir; [status: status, msg: localMsg] ¬ ExecuteCsh[hostType: hostType, targetType: targetType, commandLines: rshCmd, wDir: realDir]; IF ( NOT localMsg.Equal[NIL] ) THEN { IF ( status # 0 ) THEN { msg ¬ IO.PutFR["Command failed; error: %g, msg: %g", IO.int[status], IO.rope[localMsg]]; GOTO Failed; }; msg ¬ IO.PutFR[".\nCommand warnings: %g", IO.rope[localMsg]]; } ELSE { msg ¬ "."; }; cmd.err.PutRope[msg]; cmd.err.Flush[]; }; Process.CheckForAbort[]; <> }; UnlinkList[unlinkList]; <> IF ( xFlag ) THEN { self: ExtendADotOut.ObjectID; action: ExtendADotOut.ActionID ~ ExtendADotOut.ActionIDFromAction[xClassName]; dependList: LIST OF ExtendADotOut.ObjectID ¬ NIL; deps: ExtendADotOut.DependencyInfo; depFileList: LIST OF ROPE ¬ NIL; stamp: ExtendADotOut.VersionStamp; FOR list: LIST OF ROPE ¬ srcInFileList, list.rest WHILE list # NIL DO fileName: ROPE ~ list.first; depFileList ¬ CONS[Rope.Cat[srcDir, fileName], depFileList]; ENDLOOP; FOR list: LIST OF ROPE ¬ binInFileList, list.rest WHILE list # NIL DO fileName: ROPE ~ list.first; depFileList ¬ CONS[Rope.Cat[binDir, fileName], depFileList]; ENDLOOP; FOR list: LIST OF ROPE ¬ depFileList, list.rest WHILE list # NIL DO fileName: ROPE ~ list.first; dependList ¬ CONS[ExtendADotOut.ObjectIDFromFile[fileName], dependList]; ENDLOOP; stamp ¬ ExtendADotOut.StampFromIDs[action, dependList]; FOR list: LIST OF ROPE ¬ binOutFileList, list.rest WHILE list # NIL DO outFilename: ROPE ~ list.first; self.class ¬ ExtendADotOut.ObjectClassFromFileName[outFilename]; self.stamp ¬ stamp; self.name ¬ Rope.Cat[binDir, outFilename]; deps ¬ NEW [ExtendADotOut.DependencyInfoRep ¬ [ self: self, action: action, dependList: dependList ]]; ExtendADotOut.PutDependencyInfo[Rope.Cat[binDir, outFilename], deps]; ENDLOOP; }; msg ¬ " no errors."; EXITS Failed => { result ¬ $Failure }; }; targetClass: ROPE ¬ UserProfile.Token[key: MACHINECLASS, default: "sun4"]; hostClass: ROPE ¬ MachineClassFromMachineType[ SystemVersion.machineType ]; <> ProcessCommandLine: PROC ~ { nArgs: INT32 ~ Args.NArgs[cmd]; i: NAT; FOR i ¬ 0, i.SUCC WHILE ( i < nArgs ) DO NextRope: PROC RETURNS [ r: ROPE ] ~ INLINE { ropeArg: Args.Arg ~ Args.ArgRope[cmd, i.SUCC]; r ¬ ropeArg.rope; i ¬ i.SUCC; }; FixNextList: PROC RETURNS [ l: LIST OF ROPE ¬ NIL ] ~ INLINE { <> FOR j: INT32 ¬ i.SUCC, j.SUCC WHILE ( j < nArgs ) DO anArg: ROPE ~ Args.GetRope[cmd, j]; IF ( anArg.Fetch[0] = '- ) THEN { i ¬ j.PRED; EXIT} ; l ¬ CONS[FixPath[anArg], l]; REPEAT FINISHED => { i ¬ nArgs } ENDLOOP; }; anArg: ROPE ~ Args.GetRope[cmd, i]; SELECT TRUE FROM anArg.Equal[s2: "-binIn", case: FALSE] => { binInFileList ¬ FixNextList[] }; anArg.Equal[s2: "-srcIn", case: FALSE] => { srcInFileList ¬ FixNextList[] }; anArg.Equal[s2: "-binOut", case: FALSE] => { binOutFileList ¬ FixNextList[] }; anArg.Equal[s2: "-srcOut", case: FALSE] => { srcOutFileList ¬ FixNextList[] }; anArg.Equal[s2: "-srcDir", case: FALSE] => { srcDir ¬ NextRope[] }; anArg.Equal[s2: "-binDir", case: FALSE] => { binDir ¬ NextRope[] }; < { userHost _ NextRope[] };>> anArg.Equal[s2: "-class", case: FALSE] => { targetClass ¬ NextRope[] }; anArg.Equal[s2: "-cmd", case: FALSE] => { rshCmd ¬ NextRope[] }; anArg.Equal[s2: "-XClass", case: FALSE] => { xFlag ¬ TRUE; xClassName ¬ NextRope[] }; ENDCASE => ERROR CommandSyntaxError; ENDLOOP; IF binDir.Equal[NIL] THEN binDir ¬ srcDir; }; ProcessCommandLine[]; srcDir ¬ FixDirectory[srcDir]; binDir ¬ FixDirectory[binDir]; cmd.err.PutRope["Starting Rsh"]; cmd.err.Flush[]; InnerDoIt[ hostType: MachineTypeFromMachineClass[hostClass], targetType: MachineTypeFromMachineClass[targetClass]]; <> EXITS Failed => { result ¬ $Failure }; }; <> ComplexCC: ROPE ~ "ComplexCC"; ComplexCCDoc: ROPE ~ " - cc with all the frills. Switches are: -in -out -class -host -cSwitch -load => load compiled file together with -X => eXtend the resulting binary file with fast symbol and dependecy info -lSwitch -Lib libstring => string with the libraries to load -int => files to copy to the host before compiling -srcDir => remote source directory -binDir => remote object file directory (overridden by directory part specified in -out) "; ComplexCCUsage: ROPE ~ Rope.Concat["Usage: ComplexCC ", ComplexCCDoc]; ComplexRsh: ROPE ~ "ComplexRsh"; ComplexRshDoc: ROPE ~ " - Rsh with all the frills. Switches are: -class -host -srcIn => source files to copy to the host before doing Rsh -binIn => binary files to copy to the host before doing Rsh -srcOut => source files to copy from the host after doing Rsh -binOut => binary files to copy from the host after doing Rsh -srcDir => remote source directory (command will execute in srcDir) -binDir => remote binary directory (equal to -srcDir by default) -XClass => eXtend the resulting binary files with fast symbol and dependency information; use to identify the action performed. -cmd => command to execute remotely "; ComplexRshUsage: ROPE ~ Rope.Concat["Usage: ComplexRsh ", ComplexRshDoc]; ComplexRshUsageHostMissing: ROPE ~ Rope.Concat["No host has been specified\nUsage: ComplexRsh ", ComplexRshDoc]; ComplexErrorProc: Commander.CommandProc ~ {ERROR}; Init: PROC ~ { Commander.Register[ComplexCC, ComplexCCProc, ComplexCCDoc]; Commander.Register[ComplexRsh, ComplexRshProc, ComplexRshDoc]; Commander.Register["ComplexError", ComplexErrorProc, "raises ERROR, for debugging"]; }; Init[]; }. <> <> <> <> <<>> <> <>