STTL () SUBTTL ALCOR and DECOR -- Set up disk (or TTY) buffers ;Routine to allocate core for buffers ;Calling sequence: ; MOVEI T1,(amount of core needed) ; PUSHJ P,ALCOR ; *return* Address of core returned in T1 or -1 if none ; Uses T2 and T3 ALCOR: MOVEI T2,CORSIZ ;Assume first time here SKIPN CORBUF ;Buffer in use? MOVEM T2,CORBUF ;First time here, entire buffer is free MOVEI T2,1(T1) ;Get size + 1 (for the overhead word) MOVEI T1,CORBUF ;Start at beginning ;The word pointed to by T1 is positive if the chunk is free, negative if used ALCOR1: CAMLE T2,(T1) ;Will request fit in this chunk? JRST ALCOR2 ;No MOVN T3,T2 ;Set to negative of size EXCH T3,(T1) ;Mark this chunk as in use, get old free size SUB T3,T2 ;Decrement size of free space ADDI T2,(T1) ;T2 now points past requested chunk MOVEM T3,(T2) ;Store new free size ADDI T1,1 ;Point to the chunk (instead of overhead word) POPJ P, ;Return with addr in T1 ;Chunk is not big enough if (T1) is positive, chunk is in use if (T1) is ;negative, or CORBUF is full if (T1) is zero. ALCOR2: MOVM T3,(T1) ;Get the overhead word JUMPE T3,ALCOR3 ;Have to ask FOROTS if hit end of CORBUF ADD T1,T3 ;Point to the next overhead word JRST ALCOR1 ;Try again ;Here when CORBUF is full, get memory from FOROTS IFE FTAPLT,< IF2, ALCOR3: OUTSTR [ASCIZ / ?PLTIOD - Ran out of buffer space in ALCOR/] HALT . DECOR2: OUTSTR [ASCIZ / ?PLTIOD - Attempt to return wrong buffer space in DECOR/] HALT . > ;End of IFE FTAPLT IFN FTAPLT,< ALCOR3: MOVEI T1,-1(T2) ;Get the requested size into T1 SKIPA T2,[ALCOR.##] ;Addr of routine DECOR2: MOVEI T2,DECOR.## ;Addr of routine MOVEM T1,TEMP ;Store in memory XMOVEI L,[-1,,0 ;1 arg INTEGER TEMP ;Address of arg ]+1 ;Point to args PUSHJ P,(T2) ;Ask FOROTS to do core management MOVE T1,0 ;Result was in AC0 POPJ P, ;Return with result in T1 > ;End of IFN FTAPLT SUBTTL ALCOR and DECOR -- Release disk (or TTY) buffers ;Routine to deallocate core for buffers ;Calling sequence: ; MOVEI T1,(addr returned from ALCOR) ; PUSHJ P,DECOR ; *return* ; Uses T2 and T3 DECOR: MOVEI T1,-1(T1) ;Get addr of overhead word CAIL T1,CORBUF ;Is this an addr in CORBUF? CAIL T1,CORBUF+CORSIZ JRST DECOR2 ;No, must be for FOROTS SKIPL T2,(T1) ;Should have -SIZE IFE FTDBUG, ;Bug, don't make things worse IFN FTDBUG,)> MOVMS (T1) ;Set -SIZE to +FREE MOVEI T1,CORBUF ;Start with first chunk ;Try to consolidate contiguous free space, pointed to by T1 DECOR1: MOVM T2,(T1) ;Get -SIZE or +FREE ADDI T2,(T1) ;Point to size word at start of next chunk SKIPN (T2) ;ZERO at end of CORBUF? POPJ P, ;Yes, all done SKIPL (T1) ;Is either chunk in use? SKIPG (T2) ;(negative means in-use) JRST [MOVE T1,T2 ;Yes, point to start of next chunk JRST DECOR1] ;Look for 2 adjacent free chunks MOVE T3,(T2) ;No, get size of 2nd free chunk ADDM T3,(T1) ;Add it into the size of the first chunk JRST DECOR1 ;See if next chunk is also free IF2, %OUTST:: ;Output a message to the terminal OUTSTR (T1) ;*KLUDGE* POPJ P, TRACE: MOVEM 0,TRACEA+0 ;Preserve all ACs MOVE 0,[1,,TRACEA+1] BLT 0,TRACEA+17 PUSHJ P,TRACE.## MOVSI 16,TRACEA+0 ;Restore all ACs BLT 16,16 IFN , POPJ P, SUBTTL OUTDMP, OUTSTG, OUTWRD - Output a string of bytes ;Routine to output a string of bytes to plotter ;Call with byte pointer in T1, byte count in T2 (T2=0 if terminated by 0 byte) OUTDMP: PUSHJ P,OUTSTG ;Output the string TTYDMP: TXNE P4,P4.TTY ;Output to a terminal? PUSHJ P,DUMPBF ;Yes, dump output buffer POPJ P, OUTSTG: PUSH P,T2 ;Preserve T2 MOVEI T2,0 ;ASCIZ string PUSHJ P,OUTWRD ;Send the bytes T2POPJ: POP P,T2 ;Restore T2 POPJ P, ;Return ;Routine to output a bunch of words. Call with byte pointer in T1, ;byte count in T2, or zero in T2 if T1 points to an ASCIZ string. OUTWRD: TLCE T1,-1 ;LH of pointer 0 TLCN T1,-1 ; or -1? HRLI T1,(POINT 7,) ;Yes, default to 7-bit bytes PUSH P,T1 ;Store pointer OUTST1: ILDB T1,(P) ;Get a byte SKIPG T2 ;If T2 started at zero, JUMPE T1,T1POPJ ; then stop at end of ASCIZ PUSHJ P,OUTBYT ;Send it JUMPE T2,OUTST1 ;Always loop if ASCIZ SOJG T2,OUTST1 ;Loop if more bytes to output T1POPJ: POP P,T1 ;Updated pointer in T1 POPJ P, SUBTTL RETZER, RETM1, CPOPJ, CPOPJ1, T1POPJ, T2POPJ RETZER: TDZA T1,T1 ;Return 0 in T1 RETM1: SETO T1, ;Return -1 in T1 POPJ P, CPOPJ1: AOS (P) ;Skip return CPOPJ: POPJ P, ;Return SUBTTL Output numbers and bytes ;Output a decimal number. Uses T1 and T2 OUTDEC: IDIVI T1,^D10 ;Get a digit HRLM T2,(P) ;Store on stack SKIPE T1 ;If not done, PUSHJ P,OUTDEC ; recurs HLRZ T1,(P) ;Get digit ADDI T1,"0" ;Make printing PFALL OUTBYT ;Output the byte and return ;Output the byte in T1. Preserves all ACs OUTBYT: DMOVEM T1,OUTBT1 ;Preserve byte across call TXNN P4,P4.TT8 ;Sending 8-bit bytes to the terminal? JRST OUTBY1 ;No MOVEI T2,(T1) ;(Taken from page 2-114 of LSH T2,-4 ; the Processor Reference XORI T2,(T1) ; Manual) TRCE T2,14 TRNN T2,14 XORI T1,200 TRCE T2,3 TRNN T2,3 XORI T1,200 ;T1 is 7-bits plus even parity OUTBY1: SOSG BUFR.C(P4) ;Decrement byte count PUSHJ P,DUMPBF ;Get another output buffer IDPB T1,BUFR.P(P4) ;Store byte in buffer AOS BYTE.C(P4) ;Increment the cumulative byte count DMOVE T1,OUTBT1 ;Restore original byte and T2 POPJ P, SUBTTL Bufferred I/O, TOPS-10 and TOPS-20 ;DUMPBF - Dump output buffer, get a new one. ;Call: with P4 set up ; PUSHJ P,DUMPBF ; *only return* Preserves all ACs IF2, TOPS10< ;Use regular buffered I/O DUMPBF: PUSH P,T1 ;Preserve T1 PUSH P,T2 MOVE T2,BUFR.N(P4) ;Channel number HRRI T2,.FOOUT ;Output function MOVE T1,[1,,T2] ;1 word argument FILOP. T1, ;Get a new buffer MOVX T1,IO.ERR ;Unknown error TXNE T1,IO.ERR ;Any output errors? JRST [ERRSTR (FTL,) HALT .+1] POP P,T2 ;No errors POP P,T1 ;Restore ACs POPJ P, > ;End TOPS10 TOPS20< DUMPBF: PUSH P,T1 ;Save all ACs PUSH P,T2 PUSH P,T3 MOVEI T1,0 IDPB T1,BUFR.P(P4) ;Terminate with zero byte HLRZ T1,BUFR.N(P4) ;JFN HRRO T2,BUFR.N(P4) ;Pointer to buffer MOVEI T3,0 ;Terminated by a null SOUT% ;Output the buffer HRRZ T1,BUFR.N(P4) ;Get addr of buffer HLL T1,BUFR.H(P4) ;Make byte pointer MOVEM T1,BUFR.P(P4) ;Reset pointer to buffer HRRZ T1,BUFR.H(P4) ;Get initial byte count MOVEM T1,BUFR.C(P4) ;Set it POP P,T3 ;Restore ACs POP P,T2 POP P,T1 POPJ P, > ;End of TOPS20 SUBTTL GETNAM - Get file name from caller ;Routine to decode output device and filename for subroutine PLOTS ;Call: DMOVE T2,[POINT 7,[ASCII/DEV:FILNAM/] ; EXP BYTECOUNT] ; PUSHJ P,GETNAM Called only by PLOTS routine ; *return* Sets up Z.DNAM and Z.FNAM for device:file ;TOPS20 is also limited to 10 chars max GETNAM: MOVSI T1,'PLT' ;Logical device name for output MOVEM T1,Z.DNAM ;Save default output device SKIPE T2 ;Was byte pointer supplied? SKIPN T3 ;And byte count? JRST GETNA3 ;No, use name of program SKIPE T1,(T2) ;Is the double-precision variable zero? CAMN T1,BLANKS ; or all blank? JRST GETNA3 ;Yes, forget it HRLI T2,(POINT 7,) ;Make byte pointer ;Look for file name GETNA0: MOVE T1,[POINT 6,Z.FNAM] SETZM Z.FNAM ;Clear accumulated name GETNA1: SOJL T3,GETNA2 ;Stop at end of string ILDB T4,T2 ;Get a char JUMPE T4,GETNA2 ;In case count is wrong CAIL T4,140 ;Lowercase? SUBI T4,40 ;Yes, convert SUBI T4," "-' ' ;Convert to SIXBIT CAIL T4,'0' ;Alphameric? CAILE T4,'Z' JRST GETNA2 ;No CAILE T4,'9' CAIL T4,'A' JRST [IDPB T4,T1 ;Yes, put in Z.FNAM TLNE T2,770000 ;Done 6 chars? JRST GETNA1 ;No, loop JRST GETNA2 ] ;Yes, stop GETNA2: MOVE T1,Z.FNAM ;Get name CAIN T4,':' ;End of device? JRST [MOVEM T1,Z.DNAM ;Yes, store device name JRST GETNA0 ] ; and go for file name JUMPN T1,GETNA4 ;Use file name if nonzero GETNA3: ;Here if caller did not specify a file name TOPS10< HRROI T1,.GTPRG ;Get the name of this program GETTAB T1, > ;End of TOPS10 MOVSI T1,'PLT' ;Can never happen MOVEM T1,Z.FNAM ;Store implicit file name GETNA4: POPJ P, ;Z.DNAM and Z.FNAM are set up SUBTTL NEWFIL - Create new file name ;NEWFIL - Sets up a new file for output. Increments file name and sets up ;LOOKUP block. If the program is 'TEST', the files created will be ;'TEST.PLT', 'TEST02.PLT', 'TEST03.PLT', etc ;Call: ; PUSHJ P,NEWFIL ; *return* TOPS10< ;Unique names not needed on TOPS-20 due to file version numbers NEWFIL: SKIPE T1,FILE.N(P4) ;Has a file name been set up for this plotter? JRST [PUSHJ P,INCNAM ;Yes, increment old name MOVEM T1,FILE.N(P4) ;Store for next time JRST NEWFI1] ; and use it MOVE T1,Z.FNAM ;No, get name from call to PLOTS SETO T2, ;Get full mask NEWFI0: TDNE T1,T2 ;Found trailing spaces? JRST [LSH T2,-6 ;No, shift mask JRST NEWFI0 ] ;Try again AND T2,[SIXBIT /000000/] IOR T1,T2 ;Expand 'ABC' to 'ABC000', 'GRAPH' to 'GRAPH0' PUSHJ P,INCNAM ;Increment it (so 6th character is '1') MOVEM T1,FILE.N(P4) ;Store to be incremented again for 2nd plot MOVE T1,Z.FNAM ;Get original file name and use it for 1st plot NEWFI1: MOVEM T1,ENT+0 ;Store file name HLLZ T1,PLTEXT(P4) ;Extension (.PLT, .PIC, or .TEK) MOVEM T1,ENT+1 SETZM ENT+2 ;Default protection SETZM ENT+3 ;Default directory MOVE T1,FILE.D(P4) ;Get output device MOVEM T1,FLP+.FODEV ;Put in FILOP. block POPJ P, PAGE ;Routine to increment name in T1. 'ABCDEF' will go to 'ABCDE1', ;'ABCDE1' will go to 'ABCDE2', 'ABCDE9' to 'ABCD10', etc. ;Uses T2-T4, returns new name in T1. Called only by NEWFIL, above INCNAM: MOVEI T2,6 ;Start with 6th position INCNA1: MOVE T3,[ POINT 6,T1,5 ;1st position POINT 6,T1,11 ;2nd POINT 6,T1,17 ;3rd POINT 6,T1,23 ;4th POINT 6,T1,29 ;5th POINT 6,T1,35 ;6th ]-1(T2) ;Get byte pointer LDB T4,T3 ;Get character CAIL T4,'0' ;Digit? CAILE T4,'9' ; ... JRST [MOVEI T4,'1' ;No DPB T4,T3 ;Set byte to 1 POPJ P, ] ;And return ADDI T4,1 ;Yes, increment digit CAIN T4,'9'+1 ;Incremented 9? MOVEI T4,'0' ;Yes, reset to 0 DPB T4,T3 ;Store new char CAIN T4,'0' ;Incremented to 0? SOJG T2,INCNA1 ;Yes, increment next digit also POPJ P, ;Return with name in T1 > ;End of TOPS10 SUBTTL Open output file ;SETODV - Routine to set up output device ;If logical device is not the physical or spooled plotter, use it. TOPS10< SETODV: MOVE T1,Z.DNAM ;Get specified device MOVE T2,T1 ;Copy DEVTYP T2, ;Get device type MOVEI T2,0 ;Never happens JUMPE T2,SETOD1 ;Jump if plotter unspooled and no such device ANDX T2,TY.DEV ;Only the type CAXE T2,.TYPLT ;Is it PLT: (or logical name for PLT:)? JRST SETOD2 ;No, use it SETOD1: MOVSI T1,'DSK' ;Yes, use DSK: instead TXNE P4,P4.TTY ;Unless routine is for a graphics terminal MOVSI T1,'TTY' ; in which case use TTY: SETOD2: MOVEM T1,FILE.D(P4) ;Device to be used by this plotter POPJ P, > ;End of TOPS10 TOPS20< IFN FTDSK, SETODV: MOVSI T1,'TTY' ;Output is to TTY only MOVEM T1,FILE.D(P4) POPJ P, > ;End of TOPS20 ;ISACTV - Routine to see if the I/O channel is still active ;Call: PUSHJ P,ISACTV ; *not active* ; *is active* Preserves T1 TOPS10< ;Skip return if channel is still assigned ISACTV: HLRZ T2,BUFR.N(P4) ;Get channel number DEVNAM T2, ;Get device associated with it SKIPE T2 ;If DEVNAM returned nonzero, AOS (P) ; then the I/O channel is still OPEN POPJ P, > ;End of TOPS10 TOPS20 ISACTV: POPJ P, ;Bypass check for terminals > ;End of TOPS20 ;OPNFIL - Routine to open and create a new file ;Call: with P4 set up ; PUSHJ P,OPNFIL ; *only return* T1 is non-zero if any errors occured TOPS10< ;Do a non-superseding ENTER, incrementing the file name if necessary IF2, FTDSKO='FILOP.' IFE , IFE , OPNFIL: HLLZ T1,BUFR.N(P4) ;Get previous channel number JUMPN T1,OPNFI0 ;Use it if channel still open IFE ,< PUSHJ P,ALCHN ;Get a free channel from FOROTS HRLZS T1 > ;Put in LH IFE ,< MOVX T1,FO.ASC > ;Set bit to assign extended channel OPNFI0: HRRI T1,.FOCRE ;Code to create new file TXO T1,FO.PRV ;Allow [1,2] to write in [11,10,TEST] MOVEM T1,FLP+.FOFNC ;Channel,,code LDB T1,[POINTR PLTINI(P4),IN.BYT] ;Get the byte size LDB T2,[POINTR PLTINI(P4),IN.MOD] ;Get the I/O mode ;Enter here with byte size in T1, I/O mode in T2, FLP+.FOFNC set up IF2, REOPEN: MOVEM T1,BYTSIZ ;Save for after FILOP. MOVEM T2,FLP+.FOIOS ;Store mode .CREF IN.ACK ;This flag not used yet (for PTC-5 in the future) MOVSI T1,BUFR.H(P4) ;Get addr of 3 word buffer header MOVEM T1,FLP+.FOBRH ;Set for output only MOVSI T1,2 ;2 output buffers MOVEM T1,FLP+.FONBF MOVEI T1,ENT ;Address of ENTER block MOVEM T1,FLP+.FOLEB PUSHJ P,NEWFIL ;Set up device and ENTER block ;Reserve space for output buffers OPNFI1: MOVE T1,FILE.D(P4) ;Get current output device MOVEM T1,FLP+.FODEV ;Store for FILOP. HRRZ T1,BUFR.N(P4) ;Get address of current buffers JUMPN T1,OPNFI2 ;Use old space if set up MOVEI T1,FLP+.FOIOS ;Point to OPEN block DEVSIZ T1, ;Get size of buffers for this device JRST RETM1 ;No such device, return -1 HRRZS T1 ;Keep only buffer size IMULI T1,2 ;Get size of 2 buffers PUSHJ P,ALCOR ;Reserve space for the buffers OPNFI2: HRRM T1,BUFR.N(P4) ;Remember address for DECOR JUMPLE T1,CPOPJ ;Abort if no core available MOVE T1,.JBFF## ;Get current first-free MOVEM T1,SAVEFF ;Save .JBFF for later PAGE ;Here to create a new plot file using a non-superseding ENTER. OPNFI3: HRRZ T1,BUFR.N(P4) ;Get addr of buffer MOVEM T1,.JBFF## ;Tell monitor where to put buffers MOVE T1,[FLPLEN,,FLP];Point to args FILOP. T1, ;Open file for output JRST OPNERR ;Could be file already exists MOVE T1,BYTSIZ ;Get byte size LSH T1,^D18+6 ;Shift to position MOVEM T1,BUFR.P(P4) ; in byte pointer MOVE T1,FLP+.FOFNC ;Get channel number assigned ANDX T1,FO.CHN ;Only the channel number (not FO.PRV) HLLM T1,BUFR.N(P4) ;Store MOVE T1,SAVEFF ;Get old .JBFF MOVEM T1,.JBFF## ;Reset first-free JRST RETZER ;Return 0 in T1 ;Here when FILOP. failed. Function .FOCRE returns error if file already exists. OPNERR: CAIN T1,ERAEF% ;Already existing file? JRST [PUSHJ P,NEWFIL ;Yes, increment file name JRST OPNFI3 ] ;Try again MOVE T1,SAVEFF ;No, reset first free MOVEM T1,.JBFF## ;... MOVE T1,FLP+.FOFNC ;Get channel number HLLM T1,BUFR.N(P4) ;Store for CLSFIL JRST CLSFIL ;Release the channel and its buffers > ;End of TOPS10 TOPS20< IFN FTDSK, OPNFIL: MOVX T1,.PRIOU ;Use primary output as JFN HRLZM T1,BUFR.N(P4) MOVEI T1,^D80 ;Buffer size in words PUSHJ P,ALCOR HRRM T1,BUFR.N(P4) ;Store addr of buffer HRLI T1,(POINT 7,) ;Make into byte pointer MOVEM T1,BUFR.P(P4) HRRI T1,<^D80*5>-1 ;Byte count HRRZM T1,BUFR.C(P4) MOVEM T1,BUFR.H(P4) ;Original pointer LH and original count POPJ P, > ;End of TOPS20 ;CLSFIL - Routine to close the file, release the channel, and free the buffer ;Call: MOVE P4,PLTTAB(P3) ;Must have P4 set up ; PUSHJ P,CLSFIL ; *only return* TOPS10< ;RELEASE the channel after CLOSE CLSFIL: PUSHJ P,CLOSEF ;Do a CLOSE on the channel MOVE T1,BUFR.N(P4) ;Get channel number in left half HRRI T1,.FOREL ;Get code MOVEM T1,FLP+.FOFNC ; to RELEASe channel MOVE T2,[1,,T1] ;Point to args FILOP. T2, ;Release the channel JFCL ;Can never fail HRRZ T1,BUFR.N(P4) ;Get address of PLT buffers PUSHJ P,DECOR ;Deallocate the core IFE ,< HLRZ T1,BUFR.N(P4) ;Get channel number PUSHJ P,DECHN ;Give it back to FOROTS > ;End of 'UUOS' SETZM BUFR.N(P4) ;No channel and no buffers assigned JRST RETM1 ;Return -1 in T1 to signify failure ;CLOSEF - Close the output file checking for errors CLOSEF: MOVE T1,BUFR.N(P4) ;Get channel number in left half HRRI T1,.FOCLS ;Get code MOVEM T1,FLP+.FOFNC ; to CLOSE file MOVE T2,[1,,T1] ;Point to args FILOP. T2, ;CLOSE file (keeping channel around) SKIPA ;Should never happen POPJ P, ERRSTR (WRN,<% PLOT - Error closing plot>) POPJ P, > ;End of TOPS10 TOPS20< IFN FTDSK, CLSFIL: POPJ P, ;Don't close channel to terminal > ;End of TOPS20 SUBTTL Translate 'TTY' to appropriate plotter type ND FTTERM,0 ;Defined non-zero if any graphics terminal support IFE FTTERM, ;Return -1 in T1 if no graphics terminals IFN FTTERM,< ;This routine is called only of the plotter type is 'TTY' TOPS20< SPTYPT: MOVX T1,DTTPLT ;Use default of ASCII/TEK/ POPJ P, > ;End of TOPS20 TOPS10< ;Get terminal type corresponding to the output TTY: SPTYPT: MOVE T1,Z.DNAM ;Get device name (PLT: or TTY:) MOVE T2,T1 ;Need second copy DEVCHR T1, ;Check for TTY vs PLT vs DSK vs NUL TXNN T1,DV.TTY ;Is it a terminal (or NUL:)? MOVSI T2,'TTY' ;No, use TTY: instead of PLT: or DSK: MOVEM T2,Z.DNAM ;Store in case changed IONDX. T2, ;Get UDX of device SETZ T2, ;No such device TXNN T2,.UXTRM ;Is logical name TTY: really a terminal? JRST RETM1 ;No, give error return for no such plotter MOVX T1,.TOTRM ;Yes, get terminal type from monitor MOVE T3,[2,,T1] ;Point to args TRMOP. T3, ;Get it MOVEI T3,0 ;If 6.03A, set to default TTY plotter MOVSI T1,-TTYNUM ;Get length of table SETYPA: CAME T3,TTY6NM(T1) ;Does monitor type match (SIXBIT) ? AOBJN T1,SETYPA ;No match, try next one SKIPGE T1 ;Found a match? JRST [MOVE T1,TTY7NM(T1) ;Yes, get it POPJ P, ] HLRZ T3,T1 ;No, get first 3 letters of terminal type CAIN T3,'VT1' ;VT100 family? SKIPA T1,[ASCII /VT125/] ;Yes MOVX T1,DTTPLT ;Unknown terminal type, set default POPJ P, ;Go back and check this plotter type PAGE ;Still in IFN FTTERM ;The following table of terminal types needs to be updated to match ;the terminals defined at your site. The table currently includes only ;terminal types defined at CSM by MONGEN dialog. DEFINE TTYS, IFDEF TEKINI,< XX TK4006,4006;;Tektronix XX TK4010,4010 XX TK4012,4012 XX TK4025,4025 XX TK4113,4113 XX TEK,TEK > ;End of IFDEF TEKINI IFDEF RGSINI,< XX VK100,GIGI XX GIGI,GIGI XX VT125,VT125 XX VT100,VT125;;Assume VT125 or VK100(GIGI) in VT100 mode > ;End of IFDEF RGSINI SALL> ;End of DEFINE TTYS DEFINE XX(SIXNAM,ASCNAM),< SIXBIT /SIXNAM/ ;ASCNAM > TTY6NM: TTYS ;List of monitor types in SIXBIT TTYNUM==.-TTY6NM ;Number of equivalences DEFINE XX(SIXNAM,ASCNAM),< ASCII /ASCNAM/ ;SIXNAM > TTY7NM: TTYS ;List of plotter types in ASCII > ;End of TOPS10 SPTYPT > ;End of IFN FTTERM SUBTTL TTYINI - Set up terminal IFE FTTERM, IFN FTTERM,< TOPS10< ;Initialize the terminal for output. By using .IOBIN (binary mode) output, ;the monitor will pass tabs, formfeeds, and blank lines regardless of terminal ;settings, and will not do auto CRLF. As long as the job is not in a binary ;input wait, Control-C will stop the program. By using .IOPIM (packed image) ;for input,;the monitor will not echo the response, and will pass nulls and ;Control-C to subroutine XHAIRS. TTYINI: TXZ P4,P4.TTY!P4.TT8;Should be zero already PUSHJ P,SETUDX ;Set up TRMOP data if output to a TTY POPJ P, ;Not a terminal TXO P4,P4.TTY ;Output is going to a TTY LDB T1,[POINTR PLTINI(P4),IN.MOD] ;Get I/O mode CAILE T1,.IOASL ;ASCII or ASCII line? TXO P4,P4.TT8 ;No, set 8th bit to parity for binary modes MOVE T1,[INTDAT,,INTBLK] ;Source,,destination BLT T1,INTBLK+3 ;Set up 4-word interrupt block MOVEI T1,INTBLK ;Tell monitor EXCH T1,.JBINT## ; to trap Control-C CAIE T1,INTBLK ;Second time around? MOVEM T1,OLDINT ;No, save old .JBINT in case its important MOVEI T1,0 ;Clear send bit (TTY GAG) PJRST P,STOSND ;Set the send bit to zero INTDAT: 4,,INTNPC ;Length,,new PC on interrupt ER.ICC ;Intercept Control-C EXP 0,0 ;Last 2 words initially zero TTYFIN: MOVE T1,OLDINT ;Get previous .JBINT MOVEM T1,.JBINT## ;Restore it MOVEI T1,1 ;Bit to enable sends (TTY NO GAG) PFALL STOSND ;Set .TOSND and return STOSND: MOVEM T1,TRM+2 ;Store argument, 0=NOSEND(GAG), 1=SEND(NOGAG) MOVEI T1,.TOSND+.TOSET;Function code MOVEM T1,TRM+0 ;Store MOVE T1,[3,,TRM] ;Point to args TRMOP. T1, ;SET TTY (NO) GAG JFCL ;No big deal POPJ P, ;Here on Control-C during normal output (not during XHAIRS) ;Reset the terminal to ASCII mode. INTNPC: MOVEM 17,INTS17 ;Save all ACs MOVEI 17,INTS00 BLT 17,INTS16 MOVE P,[IOWD INTPDS,INTPDL] ;Set up new PDL PUSH P,INTBLK+.EROPC ;Save PC at time of interrupt SKIPN .JBDDT## ;If not debugging, SETZM INTBLK+.EROPC ;Trap further Control-Cs MOVSI P3,-PLTNUM ;Get size of table INTNP1: SKIPL P4,PLTTAB(P3) ;Is this plotter active? JRST INTNP2 ;No, try next one TXNN P4,P4.TTY ;Is this going to a terminal? JRST INTNP2 ;No PUSHJ P,@PLTFIN(P4) ;Yes, set plotter to ASCII mode PUSHJ P,DUMPBF ;Dump output buffer INTNP2: AOBJN P3,INTNP1 ;Loop for all IFN FT2CC,< ;Try to notify other intercept routine MOVE T1,OLDINT ;Get old value of .JBINT MOVEM T1,.JBINT## ;Restore it SETZM OLDINT ;Be paranoid and clear to prevent recursion TRNE T1,-1 ;Anything in RH? SKIPN T2,.ERCLS(T1) ;Yes, any bits set? JRST INTNP3 ;No TRNN T2,ER.ICC ;Does it want to trap Control-C JRST INTNP3 ;No POP P,.EROPC(T1) ;Get PC at time of interrupt MOVE T2,INTBLK+.ERCCL;Get cause of interrupt MOVEM T2,.ERCCL(T1) ;Copy HRRZ T2,.ERNPC(T1) ;Get address of interrupt handler HLL T2,.EROPC(T1) ;Set PC flags MOVEM T2,INTPDL ;Store in memory MOVSI 17,INTS00 ;Point to saved ACs BLT 17,17 ;Restore accumulators JRSTF @INTPDL ;Go to other Control-C handler > ;End of IFN FT2CC INTNP3: ERRSTR (NON,) MONRT. ;Exit to monitor IFE FT2CC, ;Cannot continue IFN FT2CC,< ;Try to resume MOVSI P3,-PLTNUM ;Get size of table INTNP4: SKIPGE P4,PLTTAB(P3) ;Was this plotter active? TXNN P4,P4.TTY ; and going to a TTY? JRST INTNP5 ;No, try next one PUSHJ P,@PLTINI(P4) ;Yes, set plotter to graphics mode INTNP5: AOBJN P3,INTNP4 ;Loop for all POP P,INTPDL ;Get old PC and flags MOVSI 17,INTS00 ;Point to saved ACs BLT 17,17 ;Restore accumulators JRSTF @INTPDL ;.CONTINUE > ;End of IFN FT2CC > ;End of TOPS10 SUBTTL Terminal I/O routines TOPS20< ;Need to do the following in TTYINI ; @TERMINAL NO INDICATE !Do not show Control-] as ^] ; @TERMINAL FORMFEED !Formfeed is needed to clear TEKTRONIX screen ; @TERMINAL WIDTH 0 !Do not send free CRLF after 80 characters TTPLTM: POPJ P, ;Set terminal to PLOT mode TTBINM: POPJ P, ;Set terminal to BINARY input mode TTASCM: POPJ P, ;Set terminal to text (ASCII) mode TTYINI: TXO P4,P4.TTY POPJ P, ;Initialize terminal TTYFIN: POPJ P, ;Finish up with the terminal TOWAIT: POPJ P, ;Wait so many milliseconds after output buffer is empty > ;End TOPS20 TOPS10< TTPLTM==OPNFIL ;Set terminal to PLOT output mode TTBINM==OPNFIL ;Set terminal to BINARY input mode TTASCM==CLOSEF ;Set terminal to ASCII text mode ;Routine to test for TTY as output device and set up TRMOP. data. ;Calling sequence: ; PUSHJ P,SETUDX ; *error* ;Output device not a TTY ; *ok return* ;Output device is a TTY ; Uses T1 SETUDX: HLRZ T1,BUFR.N(P4) ;Get channel number ANDI T1,(FO.CHN) ;Ignore any extra bits IONDX. T1, ;Get I/O index number MOVEI T1,0 ;Error, not a TTY MOVEM T1,TRM+1 ;Save UDX TXNE T1,.UXTRM ;Output to a TTY? AOS (P) ;Yes, give skip return POPJ P, ;Routine to wait a while after the terminal output buffer is empty. ; Calling sequence: ; MOVEI T1,(milliseconds to wait) ; PUSHJ P,TOWAIT ; *return* ; Preserves all ACs TOWAIT: PUSH P,T1 ;Save delay time PUSHJ P,SETUDX ;Set TRM if it's a TTY JRST T1POPJ ;Not, can't wait for DSK WAIT0: MOVEI T1,.TOSOP ;Set up to wait for MOVEM T1,TRM ; the TTY buffer MOVE T1,[2,,TRM] ; going empty TRMOP. T1, ;Skip if Output in Progress JRST WAIT1 ;Output buffer is empty MOVEI T1,^D250 ;Wait HIBER T1, ; 1/4 JFCL ; second JRST WAIT0 ;See if output buffer empty now WAIT1: POP P,T1 ;Get delay time JUMPE T1,GETCRL ;Zero means to wait for a CRLF HIBER T1, ;Hibernate for a while JFCL ;Can never happen POPJ P, GETCRL: SETO T1, ;For now, use CALL PLOT(X,Y,0) PJRST @PLTPAS(P4) ; ;Routine to clear input buffer of typeahead CLRIB: PUSHJ P,SETUDX ;Set up TRM POPJ P, ;No input buffer to clear MOVEI T1,.TOCIB ;Code to clear input buffer MOVEM T1,TRM+0 ;Store function MOVE T1,[2,,TRM] ;Point to args TRMOP. T1, ;Clear typeahead JFCL ;Only if detached POPJ P, ;Routine to input a character from the terminal INCHR: PUSHJ P,SETUDX ;Set up TRM JRST RETZER ;Not a TTY, return 0 in T1 MOVEI T1,.TOISC ;Code to input single char MOVEM T1,TRM+0 ;Store function MOVE T1,[2,,TRM] ;Point to args TRMOP. T1, ;Get a char SETO T1, ;Only if detached POPJ P, > ;End of TOPS10 TOPS20< ;Input a single character INCHR: PBIN% ;Read from primary input for now POPJ P, > ;End TOPS-20 ;Routine to read TTY response in binary ;Call: ; MOVEI T1,[ASCIZ /Prompt or trigger/] ; MOVEI T2,address to store bytes] ; MOVEI T3,number of bytes ; MOVEI T4,terminator (such as "]") ; PUSHJ P,RDTBIN ; *return* Returns pointer to response in T1, byte count in T2 RDTBIN: PUSHJ P,OUTDMP ;Send the prompt and dump buffers TOPS20< SIN% > ;Get the data TOPS10< PUSHJ P,CLRIB ;Clear input buffer TLCE T2,-1 ;If zero TLCE T2,-1 ; or -1, HRLI T2,(POINT 7,) ;Make into byte pointer SKIPGE T3 ;If negative, HRROI T4,0 ; then make CAME T1,T4 always fail MOVMS T3 RDTBLP: PUSHJ P,INCHR ;Get a char IDPB T1,T2 ;Store it CAME T1,T4 ;Terminator? SOJG T3,RDTBLP ;No, loop if not read enough POPJ P, > ;End of TOPS10 > ;End of IFN FTTERM SUBTTL I/O routines - Read window limits from SYS:PRIV.SYS ;GETWIN - Get window limits by reading SYS:PRIV.SYS ;Call: PUSHJ P,GETWIN ; *only return* ;X.WMAX and Y.WMAX set up DFWINS==DFWINS ;Should be about 35.0 inches IFE FTPRIV GETLIM: SETZB X,Y ;In case OPEN fails SETZM P.WIND ;Clear priv bits IFN FTDSK,< IFN FTPRIV,< ;Read file for limits IF2, FTDSKO='UUOS' IFE , IFE , IFE , IFE ,< TOPS10< %0==0 ;Temporary I/O channel, will be released before returning GETPPN T1, ;Get this guy's PPN JFCL MOVEM T1,MYPPN MOVX T1,UU.PHS!.IODMP;Physical only, dump mode MOVSI T2,'SYS' ;System device SETZ T3,0 ;No buffers OPEN %0,T1 ;Go get an I/O channel JRST GETLI9 ;??? Use default MOVE T1,['PRIV '] ;Set up to lookup file 'PRIV.SYS' MOVSI T2,'SYS' ; .. SETZB T3,T4 ; .. LOOKUP %0,T1 ;Lookup the file 'PRIV.SYS' JRST GETLI4 ;Can't find it - go use the default GETLI1: IN %0,GETLIO ;Go get a block of data TDZA T3,T3 ;Skip and set up pointer to SWBUFR JRST GETLI4 ;EOF and no match, use default > ;End of IFE FTDSKO-'UUOS' FTDSKO='FILOP.' ;*HACK* GETLI2: SKIPE T1,WINPPN(T3) ;Pick up next PPN CAML T1,MYPPN ;Searched far enough? JRST GETLI3 ;Yes, see if it matches PPN ADDI T3,WINLEN ;Increment the counter CAIGE T3,200-WINLEN ;Skip if finished with this block JRST GETLI2 ;No - go try the next entry then JRST GETLI1 ;Go read the next block GETLI3: CAME T1,MYPPN ;Searched past PPN? JRST GETLI4 ;Yes, go use the default DMOVE X,WINX(T3) ;Get max X and Y for this PPN DATE T1, ;The today's date MOVE T2,WINDAT(T3) ;Get the user's privileges and exp-date HLRZM T2,P.WIND ;Save priv bits (all zero for now) CAILE T1,(T2) ;Today less than expiration date? GETLI4: SETZB X,Y ;No, zeros means use default SKIPN X ;If expired or default, SETZM P.WIND ; clear window privs RELEAS %0 ;Release the I/O channel > ;End of TOPS10 > ;End of IFN FTPRIV > ;End of IFN FTDSK GETLI9: CAMG X,[DFWINS] ;PRIV.SYS too small or zero? MOVE X,[DFWINS] ;Yes, use default of 11.0 inches CAMG Y,[DFWINS] MOVE Y,[DFWINS] DMOVEM X,X.WMAX ;Save max from SYS:PRIV.SYS POPJ P, SUBTTL Misc - IFX.X and IFX.Y IFN FTKA,< ;PUSHJ P,IFX.X is equivalent to FIXR X,X ;Uses T2 and T3, preserves T1 IFX.X: TDZA T3,T3 ;Set up to use X IFX.Y: MOVEI T3,1 ;Set up to use Y PUSH P,T1 ;Preserve T1 MOVE T1,X(T3) ;Get value into the right place MOVSI T2,(DEC 0.5) ;Assume we round positive SKIPGE T1 ;Do we? MOVSI T2,(DEC -0.5) ;No, then use negative rounding factor FADR T1,T2 ;Round it. PUSHJ P,IFX.1## ;Go convert the number to an integer MOVEM T1,X(T3) ;Store the value back where is belongs POP P,T1 ;Restore T1 POPJ P, ;Return > ;End of IFN FTKA SUBTTL ALCHN and DECHN IFE ,< ; Subroutine ALCHN - this routine gets an I/O channel for the caller ; Calling sequence: ; PUSHJ P,ALCHN ; *no channel* ; *good return* ALCHN: PRINTX ?ALCHN/DECHN not written DECHN: POPJ P, > ;End of IFE 'UUOS' SUBTTL Data area -- Global variables TOPS10< IFN FTPRIV,< GETLIO: IOWD 200,SWBUFR ;IOWD for reading 1 block, H.ZERO must follow 0 ;Zero marks the end > ;End IFN FTPRIV > ;End TOPS10 ;Some handy constants BLANKS: ASCII / / ;5 spaces CRLF: BYTE (7) CR,LF,0 ;NOTE: All Y varibles must immediately follow the X variables for DMOVE X,var. $LOSEG ;PLOTS variables PLTTAB: BLOCK PLTNUM ;Pointers to defined plotters Z.ERRC: BLOCK 1 ;Counter for window-exceeded errors ;The following refer to the most recent call to PLOTS Z.CALL: BLOCK 1 ;Argument to PLOTS Z.NUMB: BLOCK 1 ;Plotter routine number (small integer) for WHERE Z.FLAG: BLOCK 1 ;Plotter sub-type flags Z.DNAM: BLOCK 1 ;Output device name (DSK or TTY) Z.FNAM: BLOCK 1 ;Output file name (defaults to program name) ;PLOT variables C.PLOT: BLOCK 1 ;Count of calls to PLOT (never zeroed) X.CALL: BLOCK 2 ;Last pen position as set by CALL PLOT(X,Y,I) and Y.CALL=X.CALL+1 ; returned by CALL WHERE(X,Y) P.DOWN: BLOCK 1 ;-1 to drop pen before moving, 0 to raise before moving X.ORIG: BLOCK 2 ;Offset due to origin shifting, Y.ORIG=X.ORIG+1 ; set by CALL PLOT(X,Y,-3) S.ORIG: BLOCK 1 ;Negative to set new origin ;SETWIN variables X.WIND: BLOCK 5 ;Universal window, set by call to SETWIN, and Y.WIND=X.WIND+1 ; is limited by X.WMAX and Y.WMAX X.WMAX=X.WIND+2 ;Maximum window size, as defined in SYS:PRIV.SYS Y.WMAX=X.WIND+3 ;(Subroutine GETWIN depends on this particular order) P.WIND=X.WIND+4 ;Privileges (currently zero) ;NEWPEN variables C.NPEN: BLOCK 1 ;New pen color L.NPEN: BLOCK 1 ;New pen line type (not yet implemented) ;ROTATE variables A.ROTA: BLOCK 1 ;Angle from previous call to ROTATE, in degrees X.ROTA: BLOCK 2 ;Origin set by ROTATE Y.ROTA=X.ROTA+1 ;Origin set by ROTATE ;FACTOR variables X.FACT: BLOCK 2 ;Scaling factor in X direction Y.FACT=X.FACT+1 ;Scaling factor in Y direction ;OPRTXT variables P.BYTE: BLOCK 2 ;Byte pointer C.BYTE=P.BYTE+1 ;Byte counter SUBTTL Data area -- Temporary variables SAVE0: BLOCK 17 ;Place to save ACs, 0-16 SAVET1=SAVE0+T1 SAVEL= SAVE0+L MYPPN: BLOCK 1 ;For checking in SETWIN ANGLE: BLOCK 1 ;Argument for SIN. and COS. TEMP: BLOCK 6 ;Temporary storage OUTBT1: BLOCK 2 ;Saves T1 and T2 for OUTBYT SAVEFF: BLOCK 1 ;Holds old .JBFF while creating buffers X.NEWP: BLOCK 2 ;New pen position for CHECK Y.NEWP==X.NEWP+1 ;New pen position for CHECK FILPTR: BLOCK 1 ;Pointer to file name for PLOTS BYTSIZ: BLOCK 1 ;Byte size for OPNFIL FLPLEN==6 ;Length of block FLP: BLOCK FLPLEN ;FILOP. block ENT: BLOCK 4 ;ENTER block IFN FTTERM,< TRM: BLOCK 3 ;TRMOP. block INTBLK: BLOCK 4 ;Interrupt block (Control-C) OLDINT: BLOCK 1 ;Previous value of .JBINT INTPDS==20 ;Size of interrupt PDL INTPDL: BLOCK INTPDS ;Interrupt PDL INTS00: BLOCK 20 ;Save all ACs on interrupt INTS16=INTS00+16 INTS17=INTS00+17 > ;End of IFN FTTERM IFN FTHEAD,< ;Plot headers and trailers HDRHIT: BLOCK 1 ;Height of header/trailer in inches (0.10) NINETY: BLOCK 1 ;Plot it at +90 degrees (90.0) %TABL%: BLOCK 1 ;ASCII /TABLE/ ONE: BLOCK 1 ;Number for ISETAB (must be in LOSEG) (1) HEADBF: BLOCK ^D20 ;Space for 100 chars HEADCT: BLOCK 1 ;Count of chars in HEADBF HEADBP: BLOCK 1 ;Byte pointer to HEADBF > ;End of IFN FTHEAD ND BUFSIZ,203*2 ;Default size is 2 disk buffers IFN FTAPLT,*2> ;Enough to handle 2 plotters ND CORSIZ,<1+BUFSIZ>+<1+PLTSIZ> ;Enough to handle any single plotter CORBUF: BLOCK CORSIZ+1;Used by ALCOR/DECOR L.ZERO=.-1 ;Guarenteed zero word in the LOSEG IFN FTPRIV,< SWBUFR: BLOCK 200 ;Buffer for SETWIN routine (1 block in DUMP mode) WINPPN=SWBUFR+0 ;PPN WINDAT=SWBUFR+1 ;Date in 15 bit format WINX= SWBUFR+2 ;Max X in floating point WINY= SWBUFR+3 ;Max Y in floating point WINLEN==4 ;Size of each entry > ;End of IFN FTPRIV TRACEA: BLOCK 20 ;Place to save the ACs when calling TRACE.## SUBTTL Literals and END statement $HISEG ;End of DATA, back to CODE section LITIOD: LIT PLTEND=.-1 END ;End of PLTIOD.MAC