(NUMBER) "PER BRINCH HANSEN INFORMATION SCIENCE CALIFORNIA INSTITUTE OF TECHNOLOGY UTILITY PROGRAMS FOR THE SOLO SYSTEM 18 MAY 1975" "########### # PREFIX # ###########" CONST NL = '(:10:)'; FF = '(:12:)'; CR = '(:13:)'; EM = '(:25:)'; CONST PAGELENGTH = 512; TYPE PAGE = ARRAY (.1..PAGELENGTH.) OF CHAR; CONST LINELENGTH = 132; TYPE LINE = ARRAY (.1..LINELENGTH.) OF CHAR; CONST IDLENGTH = 12; TYPE IDENTIFIER = ARRAY (.1..IDLENGTH.) OF CHAR; TYPE FILE = 1..2; TYPE FILEKIND = (EMPTY, SCRATCH, ASCII, SEQCODE, CONCODE); TYPE FILEATTR = RECORD KIND: FILEKIND; ADDR: INTEGER; PROTECTED: BOOLEAN; NOTUSED: ARRAY (.1..5.) OF INTEGER END; TYPE IODEVICE = (TYPEDEVICE, DISKDEVICE, TAPEDEVICE, PRINTDEVICE, CARDDEVICE); TYPE IOOPERATION = (INPUT, OUTPUT, MOVE, CONTROL); TYPE IOARG = (WRITEEOF, REWIND, UPSPACE, BACKSPACE); TYPE IORESULT = (COMPLETE, INTERVENTION, TRANSMISSION, FAILURE, ENDFILE, ENDMEDIUM, STARTMEDIUM); TYPE IOPARAM = RECORD OPERATION: IOOPERATION; STATUS: IORESULT; ARG: IOARG END; TYPE TASKKIND = (INPUTTASK, JOBTASK, OUTPUTTASK); TYPE ARGTAG = (NILTYPE, BOOLTYPE, INTTYPE, IDTYPE, PTRTYPE); TYPE POINTER = @BOOLEAN; TYPE ARGTYPE = RECORD CASE TAG: ARGTAG OF NILTYPE, BOOLTYPE: (BOOL: BOOLEAN); INTTYPE: (INT: INTEGER); IDTYPE: (ID: IDENTIFIER); PTRTYPE: (PTR: POINTER) END; CONST MAXARG = 10; TYPE ARGLIST = ARRAY (.1..MAXARG.) OF ARGTYPE; TYPE ARGSEQ = (INP, OUT); TYPE PROGRESULT = (TERMINATED, OVERFLOW, POINTERERROR, RANGEERROR, VARIANTERROR, HEAPLIMIT, STACKLIMIT, CODELIMIT, TIMELIMIT, CALLERROR); PROCEDURE READ(VAR C: CHAR); PROCEDURE WRITE(C: CHAR); PROCEDURE OPEN(F: FILE; ID: IDENTIFIER; VAR FOUND: BOOLEAN); PROCEDURE CLOSE(F: FILE); PROCEDURE GET(F: FILE; P: INTEGER; VAR BLOCK: UNIV PAGE); PROCEDURE PUT(F: FILE; P: INTEGER; VAR BLOCK: UNIV PAGE); FUNCTION LENGTH(F: FILE): INTEGER; PROCEDURE MARK(VAR TOP: INTEGER); PROCEDURE RELEASE(TOP: INTEGER); PROCEDURE IDENTIFY(HEADER: LINE); PROCEDURE ACCEPT(VAR C: CHAR); PROCEDURE DISPLAY(C: CHAR); PROCEDURE READPAGE(VAR BLOCK: UNIV PAGE; VAR EOF: BOOLEAN); PROCEDURE WRITEPAGE(BLOCK: UNIV PAGE; EOF: BOOLEAN); PROCEDURE READLINE(VAR TEXT: UNIV LINE); PROCEDURE WRITELINE(TEXT: UNIV LINE); PROCEDURE READARG(S: ARGSEQ; VAR ARG: ARGTYPE); PROCEDURE WRITEARG(S: ARGSEQ; ARG: ARGTYPE); PROCEDURE LOOKUP(ID: IDENTIFIER; VAR ATTR: FILEATTR; VAR FOUND: BOOLEAN); PROCEDURE IOTRANSFER (DEVICE: IODEVICE; VAR PARAM: IOPARAM; VAR BLOCK: UNIV PAGE); PROCEDURE IOMOVE(DEVICE: IODEVICE; VAR PARAM: IOPARAM); FUNCTION TASK: TASKKIND; PROCEDURE RUN(ID: IDENTIFIER; VAR PARAM: ARGLIST; VAR LINE: INTEGER; VAR RESULT: PROGRESULT); PROGRAM P(VAR PARAM: ARGLIST); "####### # IO # #######" "INSERT PREFIX HERE" VAR DRIVER: ARGTYPE; ARG: ARGLIST; OK: BOOLEAN; PROCEDURE INITWRITE; BEGIN IF TASK = INPUTTASK THEN IDENTIFY('INPUT: (:10:)') ELSE IDENTIFY('OUTPUT:(:10:)'); END; PROCEDURE WRITETEXT(TEXT: LINE); CONST NUL = '(:0:)'; VAR I: INTEGER; C: CHAR; BEGIN I:= 1; C:= TEXT(.1.); WHILE C <> NUL DO BEGIN DISPLAY(C); I:= I + 1; C:= TEXT(.I.); END; END; PROCEDURE WRITEINT(INT, LENGTH: INTEGER); VAR NUMBER: ARRAY (.1..6.) OF CHAR; DIGIT, REM, I: INTEGER; BEGIN DIGIT:= 0; REM:= INT; REPEAT DIGIT:= DIGIT + 1; NUMBER(.DIGIT.):= CHR(ABS(REM MOD 10) + ORD('0')); REM:= REM DIV 10; UNTIL REM = 0; FOR I:= 1 TO LENGTH - DIGIT - 1 DO DISPLAY(' '); IF INT < 0 THEN DISPLAY('-') ELSE DISPLAY(' '); FOR I:= DIGIT DOWNTO 1 DO DISPLAY(NUMBER(.I.)); END; PROCEDURE WRITEID(ID: IDENTIFIER); VAR I: INTEGER; C: CHAR; BEGIN FOR I:= 1 TO IDLENGTH DO BEGIN C:= ID(.I.); IF C <> ' ' THEN DISPLAY(C); END; END; PROCEDURE CONVRESULT(RESULT: PROGRESULT; VAR ID: IDENTIFIER); BEGIN CASE RESULT OF TERMINATED: ID:= 'TERMINATED '; OVERFLOW: ID:= 'OVERFLOW '; POINTERERROR: ID:= 'POINTERERROR'; RANGEERROR: ID:= 'RANGEERROR '; VARIANTERROR: ID:= 'VARIANTERROR'; HEAPLIMIT: ID:= 'HEAPLIMIT '; STACKLIMIT: ID:= 'STACKLIMIT '; CODELIMIT: ID:= 'CODELIMIT '; TIMELIMIT: ID:= 'TIMELIMIT '; CALLERROR: ID:= 'CALLERROR ' END; END; PROCEDURE WRITERESULT(ID: IDENTIFIER; LINE: INTEGER; RESULT: PROGRESULT); VAR ARG: IDENTIFIER; BEGIN WRITEID(ID); WRITETEXT(': LINE (:0:)'); WRITEINT(LINE, 4); DISPLAY(' '); CONVRESULT(RESULT, ARG); WRITEID(ARG); DISPLAY(NL); OK:= (RESULT = TERMINATED); END; PROCEDURE ERROR(TEXT: LINE); BEGIN WRITETEXT(TEXT); OK:= FALSE; END; PROCEDURE STARTIO; BEGIN OK:= TRUE; IF TASK = INPUTTASK THEN READARG(OUT, DRIVER) ELSE READARG(INP, DRIVER); IF DRIVER.TAG <> IDTYPE THEN ERROR('FILE IDENTIFIER MISSING (:10:)(:0:)'); INITWRITE; END; PROCEDURE TERMIO; VAR ARG: ARGTYPE; BLOCK: PAGE; EOF: BOOLEAN; BEGIN WITH ARG DO BEGIN TAG:= BOOLTYPE; BOOL:= OK END; IF TASK = INPUTTASK THEN BEGIN IF NOT OK THEN BEGIN BLOCK(.1.):= EM; WRITEPAGE(BLOCK, TRUE); END; WRITEARG(OUT, ARG); END ELSE BEGIN IF NOT OK THEN REPEAT READPAGE(BLOCK, EOF) UNTIL EOF; WRITEARG(INP, ARG); END; END; PROCEDURE SELECTDRIVER; VAR ATTR: FILEATTR; I: INTEGER; BEGIN WITH ARG(.1.) DO BEGIN TAG:= BOOLTYPE; BOOL:= FALSE END; FOR I:= 2 TO MAXARG DO ARG(.I.).TAG:= NILTYPE; LOOKUP(DRIVER.ID, ATTR, OK); IF OK & (ATTR.KIND <> SEQCODE) THEN WITH DRIVER DO BEGIN ARG(.2.):= DRIVER; ID:= 'DISK '; LOOKUP(ID, ATTR, OK); END; IF NOT OK THEN ERROR('FILE UNKNOWN(:10:)(:0:)') ELSE IF ATTR.KIND <> SEQCODE THEN ERROR('NOT EXECUTABLE(:10:)(:0:)'); END; PROCEDURE CALLDRIVER; VAR HEAPTOP, LINENO: INTEGER; RESULT: PROGRESULT; BEGIN MARK(HEAPTOP); RUN(DRIVER.ID, ARG, LINENO, RESULT); IF RESULT <> TERMINATED THEN WRITERESULT(DRIVER.ID, LINENO, RESULT) ELSE OK:= ARG(.1.).BOOL; RELEASE(HEAPTOP); INITWRITE; END; BEGIN IF TASK <> JOBTASK THEN REPEAT STARTIO; IF OK THEN SELECTDRIVER; IF OK THEN CALLDRIVER; TERMIO; UNTIL FALSE; END.