PeachPrintImpl.mesa
Edited by Don Curry on February 20, 1987 12:45:52 pm PST
Willie-Sue, June 13, 1986 5:47:06 pm PDT
DIRECTORY
Ascii,
Basics,
Commander,
CommandTool,
Convert,
File,
FileNames,
FS,
IO,
PeachPrint,
Process,
Pup USING [Address],
PupName USING [Error, NameLookup, MyName],
PupStream,
PupWKS USING [telnet],
Rope,
UserCredentials,
PeachPrintImpl:
CEDAR
PROGRAM
IMPORTS
Basics, Commander, CommandTool, Convert, File, FileNames, FS, IO, Process,
PupName, PupStream,
Rope, UserCredentials, UserProfile
BEGIN
PupAborted: PUBLIC ERROR = CODE;
localServer: PUBLIC Rope.ROPE ← PupName.MyName[];
localVolume: Rope.ROPE ← File.GetVolumeName[File.SystemVolume[]];
workingDir: Rope.ROPE ← FileNames.CurrentWorkingDirectory[].Substr[3];
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 };
list: LIST OF Rope.ROPE ← LIST[UserProfile.Token["PeachPrint.PrintServer", "???"]];
fork: BOOL ← FALSE;
copies: INT ← 1;
ii: INT ← 1;
argv: CommandTool.ArgumentVector ← CommandTool.Parse[cmd];
WHILE ii < argv.argc
DO
rope: Rope.ROPE ← CommandTool.ArgN[cmd, ii];
SELECT rope.Fetch[0]
FROM
'- =>
SELECT rope.Fetch[1]
FROM
'f, 'F => fork ← TRUE;
'c, 'C => {
ii ← ii+1;
copies ← MAX[0, Convert.IntFromRope[CommandTool.ArgN[cmd, ii]]]};
ENDCASE;
ENDCASE => {list ← CONS[rope, list]};
ii ← ii+1;
ENDLOOP;
IF list.rest
=NIL
THEN cmd.out.PutF["\n PeachPrint %g\n", IO.rope[doc]]
ELSE DoPeachPrintCommand[list.rest.first, list.first, cmd.out, fork, copies];
EXITS Abort => {cmd.out.PutF["aborted\n"]; RETURN[$Failure] } };
FileName:
PUBLIC
PROC[
length: PeachPrint.FileNameLength,
order: PeachPrint.FileNameOrder,
index: INT ← 1,
ext: Rope.
ROPE ←
NIL ]
RETURNS[rope: Rope.ROPE] = {
rope ←
SELECT length
FROM
fullPath => IO.PutFR["/%g/%g/", IO.rope[localServer], IO.rope[localVolume]],
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] ]};
FullMachineFileName:
PROC[file, dExt: Rope.
ROPE ]
RETURNS[fullName: Rope.
ROPE] = {
cp: FS.ComponentPositions;
server, dir, subDirs, base: Rope.ROPE;
IF file.Length[] = 0 THEN RETURN[NIL];
IF file.Find["."] =-1 THEN file ← file.Cat[dExt];
[fullName, cp, ] ← FS.ExpandName[file, Rope.Cat["///", workingDir]];
server ← fullName.Substr[cp.server.start, cp.server.length];
dir ← fullName.Substr[cp.dir.start, cp.dir.length];
subDirs ← fullName.Substr[cp.subDirs.start, cp.subDirs.length];
base ← fullName.Substr[cp.base.start];
IF server.Length[]=0 THEN server ← localServer;
IF dir.Length[]=0 THEN dir ← localVolume;
fullName ← Rope.Cat["[", server, "]<", dir, ">"];
IF subDirs.Length[]#0 THEN fullName ← fullName.Cat[subDirs, ">"];
fullName ← fullName.Cat[base];
RETURN[FileNames.ConvertToSlashFormat[fullName]]};
BadFile: SIGNAL = CODE;
DoPeachPrintCommand:
PUBLIC
PROC
[server, file: Rope.ROPE, log: IO.STREAM←IO.noWhereStream, fork: BOOL←FALSE, copies: INT𡤁]={
DO
ENABLE {
FS.Error => IF error.group = user THEN
{log.PutRope[error.explanation]; EXIT }};
request: INT ← -1;
fileCopiesTitle: Rope.ROPE ← FullMachineFileName[file, ".pd"];
IF fileCopiesTitle#
NIL
THEN {
ENABLE ABORTED => [] ← CancelRequest[server, request, log];
status: Status ← waiting;
rope: Rope.ROPE;
fileCopiesTitle ← IO.PutFR["%g %g", IO.rope[fileCopiesTitle], IO.int[copies]];
log.PutF["Post request at %g . . . ", IO.rope[server]];
[request, rope] ← GetRequestNum[server, fileCopiesTitle, 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 Copies: %g",
IO.int[request],
IO.rope[server],
IO.rope[file],
IO.int[copies]];
IF fork THEN {log.PutF["\n"]; RETURN};
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.STREAM ← IO.noWhereStream]
RETURNS[req: INT, rope: Rope.ROPE] = {
index: INT;
msgRope: Rope.ROPE ← IO.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.
STREAM ←
IO.noWhereStream]
RETURNS[status: Status] = {
msgRope: Rope.ROPE ← IO.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.
STREAM ←
IO.noWhereStream] = {
msgRope: Rope.ROPE ← IO.PutFR["Cancel %03g\n", IO.int[req]];
IF req>=0 THEN [ ] ← PeachQuery[server, msgRope, log] };
PeachQuery:
PROC[server, msg: Rope.
ROPE, log:
IO.
STREAM ←
IO.noWhereStream]
RETURNS[rope: Rope.ROPE] = {
PupAborting: BOOL ← FALSE;
BEGIN
addr: Pup.Address;
serverStream: IO.STREAM;
log.PutF["Opening connection to %g . . . ", IO.rope[server]];
addr ← PupName.NameLookup[server, PupWKS.telnet
! PupName.Error => {
log.PutF["PUP name lookup error: %g", IO.rope[text]];
Finish[log, text];
GOTO PupAbort} ];
serverStream ← PupStream.Create[addr, 60000, 60000
-- Milliseconds
! PupStream.StreamClosing =>
{log.PutF["Can't connect: %g", IO.rope[text]]; Finish[log, text]; GOTO PupAbort}];
rope ← GetResponse[serverStream, log
! PupStream.StreamClosing =>
{log.PutF["Can't get response: %g", IO.rope[text]]; Finish[log, text]; GOTO PupAbort}];
LogIn[serverStream
! PupStream.Timeout => { log.PutRope["Timeout during log in"]; RESUME} ];
rope ← GetResponse[serverStream, log
! PupStream.StreamClosing =>
{log.PutF["Can't log in: %g", IO.rope[text]]; Finish[log, text]; GOTO PupAbort} ];
serverStream.PutRope[msg]; serverStream.Flush[];
rope ← GetResponse[serverStream, log
! PupStream.StreamClosing => {
log.PutF["Server won't accept command: %g", IO.rope[text]];
Finish[log, text];
GOTO PupAbort} ];
DO
ENABLE PupStream.StreamClosing => EXIT;
serverStream.PutRope["Quit "];
serverStream.Flush[];
serverStream.Close[]; EXIT; ENDLOOP;
serverStream ← NIL;
EXITS PupAbort => PupAborting ←TRUE;
END;
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.
STREAM ←
IO.noWhereStream]
RETURNS[rope: Rope.ROPE] = {
ros: IO.STREAM ← IO.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]};
doc: Rope.ROPE ← "PeachPrinterName SomePDFile";
Commander.Register[key: "PeachPrint", proc: PeachPrintProc, doc: doc];
END.