.TITLE TEM TERMINAL EMULATOR .IDENT /84.131/ .ENABL LC .SBTTL General documentation. .DSABL GBL .NLIST BEX ;+ ; Title: TEM ; Author: T. R. Wyant ; Date: 2-Mar-83 ; Modified: ; Remarks: ; Task TEM will send and recieve data over a serial ; device line. The input data can come either from the ; user's terminal or from a file. Optionally, the ; characters recieved can be recorded in a log file. ; ; The command line is ; TEM>device/switches ; where all elements are optional, except that the device ; to be used for communication must be given on the first ; TEM prompt. TEM will also accept commands of the form ; TEM>@file ; where the file contains valid TEM commands. Command ; files can be nested up to 4 deep. The default filespec ; elements are ; SY:.CMD ; If TEM is built with the Extended Get Command Line ; interface (done by defining symbol "EXGTCM" below), ; you can execute a command library by appending the ; /LB:module switch to the file name. "Module" is the ; name of the module in the library, and defaults to ; ".MAIN.". If the /LB switch is used, the default ; filespec becomes ; SY:.CLB ; ; The command line switches may be negated by preceding ; either "-" or "NO". All switch settings and parameters ; "latch" to the last specified value except as noted. ; Switch names may be abbreviated to two characters. ; ; The switches are as follows: ; ; /ASSIGN:char:char ; Specifies that whenever the second ; character appears as input, the first ; character should be substituted for it. ; You may reassign any number of charac- ; ters. If negated, all assignments are ; cleared. The parameters are required ; if the switch is asserted, and forbidden ; if it is negated. The initial setting is ; /NOASSIGN ; ; /ATTENTION:char ; Specifies the character to type to get a ; TEM prompt. If you are transmitting from ; a file, typing this character will cause ; the file to be closed. This switch can ; not be negated. The initial setting is ; /ATTENTION:^C (control/C) ; ; /COMMAND ; Specifies that TEM should issue another ; command prompt after executing your ; command. If negated, TEM goes into ; terminal mode after executing your ; command, and you must type the attention ; character to get another command prompt. ; The initial setting is ; /NOCOMMAND ; ; /ECHO ; Local echo. If set, all characters typed ; on the user's terminal or sent from a ; file will be echoed on the user's ter- ; minal (and logged in the log file if one ; is open). The initial setting is ; /NOECHO ; ; /EOF[:char] ; Specifies the character to transmit upon ; encountering end of file on an input ; file. Negating the switch causes no EOF ; character to be sent. Asserting it with ; no parameter causes the most recently ; specified EOF character to be sent, even ; if specified as /-EOF:char. The initial ; setting is ; /EOF:^Z (control/Z). ; ; /HOLD ; Prevents the line from being hung up ; on line change or exit. Also prevents ; startup/shutdown command files from ; being executed. The initial setting is ; /NOHOLD ; ; /LIST ; Causes the log file to be opened with ; "LIST" implied carriage control. TEM ; will then analyze the input stream and ; attempt to duplicate the effect of the ; real form control characters recieved ; by positioning the record breaks ; appropriately. Perverse combinations ; of form control characters may yield ; perverse results. If the switch is ; negated, the log file is opened with ; no implied carriage control, and all ; characters are written to it with a ; record break after each . The ; initial setting is ; /LIST ; ; /LOG[:file] ; Specifies that the characters coming ; over the communication line should be ; logged to a file. If no file name is ; given (or if the switch is on due to ; being specified in a previous command ; line), the last log file will be opened, ; and the new data appended to it. In this ; case, the current setting of the /LIST ; switch will be ignored; carriage control ; processing will be according to the ; /LIST switch setting when the file was ; created A file name can be specified ; with the /-LOG version of the switch, ; but it does no good to do so. The ; default file name elements are ; SY:TEM.LOG ; The initial setting is ; /NOLOG ; ; /MAXBUFFER[:n] ; Specifies the maximum number of charac- ; ters to accumulate before writing to the ; log file. Note that in the case of a log ; file opened /LIST, the actual maximum ; record size will be smaller (by 2, nor- ; mally) because of the implied carriage ; control. The parameter is positive deci- ; mal number. If you specify a number ; outside the range 16 < n < bufsiz (512 ; by default), the nearest in-range number ; will be taken, and you get no error. If ; the switch is negated, no parameter is ; allowed, and is used. If you ; assert the switch but give no parameter, ; your terminal buffer size is used. The ; initial setting is ; /NOMAXBUFFER ; ; /MONITOR ; Specifies that all inbound control char- ; acters except , , , and ; be replaced with their ASCII names, ; enclosed in angle brackets. ; /MONITOR implies /NOLIST/NULLS, and ; /NOMONITOR implies /LIST/NONULLS. ; The initial setting is ; /NOMONITOR ; ; /NULLS ; Specifies that incoming nulls are to be ; sent to the terminal, and to the log ; file if any. If negated, inbound nulls ; are ignored. The initial setting is ; /NONULLS ; ; /PAUSE[:nnnt] ; Specifies the time to pause between ; records sent from a file. The "nnn" is ; a positive decimal number less than ; 32768, and the "t" is the letter "T" ; (for ticks), "S" (for seconds), "M" (for ; minutes), or "H" (for hours). You may ; not specify a time greater than 24 ; hours. If the switch is negated, no ; pause is done. If the /PROMPT switch ; is negated, timing starts when the ; record is sent. If the /PROMPT switch ; is asserted, timing starts when the ; prompt character is detected. ; The initial setting is ; /PAUSE:15T ; ; /PROMPT[:char] ; Specifies a single character that is ; interpreted as a prompt from the remote ; system for the next record of a file ; that is being sent. If negated, TEM does ; not do prompt synchronization. If asser- ; ted without a parameter, the last char- ; acter specified is used (even if speci- ; fied as /NOPROMPT:char). If the /PAUSE ; switch is negated, the next record is ; sent as soon as the prompt character is ; received. If the /PAUSE switch is asser- ; ted, the next record is sent after the ; specified delay following receipt of the ; prompt character. If another prompt is ; received before the delay expires, the ; delay timer is restarted. The initial ; setting is ; /PROMPT:LF ; ; /QUIET ; If asserted, output to the local terminal ; is supressed during file transmission. ; Output to the log file (if any) is not ; affected. THIS SWITCH DOES NOT LATCH. ; The initial setting is ; /NOQUIET ; ; /REMOTE[:spd] Specifies whether the driver should ; generate and monitor modem control ; signals, and if so what the answer ; speed should be. The /REMOTE setting ; is only applied when initializing the ; remote terminal; the last value speci- ; fied is used. The speed, if given, is ; any decimal number valid in the ; SET /REMOTE ; MCR command. The external settings ; available on a DH are not supported. ; If you negate the switch, you may not ; specify a speed; the result is the same ; as if you had specified /REMOTE:0. ; If you assert the switch but don't ; specify a speed, the /REMOTE setting ; of the line is not altered. Note that ; this switch will also set line speed ; unless overridden by the /SPEED. The ; initial setting is ; /REMOTE ; ; /RPA Specifies that ALL control characters ; (including control/q, control/s, and ; control/x) typed on the local terminal ; are passed to the remote line. If not ; asserted, these characters will be in- ; tercepted and interpreted by the TT: ; driver for the local terminal. The ; initial setting duplicates the local ; terminal's setting. ; ; /SEND[:file] Sends the specified file down the line, ; a record at a time. Leading and trailing ; form control characters are added to ; each record based on the implied form ; control of the file (None, List, For- ; tran, or Cobol). If the /TERMINAL ; switch is negated, implying a link to ; another computer, TEM sends one less ; leading linefeed than is implied by the ; file attributes. ; ; THIS SWITCH DOES NOT LATCH. If specified ; without a file name, the last file sent ; is retransmitted. The default file name ; elements are ; SY:TEM.INP ; If /-SEND is specified, the file name ; is ignored and input comes directly ; from the user's terminal. /SEND:TI: is ; the recommended way to run this task in ; batch mode. The initial setting is ; /NOSEND ; ; /SPEED[:spc:spc] Sets line speed. Legal speed parameters ; are the same as for /REMOTE. This switch ; cannot be negated. If given without ; parameters, the original line speed is ; used. This switch can not be negated. ; The initial setting is ; /SPEED ; ; /TERMINAL Tells TEM you are communicating with a ; terminal rather than a CPU. ; If negated: ; TEM sends one less linefeed at the ; beginning of each record of a ; "SEND" file than is implied by ; its carriage control attribute. ; The following switches are implied: ; /NOECHO/EOF/PAUSE/PROMPT ; If asserted: ; TEM appends a to every ; entered from the terminal. ; TEM sends a to the remote ; terminal before prompting for ; input from the local terminal. ; The following switches are implied: ; /ECHO/NOEOF/NOPAUSE/NOPROMPT ; The initial setting is ; /NOTERMINAL ; ; / Null switch. Since the command line ; interpreter regards an empty line as ; a comment, you can use this switch to ; go back into communications mode without ; any other changes. This switch can be ; negated, though I have no idea why you ; would want to. ; ; Note: For all switches that specify single characters ; (ie: /ATTENTION, /EOF) ; the character can be specified in any one of the ; following ways: ; (Low byte used) ; . (Low byte used) ; ' (ASCII value) ; ^ ((ASCII val)&37) ; % ((ASCII)!140) ; NU or NUL or NULL 0 ; SOH 1 (^A) ; STX 2 (^B) ; ETX 3 (^C) ; EOT 4 (^D) ; ENQ 5 (^E) ; ACK 6 (^F) ; BEL 7 (^G) ; BS 10 (^H) ; HT 11 (^I) ; LF 12 (^J) ; VT 13 (^K) ; FF 14 (^L) ; CR 15 (^M) ; SO 16 (^N) ; SI 17 (^O) ; DLE 20 (^P) ; DC1 21 (^Q) ; DC2 22 (^R) ; DC3 23 (^S) ; DC4 24 (^T) ; NAK 25 (^U) ; SYN 26 (^V) ; ETB 27 (^W) ; CAN 30 (^X) ; EM 31 (^Y) ; SUB 32 (^Z) ; ESC 33 ; FS 34 ; GS 35 ; RS 36 ; US 37 ; SPACE (abbr to 2 char) 40 ; DEL 177 ; (ASCII value) ; In general, "'" means "take the ASCII value as ; is", "^" means "convert to control character", ; "%" means "convert to lower case". An "unspecial ; character" is any printable character except "0" ; thru "9", "'", "^", "%", ":", and "/". The key- ; words may be abbreviated to two characters. For ; instance: ; /AT:^@ ! Attention character is null ; /EO:^Z ! EOF character is control/Z ; /AT:* ! Attn. character is "*". ; /AT:'% ! Attn char is "%". ; /AT:%A ! Attn char is "a". ; /AT:SP ! Attn char is " ". ; ; Note: The implied switch feature is implimented as a ; convenience. Any implied switches can be ; explicitly overridden in the same command line. ; for example, in the command line ; /NOECHO/TERMINAL ; the explicit /NOECHO overrides the /ECHO implied ; by /TERMINAL. The order of the switches in a ; command line does not affect its meaning. ; ; One of the options available with TEM is line setup and ; takedown. This feature is enabled by defining symbol ; LINSET below. If line setup and takedown are enabled, ; TEM will execute a startup command file every time a ; given line is selected, and a takedown command file when ; operations on that line are complete. The name of the ; startup command file is ; LB:[1,5]dduINI.TEM ; and the takedown command file is ; LB:[1,5]dduKIL.TEM ; where "ddu" represents the name of the device being ; started up or taken down. You can issue any valid TEM ; command in these files, except that you cannot specify ; a device name. Also, you cannot do terminal I/O from ; a startup or takedown command file. Normally, any ; command without a /SEND switch implies input from the ; terminal; but in a startup command file the input code ; is skipped unless a send file is specified. ; ; When you have automatic line setup enabled, command ; lines containing device specs are treated as follows: ; * The entire command line is parsed for validity; if ; it fails validation it is ignored. ; * All switches are stripped off and saved, except for ; /[NO]HOLD, which is executed immediately. ; * The takedown command file (if any) for the current ; remote line (if any) is executed, unless the ; /HOLD switch is asserted. ; * The old remote line is hung up, unless the /HOLD ; switch is asserted. It is detached from this ; task, and the new remote line is attached. ; * The startup command file (if any) for the new ; remote line (if any) is executed, unless the ; /HOLD switch is asserted. ; * The saved command line is re-parsed and executed. ; Note that any switches specified in the takedown or ; startup command files will be in effect when you finally ; come up on the new line, unless explicitly overridden ; in the command line that specified the new device. This ; is a "feature" in that desired setups for a given line ; can be stored centrally, but could result in obscure ; behaviour if you aren't aware of what's going on. ; ; If you don't like the current standard for startup ; and takedown command file names, see the section of ; code from "SETDV:" thru "SETKIL:". If it's not clear ; what's going on, look up "Dataset Descriptors" in the ; "I/O Operations Reference". ; ; - WARNING - ; ; The "Automatic Line Set-up" code is based on knowlege ; of the internal data structures used by GCML and EGCML. ; They are undocumented, and probably subject to change ; without notice. GCML has been around a while (see ; "I/O Operations"), and is probably stable. EGCML, on ; the other hand, is almost entirely undocumented; it was ; apparantly written for the "@" processor, and features ; not needed by "@" have a tendancy not to work. This is ; too bad, as the EGCML "FCML$" macro looks like the ; proper way to impliment this feature. The bottom line ; is this: if automatic line setup suddenly stops working ; after TEM is rebuilt, suspect a change in the internals ; of GCML (or EGCML if that's what you're using). If ; that's what happened, "GCMFRC:" will have to be ; modified to accomodate the change. ; ;- .PAGE .SBTTL MACRO-11 Setup directives. .MCALL ALUN$S,ASTX$S,CLEF$S,CMKT$S,DSAR$S,ENAR$S .MCALL EXIT$S,GLUN$S,GTIM$S,GTSK$S,MRKT$S .MCALL QIO$S,QIOW$S,SETF$C,SREX$S,WTSE$S .MCALL FINIT$,FSRSZ$,FDBDF$,FDAT$A,FDOP$A,NMBLK$ .MCALL CLOSE$,GET$,OPEN$,PUT$ .MCALL ISTAT$,STATE$,TRAN$ .GLOBL FD.CCL,FD.CR,FD.FTN,FD.PRN,FD.REC,FD.TTY .GLOBL FO.APD,FO.RD,FO.WRT .GLOBL IE.EOF,IE.WAC .GLOBL IO.ATA,IO.ATT,IO.DET,IO.HNG,IO.KIL,IO.RLB,IO.WLB .GLOBL IO.WVB .GLOBL IS.PND,IS.SUC .GLOBL R.VAR .GLOBL SF.GMC,SF.SMC .GLOBL S.0,S.50,S.75,S.110,S.134,S.150,S.200,S.300,S.600 .GLOBL S.1200,S.1800,S.2000,S.2400,S.3600,S.4800,S.7200 .GLOBL S.9600 .GLOBL TC.ABD,TC.ACR,TC.ASP,TC.BIN,TC.FDX,TC.HFF,TC.HFL .GLOBL TC.HHT,TC.NEC,TC.RAT,TC.RSP,TC.SLV,TC.SMR,TC.TBS .GLOBL TC.VFL,TC.XSP .GLOBL TF.TMO,TF.XCC .GLOBL .PCHAR,.PNUMB,.PNUMH,.PSTCN,.PSTPT .GLOBL .TPARS,.TPARD .GLOBL $DSW .GLOBL $EDMSG,$SAVRG,$SAVVR ;TRACE= 0 ; Define to assemble trace logic. ;EXGTCM= 0 ; Define to use EGCML (/LB: support). LINSET= 0 ; Define to get line setup and takedown. ACCNTG= 0 ; Define to log use in account file. CMDLUN= 1 ; Command input LUN. LOGLUN= 5 ; Log file LUN. LTELUN= 4 ; Local terminal LUN. MSGLUN= 2 ; Terminal message output LUN. RTELUN= 3 ; Remote terminal LUN. SNDLUN= 6 ; "Send" file input LUN. MAXNST= 4 ; Maximum cmd file nesting depth. LPFLG= 3 ; Event flag to fire up mainline. MSGFLG= 2 ; Terminal message sync. flag. SYNIOF= 7 ; Synchronous I/O event flag. HT= 11 ; = ASCII Horizontal Tab CR= 15 ; = ASCII Carriage Return. LF= 12 ; = ASCII Linefeed. FF= 14 ; = ASCII Formfeed. SPA= 40 ; = ASCII Space. DEL= 177 ; = ASCII Delete. .IIF NDF BUFSIZ BUFSIZ =: 512. ; I/O Buffer size .IIF NDF SYNTOM SYNTOM =: 10. ; Synchronous I/O timeout - Magnitude .IIF NDF SYNTOU SYNTOU =: 2. ; Synchronous I/O timeout - Units .IIF NDF CMDLEN CMDLEN =: 80. ; Maximum command line length. .IIF NDF U2.LOG U2.LOG =: 400 ; Set if terminal not logged on. .PAGE .SBTTL Macro definitions .MACRO GCMMAC CODE,TEXT .SAVE .PSECT PURTXT RO,D,LCL,REL,CON TXTADR= . .ASCIZ \TEXT\ .RESTORE .IF NB .BYTE CODE .BYTE 0 .WORD TXTADR .IFF ; NB .WORD 0,TXTADR .ENDC ; NB .ENDM .MACRO ASSUME A .IF NE A .ERROR A ; Code assumes A=0. .ENDC ; NE A .ENDM ASSUME .MACRO RINGDF ADDR,SIZE,LUN,CHND .IF NDF R$BUF R$FLGS = -16 ; Status flags. R$F$MO = 1 ; More data to process (1 = yes). R$DBUF = -14 ; Buffer size of device on "LUN". R$CHND = -12 ; Character handling subroutine. R$LUN = -10 ; LUN to empty ring to. R$BND = -6 ; Upper bound of ring. R$INB = -4 ; Inbound data pointer. R$OUB = -2 ; Outbound data pointer. R$BUF = 0 ; Start of current buffer. .ENDC ; NDF R$BUF .WORD 0,0 .WORD CHND,LUN,ADDR+SIZE .WORD ADDR,ADDR ADDR: .BLKB SIZE .EVEN .ENDM RINGDF .MACRO BUFDF ADDR,SIZE,FDB .IF NDF F$BFFR F$BNCH = -20 ; Location of last normal character. F$PNDL = -16 ; Pending linefeeds. F$PNDF = -14 ; Pending formfeeds. F$FDBA = -12 ; FDB address. F$FLGS = -10 ; Flags word. F$F$LM = 1 ; At left margin (0=yes). F$F$AD = 2 ; Advanced a line (0=yes). F$F$NM = 4 ; Buffer contains normal char (0=yes). F$F$PR = F$F$LM!F$F$AD!F$F$NM ; Time to print (0=yes). F$F$IS = F$F$LM!F$F$AD!F$F$NM ; Initial setting. F$BCRL = -6 ; Location of last . F$BEND = -4 ; Address of end of buffer. F$BLOC = -2 ; Current loaction in buffer. F$BFFR = 0 ; Start of buffer. .ENDC ; NDF F$BFFR .WORD ADDR,0,0 .WORD FDB,F$F$IS,ADDR .WORD ADDR+SIZE,ADDR ADDR: .BLKB SIZE .EVEN .ENDM BUFDF .IF DF TRACE .MACRO TRACER TEXT .SAVE .PSECT PURTXT RO,D,LCL,REL,CON TXTADR= . .ASCIZ \TEXT\ .RESTORE MOV #TXTADR,-(SP) JSR PC,TRCSUB .ENDM TRACER .IFF ; DF TRACE .MACRO TRACER TEXT .ENDM TRACER .ENDC ; DF TRACE .MACRO TXTTBL TEXT .SAVE .PSECT PURTXT RO,D,LCL,REL,CON TXTADR = . .ASCIZ \TEXT\ .RESTORE .WORD TXTADR .ENDM TXTTBL .MACRO EMIT CODE .LIST CODE .NLIST .ENDM EMIT .MACRO REJECT COND=R .IF NDF REJECT REJGEN COND .MEXIT .ENDC .IF LT .-REJECT REJGEN COND .MEXIT .ENDC .IF GT .-REJECT-376 REJGEN COND .MEXIT .ENDC EMIT .ENDM REJECT .MACRO REJGEN COND .IF DIF REJECT = . .IIF IDN EMIT .IIF IDN EMIT .IIF IDN EMIT .IIF IDN EMIT .IIF IDN EMIT .IIF IDN EMIT .IIF IDN EMIT .IIF IDN EMIT .IIF IDN EMIT .IIF IDN EMIT .IIF IDN EMIT .IIF IDN EMIT .IIF IDN EMIT .IIF IDN EMIT .IIF IDN EMIT .IIF IDN EMIT .IIF EQ .-REJECT .ERROR ; Unrecognized condition COND .IFTF ; DIF EMIT EMIT EMIT .IFT ; DIF .IIF NE .-REJECT-6, .ERROR ; Bad branch target computed above. .ENDC ; DIF .NLIST MEB .ENDM REJGEN .PAGE .SBTTL Pure data .PSECT PURDAT RO,D,LCL,REL,CON CCTBL: ; Fortran CC translation table. .BYTE '0,CR,0,2 ; "0" - 2 before, after. .BYTE '1,CR,FF,0 ; "1" - before, after. .BYTE '+,CR,0,0 ; "+" - nothing before, after. .BYTE '$,0,0,1 ; "$" - 1 before, nothing after. .BYTE 0,0,0,0 ; "" - nothing before or after. CCTBLE: .BYTE CR,0,1 ; Anything else - before, aftr .EVEN ; Realign the PSECT. TXTTBL DEL CTRLCR: TXTTBL NUL TXTTBL SOH TXTTBL STX TXTTBL ETX TXTTBL EOT TXTTBL ENQ TXTTBL ACK TXTTBL BEL TXTTBL BS TXTTBL HT TXTTBL LF TXTTBL VT TXTTBL FF TXTTBL CR TXTTBL SO TXTTBL SI TXTTBL DLE TXTTBL DC1 TXTTBL DC2 TXTTBL DC3 TXTTBL DC4 TXTTBL NAK TXTTBL SYN TXTTBL ETB TXTTBL CAN TXTTBL EM TXTTBL SUB TXTTBL ESC TXTTBL FS TXTTBL GS TXTTBL RS TXTTBL US .WORD 0 ; Table terminator for KEYCMP GCMTBL: .IF DF EXGTCM ; If using the EGCML interface, GCMMAC GE.IOR, ; F.ERR in the FCB seems GCMMAC GE.OPR, ; not to be valid. .IFF ; DF EXGTCM ; If using GCML, its valid. GCMMAC GE.IOR, GCMMAC GE.OPR, .IFTF ; DF EXGTCM ; Either way, do the following. GCMMAC GE.BIF, GCMMAC GE.MDE, GCMMAC GE.RBG, .IFT ; DF EXGTCM ; If using EGCML, GCMMAC GE.CMD, GCMMAC GE.VRS, .ENDC ; DF EXGTCM GCMMAC , DRVLTB: ; Legal drivers for local term. .WORD "VT,RMLOG ; VT:, Half-duplex, login. DRVRTB: ; Legal drivers for remote term. .WORD "TT,RMFDX!RMLOG!RMNUL!RMATU ; TT:, Full-duplex, login. .WORD "HT,RMFDX!RMLOG!RMATU ; HT: same as TT:. .IF NDF,TRACE .WORD "NL,0 ; Let the user do this if he wants to. .IFF ; NDF,TRACE .WORD "NL,RMFDX ; For testing. Pretend it will do FDX. .ENDC .WORD 0 ; Must be end of table. SPDTBL: ; Speed to param. transl. table. SPDZER: .WORD 0.,S.0 .WORD 2.,S.200 .WORD 3.,S.300 .WORD 6.,S.600 .WORD 12.,S.1200 .WORD 18.,S.1800 .WORD 20.,S.2000 .WORD 24.,S.2400 .WORD 36.,S.3600 .WORD 48.,S.4800 .WORD 50.,S.50 .WORD 72.,S.7200 .WORD 75.,S.75 .WORD 96.,S.9600 .WORD 110.,S.110 .WORD 134.,S.134 .WORD 150.,S.150 .WORD 200.,S.200 .WORD 300.,S.300 .WORD 600.,S.600 .WORD 1200.,S.1200 .WORD 1800.,S.1800 .WORD 2000.,S.2000 .WORD 2400.,S.2400 .WORD 3600.,S.3600 .WORD 4800.,S.4800 .WORD 7200.,S.7200 .WORD 9600.,S.9600 SPDTBE: .IF DF ACCNTG ; If using accounting, ACNTFL: .WORD SETDVL,SETDV ; Define the dataset .WORD SETUIL,SETUI ; descriptor for .WORD ACTFNL,ACTFN ; the account file. .ENDC ; DF ACCNTG .PAGE .SBTTL Messages. .PSECT PURTXT RO,D,LCL,REL,CON ASNERM: .ASCIZ \ TEM - Failed to assign LUN to device. $DSW = %D (decimal).\ ATTM: .ASCIZ \Attach terminal\ BANERM: .ASCIZ \ TEM - Communicating with %2A%Q:.\ BADDVM: .ASCIZ \ TEM - Device %2A%Q: is not a terminal.\ BADFCM: .ASCIZ \ TEM - Function not supported on %2A: driver.\ BADSYS: .ASCIZ \ TEM - This task will not run under this operating system.\ CMLMSG: .ASCIZ \ %6SIn "%VA".\ CPUTM: .ASCIZ \Put character\ DETM: .ASCIZ \Detach terminal\ DEVILL: .ASCIZ \Device spec not allowed\ DSWM: .ASCIZ \$DSW\ DUPSWM: .ASCIZ \Duplicate switch\ ERLOGO: .ASCIZ \ TEM - Device %2A%Q: is logged on.\ GCMERM: .ASCIZ \ TEM - Failed to get command line. %I.\ GETM: .ASCIZ \Get characteristics\ ILLATN: .ASCIZ \Invalid attention character\ ILLDVM: .ASCIZ \Illegal device name\ ILLFLM: .ASCIZ \Illegal file name\ ILLNEG: .ASCIZ \Illegally negated switch\ ILLNUM: .ASCIZ \Number out of range\ ILLSWM: .ASCIZ \Illegal switch\ ILLTMS: .ASCIZ \Illegal time spec\ IOM: .ASCIZ \I/O Status\ LGOPNM: .ASCIZ \ TEM - Warning - Failed to open log file. %I = %D (decimal).\ LPIOEM: .ASCIZ \ TEM - Read error. I/O status is %D, %D (decimal).\ .ASCIZ \characters written.\ OCTCTL: .ASCIZ \%Q\ PRSERM: .ASCIZ \ TEM - Syntax error. %I "%VA".\ RDYMSG: .ASCIZ \ TEM - Ready for terminal input.%N\ RDYPMP: .ASCIZ \@%N\ SETM: .ASCIZ \Set characteristics\ SMCERM: .ASCIZ \ TEM - %I error on %I:. %I = %D (decimal).\ SNOPNM: .ASCIZ \ TEM - Failed to open send file. %I = %D (decimal).\ SUMMYM: .ASCIZ \ TEM - Run complete on %2A%Q:.\ .IF DF LINSET!ACCNTG SETDV: .ASCII \LB1:\ SETDVL=:.-SETDV SETUI: .ASCII \[1,5]\ SETUIL=:.-SETUI .IF DF LINSET SETINI: .ASCIZ \%2A%QINI.TEM\ ; Line init. SETKIL: .ASCIZ \%2A%QKIL.TEM\ ; Line kill. .ENDC ; DF LINSET .IF DF ACCNTG ACTFN: .ASCII \TEMACT.TEM\ ACTFNL=:.-ACTFN ACTREC: .ASCIZ \TEM - %Y %3Z %2A%Q: %I %2A%Q:.\ ACTINI: .ASCIZ \connected to\ ACTKIL: .ASCIZ \disconnected from\ .ENDC ; DF ACCNTG .ENDC ; DF LINSET!ACCNTG .IF DF TRACE TRCSUM: .ASCIZ \ TEM - Calling subroutine %I from address %Q\ TPDEBM: .ASCII \ TEM - .TPARS is at string character %7<%D.,%7>\ .ASCIZ \state table address %O\ .IFF ; DF TRACE TRCSUM: TPDEBM: .ENDC ; DF TRACE FFBUF: .ASCII ; Used for simulating forms control. TIS: .ASCII \TI:\ ; Device name. TISL=: .-TIS ; Length of string. .EVEN .PAGE .SBTTL Impure data FSRSZ$ 2 ; Allow two open files simultaneously. ; Note that this assumes GCML will close ; its command file after each command, ; and that a send file cannot be open ; while getting a command. .PSECT IMPDAT RW,D,LCL,REL,CON BEGZER: ; Everything to ENDZER zeroed each pass. SWPRE: .BLKW 1 ; Switches present. SWASS: .BLKW 1 ; Switches asserted. SWPAU= 1 ; /PAUSE:nnnt SWECH= 2 ; /ECHO SWLOG= 4 ; /LOG:file SWNUL= 10 ; /NULLS SWEOF= 20 ; /EOF:char SWLIS= 40 ; /LIST SWMXB= 100 ; /MAXBUFFER:size SWDTE= 200 ; /TERMINAL SWHLD= 400 ; /HOLD SWMON= 1000 ; /MONITOR SWRPA= 2000 ; /RPA SWCMD=: 4000 ; /COMMAND SWPMP=: 10000 ; /PROMPT:char SWDTEI= SWPAU!SWECH!SWEOF!SWPMP ; Switches implied by /TERMINAL SWDTEA= SWECH ; Switches asserted by /TERMINAL SWMONI= SWLIS!SWNUL ; Switches implied by /MONITOR SWMONA= SWNUL ; Switches asserted by /MONITOR SWINIT= SWLIS!SWEOF!SWPAU!SWPMP ; Set on startup. SWNLAT= 0 ; Switches that don't latch. SWDVCH= SWHLD ; Switches NOT deferred on dev. chg. SWPREI: .BLKW 1 ; Implied switches present. SWASSI: .BLKW 1 ; Implied switches asserted. S2PRE: .BLKW 1 ; Second word switches present. S2ASS: .BLKW 1 ; Second word switches asserted. S2ASG=: 1 ; /ASSIGN:char:char S2ATN=: 2 ; /ATTENTION:char S2RMT=: 4 ; /REMOTE:speed S2SPD=: 10 ; /SPEED:speed:speed S2SND=: 20 ; /SEND:file S2QUI=: 40 ; /QUIET NEGATE: .BLKW 1 ; 0 if switch asserted, -1 if negated. ENDZER: ; Everything from BEGZER zeroed each pass. LPIND: .BLKW 1 ; TTY status indicators. LPRDY= 1 ; Ready to send another file record. LPREA= 2 ; Need to reassign LUN. LPREAP= 4 ; Reassign in progress. LPXIT= 400 ; Set to end the loop. LPABO= 1000 ; Set to end loop and exit. LPABP= 2000 ; Abort pending. LPCMD= LPXIT!LPABO ; Break out of loop for these. OUTDEV: .BLKW 1 ; Output device name. OUTUNT: .BLKW 1 ; Output device unit number. OLDOUD: .WORD 0 ; Old output device. OLDOUN: .WORD 0 ; Old output unit number. RCDLAY: .WORD 15 ; Ticks between records. RCDUNT: .WORD 1 ; Unit (ticks). ATNBYT: .BYTE 3 ; "Attention" character. EOFBYT: .BYTE 32 ; End-of-file character. PMPBYT: .BYTE 12 ; Prompt byte. GETAC1: .BLKB 1 ; First param. on /ASSIGN. GETAC2: .BLKB 1 ; Second param on /ASSIGN. ASGTBL: ; Character assignment table. NNN=0 .REPT 200 .BYTE NNN NNN=NNN+1 .ENDR .EVEN LCSTAT: .BLKW 1 ; Local line characteristics. RMSTAT: .BLKW 1 ; Remote line characteristics. RMFDX=: 1 ; Full-duplex line. RMLOG=: 2 ; Terminal can log in. RMNUL=: 4 ; Driver passes nulls. RMATU=: 10 ; Driver supports unsolicited input AST. PMPFLG: .BLKW 1 ; "Prompt character" processing flag. SWSTAT: .WORD SWINIT ; Preserved switch settings. DEVNAM: .BLKW 1 ; Output device name. CHARBN: .BLKW 1 ; Binary character representation. CHARCB: .BLKW 1 ; "Case conversion" clear mask. CHARSB: .BLKW 1 ; "Case conversion" set mask. TIMUNT: .BLKW 1 ; Parser time spec units. TIMMAG: .BLKW 1 ; Parser time spec magnitude. FILDSD: .BLKW 6 ; Dataset descriptor storage for parser. LOGFDB: FDBDF$ ; Log file File Descriptor Block. FDAT$A R.VAR,FD.CR ; Var. length records, list carr. ctl. FDOP$A LOGLUN,LOGDSD,LOGFNB ; Lun and dataset descriptor. LOGFNB: NMBLK$ TEM,LOG,,SY,0 ; Default filename block for log file. LOGDSD: .BLKW 6 ; Dataset descriptor for log file. .IF DF ACCNTG ; If using accounting, ACTFDB: FDBDF$ ; Define accounting file FDB. FDOP$A SNDLUN,ACNTFL,,FO.APD ; Note use of same LUN as Send. ACTDEV: .BLKW 1 ; TI: device name for accounting. ACTDAT: ; \ ACTTIM: .BLKW 6. ; Transaction time. | These .WORD ACTDEV ; Accounting info. | must ACTUNT: .WORD 1 ; TI: unit no. | remain ACTMSG: .BLKW 1 ; Transaction name. | in .WORD DEVNAM ; | order. ACTDST: .WORD 0 ; Remote unit no. / .ENDC ; DF ACCNTG ; End of accounting stuff. SNDFDB: FDBDF$ ; Send file File Descriptor Block. FDAT$A R.VAR,FD.CR ; Var. length records, list carr. ctl. FDOP$A SNDLUN,SNDDSD,SNDFNB ; Lun and dataset descriptor. SNDFNB: NMBLK$ TEM,INP,,SY,0 ; Default filename block for send file. SNDDSD: .BLKW 6 ; Dataset descriptor for send file. SNDPOS: .WORD SNDBUF ; Position in sending buffer. SNDBUF: .BLKB BUFSIZ ; Send file buffer. SNDBFL= .-SNDBUF ; Send file buffer length. .EVEN SNDSVN: NMBLK$ ; Saved name block for /SEND: SAVCMD: .BLKW 1 ; Length and .BLKB CMDLEN ; text of saved comamnd. .EVEN BANDAT: .WORD DEVNAM ; Banner data. These two DEVUNT: .WORD 0 ; must remain in order. SYNSTA: .BLKW 2 ; I/O status for synchronous I/O. DEVBUF: .BLKW 8. ; GLUN buffer. MSGBUF: .BLKB 132. ; Terminal output buffer. .EVEN PRMBUF: .BLKW 10 ; Parameter buffer for EDMSG. CCLDNG: .BLKW 1 ; Routine to generate leading carg ctrl CCTLNG: .BLKW 1 ; Routine to generate trailing carg ctrl CCTRL: .BLKB 4 ; Trailing carriage ctrl, ASCIZ string. .EVEN RINGDF OURDSC,BUFSIZ,RTELUN ; Define outbound ring. RINGDF INRDSC,BUFSIZ,LTELUN,LGOU ; Define inbound ring. BUFDF LGFDSC,BUFSIZ,LOGFDB ; Define log file buffer. TPLNAD: .BLKW 1 ; Address of start of line. TPERR: .BLKW 5 ; Parser error message. TERASA: .WORD TEROAS+1 ; Pointer to desired /REMOTE setting. SPDRRC: .WORD TERORC+1 ; Pointer to /SPEED recieve setting. SPDRSD: .WORD TEROSD+1 ; Pointer to /SPEED send setting. .WORD TERNME-TERNMC ; New remote terminal parameters. TERNMC: .BYTE TC.ACR,0 ; SET /NOWRAP .BYTE TC.FDX,1 ; SET /FDX .BYTE TC.HFF,1 ; SET /FORMFEED .BYTE TC.HFL,0 ; SET /HFIL:0 .BYTE TC.HHT,1 ; SET /HHT .BYTE TC.NEC,1 ; SET /NOECHO .BYTE TC.RAT,1 ; SET /TYPEAHEAD .BYTE TC.SLV,1 ; SET /SLAVE .BYTE TC.SMR,1 ; SET /LOWER .BYTE TC.VFL,0 ; SET /VFILL .BYTE TC.ABD,0 ; SET /NOABAUD .BYTE TC.BIN,1 ; SET /RPA TERNAS: .BYTE TC.ASP,0 ; SET /[NO]REMOTE[:speed] TERNRC: .BYTE TC.RSP,0 ; SET /SPEED:speed: TERNSD: .BYTE TC.XSP,0 ; SET /SPEED::speed TERNME: .WORD TEROME-TEROMC ; Old remote terminal params. TEROMC: .BYTE TC.ACR,0 ; SET /[NO]WRAP .BYTE TC.FDX,0 ; SET /[NO]FDX .BYTE TC.HFF,0 ; SET /[NO]FORMFEED .BYTE TC.HFL,0 ; SET /HFIL:[n] .BYTE TC.HHT,0 ; SET /[NO]HHT .BYTE TC.NEC,0 ; SET /[NO]ECHO .BYTE TC.RAT,0 ; SET /[NO]TYPEAHEAD .BYTE TC.SLV,0 ; SET /[NO]SLAVE .BYTE TC.SMR,0 ; SET /[NO]LOWER .BYTE TC.VFL,0 ; SET /[NO]VFILL .BYTE TC.ABD,0 ; SET /[NO]ABAUD .BYTE TC.BIN,0 ; SET /[NO]RPA TEROAS: .BYTE TC.ASP,0 ; SET /[NO]REMOTE[:speed] TERORC: .BYTE TC.RSP,0 ; SET /SPEED:speed: TEROSD: .BYTE TC.XSP,0 ; SET /SPEED::speed TEROME: .WORD TELOME-TELOMC ; Old local terminal parameters. TELOMC: .BYTE TC.ACR,0 ; SET /[NO]WRAP TELOBI: .BYTE TC.BIN,0 ; SET /[NO]RPA TELOME: .WORD TELNME-TELNMC ; New local terminal parameters. TELNMC: .BYTE TC.ACR,0 ; SET /NOWRAP TELNBI: .BYTE TC.BIN,0 ; SET /[NO]RPA TELNME: .IF DF EXGTCM ; If using extended get cmd interface, .MCALL EGCMI$ ; Get the "Master Macro". EGCMI$ ; Define all the other macros. GCMLD$ ; Define offsets. .PSECT IMPDAT ; Needed, since GCMLD$ left us in "blank" .GLOBL TF.CCO ; Needed. .IFF ; DF EXGTCM ; If using the normal GCML, .MCALL GCML$,GCMLB$,RCML$,GCMLD$,CBYTE$ ; Invoke needed macros. GCMLD$ ; Define offsets. G.MAXD =: G.CMLD+5 ; Loc. of max nest depth. .MACRO CMGET$ GCMB,TERM,FILE,FQFN,OVBC,ERR .MCALL LDR0$,CGET$B,CGET$W LDR0$ GCMB .IF NB .ERROR ; "Get TI: input terminator" not supported by GCML. .ENDC ; NB .NTYPE QQQQQQ,FILE .IIF NE QQQQQQ, MOV R0,FILE .ENDC ; NB .IF NB .ERROR ; "Get fully qualified file name" not supported by GCML. .ENDC ; NB .IF NB .ERROR ; Big-buffering not supported by GCML. .ENDC ; NB CGET$B G.ERR,ERR .ENDM CMGET$ .ENDC ; DF EXGTCM .IF DF LINSET ; If doing line setup/takedown, SETDDB: .WORD SETDVL,SETDV .WORD SETUIL,SETUI .WORD 0,MSGBUF GCMNST = MAXNST*2 ; Double the pushdown stack. .IFF ; DF LINSET ; If not, GCMNST = MAXNST ; Normal pushdown stack. .ENDC ; DF LINSET .ENABL LSB ; Needed for EGCML ...PC1 = . ; Needed for CBYTE$ macro. GCMLB: GCMLB$ GCMNST,TEM,,CMDLUN,,CMDLEN CBYTE$ MAXNST,G.MAXD ; Revise max. nest depth. .EVEN .DSABL LSB ; Cancel LSB .PAGE .SBTTL Command line parser tables ; $RONLY = 1 .IF NDF TRACE ISTAT$ CMDSTA,CMDTRN .IFF ISTAT$ CMDSTA,CMDTRN,$DEBUG .ENDC ; STATE$ TRAN$ $LAMDA,,TPERTN,ILLSWM,TPERR ; Assume illegal switch. STATE$ TRAN$ '/,SWNCHK,LDGSWI ; If a switch, check it. TRAN$ $LAMDA,,TPERTN,ILLDVM,TPERR ; Assume device name error. STATE$ TRAN$ $ALPHA,,DEV1 ; Get first char. of dev. name. STATE$ TRAN$ $ALPHA,,DEV2 ; Get second char. of dev. name. STATE$ TRAN$ $NUMBR,ENDDEV,UNIT ; Get the unit number if any. TRAN$ $LAMDA ; If no unit number, fine. STATE$ ENDDEV TRAN$ ':,,GOTTTY ; Gobble up trailing colon. STATE$ SWILST ; Parse the switches. TRAN$ $LAMDA,,TPERTN,ILLSWM,TPERR ; Assume illegal switch. STATE$ TRAN$ $EOS,$EXIT ; If at end of line, quit. TRAN$ '/ ; Grab the slash. STATE$ SWNCHK TRAN$ !NEGFLG,SWIKEY,CLRNEG ; See if switch negated. TRAN$ $LAMDA,SWIKEY,,-1,NEGATE ; If not, asserted. STATE$ NEGFLG TRAN$ '-,$EXIT ; A minus sign negates the switch. TRAN$ 'N ; A "N" might. STATE$ TRAN$ 'O,$EXIT ; "N" "O" spells "NO". Negate switch. STATE$ SWIKEY TRAN$ "ASSIGN",SWIASN,ASNCHK,S2ASG,S2PRE TRAN$ "ATTENTION",SWIATN,ATNCHK,S2ATN,S2PRE TRAN$ "COMMAND",SWILST,CMDCHK,SWCMD,SWPRE TRAN$ "ECHO",SWILST,ECHCHK,SWECH,SWPRE TRAN$ "EOF",SWIEOF,EOFCHK,SWEOF,SWPRE TRAN$ "HOLD",SWILST,HLDCHK,SWHLD,SWPRE TRAN$ "LIST",SWILST,LSTCHK,SWLIS,SWPRE TRAN$ "LOG",SWILOG,LOGCHK,SWLOG,SWPRE TRAN$ "MAXBUFFER",SWIMXB,MXBCHK,SWMXB,SWPRE TRAN$ "MONITOR",SWILST,MONCHK,SWMON,SWPRE TRAN$ "NULLS",SWILST,NULCHK,SWNUL,SWPRE TRAN$ "PAUSE",SWIPAU,PAUCHK,SWPAU,SWPRE TRAN$ "PROMPT",SWIPMP,PMPCHK,SWPMP,SWPRE TRAN$ "QUIET",SWILST,QUICHK,S2QUI,S2PRE TRAN$ "REMOTE",SWIRMT,RMTCHK,S2RMT,S2PRE TRAN$ "RPA",SWILST,RPACHK,SWRPA,SWPRE TRAN$ "SEND",SWISND,SNDCHK,S2SND,S2PRE TRAN$ "SPEED",SWISPD,SPDCHK,S2SPD,S2PRE TRAN$ "TERMINAL",SWILST,DTECHK,SWDTE,SWPRE TRAN$ !NULSWI,SWILST STATE$ SWILOG ; Parse filename for "/LOG:" TRAN$ ':,SWILOF,TPERTN,ILLFLM,TPERR ; If there is one, get it. TRAN$ $LAMDA,SWILST ; If none, return. STATE$ SWILOF TRAN$ !FILSPC,SWILST,SAVLOG ; If there is one, check&save it STATE$ SWISND ; Parse filename for "/SEND:" TRAN$ ':,SWISNF,TPERTN,ILLFLM,TPERR ; If there is one, get it. TRAN$ $LAMDA,SWILST ; If none, return. STATE$ SWISNF TRAN$ !FILSPC,SWILST,SAVSND ; If there is one, check&save it STATE$ SWIRMT ; Parse speed for /REMOTE: TRAN$ $LAMDA,SWILST,RMTNEG ; If negated, no param. allowed. TRAN$ ':,SWIRMP ; Pick up parameter. TRAN$ $LAMDA,SWIRMI ; If none, go set implied /SPEED STATE$ SWIRMP TRAN$ $DNUMB,,RMTSPD ; If a param, get and check. STATE$ SWIRMI TRAN$ $LAMDA,SWILST,RSPIMP ; Set implied /SPEED if needed. STATE$ SWISPD ; Parse speeds for /SPEED:: TRAN$ ':,SWISPP ; If a colon we have a param. TRAN$ $LAMDA,SWILST,SPDDEF ; If none, set the defaults. STATE$ SWISPP ; Parse the receive speed. TRAN$ $DNUMB,,SPDREC ; Must be a decimal number. STATE$ TRAN$ ': ; Must have another param. STATE$ ; Parse the transmit speed. TRAN$ $DNUMB,SWILST,SPDSND ; Must be a decimal number. STATE$ SWIMXB ; Parse /MAXBUFFER size. TRAN$ $LAMDA,SWILST,MXBNEG ; If negated, no params allowed. TRAN$ ':,SWIMXS ; If a parameter, get it. TRAN$ $LAMDA,SWILST ; If none, done. STATE$ SWIMXS ; Parse the parameter. TRAN$ $DNUMB,SWILST,MXBSIZ ; Store it. STATE$ SWIATN ; Parse /ATTENTION character. TRAN$ ': ; Parameter required. STATE$ TRAN$ !CHARSP,SWILST,GETATN ; Save it. STATE$ SWIEOF ; /EOF TRAN$ ':,SWNEOF ; If a parameter, handle. TRAN$ $LAMDA,SWILST ; If not, that's OK. STATE$ SWNEOF TRAN$ !CHARSP,SWILST,GETEOF ; Save the parameter. STATE$ SWIPMP ; /PROMPT TRAN$ ':,SWNPMP ; If a param, handle. TRAN$ $LAMDA,SWILST ; If not, that's OK. STATE$ SWNPMP TRAN$ !CHARSP,SWILST,GETPMP ; Save the character. STATE$ SWIASN ; /ASSIGN TRAN$ ':,SWIASP,REJNEG ; Params allowed only if assert. TRAN$ $LAMDA,REJSTA,REJNEG ; If asserted, require params. TRAN$ $LAMDA,SWILST ; Negated. Go for next. STATE$ SWIASP ; Parse params. TRAN$ !CHARSP,,GETAS1 ; Get first char. STATE$ TRAN$ ': ; Require another param. STATE$ TRAN$ !CHARSP,SWILST,GETAS2 ; Get second character. STATE$ SWIPAU ; /PAUSE TRAN$ ':,SWIPAT,TPERTN,ILLTMS,TPERR ; If a parameter, get it. TRAN$ $LAMDA,SWILST ; If none, just use last one. STATE$ SWIPAT TRAN$ !TIMSPC,SWILST,GETPAU ; Parse and save the time spec. STATE$ NULSWI ; Parse the null switch. TRAN$ $ANY,REJSTA,CHARSC ; Accept anything but a slash TRAN$ $LAMDA,$EXIT ; Accept on slash without using it. STATE$ REJSTA ; This state is a dead end. TRAN$ $LAMDA,$EXIT,REJECT ; Reject everything. STATE$ FILSPC TRAN$ $LAMDA,,INIDVS ; Set up to parse a file name. STATE$ TRAN$ !DEVSPC,FILUIC ; If a device spec, get it. TRAN$ $LAMDA ; If not, that's OK too. STATE$ FILUIC TRAN$ $LAMDA,,INIUIS ; Set up to parse a UIC. STATE$ TRAN$ !UICSPC,FILNME ; If a UIC, get it too. TRAN$ $LAMDA ; If not, that's OK. STATE$ FILNME TRAN$ $LAMDA,,INIFIS ; Set up to parse a file name. STATE$ TRAN$ !FLNSPC,FILFIN ; If file name, OK. TRAN$ $LAMDA ; If not, that's file too. STATE$ FILFIN ; Make sure we got everything. TRAN$ $EOS,$EXIT,FILDON ; If at EOS, OK. TRAN$ $ANY,FILFNE,CHARSC ; If anything but slash, bad. TRAN$ $LAMDA,$EXIT,FILDON ; Must be a slash. OK. STATE$ FILFNE ; Signal file error by TRAN$ $LAMDA,,REJECT ; rejecting transition. STATE$ DEVSPC ; Validate a device spec. TRAN$ $ALPHA ; First character must be alpha. STATE$ TRAN$ $ALPHA ; So must the second. STATE$ TRAN$ $NUMBR,DEVCLN,CHK256 ; If unit is given, must be < 256. TRAN$ $LAMDA ; Null unit number is also legal. STATE$ DEVCLN TRAN$ ':,$EXIT ; Trailing colon is required. STATE$ UICSPC ; Validate a UIC spec. TRAN$ '[ ; Require a left square bracket. STATE$ UICCHR ; Let FCS validate. TRAN$ '],$EXIT ; If a square bracket, done. TRAN$ $ANY,UICCHR ; Otherwise, go for another. STATE$ FLNSPC ; Parse a file name spec. TRAN$ $STRNG,FLNTYP,CLN9 ; Name is either 1-9 alphanumerics TRAN$ $LAMDA ; or null. STATE$ FLNTYP ; Type is either TRAN$ '.,FLNTYS ; preceded by a dot TRAN$ $LAMDA,FLNVER ; or defaulted. STATE$ FLNTYS ; The explicit file type can be TRAN$ $STRNG,FLNVER,CLN3 ; either 1-3 alphanumerics TRAN$ $LAMDA ; or explicitly null. STATE$ FLNVER ; The version is either TRAN$ <';>,FLNVES ; preceded by a semicolon TRAN$ $LAMDA,$EXIT ; or defaulted. STATE$ FLNVES ; The explicit version number is TRAN$ $NUMBR,$EXIT,CHKPOS ; either in range 0-77777 TRAN$ $LAMDA,$EXIT ; or defaulted. STATE$ CHARSP ; Parse a character spec. TRAN$ $NUMBR,$EXIT,CHARNO ; Get the numeric spec if applic TRAN$ $LAMDA,,CHARCL ; Initialize. STATE$ TRAN$ "NULL",$EXIT ; If null, leave value zero. TRAN$ "SPACE",$EXIT,,40,CHARBN ;If space, set and exit. TRAN$ '',CHARLT ; Apostrophe is quote. TRAN$ '%,CHARLT,,140,CHARSB ; Lowercase conversion. TRAN$ '^,CHARLT,,340,CHARCB ; Control characters. TRAN$ $STRNG,$EXIT,CHATBL ; If in table, look up value. TRAN$ $ANY,$EXIT,CHARVC ; Any but "/" and ":" OK. STATE$ CHARLT ; Pick up quoted/shifted char. TRAN$ $ANY,$EXIT,CHARVL STATE$ TIMSPC ; Parse a time spec. TRAN$ $DNUMB,,GTIMMG ; Get the time magnitude. STATE$ TRAN$ 'T,$EXIT,,1,TIMUNT ; Ticks. TRAN$ 'S,$EXIT,,2,TIMUNT ; Seconds. TRAN$ 'M,$EXIT,GTIMMC,3,TIMUNT ;Minutes. TRAN$ 'H,$EXIT,GTIMHC,4,TIMUNT ;Hours. STATE$ SCNSWI ; Look for the end of a switch. TRAN$ $EOS,$EXIT ; If end of string, found it. TRAN$ $ANY,SCNSWI,CHARSC ; If not slash, continue. TRAN$ $LAMDA,$EXIT ; Exit without taking character. STATE$ .PAGE .SBTTL Initialization code. .PSECT PURCOD RO,I,LCL,REL,CON ENTRY: FINIT$ ; Init the file storage region. MOV #DEVBUF,R2 ; Point to scratch area. GTSK$S R2 ; Get task info. CMPB G.TSSY(R2),#6 ; Are we running under RSX-11M+? BEQ 110$ ; If so, set up that way. CMPB G.TSSY(R2),#1 ; Are we running under RSX-11M? BEQ 120$ ; If so, set up that way. CMPB G.TSSY(R2),#2 ; Are we running under RSX-11S? BEQ 120$ ; If so, handle the same as RSX-11M. MOV #BADSYS,R1 ; Bad system. Get the error message. CLR R2 ; No data. CALL MSGOUT ; Write the error message. EXIT$S ; Die. 110$: ; RSX-11M+ Setup. BR 150$ ; Rejoin common code. 120$: ; RSX-11M/S Setup. BR 150$ ; Rejoin common code. 150$: MOV #DEVBUF,R0 ; Get addr of device buffer. GLUN$S #LTELUN,R0 ; Get LUN info on TI:. .IF DF ACCNTG ; If doing accounting, MOV G.LUNA(R0),ACTDEV ; Save name of our TI:. MOVB G.LUNU(R0),ACTUNT ; Save our unit no, too. .ENDC ; DF ACCNTG ; End of accounting code. MOV G.LUCW+6(R0),R0 ; Get the buffer size. MOV R0,INRDSC+R$DBUF ; Store buffer size. CALL MXBFIL ; Set the max. file buffer. MOV DEVBUF,R0 ; Get the device name. MOV #DRVLTB,R1 ; Get legal driver table. CALL DEVCHK ; Check it out. BCS 200$ ; If not OK, die. MOV R1,LCSTAT ; Store the status. CLRB TELNBI+1 ; Ensure default is /NORPA. CALL TELSET ; Attach the local terminal BCS 200$ ; If an error, exit. MOVB TELOBI+1,TELNBI+1 ; Properly default /RPA. BEQ 160$ ; If /NORPA, OK. BIS #SWRPA,SWSTAT ; If /RPA, set it. 160$: SREX$S #ABOAST ; Set requested exit AST. CLEF$S #LPFLG ; Ensure loop flag clear. CLR SAVCMD ; Clear the saved command. BR MAIN ; Go to it. 200$: EXIT$S ; Die. .PAGE .SBTTL Mainline code. MAIN: CALL GCMGEN ; Execute the commands. 20$: BIS #LPREAP,LPIND ; We are in the process of reassigning. BIC #^C,SWPRE ; Wipe out all switches that are BIC #^C,SWASS ; deferred until after dev. change. BIC SWPRE,SWSTAT ; Preserve the settings of all BIS SWASS,SWSTAT ; switches on command line. .IF DF LINSET ; If doing remote line setup, MOV #SETKIL,R1 ; Execute the line takedown CALL GCMFRC ; command file. .IFTF ; DF LINSET ; In any event, CALL TERCLR ; Clear communications with remote BIT #LPABP,LPIND ; Is it time to go bye-bye? BNE 60$ ; Yes. Do not pass GO, do not collect $200. CALL ALUN ; Assign the LUN to the new device. BCS MAIN ; If failed, prompt again. .IFT ; DF LINSET ; If doing remote line setup, MOV #SETINI,R1 ; Execute the CALL GCMFRC ; setup file. .ENDC ; DF LINSET BIC #LPREAP,LPIND ; Device specs are legal again. BR MAIN ; Go to normal code. 60$: SREX$S ; No more abort AST. CALL TELCLR ; Detach local terminal. CALL CLOLOG ; Close the log file. EXIT$S ; Goodbye, cruel world. .PAGE .SBTTL Subroutine GCMINI - Initialize before getting a command. GCMINI: BIT #LPABO,LPIND ; Have we been aborted? BNE 40$ ; If so, handle. MOV #/2,R1 ; Get words to zero. MOV #BEGZER,R0 ; Find out where to start. 20$: CLR (R0)+ ; Zero a word. SOB R1,20$ ; If not done, go again. BIC #LPCMD!LPREA,LPIND ; Clear "breakout" indicators. RETURN ; Return to caller. 40$: BIS #LPABP,LPIND ; Abort pending. BIC #LPABO,LPIND ; Clear the "immediate abort". SEC ; Error RETURN ; Return to caller. .IF DF LINSET ; If using line setup, .SBTTL Subroutine GCMFRC - Force call to command file. ; Edit spec for file name comes in in R1. GCMFRC: .ENABL LSB TST DEVNAM ; Got a device? BEQ 60$ ; If not, done. BIT #SWHLD,SWSTAT ; Want to hold the line? BNE 60$ ; If so, don't execute the file. MOV #BANDAT,R2 ; Get terminal name. MOV #MSGBUF,R0 ; Point to message area. CALL $EDMSG ; Create the file name. SUB #MSGBUF,R0 ; Compute length. MOV R0,SETDDB+10 ; Save length of file name. MOV #SETDDB,R1 ; Get dataset descr. address. ; Fall thru GCMFRG: CMGET$ #GCMLB,FILE=R0 ; Get FDB address. MOV R1,F.DSPT(R0) ; Set up dataset descr. OPEN$ ; Open. BCS 60$ ; If an error, quit. CLR SNDFDB+F.FNB+N.FID ; Get rid of send file ID. MOV #GCMLB,R0 ; Get the parameter block addr. .IF DF EXGTCM ; If using EGCML interface, MOV G.MODE(R0),-(SP) ; Save old mode. MOVB G.CDEP(R0),-(SP) ; Save current nesting depth. MOV G.PPTR(R0),R1 ; Get the pushdown pointer. MOV R1,-(SP) ; Save the pushdown pointer. MOV #G.PLFS/2,R2 ; Iteration count. 10$: CLR -(R1) ; Dummy stack entry. SOB R2,10$ ; Repeat as needed. MOV #1,-(R1) ; Fudged completion status. CLR -(R1) ; Saved MOV #1,-(R1) ; positional CLR -(R1) ; context. CMGET$ #GCMLB,FILE=R2 ; Need FDB address again. MOV #8.,-(SP) ; Kluge counter. 20$: MOV (R2)+,-(R1) ; Move in the required info. DEC (SP) ; Thru? BGT 20$ ; If not, go again. TST (SP)+ ; Clean up stack. ADD #F.FNB+N.FID-16.,R2 ; Point to file ID. MOV (R2)+,-(R1) ; Save MOV (R2)+,-(R1) ; file MOV (R2)+,-(R1) ; ID. ADD #N.DID-N.FID-6,R2 ; Point to directory ID. MOV (R2)+,-(R1) ; Save MOV (R2)+,-(R1) ; directory MOV (R2)+,-(R1) ; ID. MOV (R2)+,-(R1) ; Save device name MOV (R2)+,-(R1) ; and unit number. CLR -(R1) ; Save flags. ; CLR -(R1) ; Saved \ Not needed ; MOV #1,-(R1) ; positional | since file is ; CLR -(R1) ; context. / left open. MOV R1,G.PPTR(R0) ; Save the new pointer. MOVB #2,G.CDEP(R0) ; Set nest depth to two. BIS #GE.MCR,G.MODE(R0) ; Set the "valid MCR" bit. .IFF ; DF EXGTCM ; If using GCML MOVB G.MODE(R0),-(SP) ; Save old mode, MOVB G.CMLD+4(R0),-(SP) ; old command file nest depth, MOV G.CMLD+6(R0),-(SP) ; and old pushdown pointer. MOV G.CMLD+6(R0),R1 ; Point to stack. MOV #8.,R2 ; Iteration count. 10$: CLR (R1)+ ; Null stack for level 1. SOB R2,10$ ; If not done, repeat. CLR (R1)+ ; Set desired MOV #1,(R1)+ ; positional CLR (R1)+ ; context. MOVB #1,(R1)+ ; Fudge QIO context. MOVB F.FNB+N.UNIT(R0),(R1)+ ; Get unit number. MOV F.FNB+N.DVNM(R0),(R1)+ ; Get device name. MOV F.FNB+N.FID(R0),(R1)+ ; Get the MOV F.FNB+N.FID+2(R0),(R1)+ ; file MOV F.FNB+N.FID+4(R0),(R1)+ ; ID. BISB #200,G.MODE(R0) ; Force "valid MCR" flag. MOVB #2,G.CMLD+4(R0) ; Force nest level 2. MOV R1,G.CMLD+6(R0) ; New pushdown list pointer. CLOSE$ ; Close file. .IFTF ; DF EXGTCM ; In either case, CALL GCMINP ; Process the file. MOV #GCMLB,R0 ; Get the parameter block addr. .IFT ; DF EXGTCM ; If using EGCML, MOV (SP)+,G.PPTR(R0) ; Restore the pushdown pointer. MOVB (SP)+,G.CDEP(R0) ; Restore current nesting depth. MOV (SP)+,G.MODE(R0) ; Restore old mode. .IFF ; DF EXGTCM ; If using GCML, MOV (SP)+,G.CMLD+6(R0) ; Restore the pushdown pointer. MOVB (SP)+,G.CMLD+4(R0) ; Restore current nest depth. MOVB (SP)+,G.MODE(R0) ; Restore old mode. .ENDC ; DF EXGTCM CLR SNDFDB+F.FNB+N.FID ; Get rid of send file ID. 60$: RETURN ; Return to caller. .DSABL LSB .ENDC ; DF LINSET .PAGE .SBTTL Subroutine GCMGEN - Get a command, from whatever source. .ENABL LSB ; Shared code. GCMGEN: TST SAVCMD ; Is there a canned command? BEQ GCMINP ; If not, go to the input. CALL GCMINI ; Set up. BCS 90$ ; If abort, return. MOV #SAVCMD,R4 ; Get the command block. MOV (R4)+,R3 ; Get the length of the command. CLR SAVCMD ; Get rid of the saved command. BR 10$ ; Join normal code. .SBTTL Subroutine GCMINP - Get command from normal channel. GCMINP: CALL GCMINI ; Initialize. BCS 90$ ; If aborted, just return. MOV #GCMLB,R0 ; Get the GCML control block. GCML$ ; Get the next command line. BCS 20$ ; If an error, process it. MOV G.CMLD(R0),R3 ; Get command length. BEQ GCMINP ; If null, ignore. MOV G.CMLD+2(R0),R4 ; Get command line address. 10$: CALL GCMPRS ; Parse the command line. BCS 50$ ; If error, go report it. BIT #LPREA,LPIND ; Reassigning? BNE 90$ ; If so, go to it. CALL EXECUT ; Execute the command. BR GCMINP ; Go for another one. 20$: MOV #GCMTBL,R2 ; Get error table. CMPB #GE.EOF,G.ERR(R0) ; Was error End-of-file? BEQ 80$ ; If end of file, normal exit. 30$: CMPB (R2)+,G.ERR(R0) ; Is this the error? BEQ 40$ ; If so, use it. ADD #3,R2 ; Go to next entry. TST (R2) ; Is there one? BNE 30$ ; If so, process it. INC R2 ; Adjust R2. 40$: INC R2 ; Skip unused byte. MOV #TPERR,R1 ; Point to parameter buffer. MOV (R2)+,(R1)+ ; Fill in detail message. CMGET$ ,FILE=R2 ; Get FDB address. MOVB F.ERR(R2),R2 ; Get the error code. MOV R2,(R1)+ ; Save the error code. MOV #GCMERM,R1 ; Get the error message. 50$: MOV #TPERR,R2 ; Point to data block. CALL MSGOUC ; Write it, with command line. RCML$ #GCMLB ; Reset to top level. BR GCMINP ; Just get next command. 80$: BIT #LPREAP,LPIND ; Working on a reassign? BNE 90$ ; If so, skip. BIS #LPABP,LPIND ; Need to exit. 90$: SEC ; Set the exception bit. RETURN ; Return to caller. .DSABL LSB ; End of shared code. .PAGE .SBTTL Subroutine GCMPRS - Parse the command line. GCMPRS: MOV #2*400+0,R1 ; Allow 2-chr abbrevs, ignore blanks. MOV #CMDTRN,R2 ; Get address of keyword table. MOV #CMDSTA,R5 ; Get address of state table. CALL .TPARS ; Parse the line. BCC 40$ ; If succeeded, proceed. MOV OLDOUD,OUTDEV ; Restore the device name MOV OLDOUN,OUTUNT ; and unit number. CLR R1 ; Want exact keyword match. MOV #CMDTRN,R2 ; Get address of keyword table. MOV #SCNSWI,R5 ; Get address of state table. CALL .TPARS ; Look for end of syntax element. MOV #PRSERM,R1 ; Log a command parse error. SUB R3,TPERR+2 ; Calculate length. SEC ; Indicate an error. 40$: RETURN ; Return to caller. .PAGE .SBTTL Subroutine EXECUT - Do what's needed. EXECUT: BIC #SWNLAT,SWSTAT ; Clear all that don't latch. BIC SWPREI,SWSTAT ; Set all the implied switches first, BIS SWASSI,SWSTAT ; so actual switches override them. BIC SWPRE,SWSTAT ; Preserve the settings of all BIS SWASS,SWSTAT ; switches on command line. BIC #LPRDY,LPIND ; Init the file flag. CALL CHRASN ; Process /ASSIGN, if any. CALL TELTRM ; Set up local terminal as needed. BCS 50$ ; If failed, go no further. CALL TERSPD ; Set remote speed if needed. BCS 40$ ; If failed, quit. CALL OPNSCN ; Open the send file if needed. BCS 40$ ; If failed, punt. CALL CLOLCN ; Close log file if desired. CALL OPNLCN ; Open log file if desired. MOV #RDYPMP,R1 ; Assume want a linefeed at start. TST SNDFDB+F.BDB ; Is data coming from a send file? BNE 20$ ; If so, fine. MOV #-1,PMPFLG ; Disable prompt processing for TT: input. BIT #LPREAP,LPIND ; Are we processing a setup file? BNE 40$ ; If so, no user input allowed. BIT #SWCMD,SWSTAT ; Want an immediate return to cmd mode? BNE 40$ ; If so, go for it. 15$: BIT #SWDTE,SWSTAT ; Are we talking to a terminal? BEQ 17$ ; If not, proceed. MOV #CR,R0 ; Implied to the CALL OURING ; output terminal. MOV #LF,R0 ; Implied linefeed, CALL OURING ; too. 17$: MOV #RDYMSG,R1 ; Set up terminal prompt. 20$: CALL MSGOUT ; Issue prompt. 30$: CALL GETDAT ; Get some data to transmit. CALL ROU ; Write to remote terminal. CALL LOU ; Write to local terminal. BIT #LPCMD,LPIND ; Need to break out of loop? BEQ 30$ ; If not, go wait some more. TST SNDFDB+F.BDB ; Send file open? BEQ 40$ ; If not, need a command. CALL CLOSND ; Close send file if any. BIT #LPREAP,LPIND ; Are we processing a setup file? BNE 40$ ; If so, no user input allowed. BIT #SWCMD,SWSTAT ; What do we do after closing? BNE 40$ ; If want another cmd, go get it. BIT #RMATU,LCSTAT ; Can our TI: provide terminal mode? BEQ 40$ ; If not, go for another command. BIC #LPXIT,LPIND ; Clear the breakout indicator. BIT #LPABO,LPIND ; Aborting? BEQ 15$ ; If not, go into terminal mode. 40$: CALL TELCMD ; Put terminal back in command mode. 50$: RETURN ; Go for another command. .PAGE .SBTTL Subroutines - Parser action routines. TPERTN: MOV #TPERR,R0 ; Load up error msg block address. CLR (R0)+ ; Clear error msg address. MOV R3,(R0)+ ; Store characters left. MOV R4,(R0) ; Store address of string. RETURN ; Let parser set the message address. LDGSWI: TST OUTDEV ; Have we got a device name to work on? REJECT EQ ; If not, require one. RETURN ; If so, fine. CLRNEG: CLR NEGATE ; Set flag for negated switch. RETURN ; Return to parser. DEV1: BIT #LPREAP,LPIND ; Are we already reassigning a device? BEQ 10$ ; If not, fine. MOV #DEVILL,TPERR ; If so, can't respecify. Set error msg REJECT ; and reject the transition. 10$: MOVB .PCHAR,OUTDEV ; Save the first character. DUMMY: RETURN ; Go back to parser. DEV2: MOVB .PCHAR,OUTDEV+1 ; Save the second character. CLR OUTUNT ; Default unit number to 0. RETURN ; Go back to parser. UNIT: TST .PNUMH ; Number too big? REJECT NE ; If so, reject it. TSTB .PNUMB+1 ; More than 255.? REJECT NE ; If so, reject. MOV .PNUMB,OUTUNT ; Save the unit number. RETURN ; Return to parser. GOTTTY: CMP OUTDEV,OLDOUD ; Is this a new device? BNE 5$ ; If so, fine. CMP OUTUNT,OLDOUN ; Is it a different unit? BEQ 30$ ; If not, just return. 5$: BIS #LPREA,LPIND ; Set the "reassign" indicator. MOV #SAVCMD,R1 ; Get saved command buffer. MOV R3,R2 ; Get remaining command. BLE 20$ ; If null, fudge it. MOV R4,R0 ; Get its address. MOV R3,(R1)+ ; Save the length. 10$: MOVB (R0)+,(R1)+ ; Save a byte of the command. SOB R2,10$ ; Repeat as needed. BR 30$ ; Go return. 20$: MOV #1,(R1)+ ; Fudge in the MOVB #'/,(R1)+ ; null command. 30$: RETURN ; Return to caller. ASNCHK: MOV #S2ASG,R0 ; Checking /ASSIGN::. BR SW2CHK ; Go do it. ATNCHK: MOV #S2ATN,R0 ; Checking /ATTENTION BR SW2NGC ; Go do it (can't be negated). CMDCHK: MOV #SWCMD,R0 ; Checking /COMMAND BR SWICHK ; Go do it. DTECHK: MOV #SWDTE,R0 ; Checking /TERMINAL MOV #DTEIMP,R2 ; Point to "accepted" routine. BR SWICHA ; Go do it. ECHCHK: MOV #SWECH,R0 ; Checking /ECHO. BR SWICHK ; Go do it. EOFCHK: MOV #SWEOF,R0 ; CHecking /EOF BR SWICHK ; Go do it. HLDCHK: MOV #SWHLD,R0 ; Checking /HOLD BR SWICHK ; Go do it. LSTCHK: MOV #SWLIS,R0 ; Checking /LIST BR SWICHK ; Go do it. LOGCHK: MOV #SWLOG,R0 ; Checking /LOG: BR SWICHK ; Go do it. MONCHK: MOV #SWMON,R0 ; Checking /MONITOR MOV #MONIMP,R2 ; Got some switches to imply. BR SWICHA ; Go do it. MXBCHK: MOV #SWMXB,R0 ; Checking /MAXBUFFER: BR SWICHK ; Go do it. NULCHK: MOV #SWNUL,R0 ; Checking /NULLS BR SWICHK ; Go do it. PAUCHK: MOV #SWPAU,R0 ; Checking /PAUSE: BR SWICHK ; Go do it. PMPCHK: MOV #SWPMP,R0 ; Checking /PROMPT: BR SWICHK ; Go do it. QUICHK: MOV #S2QUI,R0 ; Checking /QUIET BR SW2CHK ; Go do it. RMTCHK: MOV #S2RMT,R0 ; Checking /REMOTE: BR SW2CHK ; Go do it. RPACHK: MOV #SWRPA,R0 ; Checking /RPA BR SWICHK ; Go do it. SNDCHK: MOV #S2SND,R0 ; Checking /SEND: BR SW2CHK ; Go do it. SPDCHK: MOV #S2SPD,R0 ; Checking /SPEED:: BR SW2NGC ; Go do it (can't be negated). SWINGC: MOV #DUMMY,R2 ; Provide dummy "accepted" routine. SWINGA: TST NEGATE ; Switch negated? BLT SWICHA ; If not, fine. MOV #ILLNEG,TPERR ; If so, set up the error message REJECT ; and reject the switch. SWICHK: MOV #DUMMY,R2 ; Provide dummy "accepted" routine. SWICHA: BIT R0,SWPRE ; Switch already seen? BNE DUPSWI ; If so, error out. TST NEGATE ; Switch negated? BGE 10$ ; If so, done. BIS R0,SWASS ; If not, mark asserted. 10$: JMP (R2) ; Go to "accepted" routine. SW2NGC: MOV #DUMMY,R2 ; Provide dummy "accepted" routine. SW2NGA: TST NEGATE ; Switch negated? BLT SW2CHA ; If not, fine. MOV #ILLNEG,TPERR ; If so, set up the error message REJECT ; and reject the switch. SW2CHK: MOV #DUMMY,R2 ; Provide dummy "accepted" routine. SW2CHA: BIT R0,S2PRE ; Switch already seen? BNE DUPSWI ; If so, error out. TST NEGATE ; Switch negated? BGE 10$ ; If so, done. BIS R0,S2ASS ; If not, mark asserted. 10$: JMP (R2) ; Go to "accepted" routine. DTEIMP: MOV #SWDTEI,R0 ; Get switches implied by /TERMINAL MOV #SWDTEA,R1 ; Get switches asserted by /TERMINAL BR COMIMP ; Do common implied switch processing. MONIMP: MOV #SWMONI,R0 ; Get switches implied by /MONITOR MOV #SWMONA,R1 ; Get switches asserted by /MONITOR BR COMIMP ; Do common implied switch processing. COMIMP: BIS R0,SWPREI ; Mark switches as present. BIC R0,SWASSI ; Override previously implied assertions TST NEGATE ; Was real switch negated? BLT 10$ ; If so, we're fine. COM R1 ; If not, reverse the implied assertions COM R0 ; Clear out the bits for switches BIC R0,R1 ; that are not implied. 10$: BIS R1,SWASSI ; Mark switches asserted as needed. RETURN ; Return to caller. SAVSND: CALL CLOSND ; Close the send file, if open. MOVB #FO.RD,F.FACC(R0) ; Open existing file readonly. BR SAVDSD ; Go process the FDB. SAVLOG: CALL CLOLOG ; Close the log file, if open. MOVB #FO.WRT,F.FACC(R0) ; Open a new file for output. SAVDSD: CLR F.FNB+N.FID(R0) ; Prevent open by file ID. MOV F.DSPT(R0),R2 ; Point to proper dataset desc. MOV #FILDSD,R1 ; Point to new dataset desc. .REPT 6 ; Copy the dataset over. MOV (R1)+,(R2)+ .ENDR RETURN ; Return to caller. GETPMP: MOV #PMPBYT,R2 ; Storing the prompt byte. BR GETBYT ; Go do it. GETAS1: MOV #GETAC1,R2 ; Storing first /ASSIGN parameter. BR GETBYT ; Go do it. GETAS2: MOV #GETAC2,R2 ; Storing second /ASSIGN parameter. BR GETBYT ; Go do it. GETEOF: MOV #EOFBYT,R2 ; Storing the /EOF value. BR GETBYT ; Go do it. GETATN: MOV #ATNBYT,R2 ; Storing the /ATTENTION value. TSTB CHARBN ; Null? BNE GETBYT ; If not, just go do it. MOV #ILLATN,TPERR ; Assume not legal. BIT #RMNUL,LCSTAT ; Null valid? REJECT EQ ; Reject if not. GETBYT: MOVB CHARBN,(R2) ; Store the value. BICB #^C177,(R2) ; Strip off unused bits. RETURN ; Return to caller. GETPAU: MOV TIMUNT,RCDUNT ; Copy over the MOV TIMMAG,RCDLAY ; pause time. RETURN ; Return to caller. REJNEG: TST NEGATE ; Negated? REJECT GE ; If so, reject. RETURN ; If not, return. DUPSWI: MOV #DUPSWM,TPERR ; Change error to dup. switch. REJECT ; Reject the transition. INIDVS: CLR FILDSD ; Set up the device name portion MOV R4,FILDSD+2 ; of the dataset descriptor. RETURN ; Return to caller. INIFIS: MOV #FILDSD+4,R0 ; Point to UIC part of DSD. BR INIFLS ; Join common code. INIUIS: MOV #FILDSD,R0 ; Point to device part of DSD. INIFLS: MOV R4,(R0)+ ; Save current location. SUB (R0)+,-4(R0) ; Calc. length of previous element. CLR (R0)+ ; Assume length of zero. MOV R4,(R0)+ ; Save current address. RETURN ; Return to caller. FILDON: MOV #FILDSD+10,R0 ; Point to filename part of DSD. MOV R4,(R0)+ ; Save current location. SUB (R0),-(R0) ; Calc. length. RETURN ; Guess what. CHKPOS: MOV #100000,R0 ; Check if number is positive. BR CHKNUM ; Join common code. CHK256: MOV #256.,R0 ; Check if number is > 1 byte. CHKNUM: TST .PNUMH ; Is it double precision? REJECT NE ; If so, reject it. CMP .PNUMB,R0 ; Is it over limit? REJECT HIS ; If so, reject it. RETURN ; If not, it's OK. CLN9: MOV #9.,R0 ; Check if string > 9. chars BR CLENG ; Join common code. CLN3: MOV #3,R0 ; Check if string > 3 chars. CLENG: CMP .PSTCN,R0 ; Is the string overlong? REJECT HI ; If so, it's no good. RETURN ; If not, OK. CHARCL: CLR CHARCB ; Initialize the character CLR CHARSB ; clear and set masks. CLR CHARBN ; Also its binary value. RETURN CHARNO: MOV .PNUMB,CHARBN ; Save the value. BIC #^C177,CHARBN ; Clear unwanted part. RETURN ; Return to parser. CHARVC: CMPB .PCHAR,#': ; Is it a colon? REJECT EQ ; If so, reject it. CHARSC: CMPB .PCHAR,#'/ ; Is it a slash? REJECT EQ ; If so, reject it. CHARVL: MOVB .PCHAR,CHARBN ; Get the character. BIC CHARCB,CHARBN ; Clear bits as needed. BIS CHARSB,CHARBN ; Set bits as needed. RETURN ; Return to caller. CHATBL: MOV #CTRLCR-2,R0 ; Pick up control char. table. CLR R1 ; Call for exact match. CALL KEYCMP ; Is the string in this table? REJECT CS ; If not, reject. DEC R0 ; Convert index to ASCII value. BIC #^C177,R0 ; Strip inwanted bits. MOV R0,CHARBN ; Store the character where needed. RETURN ; Return to parser. KEYCMP: JSR R5,$SAVRG ; Save some registers. TST R1 ; Abbreviations allowed? BEQ 10$ ; If not, fine. CMP .PSTCN,R1 ; Got enough characters? BLT 50$ ; If not, error out. 10$: MOV R1,R5 ; Save abbr. len where we can use it. CLR -(SP) ; Init. the hit counter CLR -(SP) ; and the hit index. MOV #-1,R4 ; Init the table entry counter. 20$: INC R4 ; Count another table entry. MOV (R0)+,R1 ; Get the next entry. BEQ 40$ ; If none, finish up. MOV .PSTPT,R2 ; Point to the target string. MOV .PSTCN,R3 ; Get its length. 30$: CMPB (R1)+,(R2)+ ; Match? BNE 20$ ; If not, go for next table entry. SOB R3,30$ ; Repeat as needed. TST R5 ; Want an exact match? BNE 35$ ; If not, what we have is good enough. TSTB (R1)+ ; Are we at the terminator? BNE 20$ ; If not, not really a match. 35$: INC 2(SP) ; Got a match. Count it, and MOV R4,(SP) ; save its index. BR 20$ ; Go for more. 40$: MOV (SP)+,R0 ; Get the index of the match. DEC (SP)+ ; Did we get a unique match? BEQ 60$ ; If so, just return. 50$: SEC ; Problems. Indicate an error. 60$: RETURN ; Return to caller. GTIMMG: TST .PNUMH ; Time magnitude too big? REJECT NE ; If so, reject. MOV .PNUMB,TIMMAG ; Save the low mag. REJECT LE ; Must be positive. CLR TIMUNT ; Init. the units word. RETURN ; Return to caller. GTIMHC: CMP TIMUNT,#24. ; Specified more hours than a day? REJECT GT ; If so, reject. RETURN ; If not, return. GTIMMC: CMP TIMUNT,#1440. ; Specified more minutes than in a day? REJECT GT ; If so, reject. RETURN ; If not,return. MXBSIZ: MOV .PNUMB,R0 ; Get number parsed. BR MXBFIL ; Fill it in. MXBNEG: MOV INRDSC+R$DBUF,R0 ; Get local terminal buffer size. CALL MXBFIL ; Fill it in as the default. TST NEGATE ; Switch asserted? REJECT LT ; If so, reject trans, keeping buf siz. MOV #BUFSIZ,R0 ; Switch negated. Set for max. ; Fall thru. MXBFIL: CMP R0,#16. ; Too small? BHIS 10$ ; If not, fine. MOV #16.,R0 ; If so, bump up to size. 10$: CMP R0,#BUFSIZ ; Too big? BLOS 20$ ; If not, fine. MOV #BUFSIZ,R0 ; If so, cut down to size. 20$: ADD #LGFDSC,R0 ; Point to end of buffer. MOV R0,LGFDSC+F$BEND ;Store the value. RETURN ; Return to caller. SPDDEF: MOV #TERORC+1,SPDRRC ; Default the receive and MOV #TEROSD+1,SPDRSD ; transmit speed to original. RETURN ; Return to parser. RSPIMP: BIT #S2SPD,S2PRE ; /SPEED already seen? BNE 10$ ; If so, do nothing. CMPB @TERASA,SPDZER+2; Was it /REMOTE:0? BEQ 10$ ; If so, do nothing. MOV TERASA,SPDRRC ; Make the receive and MOV TERASA,SPDRSD ; send speed same as remote speed. 10$: RETURN ; Return to parser. RMTNEG: MOV #TEROAS+1,TERASA ; Assume asserted, no param. TST NEGATE ; Asserted? REJECT LT ; If so, reject. MOV #SPDZER+2,TERASA ; If negated, turn off remote. RETURN ; and return to parser. SPDREC: MOV #SPDRRC,R0 ; Pick up where receive speed goes. BR SPDCOM ; Go validate and store. SPDSND: MOV #SPDRSD,R0 ; Pick up where send speed goes. BR SPDCOM ; Go validate and store. RMTSPD: MOV #TERASA,R0 ; Pick up where /REMOTE speed goes. BR SPDCOM ; Go validate and store. SPDCOM: TST .PNUMH ; Too big? REJECT NE ; If so, reject. MOV #SPDTBL,R1 ; Pick up table of legal speeds. 10$: CMP (R1)+,.PNUMB ; Is it this one? BEQ 20$ ; If so, go set it up. TST (R1)+ ; If not, skip over the setting. CMP R1,#SPDTBE ; Off end of table? BLO 10$ ; If not, go try again. REJECT ; If so, reject. 20$: MOV R1,(R0) ; Point to the proper mask. RETURN ; Return to caller. .PAGE .SBTTL Subroutine - Abort Task AST code. ABOAST: ADD (SP),SP ; Clean up the stack. BIS #LPABO!LPXIT,LPIND ; End loop and abort. SETF$C LPFLG,PURCOD ; Fire up mainline again. ASTX$S ; Exit the AST. .PAGE .SBTTL Subroutine ALUN - Assign remote LUN. ALUN: TRACER ALUN CALL RMTSET ; Assign the remote LUN. BCS 50$ ; If error, die. CALL TERSET ; Set up the new assignment. BCC 60$ ; If success, go return. 50$: CLR OUTUNT ; If failure, clear out CLR OUTDEV ; the device name. CLR SAVCMD ; Can't execute saved command any more. BIC #LPREAP,LPIND ; Device specs are legal again. CLR DEVNAM ; We no longer have a device. SEC ; Ensure carry set. 60$: MOV OUTUNT,OLDOUN ; Save the desired device name so that MOV OUTDEV,OLDOUD ; we can detect a change later. RETURN ; Return to caller. .SBTTL Subroutine RMTSET - Assign remote LUN and get info. RMTSET: TRACER RMTSET ALUN$S #RTELUN,OUTDEV,OUTUNT ; Assign the LUN. BCC 10$ ; If no error, okay. MOV #ASNERM,R1 ; Pick up error message MOV #$DSW,R2 ; and status code. CALL MSGOUT ; Write the message. SEC ; Ensure carry set. BR 60$ ; Go return. 10$: MOV #DEVBUF,R0 ; Point to device info buffer. GLUN$S #RTELUN,R0 ; Get info on our device. MOVB 2(R0),DEVUNT ; Get the unit number. MOV (R0),R0 ; Get device name. MOV R0,DEVNAM ; Store it. MOV #DRVRTB,R1 ; Get list of valid remotes. CALL DEVCHK ; Validate the device. BCS 60$ ; If an error, exit. BIT #RMLOG,R1 ; Device supports login? BEQ 20$ ; If not, proceed. BIT #U2.LOG,DEVBUF+G.LUCW+2 ; Logged in? BNE 20$ ; If not, okay. MOV #ERLOGO,R1 ; Get error message text MOV #BANDAT,R2 ; and name of terminal. CALL MSGOUT ; Write the message. SEC ; Set the carry. BR 60$ ; Return to caller. 20$: MOV R1,RMSTAT ; Save device status. MOV DEVBUF+G.LUCW+6,OURDSC+R$DBUF ; Save buffer size. 60$: RETURN ; Return to caller. .SBTTL Subroutine DEVCHK - Check out the device. DEVCHK: TRACER DEVCHK 10$: CMP (R1)+,R0 ; This entry? BEQ 20$ ; If so, clean up and exit. TST (R1)+ ; Skip over flags. TST (R1) ; At end of table? BNE 10$ ; If not, check next entry. MOV #BADDVM,R1 ; Pick up the error message MOV #BANDAT,R2 ; and the data. CALL MSGOUT ; Write the message. SEC ; Ensure return with carry clear. BR 60$ ; Go return. 20$: MOV (R1),R1 ; Pick up the status. 60$: RETURN ; Return to caller. .PAGE .SBTTL Subroutine CHRASN - Process /ASSIGN switch. CHRASN: TRACER CHRASN BIT #S2ASG,S2PRE ; Got a /ASSIGN? BEQ 60$ ; If not, just return. BIT #S2ASG,S2ASS ; Asserted? BEQ 20$ ; If not, clear table. CLR R0 ; Get the character to BISB GETAC2,R0 ; translate. MOVB GETAC1,ASGTBL(R0) ; Set its equivalent. BR 60$ ; Return. 20$: MOV #ASGTBL+177+1,R0 ; Point to end of table. MOV #177,R1 ; Get character code. CALL DISAST ; No AST's while table updated. 30$: MOVB R1,-(R0) ; Store code. SOB R1,30$ ; Repeat as needed. CLRB -(R0) ; Do the last one. 60$: RETURN ; Return. .PAGE .SBTTL Subroutine GETDAT - Drop send file rec. into outbound ring. GETDAT: TRACER GETDAT BIT #LPRDY,LPIND ; Ready to send another record? BNE 10$ ; If so, go get it. WTSE$S #LPFLG ; Wait for data. CLEF$S #LPFLG ; Got it. Clear wait flag. BR 50$ ; Return to caller. 10$: GET$ #SNDFDB,#SNDBUF,#SNDBFL ; Get a record from the file. CALL DISAST ; Dsabl AST's while using ring. CMPB F.ERR(R0),#IS.SUC ; Did we get the record OK? BNE 60$ ; If not, terminate transfer. MOV #-1,PMPFLG ; Assume no prompt. BIT #SWPMP,SWSTAT ; Want to check for prompts? BEQ 15$ ; If not, proceed. CLR PMPFLG ; If so, load up the MOVB PMPBYT,PMPFLG ; prompt character. BIC #LPRDY,LPIND ; Not ready any more. 15$: BIT #SWPAU,SWSTAT ; Pausing between records? BEQ 20$ ; If not, just proceed. BIC #LPRDY,LPIND ; Not ready any more. BIT #SWPMP,SWSTAT ; Want prompt as well? BNE 20$ ; If so, skip. MRKT$S ,RCDLAY,RCDUNT,#DLYAST ; Issue marktime for pause. 20$: JSR R5,$SAVRG ; Save some registers for work. MOV R0,R5 ; Relocate FDB address. MOV F.NRBD(R5),R3 ; Get size of record. MOV F.NRBD+2(R5),R4 ; Get address of record. CALL @CCLDNG ; Insert leading carriage ctl. BR 40$ ; Go process the record. 30$: MOVB (R4)+,R0 ; Get the next character. CALL OURING ; Put it in the outbound ring. 40$: DEC R3 ; Any more to do? BGE 30$ ; If so, take care of it. CALL @CCTLNG ; Insert trailing carriage ctl. 50$: RETURN ; Return to caller. 60$: JMP TERMIN ; Error - terminate transfer. .PAGE .SBTTL Subroutine INRING - Drop a character in inbound ring. INRING: .ENABL LSB ; So shared code will work. CMP R0,PMPFLG ; Is this the prompt character? BNE 30$ ; If not, just drop in ring. TST SNDFDB+F.BDB ; SENDing a file? BEQ 20$ ; If not, quit. BIT #SWPMP,SWSTAT ; Looking for prompt? BEQ 20$ ; If not, clear indicator and proceed. BIT #SWPAU,SWSTAT ; Got a /PAUSE? BNE 10$ ; If so, start the marktime. BIS #LPRDY,LPIND ; Fire up the mainline. BR 30$ ; Go drop the character in the ring. 10$: CMKT$S ,#DLYAST ; Cancel current marktime if any. MRKT$S ,RCDLAY,RCDUNT,#DLYAST ; Start the marktime. BR 30$ ; Go drop the character in the ring. 20$: MOV #-1,PMPFLG ; Insure no further matches. 30$: MOV #INRDSC,R1 ; Get the inbound ring descriptor. BIT #SWMON,SWSTAT ; Monitoring input? BEQ 90$ ; If not, join common code. CMPB R0,#40 ; Printable character? BLO 40$ ; If not, check for carriage control. CMPB R0,#DEL ; Is it a delete? BNE 90$ ; If not, handle normally. BR 50$ ; If so, expand it. 40$: CMPB R0,#CR ; Carriage control character? BHI 50$ ; Can't be. Process it. CMPB R0,#LF ; Might be, check low end. BHIS 90$ ; It is. handle normally. 50$: MOV R0,-(SP) ; Save original character, MOV R3,-(SP) ; and a working register. ASL R0 ; Convert to word offset. MOVB R0,R0 ; Sign-extend the result. ADD #CTRLCR,R0 ; Convert to table address. MOV (R0),R3 ; Get address of substitution string. MOV #'<,R0 ; Get the first angle bracket. CALL 90$ ; Drop it in the ring. BR 70$ ; Enter loop at bottom. 60$: CALL 90$ ; Drop character in ring. 70$: MOVB (R3)+,R0 ; Get the next character. BNE 60$ ; If not done, go put it in ring. MOV #'>,R0 ; Get the right angle bracket. CALL 90$ ; Drop in the trailing angle bracket. MOV (SP)+,R3 ; Restore the saved MOV (SP)+,R0 ; registers. RETURN ; Return to caller. .SBTTL Subroutine OURING - Drop a character in outbound ring. OURING: MOV R0,-(SP) ; Save the char. BIC #^C177,R0 ; Strip unused bits. MOVB ASGTBL(R0),R0 ; Remap the character. BIT #SWECH,SWSTAT ; Doing local echo? BEQ 80$ ; If not, proceed. CALL INRING ; If so, turn the character around. 80$: MOV #OURDSC,R1 ; Get the outbound ring descriptor. CALL 90$ ; Drop it in. MOV (SP)+,R0 ; Restore character. RETURN ; Return to caller. ; Subroutine 90$ - Common ring handling code. 90$: MOV R$INB(R1),R2 ; Find out where the character goes. MOVB R0,(R2)+ ; Put it there. CMP R2,R$BND(R1) ; Time to wrap around? BLO 100$ ; If not, just go store pointer. MOV R1,R2 ; If so, adjust pointer .IF NE R$BUF ; back to ADD #R$BUF,R2 ; start of .ENDC ; NE R$BUF ; buffer. 100$: MOV R2,R$INB(R1) ; Store updated pointer. RETURN ; Return to caller. .DSABL LSB ; End of shared code. .PAGE .SBTTL Subroutine CCCHEK - Check and set up implied carrg ctl. CCCHEK: MOVB F.RATT(R0),R1 ; Get implied carriage ctl. BITB #FD.CR!FD.FTN!FD.PRN,R1 ; Any carriage ctrl? BNE 20$ ; If so, figure out what. MOV #CCNONE,CCLDNG ; No implied carriage ctrl. Do MOV #CCNONE,CCTLNG ; nothing at either end of record. BR 60$ ; Return to caller. 20$: BITB #FD.CR,R1 ; List carriage control? BEQ 30$ ; If not, check again. MOV #CCLILD,CCLDNG ; Generate a before (unles computr) MOV #CCLITR,CCTLNG ; Generate a after. BR 60$ ; Return to caller. 30$: BITB #FD.FTN,R1 ; Fortran carriage control? BEQ 40$ ; If not, must be COBOL. MOV #CCFOLD,CCLDNG ; Set up to process the cc byte. MOV #CCFOTR,CCTLNG ; and thatever trailers are req'd. BR 60$ ; Return to caller. 40$: MOV #CCCOLD,CCLDNG ; Assume cobol processing. MOV #CCCOTR,CCTLNG ; for leader and trailer. 60$: RETURN ; Return to caller. .SBTTL Subroutine CCNONE - No implied carriage control. CCNONE: RETURN ; No Implied CC, do nothing. .SBTTL Subroutine CCLILD - Handle leading LIST carriage ctl. CCLILD: BIT #SWDTE,SWSTAT ; Communicating with a terminal? BEQ 10$ ; If not, no leading character. MOV #LF,R0 ; Drop a linefeed CALL OURING ; down the line. 10$: RETURN ; Return to caller. .SBTTL Subroutine CCLITR - Handle trailing LIST carriage ctl. CCLITR: MOV #CR,R0 ; Get a carriage return. ; Routine CCLICH - Drop char in ring and return to caller. CCLICH: JMP OURING ; Drop char. in ring and return. .SBTTL Subroutine CCFOLD - Handle leading FORTRAN carrg ctl. CCFOLD: MOV #CR,CCTRL ; Assume a trailing TST R3 ; Is this a null record? BEQ CCLILD ; If so, treat like carriage ctrl MOV #CCTBL,R1 ; Get the carriage ctrl table addr. 10$: CMPB (R1)+,(R4) ; Got a match? BEQ 20$ ; If so, process. ADD #3,R1 ; If not, skip this entry. CMP R1,#CCTBLE ; At end of table? BLO 10$ ; If not, go again. 20$: INC R4 ; Drop the carriage control byte DEC R3 ; from the record. MOVB (R1)+,CCTRL ; Save required trailing carriage ctrl MOVB (R1)+,R0 ; Pick up literal form ctl if needed. BNE CCLICH ; If not null, use it. MOVB (R1)+,R1 ; Pick up number of linefeeds needed. BLE 60$ ; If none, quit. BIT #SWDTE,SWSTAT ; Are we talking to a terminal? BNE 40$ ; If so, fine. DEC R1 ; If not, get rid of one. BLE 60$ ; If none left, quit. 40$: MOV R1,-(SP) ; Save iteration count. 50$: MOV #LF,R0 ; Get the linefeed. CALL OURING ; Drop it down the line. DEC (SP) ; Done? BGT 50$ ; If not, go again. TST (SP)+ ; Clean up the stack. 60$: RETURN ; Return to caller. .SBTTL Subroutine CCFOTR - Handle trailing FORTRAN carrg ctl. CCFOTR: MOV R3,-(SP) ; Save a register. MOV #CCTRL,R3 ; Point to desired form control. 10$: MOVB (R3)+,R0 ; Pick up the next character. BEQ 20$ ; If none, quit. CALL OURING ; Drop it in the ring. BR 10$ ; Go for another. 20$: MOV (SP)+,R3 ; Restore the register. RETURN ; Return to caller. .SBTTL Subroutine CCCOLD - Handle leading Cobol carriage ctl. CCCOLD: JSR R5,$SAVRG ; Save some registers. CLR R4 ; Assume we're in /TERMINAL mode. BIT #SWDTE,SWSTAT ; Are we? BNE 10$ ; If so, we're OK. INC R4 ; If not, have to knock off a linefeed. 10$: MOVB F.SEQN(R5),R3 ; Get the record seq. no. BR CCCOCM ; Enter common code. .SBTTL Subroutine CCCOTR - Handle trailing Cobol carriage ctl. CCCOTR: JSR R5,$SAVRG ; Save some registers. CLR R4 ; Never deduct a linefeed at end of rec. MOVB F.SEQN+1(R5),R3 ; Get the second byte. ; Subroutine CCCOCM - Common Cobol code. CCCOCM: BEQ 60$ ; If zero, go away. BLT 30$ ; If hi, Special treatment. 10$: SUB R4,R3 ; Deduct linefeed if needed. BLE 60$ ; If none left, go away. 20$: MOVB #LF,R0 ; Stick a linefeed CALL OURING ; in the ring. SOB R3,20$ ; If not done, go again. BR 60$ ; All done. 30$: BIC #^C177,R3 ; Trash the unwanted bits. BIT #100,R3 ; Is bit 6 set? BNE 50$ ; If so, handle. MOV R3,R0 ; Interpret as character. BIT #40,R0 ; Use as control character? BEQ 40$ ; If so, just do it. BIC #40,R0 ; Clear the unwanted bit. BIS #200,R0 ; Construct the 8-bit ctrl. char. 40$: MOV #1,R3 ; Assume we have a linefeed. MOV R0,-(SP) ; Save a copy of the character we have. BIC #^C37,(SP) ; Clear the unwanted bits. CMP (SP)+,#LF ; Is it indeed a linefeed? BEQ 10$ ; If so, go handle it in the proper way. CALL OURING ; If not, drop the character in ring. BR 60$ ; All done. 50$: ; Arrive here if bits 6 and 7 of the ; carriage control byte were set. ; This case is currently undefined, so ; we'll just do nothing. 60$: RETURN ; Return to caller. .PAGE .SBTTL Subroutine DLYAST - "Pause" marktime AST. DLYAST: JSR R1,ASTSVF ; Save some registers. BIS #LPRDY,LPIND ; Show ready for another record. RETURN ; Exit the AST. .SBTTL Subroutine LINAST - Local terminal input AST. LINAST: JSR R1,ASTSVF ; Save registers and get character. BIC #^C177,R0 ; Strip off the unwanted bits. CMPB R0,ATNBYT ; Is this the attention byte? BEQ TERMIN ; If so, go prompt again. TST SNDFDB+F.BDB ; Are we doing input from a "send" file? BNE 20$ ; If so, ignore the character. CALL OURING ; Drop character in the outbound ring. CMPB R0,#CR ; Is the character a carriage return? BNE 20$ ; If not, we're done. BIT #SWDTE,SWSTAT ; Is /TERMINAL asserted? BEQ 20$ ; If not, we're done. MOV #LF,R0 ; If needed, stuff a linefeed into the CALL OURING ; output ring. 20$: RETURN ; Exit the AST. .SBTTL Subroutine RINAST - Remote terminal input AST. RINAST: JSR R1,ASTSVF ; Save registers and get character. BIC #^C177,R0 ; Strip off the unwanted bits. BNE 10$ ; If not null, we want it. BIT #SWNUL,SWSTAT ; Are we processing nulls today? BEQ 20$ ; If not, ignore it. 10$: CALL INRING ; Put character in inbound ring. 20$: RETURN ; Exit the AST. .SBTTL Subroutine TERMIN - Terminate AST-mode communications. TERMIN: TST SNDFDB+F.BDB ; Send file open? BEQ 30$ ; If not, just fire up mainline. BIC #LPRDY,LPIND ; Not ready to send record any more. BIT #SWEOF,SWSTAT ; Need to send the EOF byte? BEQ 30$ ; If not, just fire up mainline. MOVB EOFBYT,R0 ; If so, pick up the EOF byte CALL OURING ; and drop it in the outbound ring. 30$: BIS #LPXIT,LPIND ; Set the exit bits. RETURN ; Return from AST. .PAGE .SBTTL Subroutine LOU - Empty inbound ring to local terminal. LOU: TRACER LOU .ENABL LSB ; So shared code will work. MOV #INRDSC,R1 ; Get the inbound ring descriptor. BR 30$ ; Join common code. .SBTTL Subroutine ROU - Empty outbound ring to remote terminal. ROU: TRACER ROU MOV #OURDSC,R1 ; Get the inbound ring descriptor. ; Subroutine 30$ - Empty the rings. 30$: BIC #R$F$MO,R$FLGS(R1) ; Assume we can get all data at once. MOV R$INB(R1),R2 ; Get current "front" end of ring. CMP R2,R$OUB(R1) ; Has wraparound occurred? BHI 40$ ; If not, fine. BEQ 80$ ; If buffer empty, don't process. MOV R$BND(R1),R2 ; If wrapped, only process end of ring. BIS #R$F$MO,R$FLGS(R1) ; We will have to process again. 40$: SUB R$OUB(R1),R2 ; Calculate length of buffer. BEQ 80$ ; If empty, just exit. CMP R2,R$DBUF(R1) ; Bigger than our device buffer? BLOS 50$ ; If not, everything's okay. MOV R$DBUF(R1),R2 ; If so, write only what buffer holds. BIS #R$F$MO,R$FLGS(R1) ; We will have to process again. 50$: TST R$CHND(R1) ; Got a character handler? BEQ 60$ ; If not, just write. CALL @R$CHND(R1) ; If so, call it. BCS 63$ ; If don't want write, skip it. 60$: QIOW$S #IO.WVB,R$LUN(R1),#SYNIOF,,,, ; Write. 63$: ADD R$OUB(R1),R2 ; Find out how far we have processed. CMP R2,R$BND(R1) ; Is it time to wrap around? BLO 70$ ; If not, just use this value. MOV R1,R2 ; If so, point the pointer .IF NE R$BUF ; back to the ADD #R$BUF,R2 ; start of the .ENDC ; NE R$BUF ; buffer. 70$: MOV R2,R$OUB(R1) ; Store the updated position. BIT #R$F$MO,R$FLGS(R1) ; More to do? BNE 30$ ; If so, go around again. 80$: RETURN ; Return to caller. .DSABL LSB .PAGE .SBTTL Subroutine CLOLCN - Close log file if desired. CLOLCN: TRACER CLOLCN .ENABL LSB ; So shared code will work. BIT #SWLOG,SWSTAT ; Are we supposed to be logging? BNE 60$ ; If so, leave file as is. ; If not, force closed. .SBTTL Subroutine CLOLOG - Close log file if open. CLOLOG: TRACER CLOLOG CALL LGFLU ; Flush the buffer. MOV #LOGFDB,R0 ; Pick up log file FDB. CALL 30$ ; Close the file. BCC 60$ ; If wasn't open, just return. MOVB #FO.APD,F.FACC(R0) ; Open append next time. BR 50$ ; Return with carry set. .SBTTL Subroutine CLOSND - Close send file if open. CLOSND: TRACER CLOSND BIC #LPRDY,LPIND ; No longer ready for a record. MOV #SNDFDB,R0 ; Pick up send file FDB. BIT #S2SND,S2ASS ; Got an explicit /SEND? BNE 30$ ; If so, go close. BIT #RMATU,LCSTAT ; Got support for unsol. input? BNE 30$ ; If so, just go close. CALL 30$ ; Close, but come back for more. ROL -(SP) ; Save "C" bit. ADD #F.FNB,R0 ; Point to filename block. MOV #SNDSVN,R1 ; Point to saved FNB. MOV #/2,R2 ;Get number of words. 20$: MOV (R1)+,(R0)+ ; Copy the saved info back. SOB R2,20$ ; Repeat as needed. MOV #SNDFDB,R0 ; Restore R0. ROR (SP)+ ; Restore "C" bit. ; Fall thru to close code. ; Subroutine 30$ - Close the indicated file. 30$: TST F.BDB(R0) ; Was file open? BEQ 60$ ; If not, return with carry clear. MOV R1,-(SP) ; Save a register. MOV R0,R1 ; Find address of ADD #F.FNB+N.FID,R1 ; File ID. MOV (R1)+,-(SP) ; Preserve the MOV (R1)+,-(SP) ; File MOV (R1)+,-(SP) ; ID. CLOSE$ ; Close the file. MOV (SP)+,-(R1) ; Restore the file ID so we MOV (SP)+,-(R1) ; can re-open by File ID MOV (SP)+,-(R1) ; if desired. MOV (SP)+,R1 ; Restore the register. ; Note that the following code does triple duty, as the ; exit route for CLOLOG, CLOSND, and 30$. ; Exit is with FDB address in R0, all other registers ; are unmodified. 50$: SEC ; Insure caller knows we closed a file. 60$: RETURN ; Return to caller. .DSABL LSB .PAGE .SBTTL Subroutine LGOU - Drop characters in log file buffer. LGOU: TRACER LGOU TST R2 ; Got any characters? BEQ 20$ ; If not, just ignore. JSR R2,$SAVVR ; Save registers. MOV R$OUB(R1),R1 ; Point to the characters. 10$: MOVB (R1)+,R0 ; Get the next character. CALL LGOUC ; Process it. SOB R2,10$ ; Repeat as needed. 20$: TST SNDFDB+F.BDB ; Running from a send file? BEQ 30$ ; If not, always want output. BIT #S2QUI,S2ASS ; If so, are we set quiet? BEQ 30$ ; If not, want output. SEC ; If so, don't do it. 30$: RETURN ; Return to caller. .SBTTL Subroutine LGOUC - Put a character in the log buffer. LGOUC: JSR R2,$SAVVR ; Save the registers we need. MOV #LGFDSC,R1 ; Point to the buffer descriptor. MOV F$BLOC(R1),R2 ; Get current location. CMPB R0,#SPA ; Is it a printing character? BGE 30$ ; If so, handle as such. CMPB R0,#HT ; Is it a horizontal tab? BEQ 30$ ; If so, handal like printing char. BLT 40$ ; Less than, no effect on position. CMPB R0,#CR ; Is it a carriage return? BGT 40$ ; Greater than, no effect on position. BLT 20$ ; Less than, vertical control char. BIC #F$F$LM,F$FLGS(R1) ; At left margin. MOVB R0,(R2)+ ; Store the . MOV R2,F$BCRL(R1) ; Save its position. BR 50$ ; Check for buffer full. 20$: BIC #F$F$AD,F$FLGS(R1) ; We have advanced a line. MOVB R0,(R2)+ ; Store the character. BR 50$ ; Check for buffer full. 30$: BIS #F$F$LM!F$F$AD,F$FLGS(R1) ; No longer at left margin. BIC #F$F$NM,F$FLGS(R1) ; Got a normal character. 40$: MOVB R0,(R2)+ ; Store the character. MOV R2,F$BNCH(R1) ; Save current location. 50$: MOV R2,F$BLOC(R1) ; Store current buffer positn. BIT #F$F$PR,F$FLGS(R1) ; Time to print? BEQ 70$ ; If so, go do it. CMP R2,F$BEND(R1) ; Buffer full? BHIS 60$ ; If so, force the print. RETURN ; If not, return to caller. 60$: JMP LOGFLB ; Go flush the buffer. 70$: JMP LOGWRT ; Go write. .PAGE .SBTTL Subroutine LGFLU - Flush the log file buffer. LGFLU: TRACER LGFLU MOV #LGFDSC,R1 ; Get the log file descriptor. LOGFLB: MOV F$BLOC(R1),F$BCRL(R1) ; Force location and MOV F$BLOC(R1),F$BNCH(R1) ; normal character location. BIC #F$F$PR,F$FLGS(R1) ; Clear the flags. ; and fall thru. .SBTTL Subroutine LOGWRT - Write a record on the log file. LOGWRT: MOV R1,-(SP) ; Stack control block pointer. MOV F$FDBA(R1),R0 ; Get the FDB address. MOV F$BCRL(R1),R2 ; Find the last . .IF NE,F$BFFR ; Find the start ADD #F$BFFR,R1 ; of the .ENDC ; NE,F$BFFR ; buffer. BITB #FD.CR!FD.FTN,F.RATT(R0) ; Implied CC? BEQ 80$ ; If not, go write. MOV R1,R0 ; Copy buffer address to R0 MOV (SP),R1 ; and retrieve control blk address. CLR F$PNDL(R1) ; Clear the pending line and CLR F$PNDF(R1) ; formfeed counts. 10$: MOVB (R0)+,R2 ; Get the next character. CMPB R2,#CR ; Is it a ? BEQ 10$ ; If so, ignore it. BGT 40$ ; If greater, gone too far. CMPB R2,#LF ; Is it a linefeed? BLT 40$ ; If less than, gone too far. BGT 20$ ; If greater, or . INC F$PNDL(R1) ; Count the . BR 10$ ; Check the next one. 20$: CMPB R2,#FF ; Is it a formfeed? BLT 30$ ; If not, must be a . INC F$PNDF(R1) ; Count a formfeed. CLR F$PNDL(R1) ; Clear the linefeeds. BR 10$ ; Check next char. 30$: ADD #4,F$PNDL(R1) ; Simulate by four (LF>'s. BR 10$ ; Check next character. 40$: DEC R0 ; Include last char. in buffer. MOV R0,R2 ; Copy buffer address. MOV F$FDBA(R1),R0 ; Load FDB address in R0. TST F$PNDF(R1) ; Any formfeeds? BEQ 60$ ; If not, go handle the linefeeds. TST F$PNDL(R1) ; Any linefeeds to go with them? BGT 50$ ; If so, just go process. INC F$PNDL(R1) ; Pretend we have one. MOVB #FF,-(R2) ; Fudge a formfeed into the buffer. DEC F$PNDF(R1) ; Take it off the count. BEQ 60$ ; If none left, handle linefeeds. 50$: PUT$ ,#FFBUF,#1 ; Write a formfeed. DEC F$PNDF(R1) ; Account for it. BGT 50$ ; If more left, do. 60$: DEC F$PNDL(R1) ; Any linefeeds left? BLE 70$ ; If not, time to write the record. PUT$ ,#FFBUF,#0 ; Write a null record. BR 60$ ; Check again. 70$: MOV R2,-(SP) ; Save addr. of start of buffer. MOV F$BNCH(R1),R2 ; Get end of buffer. MOV (SP)+,R1 ; Start of buffer goes in R1. 80$: SUB R1,R2 ; Find length. PUT$ ,R1,R2 ; Write the record. ADD R1,R2 ; Find last char. again. MOV (SP),R0 ; Get ctrl block pointer. MOV R0,R1 ; Find address .IF NE,F$BFFR ; of start ADD #F$BFFR,R1 ; of buffer. .ENDC ; NE,F$BFFR ; MOV F$BLOC(R0),R0 ; Get current buffer loc. SUB R2,R0 ; Find out how many chars to shuffle. BLE 100$ ; If none, go clean up. 90$: MOVB (R2)+,(R1)+ ; Move a character. SOB R0,90$ ; repeat until done. 100$: MOV (SP)+,R0 ; Get the ctrl block pointer again. MOV R1,F$BLOC(R0) ; Save our location. MOV R1,F$BCRL(R0) ; Init. position MOV R1,F$BNCH(R0) ; and normal char. position. MOV #F$F$IS,F$FLGS(R0) ; Init. the flags. RETURN ; Return to caller. .PAGE .SBTTL Subroutine OPNLCN - Open log file if desired. OPNLCN: TRACER OPNLCN .ENABL LSB ; So common code will work. CLC ; Ensure carry clear. BIT #SWLOG,SWSTAT ; Want to open the file? BEQ 60$ ; If not, return with carry clear. ; Enter here for unconditional open. MOV #LOGFDB,R0 ; Get the log file FDB address. MOV #LGOPNM,R1 ; Get address of error message. CLR R2 ; Assume no implied carriage control. BIT #SWLIS,SWSTAT ; Want list carriage control? BEQ 30$ ; If not, open as is. MOV #FD.CR,R2 ; If so, note desire in FDB. BR 30$ ; and go open the file. .SBTTL Subroutine OPNSCN - Open send file if desired. OPNSCN: TRACER OPNSCN CLC ; Ensure carry clear. BIT #S2SND,S2ASS ; Want to open the file? BNE 25$ ; If so, go do it. BIT #RMATU,LCSTAT ; Do we support unsolicited input? BNE 60$ ; If so, just return. BIT #LPREAP,LPIND ; Are we processing a setup file? BNE 50$ ; If so, no user input allowed. BIT #SWCMD,SWSTAT ; Want an immediate return to cmd mode? BNE 50$ ; If so, go for it. MOV #SNDFDB+F.FNB,R0 ;Point to filename block. MOV #SNDSVN,R1 ; Point to FNB save block. MOV #/2,R2 ;Get number of words. 20$: MOV (R0)+,(R1)+ ; Save info. SOB R2,20$ ; Repeat as needed. MOV #SNDDSD,R0 ; Point to /SAVE dataset descriptor. MOV #TISL,(R0)+ ; Save length and MOV #TIS,(R0)+ ; addr. of device spec. CLR (R0)+ ; Clear out the CLR (R0)+ ; rest of CLR (R0)+ ; the dataset CLR (R0)+ ; descriptor. ; Enter here for unconditional open. 25$: BIS #LPRDY,LPIND ; Want to send first record immed. MOV #SNDFDB,R0 ; Get the send file FDB address. MOV #SNOPNM,R1 ; Get address of error message. CLR R2 ; Assume no implied carriage control. CALL 30$ ; Open the file. BCS 60$ ; If failed, just exit. JMP CCCHEK ; Set up CC routines, & return. ; Subroutine 30$ - Open the specified file. ; Display error message on failure. 30$: CLC ; Ensure usr gets success if already opn TST F.BDB(R0) ; Is file open already? BNE 60$ ; If so, just leave. MOVB R2,F.RATT(R0) ; Set desired carriage control. OPEN$ ; Open the file as desired. BCC 60$ ; If succeeded, return to caller. MOV #IOM,PRMBUF ; Assume an I/O error. TSTB F.ERR+1(R0) ; Was it? BEQ 40$ ; If so, that's fine. MOV #DSWM,PRMBUF ; If not, must have been directive error. 40$: MOVB F.ERR(R0),R2 ; Sign- extend the error code and MOV R2,PRMBUF+2 ; pass it to the formatter. MOV #PRMBUF,R2 ; Load up parameters for the formatter. CALL MSGOUT ; Write the message. ; Note that the following code does triple duty as the ; exit point for OPNLCN, OPNSCN, and 30$ 50$: SEC ; Ensure that the carry is set. 60$: RETURN ; Return to caller. .DSABL LSB .PAGE .SBTTL Subroutine HANGCN - Hang up line if desired. HANGCN: TRACER HANGCN BIT #SWHLD,SWSTAT ; Was the /HOLD switch asserted? BNE 60$ ; If so, just return (Z-bit is set). TST OUTDEV ; Have we got a device to hang up? BEQ 50$ ; If not, don't bother. QIOW$S #IO.HNG,#RTELUN,#LPFLG ; Hang up the line. 50$: CLZ ; Clear the Z bit. 60$: RETURN .PAGE .SBTTL Coroutine ASTSVF - Save and restore registers for AST. ASTSVF: MOV R0,-(SP) ; Stack old R0. MOV 4(SP),R0 ; Get the AST parameter. MOV R2,4(SP) ; Stack old R2. CALL (R1) ; Call the caller back. MOV (SP)+,R0 ; Restore old R0. MOV (SP)+,R1 ; Restore old R1. MOV (SP)+,R2 ; Restore old R2. SETF$C LPFLG,PURCOD ; Fire up the main line. ASTX$S ; Return from AST. .SBTTL Coroutine DISAST - Disable AST's - re-enable if appropriate. DISAST: DSAR$S ; Disable AST recognition. BCS 60$ ; If failed, just return. JSR PC,@(SP)+ ; Co-routine back to caller. ENAR$S ; Re-enable AST's. 60$: RETURN ; Return to (original) caller. .PAGE .SBTTL Subroutine ACTLOG - Log accounting info. .IF DF ACCNTG ; Build only if accounting desired. ACTLOG: .IF EQ ACCNTG ; If only want to log "real" devices, CMP DEVNAM,#"NL ; On the null device? BEQ 60$ ; If so, no point in logging. .ENDC ; EQ ACCNTG ; End of "real device only" code. MOV #ACTTIM+<6*2>,R2 ; Point to info overwritten by time. MOV (R2)+,-(SP) ; Save MOV (R2)+,-(SP) ; it. GTIM$S #ACTTIM ; Get current time. MOV (SP)+,-(R2) ; Restore clobbered MOV (SP)+,-(R2) ; information. MOV R1,ACTMSG ; Store transaction name. MOV DEVUNT,ACTDST ; Get unit number for remote unit. MOV #ACTREC,R1 ; Get record. MOV #ACTDAT,R2 ; Get data. MOV #MSGBUF,R0 ; Get the message buffer. CALL $EDMSG ; Create the message. SUB #MSGBUF,R0 ; Calculate message length. MOV R0,R1 ; Relocate, since FCS needs R0. MOV #ACTFDB,R0 ; Get FDB address. MOV #5,R2 ; Retry count. 10$: OPEN$ ; Open the file. BCC 20$ ; If succeeded, proceed. CMPB F.ERR(R0),#IE.WAC ; Accessed for write? BNE 60$ ; If not, no use retrying. DEC R2 ; Retries exhausted? BLE 60$ ; If so, give up. MRKT$S #SYNIOF,#3,#2 ; Wait 3 seconds. WTSE$S #SYNIOF ; ...zzzz... BR 10$ ; Go try again. 20$: PUT$ ,#MSGBUF,R1 ; Append the stuff to the file. CLOSE$ ; Close. 60$: RETURN ; Return from whence we came. .ENDC ; DF ACCNTG ; End of accounting-specific code. .PAGE .SBTTL Subroutine TELSET - Initiate operations on local terminal. TELSET: TRACER TELSET MOV #LTELUN,R0 ; Fetch the LUN number. MOV #LINAST,R1 ; Get the address of the AST routine. CALL TEXATT ; Attach the terminal. BCS 60$ ; If an error, die. BIT #RMFDX,LCSTAT ; Full-duplex capability? BEQ 60$ ; If not, we're done. MOV #TELOMC,R1 ; Point to old param buffer. CALL TEXGMC ; Get them. BCS 50$ ; If an error, clean up. MOV #TELNMC,R1 ; Get the desired setting. CALL TEXSMC ; Set them up. BCC 60$ ; If no error, fine. 50$: CALL TEXDET ; An error has occurred. Detach, SEC ; and return an error. 60$: RETURN ; Return to caller. .SBTTL Subroutine TELCLR - Clear operations on local terminal. TELCLR: TRACER TELCLR MOV #LTELUN,R0 ; Fetch the LUN number. BIT #RMFDX,LCSTAT ; Full-duplex driver? BEQ 20$ ; If not, just detach. MOV #TELOMC,R1 ; Get the old setup. CALL TEXSMC ; Restore it. 20$: CALL TEXDET ; Detach the terminal. RETURN ; Return to caller. .SBTTL Subroutine TELCMD - Set /NORPA for command input. TELCMD: .ENABL LSB BIT #SWRPA,SWSTAT ; Need to do it? BEQ 60$ ; If not, just return. CLRB TELNBI+1 ; Put /NORPA code in buffer. BR 50$ ; Join common code. .SBTTL Subroutine TELTRM - Set /RPA for remote terminal input. TELTRM: BIT #SWRPA,SWSTAT ; Need to do it? BEQ 60$ ; If not, just return. MOVB #1,TELNBI+1 ; Put /RPA code in buffer. ; Fall thru. 50$: MOV #LTELUN,R0 ; Get local terminal LUN. MOV #TELNBI,R1 ; Point to buffer. CALL TEXSSC ; Set the terminal as desired. 60$: RETURN ; Return to caller. .DSABL LSB .SBTTL Subroutine TERSET - Initiate operations on remote terminal. TERSET: TRACER TERSET .ENABL LSB ; So can share code. MOV #RTELUN,R0 ; Fetch the LUN number. MOV #RINAST,R1 ; Get the address of the AST routine. CALL TEXATT ; Attach the terminal. BCS 60$ ; If failed, clean up and exit. BIT #RMFDX,RMSTAT ; Do we support full duplex operation? BEQ 7$ ; If not, all done. MOV #TEROMC,R1 ; Point to characteristics buffer. CALL TEXGMC ; Save them. BCS 10$ ; If failed, clean up and exit. MOVB @TERASA,TERNAS+1 ;Get the desired /REMOTE setting. MOVB @SPDRRC,TERNRC+1 ;Get the desired receive speed. MOVB @SPDRSD,TERNSD+1 ;Get the desired transmit speed. MOV #TERNMC,R1 ; Point to desired characteristics. CALL TEXSMC ; Set them up. BCS 10$ ; If an error, die. 7$: .IF DF ACCNTG ; If doing accounting, MOV #ACTINI,R1 ; We are initializing on this unit. CALL ACTLOG ; Log who, what, when, where, not why. .ENDC ; DF ACCNTG ; End of accounting code. MOV #BANERM,R1 ; Get banner message. BR 50$ ; Write it. 10$: CALL TEXDET ; If failure, detach terminal SEC ; return an error, BR 60$ ; and exit. .SBTTL Subroutine TERCLR - Clear operations on remote terminal. TERCLR: TRACER TERCLR MOV #RTELUN,R0 ; Fetch the LUN number. TST OLDOUD ; Did we ever do anything on this device BEQ 60$ ; If not, just return. CALL HANGCN ; Hang up the line if needed. BIT #RMFDX,RMSTAT ; Do we support full duplex operation? BEQ 20$ ; If not, don't reset characteristics. MOV #TEROMC,R1 ; Point to old characteristics. CALL TEXSMC ; Put setup back the way it was. 20$: CALL TEXDET ; Detach the terminal. .IF DF ACCNTG ; If doing accounting, MOV #ACTKIL,R1 ; We are finished on this unit. CALL ACTLOG ; Log who, what, when, where, not why. .ENDC ; DF ACCNTG ; End of accounting code. MOV #SUMMYM,R1 ; Point to summary message. 50$: MOV #BANDAT,R2 ; Point to data. CALL MSGOUT ; Write banner. 60$: RETURN ; Return to caller. .DSABL LSB ; End of shared code. .SBTTL Subroutine TERSPD - Set speeds on remote terminal. TERSPD: TRACER TERSPD BIT #S2RMT!S2SPD,S2PRE ; Got any switches of interest? BEQ 60$ ; If not, just exit. BIT #RMFDX,RMSTAT ; FDX TTY capability? BEQ 60$ ; If not, just exit. MOV #RTELUN,R0 ; Get the remote LUN number. ASSUME TERNRC-TERNAS-2 ; Require answer spd before rcv. ASSUME TERNSD-TERNRC-2 ; Require rcv spd before snd. MOV #TERNSD+2,R2 ; Get end of buffer. MOV #TERNRC,R1 ; Assume no /REMOTE BIT #S2RMT,S2PRE ; /REMOTE present? BEQ 20$ ; If not, fine. Only set speed. MOVB @TERASA,TERNAS+1 ;Get the desired /REMOTE setting. TST -(R1) ; Include it in the setup. 20$: SUB R1,R2 ; Calculate buffer length. MOVB @SPDRRC,TERNRC+1 ;Get the desired receive speed. MOVB @SPDRSD,TERNSD+1 ;Get the desired transmit speed. CALL TEXSCH ; Set the speeds. 60$: RETURN ; Return to caller. .PAGE .SBTTL Subroutine TEXATT - Attach a terminal. TEXATT: TRACER TEXATT .ENABL LSB ; For shared code. MOV #PRMBUF,R2 ; Point to param. buffer. MOV #ATTM,(R2)+ ; Preset the error message. MOV #IO.ATA,(R2)+ ; Get the operation code. MOV R1,(R2)+ ; Pick up AST address. CLR (R2) ; No second parameter. BR 10$ ; Join common code. .SBTTL Subroutine TEXDET - Detach a terminal. TEXDET: TRACER TEXDET MOV #PRMBUF,R2 ; Point to param. buffer. MOV #DETM,(R2)+ ; Preset the error message. MOV #IO.DET,(R2)+ ; Get the operation code. CLR (R2)+ ; No first parameter. CLR (R2) ; no second parameter. BR 10$ ; Join common code. .SBTTL Subroutine TEXGMC - Get terminal characteristics. TEXGMC: TRACER TEXGMC MOV #PRMBUF,R2 ; Point to param. buffer. MOV #GETM,(R2)+ ; Preset the error message. MOV #SF.GMC,(R2)+ ; Get the operation code. MOV R1,(R2)+ ; Get buffer addr. MOV -2(R1),(R2) ; Get buffer length. BR 10$ ; Join common code. .SBTTL Subroutine TEXSMC - Set terminal characteristics. TEXSMC: TRACER TEXSMC MOV -2(R1),R2 ; Save buffer length. BR TEXSCH ; Join common code. .SBTTL Subroutine TEXSSC - Set a single terminal char. TEXSSC: TRACER TEXSSC MOV #2,R2 ; Get buffer length. ; Fall thru to common code. .SBTTL Subroutine TEXSCH - Set terminal characteristics - General TEXSCH: MOV R2,PRMBUF+6 ; Save buffer length. MOV #PRMBUF,R2 ; Point to param. buffer. MOV #SETM,(R2)+ ; Preset the error message. MOV #SF.SMC,(R2)+ ; Get the operation code. MOV R1,(R2)+ ; Get buffer addr. BR 10$ ; Join common code. ; Common code - Issue QIO and check status. 10$: TST -(R2) ; Back up to point to buffer address. MRKT$S #SYNIOF,#SYNTOM,#SYNTOU ; Set a time limit. QIO$S -2(R2),R0,#SYNIOF,,#SYNSTA,,<(R2),2(R2)> ; Do it. BCS 20$ ; If directive failure, error out. WTSE$S #SYNIOF ; Wait for the event flag. CMPB SYNSTA,#IS.SUC ; I/O success? BEQ 60$ ; If so, just exit. CMPB SYNSTA,#IS.PND ; Still pending? BNE 12$ ; If not, go kill marktime. QIOW$S #IO.KIL,R0,#SYNIOF ; If so, kill it, BR 14$ ; and proceed with the funeral. 12$: CMKT$S #SYNIOF ; Cancel all marktimes this event flag. 14$: MOV #IOM,(R2)+ ; If not, insert proper message, CLR (R2) ; Assume code positive. MOVB SYNSTA,(R2) ; Set I/O status. BGE 30$ ; Go write if positive. DECB 1(R2) ; Twiddle sign byte. BR 30$ ; Go write. 20$: MOV #DSWM,(R2)+ ; Fill in the $DSW error message, MOV $DSW,(R2) ; and value. CMKT$S #SYNIOF ; Cancel all marktimes this event flag. 30$: JSR R2,$SAVVR ; Need to save some registers. GLUN$S R0,#DEVBUF ; Get LUN assignment for error. MOV #DEVBUF+2,R0 ; Point to unit number. CLR -(SP) ; Load up the BISB (R0),(SP) ; unit number. MOV #OCTCTL,R1 ; Point to edit string. MOV SP,R2 ; Point to number. CALL $EDMSG ; Convert to ASCII. MOV R2,SP ; Clean up stack. CLRB (R0)+ ; Terminate with null. MOV #DEVBUF,PRMBUF+2 ;Save addr. of device name. MOV #SMCERM,R1 ; Point to error message. MOV #PRMBUF,R2 ; Point to data. CALL MSGOUT ; Write the message. SEC ; Ensure carry set. 60$: RETURN ; Return to caller. .DSABL LSB ; End of shared code. .PAGE .SBTTL Subroutine MSGOUC - Write message and cmd line. MSGOUC: CALL MSGOUT ; Write primary error message. JSR R2,$SAVVR ; Save registers, restore on return. MOV #CMLMSG,R1 ; Get the text. MOV #GCMLB+G.CMLD,R2 ; Get the command line. ; Fall thru to MSGOUT. .SBTTL Subroutine MSGOUT - Write to the terminal. MSGOUT: MOV R0,-(SP) ; Save old R0. MOV #MSGBUF,R0 ; Get the message buffer address. CALL $EDMSG ; Format it. SUB #MSGBUF+1,R0 ; Calculate its length. BGT 10$ ; If positive, OK. MOV #MSGBUF,R1 ; Point to buffer again. MOVB #SPA,(R1)+ ; Fudge a blank for carriage control. MOVB #SPA,(R1)+ ; Same for data. MOV #1,R0 ; Say we have one character. 10$: CLR R1 ; Get the carriage control BISB MSGBUF,R1 ; character. CMPB R1,#'@ ; Proxy for null? BNE 20$ ; If not, fine CLR R1 ; If so, make null for real. 20$: QIOW$S #IO.WLB,#MSGLUN,#MSGFLG,,,,<#MSGBUF+1,R0,R1> ; Write. MOV (SP)+,R0 ; Restore old R0. RETURN ; Return to caller. .PAGE .SBTTL Subroutine TRCSUB - Trace subroutine calls. .IF DF TRACE TRCSUB: MOV R1,-(SP) ; Save a register. MOV R2,-(SP) ; Save another. MOV #TRCSUM,R1 ; Get the text. MOV SP,R2 ; Get the top of the stack. ADD #6,R2 ; Point to the data. JSR PC,MSGOUT ; Write it. MOV (SP)+,R2 ; Restore the MOV (SP)+,R1 ; registers. MOV (SP)+,(SP) ; Clean up the stack. RETURN ; Return to caller. .IFF ; DF TRACE TRCSUB: .IFTF ; DF TRACE .SBTTL Subroutine TPDEB - .TPARS debugger output. .IFT ; DF TRACE TPDEB: JSR R2,$SAVVR ; Save some registers. MOV #PRMBUF+4,R2 ; Parameter space. MOV R5,-(R2) ; Save parser address. SUB #CMDSTA,(R2) ; Calc. offset from start of psect. MOV R4,-(R2) ; Save current string loc. SUB TPLNAD,(R2) ; Calc. position in string. MOV #TPDEBM,R1 ; Point to format string. JMP MSGOUT ; Write. .IFF ; DF TRACE TPDEB: .ENDC ; DF TRACE .END ENTRY