" PIPELINE SYSTEM PER BRINCH HANSEN 11 MAY 1976 " "*********************** * INPUT/OUTPUT TYPES * ***********************" TYPE IODEVICE = (TYPEDEVICE, DISKDEVICE, TAPEDEVICE, PRINTDEVICE, CARDDEVICE); TYPE IOOPERATION = (INPUT, OUTPUT, MOVE, CONTROL); TYPE IORESULT = (COMPLETE, INTERVENTION, TRANSMISSION, FAILURE, ENDFILE, ENDMEDIUM, STARTMEDIUM); TYPE IOPARAM = RECORD OPERATION: IOOPERATION; STATUS: IORESULT; ARG: INTEGER END; CONST LINELENGTH = 132; TYPE LINE = ARRAY (.1..LINELENGTH.) OF CHAR; CONST NL = '(:10:)'; FF = '(:12:)'; "*************** * LINEBUFFER * ***************" TYPE LINEBUFFER = MONITOR VAR CONTENTS: LINE; FULL: BOOLEAN; SENDER, RECEIVER: QUEUE; PROCEDURE ENTRY RECEIVE(VAR TEXT: LINE); BEGIN IF NOT FULL THEN DELAY(RECEIVER); TEXT:= CONTENTS; FULL:= FALSE; CONTINUE(SENDER); END; PROCEDURE ENTRY SEND(TEXT: LINE); BEGIN IF FULL THEN DELAY(SENDER); CONTENTS:= TEXT; FULL:= TRUE; CONTINUE(RECEIVER); END; BEGIN FULL:= FALSE END; "************** * LINEMAKER * **************" TYPE LINEMAKER = CLASS(BUFFER: LINEBUFFER); VAR IMAGE: LINE; CHARNO: INTEGER; PROCEDURE ENTRY WRITE(TEXT: LINE); BEGIN FOR CHARNO:= 27 TO 106 DO IMAGE(.CHARNO.):= TEXT(.CHARNO - 26.); BUFFER.SEND(IMAGE); END; BEGIN FOR CHARNO:= 1 TO 26 DO IMAGE(.CHARNO.):= ' '; IMAGE(.107.):= NL; END; "************** * PAGEMAKER * **************" TYPE PAGEMAKER = CLASS(BUFFER: LINEBUFFER); VAR CONSUMER: LINEMAKER; LINENO: INTEGER; PROCEDURE NEWPAGE; VAR TEXT: LINE; BEGIN TEXT(.1.):= FF; CONSUMER.WRITE(TEXT); TEXT(.1.):= NL; CONSUMER.WRITE(TEXT); LINENO:= 1; END; PROCEDURE ENTRY SKIP; BEGIN NEWPAGE END; PROCEDURE ENTRY WRITE(TEXT: LINE); BEGIN CONSUMER.WRITE(TEXT); IF LINENO = 60 THEN NEWPAGE ELSE LINENO:= LINENO + 1; END; BEGIN INIT CONSUMER(BUFFER); NEWPAGE END; "************** * FILEMAKER * **************" TYPE FILEMAKER = CLASS(BUFFER: LINEBUFFER); VAR CONSUMER: PAGEMAKER; EOF: BOOLEAN; FUNCTION MORE(TEXT: LINE): BOOLEAN; VAR CHARNO: INTEGER; BEGIN IF TEXT(.1.) <> '#' THEN MORE:= TRUE ELSE BEGIN CHARNO:= 80; WHILE TEXT(.CHARNO.) = ' ' DO CHARNO:= CHARNO - 1; MORE:= (CHARNO <> 1); END; END; PROCEDURE ENTRY WRITE(TEXT: LINE); BEGIN IF EOF THEN BEGIN CONSUMER.SKIP; EOF:= FALSE END; IF MORE(TEXT) THEN CONSUMER.WRITE(TEXT) ELSE BEGIN CONSUMER.SKIP; EOF:= TRUE END; END; BEGIN INIT CONSUMER(BUFFER); EOF:= TRUE END; "**************** * CARDPROCESS * ****************" TYPE CARDPROCESS = PROCESS(BUFFER: LINEBUFFER); VAR PARAM: IOPARAM; TEXT, ERROR: LINE; CHARNO: INTEGER; BEGIN FOR CHARNO:= 1 TO 80 DO ERROR(.CHARNO.):= '?'; PARAM.OPERATION:= INPUT; WITH PARAM DO CYCLE REPEAT IO(TEXT, PARAM, CARDDEVICE) UNTIL STATUS <> INTERVENTION; IF STATUS <> COMPLETE THEN TEXT:= ERROR; BUFFER.SEND(TEXT); END; END; "**************** * COPYPROCESS * ****************" TYPE COPYPROCESS = PROCESS(INBUFFER, OUTBUFFER: LINEBUFFER); VAR CONSUMER: FILEMAKER; TEXT: LINE; BEGIN INIT CONSUMER(OUTBUFFER); WITH INBUFFER, CONSUMER DO CYCLE RECEIVE(TEXT); WRITE(TEXT) END; END; "******************* * PRINTERPROCESS * *******************" TYPE PRINTERPROCESS = PROCESS(BUFFER: LINEBUFFER); VAR PARAM: IOPARAM; TEXT: LINE; BEGIN PARAM.OPERATION:= OUTPUT; CYCLE BUFFER.RECEIVE(TEXT); REPEAT IO(TEXT, PARAM, PRINTDEVICE) UNTIL PARAM.STATUS = COMPLETE; END; END; "******************** * INITIAL PROCESS * ********************" VAR INBUFFER, OUTBUFFER: LINEBUFFER; READER: CARDPROCESS; COPIER: COPYPROCESS; PRINTER: PRINTERPROCESS; BEGIN INIT INBUFFER, OUTBUFFER, READER(INBUFFER), COPIER(INBUFFER, OUTBUFFER), PRINTER(OUTBUFFER); END.