PeachPrintImpl.mesa
Edited by Don Curry on April 10, 1986 11:37:13 pm PST
DIRECTORY
Ascii, Basics, Commander, CommandTool, Convert, FileNames, FS, IO, PeachPrint, Process, PupDefs, PupStream, PupTypes, Rope, UserCredentials, UserProfile ;
PeachPrintImpl: CEDAR PROGRAM
IMPORTS Basics, Commander, CommandTool, Convert, FileNames, FS, IO, Process, PupDefs, PupStream, Rope, UserCredentials, UserProfile EXPORTS PeachPrint =
BEGIN
PupAborted: PUBLIC ERROR  = CODE;
localServer: PUBLIC Rope.ROPE ← PupDefs.GetMyName[];
MarkByte:   TYPE = [0..256);
setLineWidth:  MarkByte = 2;
timingMark:   MarkByte = 5;
timingMarkReply: MarkByte = 6;
Status:    TYPE = {waiting, started, complete, error};
PeachPrintProc: Commander.CommandProc = {
ENABLE {
BadFile =>
{cmd.out.PutF["File Unknown. Format is: \n PeachPrint %g\n ", IO.rope[doc]]; GOTO Abort};
ABORTED  => GOTO Abort;
PupAborted => GOTO Abort };
remoteServer: Rope.ROPE ← UserProfile.Token["PeachPrint.PrintServer", "???"];
list:    LIST OF Rope.ROPE;
length:   NAT;
[list, length]  ← CommandTool.ParseToList[cmd];
SELECT length FROM
1 => {DoPeachPrintCommand[remoteServer, list.first,  cmd.out]};
2 => {DoPeachPrintCommand[list.first,   list.rest.first, cmd.out]};
ENDCASE => cmd.out.PutF["\n PeachPrint %g\n", IO.rope[doc]];
EXITS Abort => {cmd.out.PutF["aborted\n"]; RETURN[$Failure] } };
FileName: PUBLIC PROC[
length: PeachPrint.FileNameLength,
order:  PeachPrint.FileNameOrder,
index:  INT ← 1,
ext:  Rope.ROPENIL ]
RETURNS[rope: Rope.ROPE] = {
rope ← SELECT length FROM
fullPath => IO.PutFR["/%g/Cedar/", IO.rope[localServer]],
long  => "///",
ENDCASE => NIL;
IF order=primary
THEN rope ← IO.PutFR["%gPD/Plot",   IO.rope[rope] ]
ELSE rope ← IO.PutFR["%gPD/Plot%g-", IO.rope[rope] , IO.int[index] ];
rope ← IO.PutFR["%g%g%g", IO.rope[rope], IO.int[index], IO.rope[ext] ]};
ThisMachineFileName: PROC[file, ext: Rope.ROPE ] RETURNS[machineFileName: Rope.ROPE] = {
IF file.Length[]=0 THEN RETURN[NIL];
IF FS.ExpandName[file].cp.server.length=0 THEN {
file ← FileNames.FileWithSearchRules[file, ext, FALSE, FALSE, NIL].fullPath;
IF file=NIL THEN BadFile[];
file ← IO.PutFR["/%g/Cedar/%g", IO.rope[localServer], IO.rope[Rope.Substr[file, 3]]] };
RETURN[file]};
BadFile: SIGNAL = CODE;
FileName: PROC[primary: BOOLTRUE, strip: INT ← 1] RETURNS[rope: Rope.ROPE] = {
rope ← IO.PutFR["/%g/Cedar", IO.rope[localServer]];
IF primary
THEN rope ← IO.PutFR["%g/Temp/Plot%g.pd",  IO.rope[rope], IO.int[strip] ]
ELSE rope ← IO.PutFR["%g/PD/Plot%g-%g.pd", IO.rope[rope], IO.int[strip], IO.int[strip] ]};
DoPeachPrintCommand: PUBLIC PROC[server, file: Rope.ROPE, log: IO.STREAMIO.noWhereStream] = {
DO
ENABLE {
FS.Error => IF error.group = user THEN
{log.PutRope[error.explanation]; EXIT }};
request: INT ← -1;
file ← ThisMachineFileName[file, ".pd"];
IF file#NIL THEN {
ENABLE ABORTED => [] ← CancelRequest[server, request, log];
status:    Status ← waiting;
rope:    Rope.ROPE;
log.PutF["Post request at %g . . . ", IO.rope[server]];
[request, rope] ← GetRequestNum[server, file, log];
log.PutF["done\n"];
Process.CheckForAbort[];
IF request=-1 THEN {
log.PutF["\nI could not find the request number in here:\n%g\n",
IO.rope[rope]];
RETURN};
log.PutF["Request R%03g queued at %g\n %g",
IO.int[request],
IO.rope[server],
IO.rope[file]];
log.PutF[" . . . waiting . . . "];
status ← WaitOnRequest[server, request, log];
IF status=complete
THEN log.PutF["done\n"]
ELSE log.PutF["????\n"] };
EXIT ENDLOOP };
GetRequestNum: PROC[server, fileCopiesTitle: Rope.ROPE, log: IO.STREAMIO.noWhereStream]
RETURNS[req: INT, rope: Rope.ROPE] = {
index: INT;
msgRope: Rope.ROPEIO.PutFR["Print %g\n", IO.rope[fileCopiesTitle]];
temp: Rope.ROPE ← PeachQuery[server, msgRope, log];
rope ← temp;
IF (index←Rope.Index[rope, 0, "Print request "]+14)>=rope.Length[] THEN
{log.PutF["\n%g . . . ", IO.rope[rope]]; ERROR ABORTED};
temp ← Rope.Substr[rope, index];
temp ← Rope.Substr[temp, 0, Rope.Index[temp, 0, " queued"]];
IF temp.Length=0 THEN req ← -1 ELSE req ← Convert.IntFromRope[temp]};
WaitOnRequest: PROC[server: Rope.ROPE, req: INT, log: IO.STREAMIO.noWhereStream]
RETURNS[status: Status] = {
msgRope: Rope.ROPEIO.PutFR["Wait %03g\n", IO.int[req]];
rope: Rope.ROPE ← PeachQuery[server, msgRope, log];
status ← error;
IF Rope.Find[rope,"Done"]#-1
THEN status ← complete
ELSE log.PutF["<<%g>>", IO.rope[rope]]};
CancelRequest: PROC[server: Rope.ROPE, req: INT, log: IO.STREAMIO.noWhereStream] = {
msgRope: Rope.ROPEIO.PutFR["Cancel %03g\n", IO.int[req]];
IF req>=0 THEN [ ] ← PeachQuery[server, msgRope, log] };
PeachQuery: PROC[server, msg: Rope.ROPE, log: IO.STREAMIO.noWhereStream]
RETURNS[rope: Rope.ROPE] = {
PupAborting: BOOLFALSE;
PupDefs.PupPackageMake[];
BEGIN
addr: PupDefs.PupAddress;
serverStream: IO.STREAM;
log.PutF["Opening connection to %g . . . ", IO.rope[server]];
addr ← PupStream.GetPupAddress[PupTypes.telnetSoc, server
! PupStream.PupNameTrouble =>
{log.PutF["PUP name error"]; Finish[log, e]; GOTO PupAbort}];
serverStream ← PupStream.PupByteStreamCreate[addr, PupStream.SecondsToTocks[1]
! PupStream.StreamClosing =>
{log.PutF["Can't connect"]; Finish[log, text]; GOTO PupAbort}];
rope ← GetResponse[serverStream, log
! PupStream.StreamClosing =>
{log.PutF["Can't get response"]; Finish[log, text]; GOTO PupAbort}];
LogIn[serverStream];
rope ← GetResponse[serverStream, log
! PupStream.StreamClosing =>
{log.PutF["Can't log in"]; Finish[log, text]; GOTO PupAbort} ];
serverStream.PutRope[msg]; serverStream.Flush[];
rope ← GetResponse[serverStream, log
! PupStream.StreamClosing =>
{log.PutF["Server won't except command"]; Finish[log, text]; GOTO PupAbort}];
serverStream.PutRope["Quit "]; serverStream.Flush[];
serverStream.Close[];
serverStream ← NIL;
EXITS PupAbort => PupAborting←TRUE;
END;
PupDefs.PupPackageDestroy[];
IF PupAborting THEN ERROR PupAborted };
Finish: PROC [log: IO.STREAM, errorMsg: Rope.ROPE] = {
IF errorMsg # NIL THEN log.PutF[": %s.\n", IO.rope[errorMsg]]
ELSE log.PutF[".\n"] };
LogIn: PROC [serverStream: IO.STREAM] = TRUSTED {
name, password: Rope.ROPE;
PupStream.SendMark[serverStream, setLineWidth];
serverStream.PutChar[0C];
serverStream.Flush[];
[name: name, password: password] ← UserCredentials.Get[];
serverStream.PutRope["Login "];
serverStream.PutRope[name];
IF Rope.Find[s1: name, s2: "."] = -1 THEN serverStream.PutRope[".PA"];
serverStream.PutRope[" "];
serverStream.PutRope[password];
serverStream.PutRope[" \n"];
serverStream.Flush[] };
GetResponse: PROC[serverStream: IO.STREAM, log: IO.STREAMIO.noWhereStream]
RETURNS[rope: Rope.ROPE] = {
ros: IO.STREAMIO.ROS[];
lastChar: CHARACTER ← ' ;
DO
c: CHARACTER;
IF serverStream.EndOf[] THEN {
mySST: MarkByte ← PupStream.ConsumeMark[serverStream];
IF mySST = timingMark THEN PupStream.SendMark[serverStream, timingMarkReply] };
c ← serverStream.GetChar[!
PupStream.TimeOut => RESUME;
IO.EndOfStream  => LOOP];
c ← LOOPHOLE[Basics.BITAND[LOOPHOLE[c, CARDINAL], 177B], CHAR];
SELECT c FROM
'>         => {ros.PutChar[c]; IF lastChar=c THEN EXIT};
Ascii.BEL       => ERROR;
Ascii.ControlA, Ascii.BS  => ERROR;
Ascii.TAB, IN[Ascii.SP..0176C] => ros.PutChar[c];
Ascii.LF       => ros.PutChar[Ascii.CR];
ENDCASE       => NULL;
lastChar ← c;
Process.CheckForAbort[];
ENDLOOP;
rope ← IO.RopeFromROS[ros];
log.PutRope[rope];
};
doc: Rope.ROPE ← "PeachPrinterName SomePDFile";
Commander.Register[key: "PeachPrint", proc: PeachPrintProc, doc: doc];
END.