UNIVERSAL IOPARM--PARAMETERS FOR THE FOLLOWING ASSEMBLIES XPUNGE HSORG==400000 DEBUG==1 ;NON-ZERO IF DEBUGGING CODE IS GENERATED ;ACCUMULATOR ASSIGNMENTS F==0 ;FLAGS LFQFLG==1B1 ;NEWLINE REQUIRED BEFORE FURTHER OUTPUT. RD2FLG==1B2 ;READ TYPE FLAG = 1 IFF READ2. T==1 ;A TEMP T2==2 ;A TEMP T3==3 ;A TEMP T4==4 ;A TEMP A5==5 A6==6 A7==7 A10==10 A11==11 A12==12 A13==13 A14==14 R==15 ;SOMETIMES A RETURN ADDRESS OR SECOND PARAMETER A==16 ;PARAMETERS AND JUNK P==17 ;STACK CONTROL WORD OPDEF GOTO[JRST] OPDEF SKIP1[TRNA] OPDEF INVOKE[PUSHJ P,] OPDEF RETURN[POPJ P,] OPDEF SAVE[PUSH P,] OPDEF RESTORE[POP P,] TTY==1 ;TTY I/O CHANNEL NUMBER. DEFINE ERRMSG(A,B)< TTCALL 3,[ASCIZ/A'B /] EXIT 1, > ;EXAMPLE: ERRMSG(?IMPOSSIBLE LINE NUMBER--NOW IN ACCUMULATOR,\A) PRGEND TITLE NUMBER--NUMERIC I/O ROUTINES SEARCH IOPARM TWOSEG HSORG ENTRY READ,READ2,READPR,OUTFIX,OUTINT,OUTF.0,OUTF.1,OUTF.2,OUTF.3 EXTERN INCHR,OUTCHR,OUTSTR RELOC HSORG ;READ --SUBROUTINE TO READ ONE NUMBER FROM ONE LINE FROM THE TTY. ;READ2 --SUBROUTINE TO READ ONE NUMBER FROM PART OF A LINE. ;CALL: PUSHJ P,READ ; (END-OF-FILE RETURN WITH NUMBER IN A) ; (RETURN WITH SINGLE PRECISION FLOATING POINT IN A) READ2: TLOA F,(RD2FLG) ;INDICATE READ TYPE. READ: TLZ F,(RD2FLG) SAVE A5 SAVE A6 SAVE A7 MOVSI A5,(1.0) ;SET INITIAL SIGN. CLEAR A6, ;SET INITIAL NUMBER. CLEAR A7, ;SET INITIAL DECIMAL POINT CORRECTION. GOTO READLK ;LOOK FOR FIRST DIGIT READMN: CAIN A,"-" ;IF MINUS SIGN DETECTED, MOVN A5,A5 ;SWITCH THE SIGN. READLK: INVOKE INCHR ;GET A CHARACTER. GOTO READEF ;QUIT IF END-OF-FILE JSP R,DIGADD ;ADD A DIGIT TO THE NUMBER. GOTO READED ;QUIT IF END OF LINE. GOTO READMN ;KEEP LOOKING IF NOT DIGIT OR PERIOD. GOTO READFR ;IF PERIOD, COMPILE A FRACTION. ;ASSEMBLE INTEGER PART READIN: INVOKE INCHR ;GET A CHARACTER. GOTO READEF ;QUIT IF END OF FILE. JSP R,DIGADD ;ADD A DIGIT TO THE NUMBER. GOTO READED ;QUIT IF END OF LINE. GOTO READFN ;TERMINATE IF END OF NUMBER. GOTO READFR ;ADD A FRACTION IF A PERIOD. GOTO READIN ;REPEAT IF A DIGIT. ;ASSEMBLE FRACTION PART READFR: INVOKE INCHR ;GET A CHARACTER. GOTO READEC ;IF EOF, FINISH NUMBER AND QUIT. JSP R,DIGADD ;ADD DIGIT TO NUMBER. GOTO READCR ;IF BREAK OR NON-DIGIT, GOTO READCR ;CORRECT MAGNITUDE FOR FRACTION. GOTO READCR ;TREAT A PERIOD AS A DELIMITER. AOJA A7,READFR ;COUNT DIGITS TO RIGHT OF DECIMAL POINT. ;CORRECT FOR DECIMAL POINT READEC: SOS -3(P) ;CAUSE END OF FILE RETURN. MOVEI A,12 ;SET FALSE BREAK CHARACTER. READCR: SOJL A7,READFN ;DIVIDE RESULT BY ^D10 ONCE FOR FDVRI A6,(10.0) ;EACH DIGIT AFTER DECIMAL POINT. SOJGE A7,.-1 ;IGNORE REMAINDER OF LINE READFN: TLNE F,(RD2FLG) ; ... ONLY IF TYPE 1 READ. GOTO READED READNX: JSP R,BREAKT ;IS THIS CHARACTER A BREAK? GOTO READED ;YES--RETURN TO CALLER. INVOKE INCHR ;NO--TRY NEXT CHARACTER. GOTO READEF ;IF EOF, USE THE SPECIAL RETURN. GOTO READNX ;CONTINUE LOOKING FOR A BREAK. READED: AOS -3(P) ;CAUSE A NORMAL (SKIP) RETURN. READEF: MOVE A,A6 ;PROVIDE RESULT OF ALL THIS COMPUTATION. FMPR A,A5 ;GIVE IT THE DESIRED SIGN. RESTORE A7 ;WE SAVED THESE ABOVE. RESTORE A6 RESTORE A5 RETURN ;THE LAST RESORT. ;READPR--TRIES TO READ TWO NUMBERS FROM ONE LINE. ;CALL: INVOKE READPR ; (END-OF-FILE RETURN) ; (RETURN WITH FIRST NUMBER IN R, SECOND IN A) READPR: INVOKE READ2 RETURN SAVE A INVOKE READ SKIP1 AOS -1(P) RESTORE R RETURN ;OUTINT--SUBROUTINE TO TYPE A SIGNED INTEGER. ;CALL: MOVE A,INTEGER ; INVOKE OUTINT ; (RETURN) OUTINT: MOVM T,A ;GET MAGNITUDE OF THE INTEGER. JUMPGE A,OUTINX ;IF NUMBER WAS NEGATIVE, SAVE T ;OUTPUT A MINUS SIGN. MOVEI A,"-" ;IN THIS CASE, IT IS NOT PROPER TO INVOKE OUTCHR ;ASSUME THAT OUTCHR DOES NOT RESTORE T ;USE THE TEMPORARY ACCUMULATORS. OUTINX: IDIVI T,^D10 ;EXTRACT THE ONE'S DIGIT. SAVE T2 ;(T2=T+1 CONTAINS THE REMAINDER) SKIPE T ;IF THE OTHER DIGITS ARE NOT ZERO, INVOKE OUTINX ;OUTPUT THEM. RESTORE A ;NOW OUTPUT THIS ONE: ADDI A,"0" ;CONVERT TO ASCII. GOTO OUTCHR ;GIVE TO OUTPUT ROUTINE. ;NIFTY SUBROUTINES USE BY READ ;TO TEST BREAK CHARACTERS LAST IN BUFFER: IFE DEBUG, IFN DEBUG, ;BREAKT--TESTS FOR BREAK CHARACTERS ;CALL: MOVE A,CHARACTER ; JSP R,BREAKT ; (BREAK RETURN) ; (OTHER RETURN) BREAKT: CAIE A,7 ;TEST FOR BELL AND ESCAPE. CAIN A,33 BRKRET CAIE A,175 ;TEST FOR THE OLD ALTMODES. CAIN A,176 BRKRET CAIL A,12 ;TEST FOR LF,VT,FF. CAILE A,14 GOTO 1(R) BRKRET ;DIGADD--TESTS FOR BREAKS, PERIODS, DIGITS AND ADDS DIGITS TO RUNNING SUM IN A6. ;CALL: MOVE A,CHARACTER ; JSP R,DIGADD ; (BREAK RETURN--CHARACTER STILL IN A) ; (OTHER RETURN--CHARACTER STILL IN A) ; (PERIOD RETURN--CHARACTER STILL IN A) ; (DIGIT RETURN--FLOATING POINT DIGIT IN A) DIGADD: CAIN A,"." ;IF PERIOD, GIVE PERIOD RETURN. GOTO 2(R) CAIL A,"0" CAILE A,"9" ;IS CHARACTER A DIGIT? GOTO BREAKT ;NO--MUST BE A BREAK OR AN OTHER. SUBI A,"0" ;YES--CONVERT TO BINARY VALUE. FLTR A,A ;WE WANT FLOATING POINT ARITHMETIC. FMPRI A6,(10.0) ;APPEND THE DIGIT TO THE CURRENT NUMBER. FADR A6,A GOTO 3(R) ;GIVE A DIGIT RETURN. OUTF.3: MOVEI R,3 ;OUTPUT FLOATING POINT WITH 3 GOTO OUTFIX ;DIGITS AFTER THE DECIMAL POINT. OUTF.2: MOVEI R,2 ;OUTPUT FLOATING POINT WITH 2 GOTO OUTFIX ;DIGITS AFTER DECIMAL POINT. OUTF.1: MOVEI R,1 ;SAME AS ABOVE BUT ONLY ONE DIGIT. GOTO OUTFIX OUTF.0: MOVEI R,0 GOTO OUTFIX ;OUTFIX--SUBROUTINE TO OUTPUT A FLOATING POINT NUMBER IN FIXED POINT FORMAT ;CALL: MOVE A,FLOATINGPOINTNUMBER ; MOVEI R,NUMBEROFDIGITSAFTERDECIMALPOINT ; INVOKE OUTFIX ; (RETURN) OUTFIX: JUMPGE A,OUTMAG ;IF NUMBER IS NEGATIVE, MOVM A,A ;OUTPUT A MINUS SIGN AND SAVE A ;USE ITS MAGNITUDE INSTEAD. SAVE R MOVEI A,"-" INVOKE OUTCHR RESTORE R RESTORE A OUTMAG: CAML A,OUTLRG ;TEST FOR A NUMBER TOO LARGE. GOTO OUTOVR JUMPLE R,OUTFDG ;TEST FOR NO FRACTION REQUESTED. CAILE R,^D10 ;LIMIT FRACTION TO TEN PLACES. MOVEI R,^D10 FIX T4,A ;BREAK UP THE NUMBER INTO AN FLTR T,T4 ;INTEGRAL PART AND A FRACTIONAL PART. FSBR A,T ;SAVE THE INTEGRAL PART AND MOVE T3,R ;EXTRACT THE REQUIRED PLACES FMPRI A,(10.0) ;FROM THE FRACTIONAL PART. SOJG T3,.-1 FIXR T,A OUTFRC: IDIVI T,^D10 ;THIS CODE PUSHES THE FRACTION SAVE T2 ;DOWN INTO THE STACK. SOJLE R,OUTRND INVOKE OUTFRC OUTFRX: RESTORE A ;THIS CODE POPS THE FRACTION ADDI A,"0" ;UP OUT OF THE STACK AND PRINTS IT. GOTO OUTCHR OUTRND: ADD T4,T ;IF THE FRACTION ROUNDS MOVE A,T4 ;UP TO 1.000, FUDGE IT. INVOKE OUTINT ;NOW WE CAN OUTPUT THE INTEGER, MOVEI A,"." ;FRACTION, AND PERIOD. INVOKE OUTCHR GOTO OUTFRX OUTFDG: FIXR A,A ;IN CASE NO FRACTION REQUESTED. GOTO OUTINT OUTOVR: MOVEI A,[ASCIZ/****/] ;IN CASE OF OVERFLOW. GOTO OUTSTR OUTLRG: 1.0E10 LIT PRGEND TITLE ALTFIL--ALTERNATE I/O AID SEARCH IOPARM TWOSEG HSORG ENTRY FILINF EXTERN FILSPC,FILERR,INCHR,OUTSTR,BRKOUT,ENDMSG,TTYCLS RELOC HSORG ;SETUP OPEN AND LOOKUP BLOCKS (I.E. READ FILE SPECIFICATION): ;ALSO CHECK FOR PROPER I/O MODE: ;CALL: MOVE A,OPENBLOCKADDRESS=LOOKUPBLOCKADDRESS-3 ; MOVEI R,[DEFAULT OPEN AND LOOKUP BLOCK CONTENTS] ; INVOKE FILINF ; (TTY-EOF-RETURN -- FILE SPEC NOT SET) ; (NORMAL RETURN) FILINF: SAVE A5 ;SAVE SOME USEFUL ACCUMULATORS. SAVE A6 MOVE A5,A MOVE A6,R FILAGN: MOVEI A,[ASCIZ/ENTER FILE SPECIFICATION: /] INVOKE OUTSTR INVOKE BRKOUT MOVSI T,(A6) ;SET DEFAULT ARG BLOCK CONTENTS. ORI T,(A5) BLT T,5(A5) GETPPN T, ;SET DEFAULT PPN: JFCL MOVEM T,6(A5) MOVEI T4,FILINP ;SET PARAMETERS FOR FILSPC. MOVEI T3,0 MOVSI T2,(A5) ORI T2,3(A5) JSP T,FILSPC ;USE A CONVENIENT FILE SPEC READER. GOTO FILBDS ;RETURNS HERE IF SYNTAX ERROR. JUMPN T2,FILTMY ;T2=0 IFF ONLY ONE SPEC GIVEN. MOVE T,1(A5) ;GET CHARACTERISTICS OF REQUESTED DEVICE. DEVCHR T, MOVEI T2,1 MOVE T3,(A5) ;MAKE SURE IT TAKES REQUESTED I/O MODE. LSH T2,(T3) AND T2,T JUMPE T2,FILBDV AOS -2(P) ;GIVE SKIP RETURN IF ALL OK. FILRET: RESTORE A6 RESTORE A5 RETURN ;REQUIRED SUBROUTINES AND GARBAGE: FILINP: INVOKE INCHR ;TTY INPUT ROUTINE FOR FILSPC. GOTO FILRET ;PASS BACK EOF RETURNS. CAIN A,15 GOTO FILINP ;IGNORE CARRIAGE RETURNS. CAIN A,12 MOVEI A,0 ;REPLACE LINE FEEDS WITH NULS. CAIN A,32 ;CONTROL Z'S MEAN END OF FILE. GOTO FILINP MOVE T2,A ;PUT CHAR WHERE FILSPEC EXPECTS IT. JSP T4,(T4) ;RESUME FILSPC GOTO FILINP FILTMY: MOVEI A,[ASCIZ/?ONLY ONE FILE CAN BE SPECIFIED/] FILTMX: INVOKE ENDMSG FILTMZ: INVOKE TTYCLS ;IGNORE REST OF TTY BUFFER. GOTO FILAGN FILBDV: MOVEI A,[ASCIZ"?I/O DEVICE DOES NOT TAKE REQUESTED I/O MODE!"] GOTO FILTMX FILBDS: JSP T,FILERR ;IN CASE OF ERROR RETURN FROM FILSPC. GOTO FILTMZ LIT PRGEND TITLE IORUTS--SOME HANDY TTY I/O ROUTINES. SEARCH IOPARM TWOSEG HSORG ENTRY INCHR,TTYINT,TTYCLS,OUTCHR,BRKOUT,WAITTY,OUTSTR,ENDMSG,NEWLIN,PAGE IFN DEBUG, RELOC 0 TTYOHD: BLOCK 3 ;TTY OUTPUT BUFFER HEADER TTYIHD: BLOCK 3 ;TTY INPUT BUFFER HEADER WATBLK: BLOCK 2 ;ARG BLOCK FOR TRMOP. UUO RELOC HSORG ;INCHR --ROUTINE TO GET ONE CHARACTER FROM THE TTY. ;CALL: INVOKE INCHR ; (END-OF-FILE RETURN) ; (RETURN WITH A CHARACTER IN A) INCHR: SOSGE TTYIHD+2 ;DECREMENT BYTE COUNT. GOTO GETBUF ;IF BUFFER IS EMPTY, HAVE IT FILLED. ILDB A,TTYIHD+1 ;GET A CHARACTER. JUMPE A,INCHR ;IF NULL, KEEP TRYING. AOS (P) RETURN GETBUF: IN TTY, ;GET A BUFFER FROM THE MONITOR. GOTO INCHR ;IF NO ERRORS, RESUME INCHR. GETSTS TTY,A ;ELSE GET THE TTY STATUS. TRNN A,1B22 ;SEE IF END OF FILE. GOTO TTYIER ;NO--MUST BE OTHER ERROR. ;YES--DUMP ALL PENDING OUTPUT. TTYCLS: CLOSE TTY, ;REINIT THE TTY. TLZ F,(LFQFLG) ;CLEAR THE NEWLINE FLAG. RETURN ;GIVE THE END-OF-FILE RETURN. TTYIER: ERRMSG(?INP ERR ON TTY. FILE STATUS IN AC,\A) TTYINT: OPEN TTY,TTYBLK ;INITIALIZE THE TTY. HALT INBUF TTY,1 OUTBUF TTY,1 TLZ F,(LFQFLG) ;CLEAR THE NEWLINE FLAG. PJOB T, ;SET UP THE TTY WAIT DATA. TRMNO. T, HALT MOVEM T,WATBLK+1 MOVEI T,<.TOSOP==2> MOVEM T,WATBLK RETURN ;RETURN TO CALLER TTYBLK: 1 ;TTY OPEN ARGUMENT BLOCK: MODE=ASCII LINE. SIXBIT/TTY/ TTYOHD,,TTYIHD ;OUTCHR--ROUTINE TO OUTPUT ONE CHARACTER TO THE TTY ;CALL: MOVE A,CHARACTER ; INVOKE OUTCHR ; (RETURN) OUTCHR: TLZE F,(LFQFLG) ;GOTO A NEW LINE IFF REQUIRED. INVOKE OUTCHL SOSG TTYOHD+2 ;ADVANCE BYTE COUNTER. INVOKE BRKOUT ;OUTPUT THE BUFFER IF FULL. OUTCHX: IDPB A,TTYOHD+1 ;DUMP BYTE INTO BUFFER. RETURN ;RETURN TO CALLER. OUTCHL: SAVE A ;DO THIS TO TYPE A NEWLINE INVOKE NEWLIN ;WHILE SAVING AC A. RESTORE A RETURN BRKOUT: OUT TTY, ;GET AN EMPTY BUFFER FROM THE MONITOR. RETURN ;IF NO ERRORS, RESUME NORMAL OUTPUT, GETSTS TTY,T ;ELSE SEND AN APPROPRIATE ERROR MESSAGE AND QUIT. ERRMSG(?OUTP ERR ON TTY. FILE STATUS IN AC,\T) ;WAITTY--WAIT UNTIL TTY OUTPUT DONE OR TTY INPUT READY ;CALL: INVOKE WAITTY ; (RETURN) WAITTY: INVOKE BRKOUT ;GIVE OUTPUT BUFFER TO MONITOR. WAITTL: MOVE T,WATLOC TRMOP. T, ;SKIP IF OUTPUT NOT DONE. RETURN ;ELSE END WAIT. MOVE T,WATWRD ;MARK TIME FOR 1 SECOND. HIBER T, HALT SKPINL ;IF NO INPUT LINE READY, GOTO WAITTL ;TRY AGAIN. RETURN ;ELSE END WAIT. WATLOC: XWD 2,WATBLK WATWRD: EXP 1B13+^D1500 ;OUTSTR--SUBROUTINE TO TYPE A STRING OF ASCII CHARACTERS. ;CALL: MOVEI A,[ASCIZ/CHARACTER STRING/] ; INVOKE OUTSTR ; (RETURN) OUTSTR: SAVE A7 MOVSI A7,(POINT 7,0) ;CONSTRUCT A BYTE POINTER ORI A7,(A) ;FOR THE MESSAGE. SKIP1 OUTSTX: INVOKE OUTCHR ;OUTPUT A CHARACTER. ILDB A,A7 ;GET THE NEXT CHARACTER. JUMPN A,OUTSTX ;IF THIS ONE IS NOT NULL, REPEAT. RESTORE A7 RETURN ;ENDMSG--SUBROUTINE TO TYPE A MESSAGE AND A NEW LINE. ;NEWLINE--OUTPUTS A CARRIAGE RETURN AND A LINE FEED. ENDMSG: INVOKE OUTSTR ;OUTPUT THE MESSAGE. NEWLIN: MOVEI A,LINCHR ;OUTPUT A CARRIAGE RETURN. GOTO OUTSTR LINCHR: BYTE (7)15,12 ;PAGE --OUTPUTS A FORM FEED. PAGE: MOVEI A,14 GOTO OUTCHR LIT END