.TITLE TEM TERMINAL EMULATOR .IDENT /85.008/ .ENABL LC .SBTTL General documentation. .DSABL GBL .NLIST BEX ;+ ; Title: TEM ; Author: T. R. Wyant ; Date: 2-Mar-83 ; Modified: ; Since Spring 1984 DECUS version (IDENT 84.131) ; ; 17-Jun-84 -- T. R. Wyant ; TW001 - Fixed /NOREMOTE so it works. ; TW002 - Single-argument /SPEED switch. ; ; 21-Jun-84 -- T. R. Wyant ; TW003 - Bypass /SPEED and /REMOTE for DL11 ; and DJ11 lines. ; ; 25-Jun-84 -- T. R. Wyant ; TW004 - Cancel control/s on attachment to ; remote terminal. ; ; 12-Jul-84 -- T. R. Wyant ; TW005 - Make /SPEED and /REMOTE on DL11 and ; DJ11 no-ops with a warning. ; ; 31-Jul-84 -- T. R. Wyant ; TW006 - Added the /TRANSLATE:: switch. ; ; 08-Aug-84 -- T. R. Wyant ; TW007 - Set up "Fuse" on control/C and abort ; AST, to make sure we get out. ; ; ........................................................ ; ; Incomaptability with previous versions introduced here ; by changing /PAUSE: to /DELAY: so as not to conflict ; with /PARITY:. /PAUSE: is in fact still available, but ; cannot be abbreviated to 2 characters. ; ; 10-Aug-84 -- T. R. Wyant ; TW008 - Add parity support for output. Changed ; /PAUSE: to /DELAY: ; ; 27-Aug-84 -- T. R. Wyant ; TW009 - Remove incorrect application of parity ; to translation table. ; ; 28-Aug-84 -- T. R. Wyant ; TW010 - Fix /MAXBUFFER for proper default, and ; move the bit to switch word 2. ; ; 31-Aug-84 -- T. R. Wyant ; TW011 - Add /CHECKPARITY switch. ; ; 25-Sep-84 -- T. R. Wyant ; TW012 - Change default for /RPA switch to "/RPA", ; tie it to /TERMINAL ; ; 26-Sep-84 -- T. R. Wyant ; TW013 - Add /STOP function. ; ; 28-Sep-84 -- T. R. Wyant ; TW014 - Move code for /NULL from input AST to ; INRING:, after translation. ; ; 18-Oct-84 -- T. R. Wyant ; TW015 - Add /EXIT switch to defer exit on ; command-level EOF. ; ; 22-Oct-84 -- T. R. Wyant ; TW016 - (Attempt to) provide positive loop ; exit on attention character. ; ; 08-Jan-85 -- T. R. Wyant ; TW017 - (Attempt to) conditionalize for use ; with RSX-11M V3.2. ; ; 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 from the ; local terminal or a /SEND file, 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) ; ; /CHECKPARITY[:char] ; Specifies whether parity is checked, and ; if so what character to substitute on a ; parity error. The parity checked for is ; that specified by the /PARITY switch. ; If the character is omitted, the default ; is the last character specified on this ; switch, even if specified with ; /NOCHECKPARITY. The initial setting is ; /NOCHECKPARITY:^Z (control/z) ; ; /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 ; ; /DELAY[: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 ; /DELAY:15T ; ; /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 ; ; /EXIT ; Causes TEM to exit on an EOF of the top ; level command file. If negated, TEM will ; prompt for a command line after EOF at ; the top level, and implicitly assert ; /EXIT. This won't work unless automatic ; line setup is supported. The initial ; setting is ; /NOEXIT ; ; /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 ; ; /PARITY:spec ; Set the output parity. Parity can be ; specified as ; SPACE ; MARK ; EVEN ; ODD ; The parity specs can be abbreviated to ; one character. This switch cannot be ; negated. The initial setting is ; /PARITY:SPACE ; ; /PAUSE[:nnnt] ; A synonym to /DELAY, for backward com- ; patibility. Note that the minimum abbre- ; viation for /PAUSE is three characters, ; because of the conflict with /PARITY. ; ; /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 /DELAY ; switch is negated, the next record is ; sent as soon as the prompt character is ; received. If the /DELAY 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 is ; /RPA ; ; /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. If only the first parameter is ; given, the second parameter defaults to ; the value given for the first parameter. ; The initial setting is ; /SPEED ; ; /STOP ; Causes TEM to suspend operations, and ; returns you to your normal CLI. You ; resume by ; MCR>UNSTOP TEM or ; DCL>START TEM ; This switch can not be negated. ; ; /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/DELAY/PROMPT/RPA ; 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 ; /NORPA ; The initial setting is ; /NOTERMINAL ; ; /TRANSLATE:char:char ; Specifies that whenever the first char- ; acter is received from the remote ter- ; minal, it is translated into the second. ; You may translate any number of charac- ; ters. If negated, all translations are ; cleared. The parameters are required ; if the switch is asserted, and forbidden ; if it is negated. The /PROMPT switch ; applies to the translated character, not ; to the raw input character. The initial ; setting is ; /NOTRANSLATE ; ; / 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,DIR$,DSAR$S,ENAR$S .MCALL EXIT$S,GLUN$S,GTIM$S,GTSK$S,MRKT$S .MCALL QIO$S,QIOW$S,RSUM$S,SETF$C,SPND$ ; TW013 .MCALL SREX$S,STOP$,USTP$S,WTSE$S ; TW013 .MCALL FINIT$,FSRSZ$,FDBDF$,FDAT$A,FDOP$A,NMBLK$ .MCALL CLOSE$,GET$,OPEN$,PUT$ .MCALL ISTAT$,STATE$,TRAN$ .IIF NDF RSXVER, RSXVER = 40. ; TW017 .GLOBL FD.CCL,FD.CR,FD.FTN,FD.PRN,FD.REC,FD.TTY .GLOBL FO.APD,FO.RD,FO.WRT .GLOBL IE.EOF,IE.SDP,IE.WAC ; TW013 .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 .IF GE RSXVER-40. ; If at least M4.0 or M+ 2.0, ; TW017 .GLOBL TC.ABD,TC.ASP ; TW017 .ENDC ; GE RSXVER-40. ; TW017 .GLOBL TC.ACR,TC.BIN,TC.CTS,TC.DLU,TC.FDX ; TW004 .GLOBL TC.HFF,TC.HFL,TC.HHT,TC.NEC,TC.RAT,TC.RSP,TC.SLV ; TW004 .GLOBL TC.SMR,TC.TBS,TC.VFL,TC.XSP ; TW004 .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. EOF= 32 ; = ASCII ^Z. 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. .IIF NDF U2.DH1 U2.DH1 =: 100000 ; Set if terminal on mux. ; TW003 .IIF NDF U2.DJ1 U2.DJ1 =: 40000 ; Set if terminal on DJ11 ; TW003 .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. ZERO: .WORD 0 ; Program constant, where needed. ; TW001 ONE: .WORD 1 ; Program constant, where needed. ; TW001 STPDIR: STOP$ ; Stop directive, where needed. ; TW013 SPNDIR: SPND$ ; Suspend directive, where needed. ; TW013 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 PARTBL: TXTTBL SPACE ; Parity spec. table. The entries ; TW008 TXTTBL MARK ; must be in the same order as ; TW008 TXTTBL EVEN ; the branch table in subroutine ; TW008 TXTTBL ODD ; PARITY:. ; TW008 .WORD 0 ; End of table. ; TW008 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: RTYDTB: ; Remote setup disp. tbl. ; TW001 .IF GE RSXVER-40. ; If at least M4.0 or M+ 2.0, ; TW017 ASSUME TERNAS-TERNDU-2 ; Require remt before ans spd ; TW001 .WORD TERNDU,SWNRE,S2RMT,4,TERDLU,TERASA ; TW005 .IFF ; GE RSXVER-40. ; TW017 .WORD TERNDU,SWNRE,S2RMT,2,TERDLU ; TW005 .ENDC ; GE RSXVER-40. ; TW017 ASSUME TERNSD-TERNRC-2 ; Require rcv spd before snd. ; TW001 .WORD TERNRC,SWNSP,S2SPD,4,SPDRRC,SPDRSD ; TW005 .WORD 0 ; Terminate table. ; TW005 .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.\ BADSYS: .ASCIZ \ TEM - This task will not run under this operating system.\ CMLMSG: .ASCIZ \ %6SIn "%VA".\ DCLUNS: .ASCIZ \%N%29Sor DCL>START %I.\ ; TW013 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\ ILLFNC: .ASCIZ \ TEM - Warning - %I doesn't work on this device.\ ; TW005 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).\ MCRUNS: .ASCIZ \UNS\ ; TW013 MCRRES: .ASCIZ \RES\ ; TW013 OCTCTL: .ASCIZ \%Q\ PRSERM: .ASCIZ \ TEM - Syntax error. %I "%VA".\ RDYMSG: .ASCIZ \ TEM - Ready for terminal input.%N\ RDYPMP: .ASCIZ \@%N\ R5FMT: .ASCIZ \%2R\ ; TW013 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).\ STPMSG: .ASCIZ \ TEM - Stopped. To restart, type MCR>%I %I%I\ ; TW013 SUMMYM: .ASCIZ \ TEM - Run complete on %2A%Q:.\ SWNRE: .ASCIZ \/REMOTE\ ; TW005 SWNSP: .ASCIZ \/SPEED\ ; TW005 .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 ; /DELAY:nnnt SWECH=: 2 ; /ECHO SWLOG=: 4 ; /LOG:file SWNUL=: 10 ; /NULLS SWEOF=: 20 ; /EOF:char SWLIS=: 40 ; /LIST SWDTE=: 100 ; /TERMINAL ; TW010 SWHLD=: 200 ; /HOLD ; TW010 SWMON=: 400 ; /MONITOR ; TW010 SWRPA=: 1000 ; /RPA ; TW010 SWCMD=: 2000 ; /COMMAND ; TW010 SWPMP=: 4000 ; /PROMPT:char ; TW010 SWXIT=: 10000 ; /EXIT ; TW015 SWDTEI= SWECH!SWPAU!SWEOF!SWPMP!SWRPA ; Swits implied by /TERMINAL ; TW012 SWDTEA= SWECH ; Switches asserted by /TERMINAL SWMONI= SWLIS!SWNUL ; Switches implied by /MONITOR SWMONA= SWNUL ; Switches asserted by /MONITOR SWINIT= SWLIS!SWPAU!SWEOF!SWPMP!SWRPA!SWXIT ; Set on startup. ; TW015 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 S2TRN=: 100 ; /TRANSLATE:char:char ; TW006 S2PAR=: 200 ; /PARITY: ; TW008 S2MXB=: 400 ; /MAXBUFFER:size ; TW010 S2CKP=: 1000 ; /CHECKPARITY:char ; TW011 S2STP=: 2000 ; /STOP ; TW013 S2PREI: .BLKW 1 ; Implied switches present. ; TW001 S2ASSI: .BLKW 1 ; Implied switches asserted. ; TW001 NEGATE: .BLKW 1 ; 0 if switch asserted, -1 if negated. FUSELN: .BLKW 1 ; Offset into jump table for "fuse" subr; TW007 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. LPMCRC= 10 ; Checked where command came from. ; TW015 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). PARTMP: .BLKW 1 ; Temporary parity spec. ; TW008 ATNBYT: .BYTE 3 ; "Attention" character. EOFBYT: .BYTE EOF ; End-of-file character. PMPBYT: .BYTE LF ; Prompt byte. BADPAC: .BYTE EOF ; Bad parity character ; TW011 GETAC1: .BLKB 1 ; First param. on /ASSIGN. GETAC2: .BLKB 1 ; Second param on /ASSIGN. GETTC1: .BLKB 1 ; First param. on /TRANSLATE. GETTC2: .BLKB 1 ; Second param on /TRANSLATE. GETPC1: .BYTE 200 ; Param. on /CHECKPARITY ; TW011 ASGTBL: ; Character assignment table. NNN=0 .REPT 177+1 ; TW006 .BYTE NNN NNN=NNN+1 .ENDR TRNTBL: ; Character translation table. ; TW006 .REPT 2 ; TW011 NNN=0 ; TW006 .REPT 200 ; TW011 .BYTE NNN ; TW006 NNN=NNN+1 ; TW006 .ENDR ; TW006 .ENDR ; TW011 .EVEN MXBTMP: .BLKW 1 ; Parsed maxbuf spec. ; TW010 PARSPC: .WORD 0 ; Parity spec. ; TW008 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. RMSWS=: 20 ; Device has software control of speed. ; TW003 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. .IFTF ; DF ACCNTG ; Regardless of whether accounting. ; TW015 ACTDEV: .BLKW 1 ; TI: device name for accounting. .IFT ; DF ACCNTG ; If accounting. ; TW015 ACTDAT: ; \ ACTTIM: .BLKW 6. ; Transaction time. | These .WORD ACTDEV ; Accounting info. | must .IFTF ; DF ACCNTG ; Regardless. | ; TW015 ACTUNT: .WORD 1 ; TI: unit no. | remain .IFT ; DF ACCNTG ; | ; TW015 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 PAUDIR: .WORD STPDIR ; Directive to use to stop. ; TW013 UNSDAT: .WORD MCRUNS,ASCTSK,DCLUNS,ASCTSK ; /STOP msg data. ; TW013 BANDAT: .WORD DEVNAM ; Banner data. These two DEVUNT: .WORD 0 ; must remain in order. SYNSTA: .BLKW 2 ; I/O status for synchronous I/O. ASCTSK: .BLKW 4 ; Our task name, in ASCIZ format. ; TW013 DEVBUF: .BLKW 6 ; GLUN buffer. ; TW013 TSKNAM: .BLKW 2 ; Our task name, in RAD50. Must come ; TW013 ; before at least 14 wds of scratch. ; TW013 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. TERDLU: .WORD TERODU+1 ; Pointer to desired /REMOTE setting. ; TW001 .IF GE RSXVER-40. ; If at least M4.0 or M+ 2.0, ; TW017 TERASA: .WORD TEROAS+1 ; Pointer to desired answer speed. ; TW001 .ENDC ; GE RSXVER-40. ; TW017 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.BIN,1 ; SET /RPA ; TW003 .BYTE TC.CTS,0 ; Cancel control/S ; TW004 TERNDL: ; All device ctrl below here. ; TW003 .IF GE RSXVER-40. ; If at least M4.0 or M+ 2.0, ; TW017 .BYTE TC.ABD,0 ; SET /NOABAUD ; TW003 .ENDC ; GE RSXVER-40. ; TW017 TERNDU: .BYTE TC.DLU,0 ; SET /NOREMOTE ; TW001 .IF GE RSXVER-40. ; If at least M4.0 or M+ 2.0, ; TW017 TERNAS: .BYTE TC.ASP,0 ; SET /NOREMOTE[:speed] .ENDC ; GE RSXVER-40. ; TW017 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.BIN,0 ; SET /[NO]RPA ; TW003 .BYTE TC.CTS,0 ; Old control/s state. ; TW004 TERODL: ; All device control below here ; TW003 .IF GE RSXVER-40. ; If at least M4.0 or M+ 2.0, ; TW017 .BYTE TC.ABD,0 ; SET /[NO]ABAUD ; TW003 .ENDC ; GE RSXVER-40. ; TW017 TERODU: .BYTE TC.DLU,0 ; SET /[NO]REMOTE ; TW001 .IF GE RSXVER-40. ; If at least M4.0 or M+ 2.0, ; TW017 TEROAS: .BYTE TC.ASP,0 ; SET /[NO]REMOTE[:speed] .ENDC ; GE RSXVER-40. ; TW017 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 /NORPA ; TW012 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.CDEP =: G.CMLD+4 ; Loc. of current nest dep. G.MAXD =: G.CMLD+5 ; Loc. of max nest depth. G.PPTR =: G.CMLD+6 ; Loc. of pushdown list pointer. ; TW015 .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$ "CHECKPARITY",SWICKP,CKPCHK,S2CKP,S2PRE ; TW011 TRAN$ "COMMAND",SWILST,CMDCHK,SWCMD,SWPRE TRAN$ "DELAY",SWIPAU,PAUCHK,SWPAU,SWPRE ; TW008 TRAN$ "ECHO",SWILST,ECHCHK,SWECH,SWPRE TRAN$ "EOF",SWIEOF,EOFCHK,SWEOF,SWPRE .IF DF LINSET ; If line setup is supported, ; TW015 TRAN$ "EXIT",SWILST,XITCHK,SWXIT,SWPRE ; TW015 .ENDC ; DF LINSET ; TW015 TRAN$ "HOLD",SWILST,HLDCHK,SWHLD,SWPRE TRAN$ "LIST",SWILST,LSTCHK,SWLIS,SWPRE TRAN$ "LOG",SWILOG,LOGCHK,SWLOG,SWPRE TRAN$ "MAXBUFFER",SWIMXB,MXBCHK,S2MXB,S2PRE ; TW010 TRAN$ "MONITOR",SWILST,MONCHK,SWMON,SWPRE TRAN$ "NULLS",SWILST,NULCHK,SWNUL,SWPRE TRAN$ "PARITY",SWIPAR,PARCHK,S2PAR,S2PRE ; TW008 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$ "STOP",SWILST,STPCHK,S2STP,S2PRE ; TW013 TRAN$ "TERMINAL",SWILST,DTECHK,SWDTE,SWPRE TRAN$ "TRANSLATE",SWITRN,TRNCHK,S2TRN,S2PRE ; TW006 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. .IF GE RSXVER-40. ; If at least M4.0 or M+ 2.0, ; TW017 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. .ENDC ; GE RSXVER-40. ; TW017 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$ ':,SWISPX ; If have another param, check. ; TW002 TRAN$ $LAMDA,SWILST,SPDSDF ; If not, default xmit speed. ; TW002 STATE$ SWISPX ; Parse the transmit speed. ; TW002 TRAN$ $DNUMB,SWILST,SPDSND ; Must be a decimal number. STATE$ SWIPAR ; Parse /PARITY spec. ; TW008 TRAN$ ': ; Parameter req'd. ; TW008 STATE$ ; Parse it. ; TW008 TRAN$ $STRNG,SWILST,GETPAR ; Get it as a string. ; TW008 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$ SWICKP ; /CHECKPARITY ; TW011 TRAN$ ':,SWNCKP ; If a param, handle. ; TW011 TRAN$ $LAMDA,SWILST ; If not, that's OK. ; TW011 STATE$ SWNCKP ; TW011 TRAN$ !CHARSP,SWILST,GETCKP ; Save the character. ; TW011 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$ SWITRN ; /TRANSLATE ; TW006 TRAN$ ':,SWITRP,REJNEG ; Params allowed only if assert.; TW006 TRAN$ $LAMDA,REJSTA,REJNEG ; If asserted, require params. ; TW006 TRAN$ $LAMDA,SWILST ; Negated. Go for next. ; TW006 STATE$ SWITRP ; Parse params. ; TW006 TRAN$ !CHARSP,,GETTR1 ; Get first char. ; TW006 STATE$ ; TW006 TRAN$ ': ; Require another param. ; TW006 STATE$ ; TW006 TRAN$ !CHARSP,SWILST,GETTR2 ; Get second character. ; TW006 STATE$ SWIPAU ; /DELAY 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 #TSKNAM,R2 ; Pick up address of taskname buffr. ; TW013 GTSK$S R2 ; Get task info. ; TW013 MOV #MCRUNS,UNSDAT ; Assume we will use UNSTOP ; TW013 MOV #DCLUNS,UNSDAT+4 ; to get started again. ; TW013 MOV #STPDIR,PAUDIR ; Point to the stop directive. ; TW013 CALL RESUME ; Restart us, and see how it's done. ; TW013 BEQ 10$ ; If unstopped, assumption correct. ; TW013 MOV #MCRRES,UNSDAT ; Set the message for RESUME, ; TW013 MOV #ZERO,UNSDAT+4 ; which has no DCL counterpart. ; TW013 MOV #SPNDIR,PAUDIR ; Set up the proper directive. ; TW013 10$: MOV #R5FMT,R1 ; Get translation instrs, ; TW013 MOV #ASCTSK,R0 ; Get task name buffer. ; TW013 CALL $EDMSG ; Translate to ASCII. ; TW013 20$: CLRB (R0) ; Terminate with null. ; TW013 CMPB -(R0),#40 ; Is this a space? ; TW013 BEQ 20$ ; If so, go clear it. ; TW013 MOV #TSKNAM,R2 ; Point to scratch area. ; TW013 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:. MOV G.LUNA(R0),ACTDEV ; Save name of our TI:. MOVB G.LUNU(R0),ACTUNT ; Save our unit no, too. MOV G.LUCW+6(R0),R0 ; Get the buffer size. MOV R0,INRDSC+R$DBUF ; Store buffer size. MOV #BUFSIZ,R0 ; Get output buffer size. ; TW010 CALL MXBFIL ; Find the max. file buffer. ; TW010 MOV MXBTMP,LGFDSC+F$BEND ; Set it up. ; TW010 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. CALL TELSET ; Attach the local terminal BCS 200$ ; If an error, exit. 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: CMKT$S ,#FUSEAS ; Kill the fuse. ; TW007 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. BIT #LPABO,LPIND ; Have we been aborted? ; TW007 BNE 40$ ; If so, handle. ; TW007 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.CDEP(R0),-(SP) ; old command file nest depth; TW015 MOV G.PPTR(R0),-(SP) ; and old pushdown pointer. ; TW015 MOV G.PPTR(R0),R1 ; Point to stack. ; TW015 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.CDEP(R0) ; Force nest level 2. ; TW015 MOV R1,G.PPTR(R0) ; New pushdown list pointer. ; TW015 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.PPTR(R0) ; Restore the pushdown pointer. ; TW015 MOVB (SP)+,G.CDEP(R0) ; Restore current nest depth. ; TW015 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 19$ ; 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 19$ ; If aborted, just return. MOV #GCMLB,R0 ; Get the GCML control block. 5$: GCML$ ; Get the next command line. BCS 20$ ; If an error, process it. .IF DF LINSET ; If doing line setup: ; TW015 BIT #LPMCRC,LPIND ; Have we already checked cmd origin? ; TW015 BNE 7$ ; If so, don't check again. ; TW015 BIS #LPMCRC,LPIND ; Set the cmd check flag. ; TW015 .IF DF EXGTCM ; If using EGCML ; TW015 BIT #GE.MCR,G.MODE(R0) ; Come from MCR? ; TW015 BEQ 7$ ; If not, skip. ; TW015 .IFF ; DF EXGTCM ; If just using GCML ; TW015 TSTB G.MODE(R0) ; Come from MCR? ; TW015 BGE 7$ ; If not, skip. ; TW015 .ENDC ; DF EXGTCM ; End of CLI interface-dependant code. ; TW015 BIC #SWXIT,SWSTAT ; Inhibit exit. ; TW015 7$: ; TW015 .ENDC ; DF LINSET ; End of line setup code. ; TW015 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 19$ ; If so, go to it. CALL EXECUT ; Execute the command. BR GCMINP ; Go for another one. 19$: SEC ; Set the exception bit. ; TW015 RETURN ; Return to caller. ; TW015 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. .IF DF LINSET ; If we have line setup. ; TW015 BIT #SWXIT,SWSTAT ; Deferred exit? ; TW015 BNE 89$ ; If not, just leave. ; TW015 BIS #SWXIT,SWSTAT ; If so, leave next time. ; TW015 MOVB #1,G.CDEP(R0) ; Reset command nest depth. ; TW015 MOV G.PPTR(R0),R1 ; Get pushdown addr. ; TW015 .IF DF EXGTCM ; If using extended GCML, ; TW015 BIC #GE.MCR,G.MODE(R0) ; Clear the "valid MCR" bit. ; TW015 CLR -(R1) ; Fudge saved ; TW015 MOV #1,-(R1) ; positional ; TW015 CLR -(R1) ; context. ; TW015 MOV #6401,-(R1) ; Whatever. ; TW015 CLR -(R1) ; " ; TW015 CLR -(R1) ; " ; TW015 CLR -(R1) ; " ; TW015 MOV #1002,-(R1) ; Fudge up ; TW015 MOV #120,-(R1) ; the ; TW015 CLR -(R1) ; first ; TW015 CLR -(R1) ; eight ; TW015 CLR -(R1) ; words ; TW015 MOV #1,-(R1) ; of ; TW015 CLR -(R1) ; the ; TW015 MOV #3400,-(R1) ; FDB. ; TW015 MOV #1,-(R1) ; Fudge up ; TW015 CLR -(R1) ; the ; TW015 CLR -(R1) ; file ID. ; TW015 MOV #4,-(R1) ; Fudge up the ; TW015 MOV #4,-(R1) ; directory ; TW015 CLR -(R1) ; ID. ; TW015 MOV ACTDEV,-(R1) ; Save TI:'s device name ; TW015 MOV ACTUNT,-(R1) ; and unit number. ; TW015 CLR -(R1) ; Fudge flags. ; TW015 .IFF ; DF EXGTCM ; If not using EGCML, ; TW015 CLR (R1)+ ; Clear out ; TW015 CLR (R1)+ ; positional ; TW015 CLR (R1)+ ; context. ; TW015 MOVB #1,(R1)+ ; Fudge QIO context. ; TW015 MOVB ACTUNT,(R1)+ ; Get TI: unit number. ; TW015 MOV ACTDEV,(R1)+ ; Get TI: device name. ; TW015 MOV #1,(R1)+ ; Fudge the ; TW015 CLR (R1)+ ; file ; TW015 CLR (R1)+ ; ID ; TW015 .ENDC ; DF EXGTCM ; End of CLI interface dependant; TW015 MOV R1,G.PPTR(R0) ; Save the new stack pointer. ; TW015 JMP 5$ ; Go retry the operation. ; TW015 .ENDC ; DF LINSET ; End of line setup conditional.; TW015 89$: BIS #LPABP,LPIND ; Need to exit. ; TW015 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 S2PRE,S2PREI ; Don't imply any switches that ; TW001 BIC S2PRE,S2ASSI ; appeared explicitly. ; TW001 BIS S2PREI,S2PRE ; Set any implied switches ; TW001 BIS S2ASSI,S2ASS ; that are left. ; TW001 BIC #LPRDY,LPIND ; Init the file flag. CALL SWIPRC ; Process values of applied switches. ; TW010 BIT #LPCMD,LPIND ; Need to break out of loop? ; TW013 BNE 70$ ; If so, go do it. ; TW013 CALL TELTRM ; Set up local terminal as needed. BCS 70$ ; If failed, go no further. CALL TERSPD ; Set remote speed if needed. BCS 60$ ; If failed, quit. CALL OPNSCN ; Open the send file if needed. BCS 60$ ; 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 30$ ; If so, fine. MOV #-1,PMPFLG ; Disable prompt processing for TT: input. BIT #LPREAP,LPIND ; Are we processing a setup file? BNE 60$ ; If so, no user input allowed. BIT #SWCMD,SWSTAT ; Want an immediate return to cmd mode? BNE 60$ ; If so, go for it. 10$: BIT #SWDTE,SWSTAT ; Are we talking to a terminal? BEQ 20$ ; If not, proceed. MOV #CR,R0 ; Implied to the CALL OURING ; output terminal. MOV #LF,R0 ; Implied linefeed, CALL OURING ; too. 20$: MOV #RDYMSG,R1 ; Set up terminal prompt. 30$: CALL MSGOUT ; Issue prompt. BR 50$ ; Enter loop at bottom. ; TW013 40$: CALL GETDAT ; Get some data to transmit. CALL ROU ; Write to remote terminal. CALL LOU ; Write to local terminal. 50$: BIT #LPCMD,LPIND ; Need to break out of loop? ; TW013 BEQ 40$ ; If not, go wait some more. TST SNDFDB+F.BDB ; Send file open? BEQ 60$ ; If not, need a command. CALL CLOSND ; Close send file if any. BIT #LPREAP,LPIND ; Are we processing a setup file? BNE 60$ ; If so, no user input allowed. BIT #SWCMD,SWSTAT ; What do we do after closing? BNE 60$ ; If want another cmd, go get it. BIT #RMATU,LCSTAT ; Can our TI: provide terminal mode? BEQ 60$ ; If not, go for another command. BIC #LPXIT,LPIND ; Clear the breakout indicator. BIT #LPABO,LPIND ; Aborting? BEQ 10$ ; If not, go into terminal mode. 60$: CALL TELCMD ; Put terminal back in command mode. 70$: 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). CKPCHK: MOV #S2CKP,R0 ; Checking /CHECKPARITY: ; TW011 MOVB BADPAC,GETPC1 ; Default the parameter. ; TW011 BR SW2CHK ; Go do it. ; TW011 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 #S2MXB,R0 ; Checking /MAXBUFFER: ; TW010 BR SW2CHK ; Go do it. ; TW010 NULCHK: MOV #SWNUL,R0 ; Checking /NULLS BR SWICHK ; Go do it. PARCHK: MOV #S2PAR,R0 ; Checking /PARITY: ; TW008 BR SW2NGC ; Go do it (can't be negated). ; TW008 PAUCHK: MOV #SWPAU,R0 ; Checking /DELAY: 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. ; TW005 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). ; TW005 STPCHK: MOV #S2STP,R0 ; Checking /STOP ; TW013 BR SW2NGC ; Go do it (can't be negated). ; TW013 TRNCHK: MOV #S2TRN,R0 ; Checking /TRANSLATE:: ; TW006 BR SW2CHK ; Go do it. ; TW006 .IF DF LINSET ; If line setup is supported, ; TW015 XITCHK: MOV #SWXIT,R0 ; Checking /EXIT ; TW015 BR SWICHK ; Go do it. ; TW015 .ENDC ; DF LINSET ; TW015 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. DUPSWI: MOV #DUPSWM,TPERR ; Change error to dup. switch. ; TW008 REJECT ; Reject the transition. ; TW008 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. GETCKP: MOV #GETPC1,R2 ; Storing the bad parity byte. ; TW011 BR GETBYT ; Go do it. ; TW011 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. GETTR1: MOV #GETTC1,R2 ; Storing first /TRANSLATE parameter. ; TW006 BR GETBYT ; Go do it. ; TW006 GETTR2: MOV #GETTC2,R2 ; Storing second /TRANSLATE parameter. ; TW006 BR GETBYT ; Go do it. ; TW006 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. GETPAR: MOV #PARTBL,R0 ; Get address of parity spec. table. ; TW008 MOV #1,R1 ; Can abbreviate to one character. ; TW008 CALL KEYCMP ; Look up the keyword. ; TW008 REJECT CS ; If not found, reject. ; TW008 ASL R0 ; Convert index to word offset. ; TW008 MOV R0,PARTMP ; Save the index. ; TW008 RETURN ; Return to parser. ; TW008 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. 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$: CLC ; Clear possible carry bit. ; TW008 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,MXBTMP ; Store the value. ; TW010 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. .IF GE RSXVER-40. ; If at least M4.0 or M+ 2.0, ; TW017 RSPIMP: BIT #S2SPD,S2PRE ; /SPEED already seen? BNE 10$ ; If so, do nothing. ; /RE:0 no longer special case. ; TW001 BIS #S2SPD,S2PREI ; Imply the /SPEED ; TW001 BIS #S2SPD,S2ASSI ; switch. ; TW001 MOV TERASA,SPDRRC ; Make the receive and MOV TERASA,SPDRSD ; send speed same as remote speed. 10$: RETURN ; Return to parser. .ENDC ; GE RSXVER-40. ; TW017 RMTNEG: MOV #ONE,TERDLU ; Assume asserted, ; TW001 .IF GE RSXVER-40. ; If at least M4.0 or M+ 2.0, ; TW017 MOV SPDRRC,TERASA ; with no parameters ; TW001 .IFTF ; GE RSXVER-40. ; TW017 TST NEGATE ; Asserted? .IFT ; GE RSXVER-40. ; TW017 REJECT LT ; If so, reject. .IFF ; GE RSXVER-40. ; TW017 BLT 10$ ; If so, we're just fine. ; TW017 .ENDC ; GE RSXVER-40. ; TW017 MOV #ZERO,TERDLU ; If negated, turn off remote. ; TW001 10$: RETURN ; and return to parser. ; TW017 SPDSDF: MOV SPDRRC,SPDRSD ; Default send speed to receive speed. ; TW002 RETURN ; Return to parser. ; TW002 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. .IF GE RSXVER-40. ; If at least M4.0 or M+ 2.0, ; TW017 RMTSPD: MOV #TERASA,R0 ; Pick up where /REMOTE speed goes. BR SPDCOM ; Go validate and store. .ENDC ; GE RSXVER-40. ; TW017 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. CALL RESUME ; Unstop, if needed. ; TW013 CALL FUSE ; Light the fuse. ; TW007 ASTX$S ; Exit the AST. .SBTTL Subroutine RESUME - Unstop or resume as appropriate ; Status return: ; C-bit clear - Task unstopped or resumed ; C-bit set - Task not unstopped or resumed. ; Z-bit set - System has stop bit support ; Z-bit clear - System does not have stop bit support. RESUME: CLR -(SP) ; Save status indicator. ; TW013 USTP$S #TSKNAM ; Unstop us. ; TW013 BCC 60$ ; If success, fine. ; TW013 CMPB $DSW,#IE.SDP ; Directive supported? ; TW013 BNE 50$ ; If so, a real error. ; TW013 DEC (SP) ; Flag no stop bit support. ; TW013 RSUM$S #TSKNAM ; Resume operations. ; TW013 BR 60$ ; Take whatever result we got. ; TW013 50$: SEC ; Flag an error. ; TW013 60$: MOV (SP),(SP)+ ; Toggle "Z" and "N" bits only. ; TW013 RETURN ; Return to caller. ; TW013 .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 #TERODL-TEROMC,TEROMC-2 ; Assume we're on a ; TW003 MOV #TERNDL-TERNMC,TERNMC-2 ; DL11 or DJ11 ; TW003 BIT #U2.DH1,DEVBUF+G.LUCW+2 ;Are we a multiplexer? ; TW003 BEQ 30$ ; If not, we're a DL11. Assumed right. ; TW003 BIT #U2.DJ1,DEVBUF+G.LUCW+2 ;Are we a DJ11? ; TW003 BNE 30$ ; If so, assumption was right. ; TW003 BIS #RMSWS,R1 ; It's a DZ11 or DH11. Has soft speed. ; TW003 MOV #TEROME-TEROMC,TEROMC-2 ; Include speed in the ; TW003 MOV #TERNME-TERNMC,TERNMC-2 ; line setup. ; TW003 30$: MOV R1,RMSTAT ; Save device status. ; TW003 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 SWIPRC - Process switch values. SWIPRC: TRACER SWIPRC ; TW010 CALL SWIAST ; Process /STOP ; TW013 CALL SWIACH ; Process /CHECKPARITY ; TW011 CALL SWIAMA ; Process /MAXBUFFER ; TW011 CALL SWIAAS ; Process /ASSIGN ; TW011 CALL SWIATR ; Process /TRANSLATE ; TW011 CALL SWIAPA ; Process /PARITY ; TW011 RETURN ; Return to caller. ; TW011 SWIAMA: BIT #S2MXB,S2PRE ; Got a /MAXBUFFER:? ; TW011 BEQ 10$ ; If no, skip. ; TW010 MOV MXBTMP,LGFDSC+F$BEND ; If so, store the value. ; TW010 10$: RETURN ; Return to caller. ; TW011 SWIAAS: BIT #S2ASG,S2PRE ; Got a /ASSIGN? ; TW011 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,R2 ; Get the character it becomes. ; TW008 CALL PARITY ; Calculate the parity bit. ; TW008 MOVB R1,ASGTBL(R0) ; Set the equivalent. ; TW008 BR 60$ ; Return. 20$: MOV #ASGTBL+177+1,R0 ; Point to end of table. MOV #177,R2 ; Get character code. ; TW008 CALL DISAST ; No AST's while table updated. 30$: CALL PARITY ; Calculate the parity. ; TW008 MOVB R1,-(R0) ; Store code. ; TW008 SOB R2,30$ ; Repeat as needed. ; TW008 CALL PARITY ; Calculate parity for null. ; TW008 MOVB R1,-(R0) ; Store code. ; TW008 60$: RETURN ; Return to caller. ; TW011 SWIATR: BIT #S2TRN,S2PRE ; Got a /TRANSLATE? ; TW011 BEQ 60$ ; If not, just return. ; TW011 CALL DISAST ; Disable AST's during update. ; TW011 BIT #S2TRN,S2ASS ; Asserted? ; TW006 BEQ 10$ ; If not, clear table. ; TW011 CLR R2 ; Get the character to ; TW011 BISB GETTC1,R2 ; translate. ; TW011 MOVB GETTC2,R0 ; Get its equivalent. ; TW011 BIC #^C177,R0 ; Strip unused bits. ; TW011 MOVB R0,TRNTBL(R2) ; Set the equivalent, ; TW011 MOVB R0,TRNTBL+200(R2) ; assuming no checking. ; TW011 MOVB BADPAC,R0 ; Get the bad parity character. ; TW011 BGE 60$ ; If not checking parity, done. ; TW011 CALL PARIBD ; Calc. the "wrong" parity. ; TW011 MOVB R0,TRNTBL(R1) ; Set it to the error char. ; TW011 BR 60$ ; Return. ; TW011 10$: MOV #177,R2 ; Get character code. ; TW011 20$: MOVB R2,TRNTBL(R2) ; Store code, ; TW011 MOVB R2,TRNTBL+200(R2) ; assuming no checking. ; TW011 MOVB BADPAC,R0 ; Get the bad parity character. ; TW011 BGE 30$ ; If not checking, done. ; TW011 CALL PARIBD ; Calc. the "wrong" parity. ; TW011 MOVB R0,TRNTBL(R1) ; Set it to the error char. ; TW011 30$: DEC R2 ; Count down a character. ; TW011 BGE 20$ ; If not done, loop. ; TW011 60$: RETURN ; Return to caller. ; TW011 SWIAPA: BIT #S2PAR,S2ASS ; Do we have the parity switch? ; TW011 BEQ 60$ ; If not, skip. ; TW011 CMP PARTMP,PARSPC ; Duplicate spec? ; TW011 BEQ 60$ ; If so, skip. ; TW011 CALL DISAST ; Disable AST's during update. ; TW011 TSTB BADPAC ; Checking parity? ; TW011 BGE 20$ ; If not, skip this code. ; TW011 MOVB BADPAC,-(SP) ; Save the check char. ; TW011 CLRB BADPAC ; Set for no check. ; TW011 CALL SWIACX ; Remove parity checking. ; TW011 MOVB (SP)+,BADPAC ; Restore the check char. ; TW011 20$: MOV PARTMP,PARSPC ; Update the parity spec. ; TW011 MOV R3,-(SP) ; Save a register. ; TW011 MOV #177+1,R3 ; Size of assignment table. ; TW008 MOV #ASGTBL,R0 ; Address of assignment table. ; TW008 30$: MOVB (R0),R2 ; Get the character. ; TW011 CALL PARITY ; Recalculate parity. ; TW008 MOVB R1,(R0)+ ; Store the character back. ; TW008 SOB R3,30$ ; Repeat as needed. ; TW011 MOV (SP)+,R3 ; Restore the register. ; TW008 TSTB BADPAC ; Checking parity? ; TW011 BGE 60$ ; If not, skip this code. ; TW011 CALL SWIACX ; Restore the parity check. ; TW011 60$: RETURN ; Return. ; TW011 SWIAST: BIT #S2STP,S2ASS ; Got /STOP? ; TW013 BEQ 60$ ; If not, ignore it. ; TW013 CALL TELCLR ; Clear the local terminal. ; TW013 10$: MOV #UNSDAT,R2 ; Point to the message buffer. ; TW013 MOV #STPMSG,R1 ; Point to our message. ; TW013 CALL MSGOUT ; Write our message. ; TW013 DIR$ PAUDIR ; Stop the task. ; TW013 CALL TELSET ; Re-init the local terminal. ; TW013 BCS 10$ ; Failed. stop again. ; TW013 60$: RETURN ; Return to caller. ; TW013 .ENABL LSB ; For shared code below. ; TW011 SWIACH: BIT #S2CKP,S2PRE ; Got /CHECKPARITY? ; TW011 BEQ 60$ ; If not, just return. ; TW011 BICB #200,GETPC1 ; Clear the parity bit. ; TW011 BIT #S2CKP,S2ASS ; Want checking? ; TW011 BEQ 10$ ; If not, fine. ; TW011 BISB #200,GETPC1 ; If so, signal it. ; TW011 10$: CMPB GETPC1,BADPAC ; Any change? ; TW011 BEQ 60$ ; If not, no update. ; TW011 MOVB GETPC1,BADPAC ; Update the check char. ; TW011 SWIACX: CALL DISAST ; Disable AST's. ; TW011 MOV #177,R2 ; Tran. table loc. ; TW011 20$: CALL PARITY ; Find the valid character. ; TW011 MOVB TRNTBL(R1),R0 ; Get it. ; TW011 ADD #200,R1 ; Find the "wrong" parity. ; TW011 BIC #^C377,R1 ; Clear unwanted bits. ; TW011 MOVB R0,TRNTBL(R1) ; Assume no parity checking. ; TW011 MOVB BADPAC,R0 ; Checking parity? ; TW011 BGE 50$ ; If not, skip. ; TW011 MOVB R0,TRNTBL(R1) ; If so, flag the bad character.; TW011 50$: DEC R2 ; Count down. ; TW011 BGE 20$ ; Loop. ; TW011 60$: RETURN ; Return to caller. ; TW011 .DSABL LSB ; End of shared code. ; TW011 .PAGE .SBTTL Subroutine PARITY - Calc. the parity of a character. ; Input: ; R2 - Character to "Paritize". ; ; Output: ; R1 - Character with parity. ; All other registers preserved. PARITY: MOV R2,R1 ; Copy input to output. ; TW008 BIC #^C377,R1 ; Clear unwanted bits. ; TW008 ADD PARSPC,PC ; Take the proper branch. ; TW008 BR 10$ ; Space - PARSPC = 0. ; TW008 BR 20$ ; Mark - PARSPC = 2. ; TW008 BR 30$ ; Even - PARSPC = 4. ; TW008 BR 40$ ; Odd - PARSPC = 6. ; TW008 10$: BIC #200,R1 ; Space - Clear the parity bit. ; TW008 RETURN ; Done. Return to caller. ; TW008 20$: BIS #200,R1 ; Mark - Set the parity bit. ; TW008 RETURN ; Done. Return to caller. ; TW008 30$: CLR -(SP) ; Even - Clear XOR mask. ; TW008 BR 50$ ; Join common code. ; TW008 40$: MOV #200,-(SP) ; Odd - Set XOR mask. ; TW008 50$: BIC #200,R1 ; Clear the parity bit. ; TW008 BEQ 80$ ; If null, done. ; TW008 MOV R1,-(SP) ; Save the character. ; TW008 CLR -(SP) ; Parity accumulator. ; TW008 60$: ADC (SP) ; Accumulate the next bit. ; TW008 ROR R1 ; Get the next bit. ; TW008 BNE 60$ ; If not done, accumulate. ; TW008 ADC (SP) ; Accumulate the last. ; TW008 ROR (SP)+ ; Get the parity. ; TW008 BCC 70$ ; If even, skip. ; TW008 BIS #200,(SP) ; If odd, set it. ; TW008 70$: MOV (SP)+,R1 ; Get the character and parity. ; TW008 80$: ADD (SP)+,R1 ; Flip parity bit if needed. ; TW008 BIC #^C377,R1 ; Clear any superfluous bits. ; TW008 RETURN ; Return to caller. ; TW008 .SBTTL Subroutine PARIBD - Calculate the wrong parity. PARIBD: CALL PARITY ; Calculate the parity. ; TW011 ADD #200,R1 ; Flip the parity bit. ; TW011 BIC #^C377,R1 ; Clear unwanted bits. ; TW011 RETURN ; Return to caller. ; TW011 .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. MOV R0,-(SP) ; Save any needed ; TW006 MOV R3,-(SP) ; registers ; TW006 BIC #^C377,R0 ; Clear unwanted bits. ; TW011 MOVB TRNTBL(R0),R0 ; Get the revised value. ; TW006 BIC #^C177,R0 ; Clear unwanted bits. ; TW006 BNE 10$ ; If not a null, fine. ; TW014 BIT #SWNUL,SWSTAT ; Are we keeping nulls? ; TW014 BEQ 100$ ; If not, quit. ; TW014 10$: CMP R0,PMPFLG ; Is this the prompt character? ; TW014 BNE 40$ ; If not, just drop in ring. TST SNDFDB+F.BDB ; SENDing a file? BEQ 30$ ; If not, quit. BIT #SWPMP,SWSTAT ; Looking for prompt? BEQ 30$ ; If not, clear indicator and proceed. BIT #SWPAU,SWSTAT ; Got a /DELAY? BNE 20$ ; If so, start the marktime. BIS #LPRDY,LPIND ; Fire up the mainline. BR 40$ ; Go drop the character in the ring. 20$: CMKT$S ,#DLYAST ; Cancel current marktime if any. MRKT$S ,RCDLAY,RCDUNT,#DLYAST ; Start the marktime. BR 40$ ; Go drop the character in the ring. 30$: MOV #-1,PMPFLG ; Insure no further matches. 40$: MOV #INRDSC,R1 ; Get the inbound ring descriptor. BIT #SWMON,SWSTAT ; Monitoring input? BEQ 90$ ; If not, join common code. ; TW006 CMPB R0,#40 ; Printable character? BLO 50$ ; If not, check for carriage control. CMPB R0,#DEL ; Is it a delete? BNE 90$ ; If not, handle normally. ; TW006 BR 60$ ; If so, expand it. 50$: CMPB R0,#CR ; Carriage control character? BHI 60$ ; Can't be. Process it. CMPB R0,#LF ; Might be, check low end. BHIS 90$ ; It is. handle normally. ; TW006 60$: ASL R0 ; Convert to word offset. ; TW006 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 120$ ; Drop it in the ring. BR 80$ ; Enter loop at bottom. 70$: CALL 120$ ; Drop character in ring. 80$: MOVB (R3)+,R0 ; Get the next character. BNE 70$ ; If not done, go put it in ring. MOV #'>,R0 ; Get the right angle bracket. 90$: CALL 120$ ; Drop in the trailing angle bracket. ; TW006 100$: MOV (SP)+,R3 ; Restore the saved ; TW014 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. BIC #^C377,R0 ; Strip unused bits. ; TW008 BIT #SWECH,SWSTAT ; Doing local echo? BEQ 110$ ; If not, proceed. CALL INRING ; If so, turn the character around. 110$: MOV #OURDSC,R1 ; Get the outbound ring descriptor. CALL 120$ ; Drop it in. MOV (SP)+,R0 ; Restore character. RETURN ; Return to caller. ; Subroutine 120$ - Common ring handling code. 120$: 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 130$ ; 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. 130$: 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 FUSE - Insure return to mainline. FUSE: ; TW007 .ENABLE LSB ; For shared code. ; TW007 TST FUSELN ; Is the fuse already lit? ; TW007 BNE 60$ ; If so, just exit. ; TW007 BR 20$ ; Handle. ; TW007 ; TW007 FUSEAS: JSR R1,ASTSVF ; Save some registers. ; TW007 ; TW007 20$: MRKT$S ,#5,#2,#FUSEAS ; (Re-)light the fuse. ; TW007 MOV FUSELN,R0 ; Get current status. ; TW007 ADD #2,FUSELN ; Update the status. ; TW007 ADD R0,PC ; Dispatch the fuse handler. ; TW007 BR 60$ ; First call - do nothing. ; TW007 BR 30$ ; Second call - Issue IO.KIL on both. ; TW007 BR 40$ ; Third call - Die horribly. ; TW007 ; TW007 30$: MOV #RTELUN,R0 ; Load the remote LUN. ; TW007 CALL 70$ ; Issue the kill. ; TW007 MOV #LTELUN,R0 ; Load the local LUN. ; TW007 CALL 70$ ; Same. ; TW007 BR 60$ ; Done. ; TW007 ; TW007 40$: BIT #LPABO,LPIND ; Is this an abort? ; TW007 BEQ 50$ ; If not, kill fuse. ; TW007 CALL TERCLR ; Clear operations on remote. ; TW007 CALL TELCLR ; Clear operations on local. ; TW007 EXIT$S ; Goodbye, cruel world. ; TW007 ; TW007 50$: CLR FUSELN ; Douse the fuse. ; TW007 ; TW007 60$: RETURN ; Return to caller. ; TW007 ; TW007 70$: QIO$S #IO.KIL,R0 ; Issue IO.KIL on desired LUN. ; TW007 RETURN ; Return to caller. ; TW007 .DSABL LSB ; End of local symbol block. ; TW007 .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 #^C377,R0 ; Strip off unwanted bits. ; TW011 JMP INRING ; Put character in inbound ring. ; TW014 .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. CALL FUSE ; Light the fuse. ; TW007 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? BHIS 40$ ; If not, fine. 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 70$ ; If empty, just check for wrap. ; TW016 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 70$ ; If don't want write, skip it. 60$: QIOW$S #IO.WVB,R$LUN(R1),#SYNIOF,,,, ; Write. 70$: ADD R$OUB(R1),R2 ; Find out how far we have processed. CMP R2,R$BND(R1) ; Is it time to wrap around? BLO 80$ ; 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. 80$: MOV R2,R$OUB(R1) ; Store the updated position. BIT #LPCMD,LPIND ; Do we have a breakout pending? ; TW016 BNE 90$ ; If so, leave. ; TW016 BIT #R$F$MO,R$FLGS(R1) ; More to do? BNE 30$ ; If so, go around again. 90$: 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 70$ ; If failed, clean up and exit. BIT #RMFDX,RMSTAT ; Do we support full duplex operation? BEQ 30$ ; If not, all done. MOV #TEROMC,R1 ; Point to characteristics buffer. CALL TEXGMC ; Save them. BCS 40$ ; If failed, clean up and exit. MOVB TERODU+1,TERNDU+1 ;Get desired /REMOTE setting. ; TW001 .IF GE RSXVER-40. ; If at least M4.0 or M+ 2.0, ; TW017 MOVB TEROAS+1,TERNAS+1 ;Get the desired /REMOTE answr speed. ; TW001 .ENDC ; GE RSXVER-40. ; TW017 MOVB TERORC+1,TERNRC+1 ;Get the desired receive speed. ; TW001 MOVB TEROSD+1,TERNSD+1 ;Get the desired transmit speed. ; TW001 MOV #TERNMC,R1 ; Point to desired characteristics. CALL TEXSMC ; Set them up. BCS 40$ ; If an error, die. 30$: .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 60$ ; Write it. 40$: CALL TEXDET ; If failure, detach terminal SEC ; return an error, BR 70$ ; 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 70$ ; If not, just return. CALL HANGCN ; Hang up the line if needed. BIT #RMFDX,RMSTAT ; Do we support full duplex operation? BEQ 50$ ; If not, don't reset characteristics. MOV #TEROMC,R1 ; Point to old characteristics. CALL TEXSMC ; Put setup back the way it was. 50$: 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. 60$: MOV #BANDAT,R2 ; Point to data. CALL MSGOUT ; Write banner. 70$: RETURN ; Return to caller. .DSABL LSB ; End of shared code. .SBTTL Subroutine TERSPD - Set speeds on remote terminal. TERSPD: TRACER TERSPD JSR R5,$SAVRG ; Save some registers. ; TW001 MOV #RTYDTB,R5 ; Get the dispatch table. ; TW001 BR 50$ ; Enter post-test loop. ; TW005 10$: MOV R5,R2 ; Save error msg. address. ; TW005 TST (R5)+ ; Skip over it. ; TW005 BIT (R5)+,S2PRE ; Have we got this switch? ; TW001 BEQ 20$ ; If not, just skip over data. ; TW005 CMP R1,#TERNDL ; Is this a device setup? ; TW005 BLO 30$ ; If not, it's OK to do. ; TW005 BIT #RMSWS,RMSTAT ; Is the remote line a DL? ; TW005 BNE 30$ ; If not, it's OK to do. ; TW005 MOV #ILLFNC,R1 ; Get the general warning text. ; TW005 CALL MSGOUT ; Write the message. ; TW005 20$: ADD (R5)+,R5 ; Skip over the data. ; TW005 BR 50$ ; Go for the next switch. ; TW005 30$: MOV (R5)+,R2 ; Get data length. ; TW005 MOV R1,R3 ; Copy the table address. ; TW001 MOV R2,R4 ; Copy the table length, ; TW001 ASR R4 ; and convert to count. ; TW001 40$: INC R3 ; Go to data field. ; TW005 MOV @(R5)+,R0 ; Get address of desired value. ; TW001 MOVB (R0),(R3)+ ; Fill in the desired value. ; TW001 SOB R4,40$ ; Repeat as needed. ; TW005 MOV #RTELUN,R0 ; Get LUN for remote terminal. ; TW001 CALL TEXSCH ; Perform the function. ; TW001 50$: MOV (R5)+,R1 ; Get buffer address. ; TW005 BNE 10$ ; If have one, process it. ; TW005 RETURN ; Restore registers and return. ; TW001 .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 20$ ; 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 20$ ; 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 20$ ; 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 20$ ; Join common code. ; Common code - Issue QIO and check status. 20$: 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 50$ ; If directive failure, error out. WTSE$S #SYNIOF ; Wait for the event flag. CMPB SYNSTA,#IS.SUC ; I/O success? BEQ 70$ ; If so, just exit. CMPB SYNSTA,#IS.PND ; Still pending? BNE 30$ ; If not, go kill marktime. QIOW$S #IO.KIL,R0,#SYNIOF ; If so, kill it, BR 40$ ; and proceed with the funeral. 30$: CMKT$S #SYNIOF ; Cancel all marktimes this event flag. 40$: MOV #IOM,(R2)+ ; If not, insert proper message, CLR (R2) ; Assume code positive. MOVB SYNSTA,(R2) ; Set I/O status. BGE 60$ ; Go write if positive. DECB 1(R2) ; Twiddle sign byte. BR 60$ ; Go write. 50$: MOV #DSWM,(R2)+ ; Fill in the $DSW error message, MOV $DSW,(R2) ; and value. CMKT$S #SYNIOF ; Cancel all marktimes this event flag. 60$: 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. 70$: 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