Trailing-Edge
-
PDP-10 Archives
-
decuslib10-12
-
43,50547/pltlib/v12a/pltiod.mac
There are 2 other files named pltiod.mac in the archive. Click here to see a list.
STTL (<PLTIOD - Subroutines, I/O, and Data>)
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,<PRINTX %PLTIOD - *HACK* ALCOR3 and DECOR2 need to use FUNCT. *HACK*>
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,<POPJ P,> ;Bug, don't make things worse
IFN FTDBUG,<ERRSTR (WRN,<Problems in DECOR>)>
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,<PRINTX %PLTIOD - *HACK* %OUTST needs to be written *HACK*>
%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 <P-17>,<MOVE 17,TRACEA+17>
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,<PRINTX %DUMPBF - *HACK* Not using FTTYIO *HACK*>
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,<?PLOT - I/O error on output>)
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,<PRINTX ?SETODV does not handle TOPS-20 disks yet>
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<IFN FTDSK,<PRINTX ?ISACTV not written for TOPS-20 disks>
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,<PRINTX %PLTIOD - *HACK* Using FTDSKO='FILOP.' *HACK*>
FTDSKO='FILOP.'
IFE <FTDSKO-'FOROTS'>,<PRINTX ?PLTIOD - no code for FTDSKO='FOROTS'>
IFE <FTDSKO-'JSYS' >,<PRINTX ?PLTIOD - no code for FTDSKO='JSYS'>
OPNFIL: HLLZ T1,BUFR.N(P4) ;Get previous channel number
JUMPN T1,OPNFI0 ;Use it if channel still open
IFE <FTDSKO-'UUOS'>,<
PUSHJ P,ALCHN ;Get a free channel from FOROTS
HRLZS T1 > ;Put in LH
IFE <FTDSKO-'FILOP.'>,<
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,<PRINTX %PLTIOD - *HACK* Not using FTTYIO at all *HACK*>
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,<PRINTX ?OPNFIL not written>
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 <FTDSKO-'UUOS'>,<
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,<PRINTX ?CLSFIL not written>
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,<SPTYPT==RETM1> ;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,<XALL;;List of monitor names and plot names for graphics terminals
;; <SIXBIT,ASCII>
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,<TTYINI: TTYFIN: TOWAIT: POPJ P,>
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,<PLOT - Aborted graphics due to Control-C>)
MONRT. ;Exit to monitor
IFE FT2CC,<JRST INTNP3> ;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,<PRINTX %PLTIOD - *HACK* Using FTDSKO='UUOS' in GETLIM *HACK*>
FTDSKO='UUOS'
IFE <FTDSKO-'FILOP.'>,<PRINTX ?GETLIM - No code for FTDSKO='FILOP.'>
IFE <FTDSKO-'FOROTS'>,<PRINTX ?GETLIM - No code for FTDSKO='FOROTS'>
IFE <FTDSKO-'JSYS' >,<PRINTX ?GETLIM - No code for FTDSKO='JSYS'>
IFE <FTDSKO-'UUOS'>,<
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 <FTDSKO-'UUOS'>,<
; 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,<ND CORSIZ,<BUFSIZ+PLTSIZ+2>*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