Trailing-Edge
-
PDP-10 Archives
-
bb-d868e-bm_tops20_v41_2020_dist_1of2
-
language-sources/oprpar.mac
There are 36 other files named oprpar.mac in the archive. Click here to see a list.
TITLE OPRPAR PARSING ROUTINE FOR OPR AND ORION
SUBTTL Murray Berkowitz/PJT 1-Jan-82
;
;
; COPYRIGHT (c) 1975,1976,1977,1978,1979,1980,1981,1982
; DIGITAL EQUIPMENT CORPORATION
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; AND COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE
; AND WITH THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS
; SOFTWARE OR ANY OTHER COPIES THEREOF MAY NOT BE PROVIDED OR
; OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON. NO TITLE TO
; AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED.
;
; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE
; WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT
; BY DIGITAL EQUIPMENT CORPORATION.
;
; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY
; OF ITS SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY
; DIGITAL.
SEARCH GLXMAC,ORNMAC
PROLOG (OPRPAR)
PAREDT==:101
TWOSEG
RELOC 400000
SUBTTL Table of Contents
; TABLE OF CONTENTS FOR oprpar
;
;
; SECTION PAGE
; 1. Table of Contents......................................... 2
; 2. Revision History.......................................... 3
; 3. Entry points.............................................. 4
; 4. Storage and constants..................................... 5
; 5. P$INIT Initialize and set timer (TOPS20 only)............ 6
; 6. PARINI Initialize the database........................... 7
; 7. PARSER Main entry to parse a command..................... 8
; 8. PARCMD Do the command parse.............................. 9
; 9. VALCMD Process a valid command field..................... 10
; 10. PARRET Setup arguments and return........................ 11
; 11. PARERR COMND JSYS error routine......................... 12
; 12. CHKEOF Check for end of take file........................ 13
; 13. CLSTAK Close the take file............................... 14
; 14. TAKCLR Cleanup after take file........................... 14
; 15. ERREXT Error return from parser.......................... 15
; 16. INCORE Check and setup for incore processing............. 16
; 17. CMDMES Check and/or setup the command message............ 17
; 18. SETPMT Setup the prompt pointer.......................... 18
; 19. RESCN Rescan routine to setup initial command.......... 19
; 20. Dispatch for Parser Save Routines......................... 20
; 21. SAVKEY/SAVSWI Save a switch or keyword.................... 21
; 22. SAVFIL Save a filespec................................... 22
; 23. SAVNUM Save a number..................................... 23
; 24. SAVZER Save a COMMA or CONFRM............................ 23
; 25. SAVUQS Save an unquoted string........................... 24
; 26. SAVATM Save the atom as the argument..................... 24
; 27. SAVRES Save a 2 word argument............................ 25
; 28. SAVDEV Save routine for a device......................... 26
; 29. SAVTOK Save routine to save a token...................... 27
; 30. SAVNOD Save node specification........................... 27
; 31. SAVINI Initialize the returned arguments................. 27
; 32. REPARS Set up for COMND reparse.......................... 28
; 33. FILDEF Fill in defaults for COMND........................ 29
; 34. PDBCPY Copy a switch table............................... 30
; 35. STBDEL Delete a local switch table entry................. 30
; 36. TXTINP Multiple line text input routines................. 31
; 37. GETTXT Get multiple lines of text........................ 32
; 38. TAKFDB TAKE command tables............................... 33
; 39. TAKDEF Take default setting.............................. 33
; 40. TAKRTN Special routines for TAKE commands................ 34
; 41. WAIFDB WAIT command tables............................... 35
; 42. P$STAK Setup TAKE command................................ 36
; 43. P$TAKE Routine to setup a TAKE command................... 37
; 44. P$SETU Setup the parser block pointer address............ 38
; 45. P$CURR Get the address of the current entry.............. 38
; 46. P$PREV Position to previous parser entry................. 38
; 47. P$NEXT Bump the pointer to next field.................... 39
; 48. P$NFLD Get header and data for a parser element.......... 39
; 49. P$CFM Check for a confirm in next block................. 40
; 50. P$COMMA Check for a comma in next block................... 41
; 51. P$KEYW Get a keyword from the parsed data................ 42
; 52. P$SWIT Get a switch from the parsed data................. 43
; 53. P$USER Get the user id field............................. 44
; 54. P$FLOT Get the floating point number..................... 45
; 55. P$DIR Get the directory field........................... 46
; 56. P$TIME Get the time/date field........................... 47
; 57. P$NUM Get a number from the parser block................ 48
; 58. P$FILE Get a filespec from the parser block.............. 49
; 59. P$FLD Get a text field from block....................... 50
; 60. P$NODE Get a node from block............................. 51
; 61. P$SIXF Get a sixbit field type........................... 52
; 62. P$RNGE Get a range back.................................. 53
; 63. P$TEXT Get a text address and length..................... 54
; 64. P$DEV Get a device address and length................... 55
; 65. P$QSTR Get a quoted string............................... 56
; 66. P$UQSTR Get an unquoted string............................ 57
; 67. P$ACCT Get an account string............................. 58
; 68. P$NPRO No processing required............................ 59
; 69. P$GPDB Get the PDB address if any data................... 60
; 70. P$PNXT Get next PDB given a PDB block.................... 61
; 71. P$PERR Get error routine given a PDB block............... 62
; 72. P$PDEF Get default filler routine given a PDB block...... 63
; 73. P$PACT Get action routine given a PDB block.............. 64
; 74. P$INTR Interrupt support code............................ 65
; 75. SETTIM Setup the timer function.......................... 66
; 76. CLRTIM Clear the timer function.......................... 67
; 77. P$TINT Timer interrupt routine........................... 68
; 78. CNTCHR Count characters in the buffer.................... 69
; 79. REPRMT Do reprompt of command............................ 70
; 80. P$HELP Routine to display help from file................. 71
SUBTTL Revision History
COMMENT \
2 OPRPAR 8-Sept-78 Fix INCORE parsing and Add P.ENDT. Also
Release JFNS in file save routines
3 OPRPAR 12-Sept-78 Add GETTXT AND TXTINP Routines from OPR
4 OPRPAR 15-Sept-78 Have OPRPAR take a pointer for Incore parsing
5 OPRPAR 29-Sept-78 Add P$KEYW ..etc for Analyzing Parsed Blocks
6 OPRPAR 15-Oct-78 Fix PARSER to accept address in PAR.CM
7 OPRPAR 30-Oct-78 Fix .CMDEV Save Routines as well as
add P$DEV to Get Device Data
add P$QSTR to get Quoted String
10 OPRPAR 15-Nov-78 Fix GETTXT Routine to put out correct prompt
11 OPRPAR 15-Nov-78 Add Unquoted String and Accounting Routine to
the Parser.
12 OPRPAR 5-Dec-78 Fix P$NODE on the -10 to accept field as SIXBIT
13 OPRPAR 26-Dec-78 Fix INCORE to accept all Byte Pointers
14 OPRPAR 28-Dec-78 Fix GETTXT bug. Did not put null on end
15 OPRPAR 4-JAN-79 Allow non-dispatch keywords and
change KEYTAB to ORNKEY
change SWITAB To ORNSDP
Add S1 value on action false return to
PRT.EC of return block
16 OPRPAR 8-JAN-79 SETUP CURPDB FOR CURRENT PDB
17 OPRPAR 24-JAN-79 ADD P$COMMA TO CHECK FOR A COMMA
20 OPRPAR 26-JAN-79 ADD P$TIME TO RETURN UDT FOR TIME/DATE
21 OPRPAR 29-JAN-79 CHANGE BUMPPB TO P$NEXT TO BUMP TO NEXT FIELD
22 OPRPAR 6-FEB-79 ADD P$DIR TO GET DIRECTORY INFO
23 OPRPAR 7-FEB-79 CREATE P$NFLD TO RETURN FIELD HEADER IN S1,
ADDRESS OF BLOCK IN S2, AND PB TO NEXT FIELD
24 OPRPAR 9-Feb-79 Correct byte Pointers for SAVTOK and SETPMT.
Check temp table size when moving data
25 OPRPAR 23-Feb-79 Add Timer and Interrupt support into OPRPAR
and define P$INIT,P$INTR, AND P$TINT
26 OPRPAR 5-Mar-79 Add P$STAK to setup JFN for TAKE Command for
Take Commands not using TAKFDB
27 OPRPAR 7-MAR-79 Correct memory bug with ERRSAV
30 OPRPAR 13-MAR-79 Fix Timer Bug
31 OPRPAR 16-MAR-79 Add new ERRPDB support, Call ERROR and DEFAULT
Filling with CMDRET block and move DEFAULT
Filling before call to S%CMND
32 OPRPAR 20-Mar-79 Remove ac M from OPRPAR and Create PARDAT to
Hold address of the page
33 OPRPAR 11-Apr-79 Clear the Timer if set in CLRTIM using TIMSET
as the flag instead of TIMINT
34 OPRPAR 13-Apr-79 Add P$FLOT for Floating Point data
35 OPRPAR 19-Apr-79 Fix Save for Unquoted String to check if null
Input
36 OPRPAR 26-Apr-79 Clear all Take Flags on Take error
37 OPRPAR 26-Apr-79 Clear Reparse flag at VALC.4, used
wrong AC
40 OPRPAR 6-May-79 use F%REL to close Take file on the -20
Reset the buffer pointers in CMDBLK
ON A SUCCESSFUL PARSE.
41 OPRPAR 15-May-79 Reset .CMCNT on good command
42 OPRPAR 25-May-79 Have the ERROR routines continue on if return
true assuming that the caller has updated the
PDB of where to go next
43 OPRPAR 30-May-79 Add a WAIT command that will sleep for a
period of time and/or an interrupt
44 OPRPAR 12-Jun-79 Add P$SETU, P$CURR and P$PREV and eliminate
PB from being used
45 OPRPAR 14-Jun-79 Change the default for Take files to be DSK:
instead of SYS:
46 OPRPAR 21-Jun-79 Strip sequence numbers on TAKE files and
add PRT.CF to the return block for the command
Flag word incase user wishes to see the COMND
Block
47 OPRPAR 24-Jun-79 Add support for new PDB macros which only expand
what is needed
50 OPRPAR 29-Jun-79 Add another word to the calling block for the
ACTION routines which contains the address of
the saved data. The ERROR and PREFILL routines
will also have this value but will contain the
address of the last saved argument or zero
51 OPRPAR 2-Jul-79 Allow line sequence numbers for take files on
the -20 and breakout file open and close for
take files as separate routines
52 OPRPAR 13-Jul-79 Fix Reparse Bug
53 OPRPAR 24-Jul-79 Fix -10 Take Bug.. forgot a $RETT
54 OPRPAR 18-Sept-79 Support a RESCAN on an incore parse if the
incore flag is -1.
55 OPRPAR 19-Sept-79 Change WAITRN on the -10 to use SLEEP UUO
56 OPRPAR 20-Sept-79 Add support for P.CEOF EOF on INCORE parse.
57 OPRPAR 13-Oct-79 Add P$HELP routine
60 OPRPAR 24-Oct-79 Add reparse flag for parser for interrupt
61 OPRPAR 27-Oct-79 Fix GETTXT to work with usersupplied block
entry. Change CLRTIM and SETTIM to use
absolute times instead of clearing all
outstanding interrupts.
62 OPRPAR 28-Oct-79 Add P$TAKE to setup for take command
63 OPRPAR 3-Nov-79 Fix a bug in P$STAK
64 OPRPAR 21-Nov-79 Always return buffer address on return
from parser.
65 OPRPAR 29-Nov-79 Fix a bug in P$HELP
66 OPRPAR 10-Jan-80 Change Rescan routine on TOPS10 to
preserve any typeahead and replace
standard TOPS10 break characters with
a <CRLF>
67 OPRPAR 14-May-80 Merge edits 63-65 which where made
in TOPS20 sources
70 OPRPAR 5-Nov-80 Correct spelling of 'during'
71 OPRPAR 15-Dec-80 Zero out display flag in TAKE command if failed
to open file. This is alright since we do not
allow nested takes.
72 OPRPAR 23-Dec-80 TWOSEG OPRPAR so that MOUNT can load it into the
high segment with the library.
73 6/15/81 Add a cleanup section to P$TAKE so any failure causes all
to be cleaned up and released.
Initialize CMDRET correctly in PARINI
74 9/23/81 @STBD.2 save the suppress def. help mess. flag in the
correct word (TEMFDB+1+.CMFNP).
75 10/26/81 Allow ERREXT to output atom buffer that failed to parse.
76 11/18/81 Fix the help processing. Allow spaces and tabs at the
end of a help specification. Only display the exact field specified.
77 2/26/82 Fix the problem with entered line disappearing when
interrupted for output.
100 6/3/82 Insert fix from PCO OPR-006. OPR and ORION crashes after
an OPR SEND with a long text string. GCO 4.2.1359
101 6/24/82 Clear TIMINT in one and only one place, in the literal
after the SKIPE TIMINT in PARS.2. GCO 4.2.1396
\
SUBTTL Entry points
ENTRY PARSER ;MAIN ENTRY POINT
ENTRY P$GPDB ;GET THE PDB BLOCK
ENTRY P$PNXT ;GET NEXT PDB GIVEN A PDB BLOCK
ENTRY P$PERR ;GET ERROR BLOCK FROM PDB GIVEN A PDB
ENTRY P$PDEF ;GET DEFAULT FILLING ROUTINE GIVEN A PDB
ENTRY P$PACT ;GET ACTION ROUTINE GIVEN A PDB
ENTRY P$NARG ;NEXT ARGUMENT TYPE TO PROCESS
ENTRY P$SETU ;SETUP POINTER TO PARSER BLOCKS
ENTRY P$CURR ;GET THE CURRENT LOCATION
ENTRY P$PREV ;SET THE PREVIOUS TO CURRENT
ENTRY P$FLOT ;FLOATING POINT NUMBER
ENTRY P$TAKE ;SETUP STATE BLOCK FOR TAKE ROUTINE
ENTRY P$INIT ;PARSER INIT
ENTRY P$NPRO ;NO PROCESSING REQUIRED
ENTRY P$INTR ;PARSER INTERRUPTS
ENTRY P$TINT ;TIMER INTERRUPTS
ENTRY P$NFLD ;GET NEXT FIELD DATA
ENTRY P$DIR ;GET THE DIRECTORY FIELD
ENTRY P$NEXT ;GET TO NEXT FIELD
ENTRY P$TIME ;GET DATE/TIME
ENTRY P$COMMA ;COMMA CHECK
ENTRY P$CFM ;CONFIRM CHECK
ENTRY P$KEYW ;KEYWORD CHECK
ENTRY P$SWIT ;SWITCH CHECK
ENTRY P$USER ;USER CHECK
ENTRY P$NUM ;NUMBER CHECK
ENTRY P$FILE ;FILE SPEC CHECK
ENTRY P$IFIL ;INPUT FILE SPEC
ENTRY P$OFIL ;OUTPUT FILE SPEC
ENTRY P$FLD ;FIELD CHECK
ENTRY P$TOK ;TOKEN CHECK
ENTRY P$NODE ;NODE CHECK
ENTRY P$SIXF ;SIXBIT FIELD CHECK
ENTRY P$RNGE ;RANGE OF NUMBERS
ENTRY P$TEXT ;TEXT CHECK
ENTRY P$DEV ;GET A DEVICE STRING
ENTRY P$QSTR ;QUOTED STRING
ENTRY P$UQSTR ;UNQUOTED STRING
ENTRY P$ACCT ;ACCOUNT STRING
;NON-STANDARD ROUTINES
ENTRY P$STAK ;SETUP FOR TAKE
ENTRY PDBCPY ;COPY A PDB
ENTRY TXTINP ;GET TEXT BLOCK FROM TERMINAL
GLOB <TAKFDB,WAIFDB,BADIFI,TEMFDB>
SUBTTL Storage and constants
XLIST ;TURN LISTING OFF
LIT ;DUMP LITERALS
LIST ;TURN LISTING ON
RELOC 0
$DATA CURRPB,1 ;CURRENT PARSER BLOCK ADDRESS
$DATA PREVPB,1 ;PREVIOUS PARSER BLOCK ADDRESS
$DATA PRMFLG,1 ;FLAG FOR "PROCESSING MESSAGES"
$DATA CURPMT,1 ;POINTER TO CURRENT PROMPT
$DATA CURPTR,1 ;POINTER TO START OF LAST FIELD
$DATA CURPDB,1 ;PDB FOR THE DEFAULT FILLER
$DATA TIMSET,1 ;TIMER WAS SET
$DATA TIMINT,1 ;TIMER INTERUPT BREAKOUT
$DATA TIMCHK,1 ;FLAG THAT TIMER CHECKS IN USE
$DATA TIMDAT,2 ;DATA FROM PARSER INIT CALL
$DATA TIMPC,1 ;ADDRESS OF THE PC AT INTERRUPT
$DATA TIMSTI,1 ;TIMER INTERUPT CHARACTER SETUP
$DATA PRMTSZ,1 ;SIZE OF THE PROMPT
$DATA OPRTAK,1 ;DEFAULT DISPLAY FOR ALL TAKES
$DATA TXTDAT,.RDBRK+1 ;TEXTI ARGUMENT BLOCK
$DATA TEMPTR,1 ;TEMPORARY TEXT POINTER
$DATA DSPTAK,1 ;DISPLAY TAKE COMMAND FLAG
$DATA PARBLK,PRT.SZ ;PARSER RETURN BLOCK
$DATA PARINT,1 ;PARSER INITIALIZED FLAG
$DATA CORPAR,1 ;INITIAL SETTING FOR CORE PARSE
$DATA REEPAR,1 ;FLAG SAYS WE WERE CALLED FOR REPARSE
$DATA CMDBLK,.CMGJB+5 ;COMMAND STATE BLOCK FOR COMND JSYS
$DATA BUFFER,BUFSIZ ;INPUT TEXT STORED HERE
$DATA ATMBFR,ATMSIZ ;ATOM BUFFER FOR COMND JSYS
$GDATA GJFBLK,GJFSIZ ;GTJFN BLOCK FOR COMND JSYS
;***MIGHT NEED TO ENLARGE OR MAKE DYNAMIC
$DATA DENTRY,2 ;DELETE ENTRY WORDS(S1 AND S2)
$DATA DFLAGS,1 ;DELETE FLAG FOR TEMP SWITCH TAB
$DATA TEMTAB,TEMTSZ ;SAVE 10 WORDS FOR SWITCH TABLE
$GDATA TEMFDB,PDB.SZ ;TEMP FDB AREA
$DATA CMDERR,^D50 ;SPACE FOR COMMAND ERROR TEXT
$DATA CMDEPT,1 ;COMMAND ERROR MESSAGE POINTER
$DATA CMDECT,1 ;COMMAND ERROR MESSAGE COUNT
$DATA CMDRET,PC.SIZ ;COMMAND RETURN DATA
$DATA ARGSAV,PAR.SZ ;SAVE AREA FOR PARSER ARGUMENTS
$DATA ERRSAV,1 ;MESSAGE ADDRESS ON ERROR
$DATA ERRSTG,1 ;ADDRESS OF ERROR MESSAGE
;STORAGE FOR $TEXT CHARACTER STORER
$DATA STRBP,1 ;SPACE FOR A BYTE POINTER
;STORAGE FOR PARSER TO EVENT PROCESSOR COMMUNICATION
$DATA PARDAT,1 ;ADDRESS OF PARSER DATA MESSAGE
$GDATA ARGFRE,1 ;POINTER TO FIRST FREE WORD IN ARG SPACE
$DATA FLAGS,1 ;PARSER FLAG WORD
$DATA ERRSTK,1 ;ERROR STACK FOR COMMAND
$DATA INTEXT,1 ;INTERRUPT EXIT
;TAKE STORAGE
$DATA CMDIFN,1 ;STORAGE FOR COMMAND FILE IFN
$DATA LOGIFN,1 ;STORAGE FOR LOGGING FILE IFN
$DATA CMDJFN,1 ;STORAGE FOR COMMAND FILE JFN
$DATA LOGJFN,1 ;STORAGE FOR LOGGING FILE JFN
$DATA TAKFLG,1 ;FLAG TO INDICATE WE ARE IN TAKE COMMAND
RELOC
SUBTTL P$INIT Initialize and set timer (TOPS20 only)
;THIS ROUTINE WILL SETUP FOR TIMER INTERRUPTS IF POSSIBLE(20 ONLY)
;AND INIT THE PARSER
;CALL S1/ LEVEL,, TIMER CHANNEL OR OFFSET
; S2/ BASE OF INTERRUPT SYSTEM OR <LEVTAB,,CHNTAB>
P$INIT: SETZM TIMCHK ;CLEAR TIMCHK SETTING
DMOVEM S1,TIMDAT ;SAVE THE VALUES
$CALL PARINI ;INIT THE PARSER
SKIPN TIMDAT+1 ;ANYTHING SPECIFIED?
$RETT ;NO, RETURN
TOPS20 <
MOVX S2,1B0 ;PLACE A BIT IN WORD
HRRZ S1,TIMDAT ;GET THE CHANNEL
MOVN S1,S1 ;MAKE IT NEGATIVE
LSH S2,0(S1) ;POSITION THE CHANNEL NUMBER
MOVEI S1,.FHSLF ;GET MY HANDLE
AIC ;ATTACH TO INTERRUPT SYSTEM
HRRZ S2,TIMDAT+1 ;GET CHANNEL TABLE ADDRESS
HRRZ TF,TIMDAT ;GET THE CHANNEL
ADD S2,TF ;GET CHANNEL TABEL LOCATION
HLLZ S1,TIMDAT ;GET LEVEL VALUE
HRRI S1,P$TINT ;TIMER INTERRUPT LOCATION
MOVEM S1,(S2) ;SAVE IN CHANNEL TABLE
SETOM TIMCHK ;SET TIME CHECK IN EFFECT
HLRZ S1,TIMDAT+1 ;GET LEVTAB ADDRESS
HLRZ S2,TIMDAT ;GET LEVTAB LEVEL
ADDI S1,-1(S2) ;GET LEVTAB ADDRESS
MOVE S2,(S1) ;GET ADDRESS OF PC
MOVEM S2,TIMPC ;SAVE THE PC ADDRESS WORD
> ;End TOPS20
TOPS10 <
MOVE S1,TIMDAT+1 ;ADDRESS OF VECTOR
ADDI S1,.PSVOP ;PC ADDRESS WORD
MOVEM S1,TIMPC ;SAVE ADDRES WORD
> ;End TOPS10
$RETT ;RETURN
SUBTTL PARINI Initialize the database
;THIS ROUTINE IS CALLED TO SET UP THE PARSER DATA BASE FOR
;USE IN SUBSEQUENT CALLS TO THE PARSER ENTRY PARRTN
PARINI: SETOM PARINT ;REMEMBER PARSER INITIALIZED
HRROI S1,[ASCIZ /PARSER>/] ;GET POINTER TO PROMPT STRING
MOVEM S1,CMDBLK+.CMRTY ;PUT RE-TYPE PROMPT POINTER IN STATE BLOCK
HRROI S1,BUFFER ;GET POINTER TO INPUT TEXT BUFFER
MOVEM S1,CMDBLK+.CMPTR ;SAVE POINTER TO COMMAND STRING
MOVEM S1,CMDBLK+.CMBFP ;SAVE POINTER TO START-OF-BUFFER
MOVEI S1,.PRIIN ;SET PRIMARY INPUT
MOVEM S1,CMDJFN
MOVEI S1,.PRIOU ;SET PRIMARY OUTPUT
MOVEM S1,LOGJFN
MOVEI S1,REPARS ;GET RE-PARSE ADDRESS
MOVEM S1,CMDBLK+.CMFLG ;SAVE RE-PARSE ADDRESS
SETZM CMDBLK+.CMINC ;INITIALIZE # OF CHARACTERS AFTER POINTER
MOVEI S1,BUFSIZ*NCHPW ;GET # OF CHARACTERS IN BUFFER AREA
MOVEM S1,CMDBLK+.CMCNT ;SAVE INITIAL # OF FREE CHARACTER POSITIONS
HRROI S1,ATMBFR ;GET POINTER TO ATOM BUFFER
MOVEM S1,CMDBLK+.CMABP ;SAVE POINTER TO LAST ATOM INPUT
MOVEI S1,ATMSIZ*NCHPW ;GET # OF CHARACTERS IN ATOM BUFFER
MOVEM S1,CMDBLK+.CMABC ;SAVE COUNT OF SPACE LEFT IN ATOM BUFFER
MOVEI S1,GJFBLK ;GET ADDRESS OF GTJFN BLOCK
MOVEM S1,CMDBLK+.CMGJB ;SAVE IN COMMAND STATE BLOCK
SETZM ERRSAV ;CLEAR THE ERROR SAVE MESSAGE PAGE
MOVEI S1,CMDBLK ;GET THE COMMAND STATE BLOCK
MOVEM S1,CMDRET+CR.FLG ;SAVE IN FLAG WORD
SETZM CMDRET+CR.RES ;CLEAR RESULT FIELD
SETZM CMDRET+CR.COD ;CLEAR THE FIELD CODE
MOVE S1,ARGSAV+PAR.TB ;GET THE TABLE ADDRESS
AOS S1 ;POSITION TO THE PDB
MOVEM S1,CMDRET+CR.PDB ;SAVE AS THE CURRENT PDB
$RET ;RETURN
SUBTTL PARSER Main entry to parse a command
;THIS ROUTINE HAS THE FOLLOWING CONVENTIONS
;
;CALL: S1/ SIZE OF THE ARGUMENT BLOCK
; S2/ ADDRESS OF THE ARGUMENT BLOCK
;
;RETURN TRUE: S1/LENGTH OF ARGUMENT BLOCK
; S2/ ADDRESS OF THE BLOCK
;
;RETURN FALSE: S1/LENGTH OF RETURN BLOCK
; S2/ ADDRESS OF RETURN BLOCK
PARSER: $CALL .SAVET ;Save the temporaries
CAIE S1,0
CAILE S1,PAR.SZ ;WITHIN PROPER BOUNDS
JRST [MOVEI S2,[ASCIZ/Invalid parser block size/]
PJRST ERREXT] ;SETUP RETURN BLOCK
SETOM REEPAR ;ASSUME REPARSE
JUMPL S1,PARS.2 ;ARE WE?
SETZM REEPAR ;NO, CLEAR THE FLAG
HRLZ S2,S2 ;SOURCE OF THE ARGUMENTS LH
HRRI S2,ARGSAV ;DESTINATION
BLT S2,ARGSAV-1(S1) ;MOVE THE DATA
PARS.1: CAIE S1,PAR.SZ ;DONE ALL ARGUMENTS?
JRST [SETZM ARGSAV(S1) ;NO, CLEAR THE FIELD
AOJA S1,PARS.1] ;CHECK FOR ALL
PARS.2: SKIPN PARINT ;INITIALIZED?
$CALL PARINI ;NO, THEN DO IT
$CALL INCORE ;CHECK IF INCORE PROCESSING
$CALL CMDMES ;SET UP COMMAND MESSAGE BLOCK
SKIPN S1,ARGSAV+PAR.PM ;PROMPT PROVIDED?
MOVEI S1,[ASCIZ/PARSER>/] ;NO USE THE DEFAULT
$CALL SETPMT ;SET THE PROMPT
MOVE S2,ARGSAV+PAR.TB ;ADDRESS OF THE TABLES
AOS S2 ;POSITION TO THE FDB
MOVEM S2,CMDRET+CR.PDB ;SAVE AS THE CURRENT PDB
SKIPN REEPAR ;DOING REPARSE
SKIPE CORPAR ; OR CORE PARSE BEING DONE?
PJRST REPARSE ;YES, TREAT IT AS A REPARSE
SKIPE TIMINT ;WAS THERE A TIMER INTERRUPT
JRST [SETZM TIMINT ;Yes, clear the timer interrupt flag
LOAD T1,.CMFNP(S2),CM%FNC ;GET THE FUNCTION CODE
CAIN T1,.CMINI ;NOT .CMINI SKIP REPROMPT
$CALL REPRMT ;REPROMPT
JRST REPARSE] ;AND REPARSE
PJRST PARCMD ;PARSE THE COMMAND
SUBTTL PARCMD Do the command parse
;THIS ROUTINE WILL DO ANY DEFAULT FILLING AND THEN CALL
;S%CMND TO PARSE THE COMMAND
PARCMD: $CALL FILDEF ;FILL IN ANY DEFAULTS IF NEEDED
JUMPF ERREXT ;ERROR..RETURN
SKIPE DFLAGS ;ANY ENTRY TO DELETE
$CALL STBDEL ;DELETE THE ENTRY
LOAD S2,CMDRET+CR.PDB,RHMASK ;GET THE CURRENT PDB
MOVE S1,CMDBLK+.CMPTR ;GET CURRENT BUFFER POINTER
MOVEM S1,CURPTR ;SAVE CURRENT POINTER
MOVEI S1,CMDBLK ;ADDRESS OF THE COMMAND BLOCK
$CALL S%CMND ;CALL COMND TO PARSE COMMAND
MOVE T1,CR.FLG(S2) ;GET THE RETURNED FLAGS
MOVEM T1,PARBLK+PRT.CF ;SAVE THE COMMAND FLAGS
JUMPF PARERR ;PARSER ERROR ROUTINE
HRLZ T2,S2 ;SOURCE IN LEFT HALF
HRRI T2,CMDRET ;SOMMAND RETURN BLOCK
BLT T2,CMDRET-1(S1) ;SAVE THE DATA
TXNE T1,CM%INT ;INTERRUPT OCCUR
JRST ERRINT ;ERROR INTERRUPT RETURN
TXNN T1,CM%NOP ;VALID COMMAND ENTERED
JRST VALCMD ;YES, CHECK IT OUT
PARC.1: LOAD S1,CR.PDB(S2),LHMASK ;GET STARTING PDB
$CALL P$PERR ;GET THE ERROR PDB
JUMPF PARERR ;NONE..ERROR..
MOVE T1,S1 ;SAVE THE ERROR BLOCK
TLZE T1,400000 ;PARSER ERROR PDB?
JRST [STORE T1,CMDRET+CR.PDB,RHMASK ;SAVE AS NEXT PDB
JRST PARCMD] ;ANY RETRY THE PARSE
MOVEI S1,PC.SIZ ;GET THE ARGUMENT BLOCK
MOVEI S2,CMDRET ;GET BLOCK ADDRESS
$CALL (T1) ;USE THE ERROR ROUTINE
JUMPT PARCMD ;GOOD RETURN .. PARSE THE COMMAND
SKIPE S2 ;IF S2 HAS ERROR SET..SKIP
PJRST ERREXT ;ERROR CODE..GO TO EXIT
$CALL S%ERR ;SET UP THE ERROR RETURN
MOVE S2,S1 ;ADDRESS OF MESSAGE IN S2
PJRST ERREXT ;PARSER ERROR RETURN
SUBTTL VALCMD Process a valid command field
;THIS ROUTINE WILL GET CONTROL ON A SUCCESSFUL PARSE FROM COMMAND
VALCMD: SKIPL T1,CMDRET+CR.COD ;GET THE PARSED FIELD CODE
CAILE T1,.CMNOD ;WITHIN RANGE OF VALID FUNCTIONS
$STOP(IFC,INVALID FUNCTION CODE FROM COMMAND)
MOVE S1,ARGFRE ;ADDRESS OF NEXT PLACE TO SAVE
MOVEM S1,CMDRET+CR.SAV ;SAVE THE ELEMENT
MOVX S1,PC.SIZ ;SIZE OF THE BLOCK
MOVEI S2,CMDRET ;COMMAND RETURN BLOCK
$CALL @PARTAB(T1) ;SAVE THE DATA FROM COMMAND
LOAD S1,CMDRET+CR.PDB,RHMASK ;GET THE USED PDB BYE COMMAND
$CALL P$PACT ;ANY ACTION ROUTINE
JUMPF VALC.1 ;NO, CONTINUE ON
MOVE T2,S1 ;SAVE ROUTINE IN T2
MOVX S1,PC.SIZ ;SIZE OF THE BLOCK
MOVEI S2,CMDRET ;COMMAND RETURN BLOCK
$CALL (T2) ;PROCESS THE ROUTINE
JUMPF VALC.3 ;BAD RETURN..SET UP ERROR
VALC.1: MOVE T1,CMDRET+CR.COD ;GET THE CODE FIELD
MOVE T2,CMDRET+CR.RES ;DATA FROM COMMAND PARSE
LOAD S1,CMDRET+CR.PDB,RHMASK ;GET THE USED PDB FROM PARSE
$CALL P$PNXT ;IS THERE A NEXT FIELD?
JUMPT VALC.2 ;GO USE IT
CAXE T1,.CMKEY ;YES, WAS IT A KEYWORD?
CAXN T1,.CMSWI ;OR A SWITCH?
SKIPA ;YES,
JRST PARRET ;NO NEXT..RETURN
HRRZ S1,(T2) ;<R15>YES, GET NEXT PDB FROM DSPTAB
MOVE S1,(S1) ;<R15>NOT FROM PDB
HRRZS S1 ;PASS ONLY THE RIGHT HALF
JUMPE S1,PARRET ;NONE..RETURN WITH MESSAGE
VALC.2: AOS S1 ;BUMP TO FDB OVER THE HEADER
STORE S1,CMDRET+CR.PDB,RHMASK ;SAVE THE NEXT BLOCK
JRST PARCMD ;GO FINISH THE COMMAND
VALC.3: MOVX T2,P.REPA ;REPARSE FLAG SET
TDNE T2,FLAGS ;WAS IT SET??
JRST VALC.4 ;YES, SETUP FOR REPARSE
SKIPN S2 ;IF S2 HAS ERROR SET..SKIP
MOVEI S2,[ASCIZ/Action routine error aborted command/]
MOVX T2,P.ACTE ;ACTION ROUTINE ERROR
IORM T2,FLAGS ;SAVE IN THE FLAGS
MOVEM S1,PARBLK+PRT.EC ;SAVE ANY CODE FOR CALLER
PJRST ERREXT ;ERROR RETURN
VALC.4: ANDCAM T2,FLAGS ;CLEAR REPARSE FLAG
JRST REPARS ;FORCE THE REPARSE
SUBTTL PARRET Setup arguments and return
PARRET: MOVE S1,ARGFRE ;LAST FREE LOCATION
ANDI S1,777 ;MAKE AN OFFSET
MOVE T3,PARDAT ;GET ADDRESS OF PARSER DATA MESSAGE
SKIPE COM.CM(T3) ;ALREADY SETUP TEXT
JRST PARR.2 ;YES, DO NOT MOVE TEXT
MOVEM S1,COM.CM(T3) ;POINTER FOR MESSAGE TEXT
HRLI T1,(POINT 7,0) ;SOURCE BYTE POINTER
HRRI T1,BUFFER ;SOURCE TEXT OF COMMAND
HRRZ T2,ARGFRE ;DESTINATION POINTER
AOS T2 ;LEAVE ROOM FOR HEADER
HRLI T2,(POINT 7,0) ;DESTINATION BYTE POINTER
PARR.0: ILDB S1,T1 ;GET A BYTE
PARR.1: IDPB S1,T2 ;SAVE A BYTE
JUMPN S1,PARR.0 ;NON-ZERO..KEEP CHECKING
HRRZI S1,1(T2) ;GET NEXT LOCATION AND CLEAR LH
ANDI S1,777 ;MAKE INTO LENGTH (OFFSET)
PARR.2: STORE S1,.MSTYP(T3),MS.CNT ;SAVE NEW LENGTH
MOVE S2,ARGFRE ;GET START OF TEXT ADDRESS
ANDI S2,777 ;USE AS LENGTH
SUBI S1,(S2) ;GET LENGTH OF BLOCK
STORE S1,@ARGFRE,AR.LEN ;SAVE ARGUMENT LENGTH
MOVX S1,P.NPRO ;NO PROCESSING REQUIRED
TDNN S1,FLAGS ;WAS IT SET
JRST PARR.3 ;NO, SEND TO ORION TO PROCESS
MOVX S1,CM.NPR ;NO PROCESSING REQUIRED
IORM S1,.OFLAG(T3) ;SAVE IN THE MESSAGE FLAGS
PARR.3: MOVX S1,COM.AL ;GET ARGUMENT LENGTH
MOVEM S1,.OARGC(T3) ;SAVE IN MESSAGE
SETZ S1, ;CLEAR S1
EXCH S1,FLAGS ;GET THE CURRENT FLAGS AND RESET
SKIPE DSPTAK ;DISPLAY TAKE COMMANDS
TXO S1,P.DSPT ;SET DISPLAY TAKE FLAG
MOVEM S1,PARBLK+PRT.FL ;SAVE THE FLAGS
MOVEM T3,PARBLK+PRT.CM ;SAVE THE COMMAND MESSAGE
MOVX S1,CM%INT ;GET COMMAND FLAG
ANDCAM S1,CMDBLK+.CMFLG ;CLEAR FLAG ON GOOD RETURN
$CALL CLRTIM ;CLEAR THE TIMER
HRROI S1,BUFFER ;RESET COMMAND POINTER TO STRING
MOVEM S1,CMDBLK+.CMPTR ;SAVE POINTER TO COMMAND STRING
MOVEI S1,BUFSIZ*NCHPW ;GET # OF CHARACTERS IN BUFFER AREA
MOVEM S1,CMDBLK+.CMCNT ;SAVE IN COMMAND BLOCK
MOVEI S1,BUFFER ;RETURN ADDRESS OF BUFFER
MOVEM S1,PARBLK+PRT.MS
MOVEI S1,PRT.SM ;SMALL SIZE MESSAGE
MOVEI S2,PARBLK ;PARSER RETURN BLOCK
$RETT ;RETURN
SUBTTL PARERR COMND JSYS error routine
; IF END OF FILE REACHED ON A TAKE FILE, THE NEXT COMMAND
; IS SIMPLY PROCESSED. ELSE AN ERROR MESSAGE IS ISSUED AND
; THE PROGRAM IS RESTARTED.
;
;CALL: JRST PARERR
PARERR: SKIPE CORPAR ;DOING A CORE PARSE?
JRST PARE.6 ;YES?
SKIPN TAKFLG ;PROCESSING A TAKE FILE ?
JRST PARE.1 ;NO, GET THE ERROR
$CALL CHKEOF ;CHECK FOR END OF FILE
JUMPF PARE.1 ;NO, PROCESS THE ERROR
$CALL CLSTAK ;CLOSE THE TAKE FILE
JUMPT PARE.3 ;CLEANUP AND RETURN
JRST PARE.4 ;ERROR CLOSING TAKE FILE
PARE.1: $CALL S%ERR ;DO ANY ERROR TYPEOUT
MOVE S2,S1 ;ADDRESS OF MESSAGE IN S2
PJRST ERREXT ;ERROR RETURN
PARE.3: $CALL TAKCLR ;CLEAR THE TAKE INDICATORS
JRST PARE.5 ;GIVE END OF TAKE ERROR..
PARE.4: $CALL TAKCLR ;CLEAR THE TAKE INDICATORS
MOVEI S2,[ASCIZ/Error closing TAKE command file/]
PJRST ERREXT ;ERROR RETURN
PARE.5: MOVX S1,P.ENDT ;END OF THE TAKE FILE
IORM S1,FLAGS ;TURN ON THIS FLAG
SETOM INTEXT ;MARK AS INTERRUPT EXIT
MOVEI S2,[ASCIZ/End of file during TAKE command/]
PJRST ERREXT ;DO ERROR PROCESSING AND RETURN FALSE
PARE.6: TXNE T1,CM%NOP ;VALID COMMAND ENTERED
JRST PARE.1 ;NO, GENERATE THE ERROR
MOVX S1,P.CEOF ;CORE PARSE END OF FILE
IORM S1,FLAGS ;SET THE FLAGS
MOVEI S2,[ASCIZ/End of string during incore parse/]
SETOM INTEXT ;MARK AS INTERRUPT EXIT
PJRST ERREXT ;EXIT
SUBTTL CHKEOF Check for end of take file
;CHECK IF END OF FILE ON TAKE FILE
TOPS20 <
CHKEOF: HLRZ S1,CMDBLK+.CMIOJ ;GET INPUT FILE JFN FOR TAKE FILE
GTSTS ;GET THE FILE'S STATUS
TXNN S2,GS%EOF ;AT END OF FILE ?
$RETF ;RETURN FALSE
$RETT ;RETURN TRUE
> ;End TOPS20
TOPS10 <
CHKEOF: CAXE S1,EREOF$ ;END OF FILE ERROR??
$RETF ;NO, LOSE
$RETT ;YES,
> ;End TOPS10
SUBTTL CLSTAK Close the take file
SUBTTL TAKCLR Cleanup after take file
CLSTAK: MOVE S1,CMDIFN ;GET IFN FOR THE TAKE FILE
$CALL F%REL ;RELEASE THE FILE
$RETIF ;Return the error on failure
MOVE S1,LOGIFN ;Release the logging file
CAIE S1,.NULIO
$CALL F%REL
$RETIF ;Return the error on failure
$RETT
TAKCLR: MOVEI S1,.PRIIN ;Set primary input
MOVEM S1,CMDJFN
MOVEI S1,.PRIOU ;Set primary output
MOVEM S1,LOGJFN
SETZM DSPTAK ;CLEAR DISPLAY TAKE FLAG
SETZM TAKFLG ;MARK THAT TAKE FILE NOT BEING PROCESSED
MOVX S1,P.CTAK ;CLEAR IN TAKE FILE
ANDCAM S1,FLAGS ;CLEAR THE FLAG VALUE
$RET ;RETURN
SUBTTL ERREXT Error return from parser
ERRINT: MOVX S1,CM%INT ;GET INTERRUPT FLAG
ANDCAM S1,CMDBLK+.CMFLG ;CLEAR THE FLAG VALUE
TXNE T1,CM%NOP ;ALSO HAVE NO PARSE LIT?
JRST PARC.1 ;YES, TREAT AS NO PARSE
MOVX S1,P.INTE ;INTERRUPT EXIT
IORM S1,FLAGS ;SAVE IN FLAG WORD
SETOM INTEXT ;INTERRUPT EXIT
MOVEI S2,[ASCIZ/Interrupt during command parse/]
ERREXT: MOVEM S2,ERRSTG ;SAVE THE STRING ADDRESS
$CALL CLRTIM ;CLEAR THE TIMER
MOVE T3,PARDAT ;GET PAGE ADDRESS
SKIPE ARGSAV+PAR.CM ;COMMAND MESSAGE PROVIDED
JRST ERRE.3 ;YES, JUST SET S1 WITH FLAGS
SKIPE S1,ERRSAV ;IS THERE A PAGE ALREADY
JRST ERRE.1 ;ALREADY SET..FREE THE PAGE
MOVEM T3,ERRSAV ;SAVE PAGE ADDRESS
JRST ERRE.2 ;CONTINUE ON
ERRE.1: $CALL M%RPAG ;RELEASE THE PAGE
MOVEM T3,ERRSAV ;SAVE ADDRESS OF PAGE TO REUSE
ERRE.2: SKIPE INTEXT ;INTERRUPT EXIT PROCESSING
JRST ERRE.4 ;YES, SKIP MESSAGE SETUP
ERRE.3: MOVSI T1,(POINT 7,0) ;SETUP BYTE POINTER
HRRI T1,CMDERR ;BUFFER FOR DATA
MOVEM T1,CMDEPT ;SAVE THE POINTER
MOVEI T1,^D50*5 ;SIZE OF BUFFER
MOVEM T1,CMDECT ;SAVE THE COUNT
$TEXT (ERRRTN,<^T/@ERRSTG/: "^T/ATMBFR/"^0>)
MOVEI S2,CMDERR ;SETUP ERROR POINTER
ERRE.4: SETZ S1, ;CLEAR FLAG WORD
EXCH S1,FLAGS ;GET THE CURRENT FLAGS AND RESET
TXO S1,P.ERRO ;ERROR FLAG SET
MOVEM S1,PARBLK+PRT.FL ;SAVE THE FLAGS
MOVEM S2,PARBLK+PRT.EM ;SAVE THE ERROR MESSAGE
MOVEM T3,PARBLK+PRT.CM ;SAVE COMMAND MESSAGE..AS IS
MOVEI S1,BUFFER ;ADDRESS OF COMMAND TEXT
MOVEM S1,PARBLK+PRT.MS ;SAVE THE MESSAGE
MOVEI S1,PRT.SZ ;SIZE OF THE BLOCK
MOVEI S2,PARBLK ;ADDRESS OF THE BLOCK
SETZM INTEXT ;CLEAR INTERRUPT EXIT FLAG
$RETF ;RETURN FALSE
ERRRTN: SOSGE CMDECT ;DECREMENT COUNT
$RETF ;TOO MUCH TRUNCATE BUFFER
IDPB S1,CMDEPT ;SAVE THE BYTE
$RETT ;RETURN TRUE
SUBTTL INCORE Check and setup for incore processing
;THIS ROUTINE WILL VALIDATE THE INCORE ARGUMENT AND MAKE THE
;NECESSARY CHANGES TO PROCESS A COMMAND IN CORE
INCORE: SETZM CORPAR ;RESET CORE PARSE FLAG
SKIPN TAKFLG ;PROCESSING A TAKE COMMAND
SKIPN S1,ARGSAV+PAR.SR ;IS THERE A SOURCE POINTER
JRST INCO.4 ;NO, DO NORMAL PROCESSING
MOVE T1,[.NULIO,,.NULIO] ;SET UP NULL I/O FOR COMND
STORE T1,CMDBLK+.CMIOJ ;SAVE IN THE COMMAND STATE BLOCK
HRLI T2,(POINT 7,0) ;SETUP DESTINATION POINTER
HRRI T2,BUFFER ;GET BUFFER ADDRESS
SETZM T3 ;CLEAR A COUNT
CAMN S1,[-1] ;CHECK FOR RESCAN ON INCORE PARSE
JRST INCO.7 ;YES, DO RESCAN
$CALL MAKPTR ;MAKE THE POINTER FROM S1 AND PUT IN S2
INCO.1: ILDB T4,S2 ;GET A BYTE
JUMPE T4,INCO.2 ;NULL..END OF DATA
IDPB T4,T2 ;SAVE THE BYTE
AOJA T3,INCO.1 ;BUMP THE COUNT
INCO.2: IDPB T4,T2 ;SAVE THE NULL
INCO.3: MOVEM T3,CORPAR ;SAVE BYTE COUNT
MOVEM T3,CMDBLK+.CMINC ;SAVE THE CHARACTER COUNTS
HRROI S1,BUFFER ;GET BUFFER POINTER
MOVEM S1,CMDBLK+.CMPTR ;SAVE POINTER TO COMMAND STRING
MOVEM S1,CMDBLK+.CMBFP ;SAVE POINTER TO START-OF-BUFFER
$RET ;RETURN
INCO.4: MOVX T1,P.CTAK ;COMMAND FROM TAKE FILE
SKIPE TAKFLG ;DOING A TAKE?
IORM T1,FLAGS ;YES, TURN IT ON IN FLAGS
HRLZ T1,CMDJFN ;Get input JFN
HRR T1,LOGJFN ;Get output JFN
INCO.5: STORE T1,CMDBLK+.CMIOJ ;Save for COMND
SKIPE TIMINT ;WAS THERE A TIMER INTERRUPT
$RET ;YES, LEAVE STATE ALONE
SETZM CMDBLK+.CMINC ;CLEAR COUNT OF CHAR IN BUFFER
HRROI S1,BUFFER ;GET POINTER TO INPUT TEXT BUFFER
MOVEM S1,CMDBLK+.CMBFP ;SAVE POINTER TO START-OF-BUFFER
$RET ;RETURN
INCO.7: $CALL RESCN ;DO THE RESCAN
MOVE T3,S1 ;GET THE COUNT
JRST INCO.3 ;FINISH OFF THE INCORE FLAGS
SUBTTL CMDMES Check and/or setup the command message
;THIS ROUTINE WILL VALIDATE THE COMMAND MESSAGE ARGUMENT FIELD
;IF PRESENT. IF NOT, IT WILL CREATE A PAGE AND SETUP THE MESSAGE
CMDMES: SKIPN T3,ARGSAV+PAR.CM ;ANY COMMAND MESSAGE SUPPLIED?
JRST CMDM.1 ;NO, SETUP THE PAGE
MOVEM T3,PARDAT ;SAVE ADDRESS OF PARSER DATA
LOAD T1,.MSTYP(T3),MS.CNT ;GET THE LENGTH
AOS T1 ;BUMP IT BY 1
MOVEM T1,COM.PB(T3) ;SAVE IN THE MESSAGE
ADDI T1,(T3) ;MAKE AN ADDRESS
MOVEM T1,ARGFRE ;SAVE AS POINTER TO FREE AREA
$RET ;RETURN
CMDM.1: SKIPE T3,ERRSAV ;NO SAVED MESSAGE
JRST CMDM.3 ;USE SAVED PAGE
DMOVE T1,S1 ;SAVE THE ARGUMENT BLOCK
$CALL M%GPAG ;GET A PAGE FOR COMMAND
MOVEM S1,PARDAT ;SAVE THE PAGE ADDRESS
CMDM.2: MOVEI T1,COM.SZ ;SIZE OF THE COMMAND HEADER
MOVEM T1,COM.PB(S1) ;SAVE AS PARSER BLOCK POINTER
ADDI T1,(S1) ;CONVERT TO FULL ADDRESS
MOVEM T1,ARGFRE ;SAVE AS START OF ARGUMENT AREA
MOVX T1,.OMCMD ;GET THE COMMAND MESSAGE TYPE
STORE T1,.MSTYP(S1),MS.TYP ;SAVE TYPE IN MESSAGE
$RET ;RETURN
CMDM.3: MOVEM T3,PARDAT ;SAVE THE PAGE ADDRESS
SETZM ERRSAV ;CLEAR THE SAVED ADDRESS HOLDER
$RET ;RETURN..***MIGHT NEED TO CLEAR
;BY CALLING .ZPAGE
SUBTTL SETPMT Setup the prompt pointer
;THIS ROUTINE WILL SET UP THE PROPER PPROMPT STRING FOR COMND.
;THE DEFAULT STRING IS PARSER> ELSE THE
;POINTER GIVEN IN THE PARSER CALL WILL BE USED.
SETPMT: $CALL MAKPTR ;MAKE A POINTER FROM S1 AND RETURN IN S2
MOVEM S2,CMDBLK+.CMRTY ;SAVE THE PROMPT FOR COMMAND
MOVEM S2,CURPMT ;SAVE THE CURRENT PROMPT
SETZ T1, ;CLEAR S2
SETP.1: ILDB S1,S2 ;GET A BYTE
SKIPE S1 ;WAS IT NULL?
AOJA T1,SETP.1 ;NO, COUNT IT
MOVEM T1,PRMTSZ ;SAVE PROMPT SIZE
$RETT ;RETURN TRUE
;THIS ROUTINE WILL MAKE A BYTE POINTER FROM ARGUMENT IN S1
;AND RETURN POINTER IN S2
MAKPTR: HLLZ S2,S1 ;GET THE LEFT HALF AND CHECK FOR POINTER
TLCE S2,-1 ;LEFT HALF = 0
TLCN S2,-1 ; OR -1
HRLI S2,(POINT 7,0) ;YES, SETUP A BYTE POINTER
HRR S2,S1 ;GET THE REST OF THE DATA
$RET ;RETURN
SUBTTL RESCN Rescan routine to setup initial command
;This routine will read the characters from the previous command
;line and place them in the command buffer for reparsing.
;
;For TOPS10 the buffer will always be terminated by a <CRLF>
;regardless of the actual break character used to terminate
;the line at command level.
;RETURN S1/ COUNT OF CHARACTERS
TOPS20 <
RESCN: MOVEI S1,.RSINI ;Make characters available
RSCAN
ERJMP [$FATAL <Rescan JSYS failed, ^E/[-2]/>]
MOVEI S1,.RSCNT ;Get the number of characters available
RSCAN
ERJMP [$FATAL <Rescan JSYS failed, ^E/[-2]/>]
MOVE T1,S1 ;Put count in T1
MOVE T3,T1 ;ALSO SAVE IT IN T3
RESCN1: SOJL T1,RESCN2 ;Exit when count exhausted
$CALL K%BIN ;Read a byte
IDPB S1,T2 ;Store in rescan buffer
JRST RESCN1 ;Back to get the rest
> ;End TOPS20 conditional
TOPS10 <
;Line break set definition for TOPS10
;<ESC><^Z><DC1-DC4><DLE><FF><VT> and <LF>
LINBRK==^B00001100000111110001110000000000
RESCN: MOVEI T3,1 ;Initialize count
RESCAN 1 ;Anything to be had?
JRST RESCN1 ;Yes..get it
JRST RESCN2 ;No..just return
RESCN1: $CALL K%BIN ;YES, get it
IDPB S1,T2 ;Store it
CAIL S1,.CHLFD ;Possible break character?
CAILE S1,.CHESC
AOJA T3,RESCN1 ;No..get next character
MOVEI S2,1 ;Get a bit to use for test
LSH S2,0(S1)
TXNN S2,LINBRK ;Is it a break character?
AOJA T3,RESCN1 ;No..get next character
CAIN S1,.CHLFD ;Yes..was it line feed?
JRST RESCN2 ;Yes..terminate the buffer
MOVEI S1,.CHCRT ;No..replace it with <CRLF>
DPB S1,T2
MOVEI S1,.CHLFD
IDPB S1,T2
AOJA T3,RESCN2 ;Bump count for extra character
> ;End TOPS10 conditional
RESCN2: SETZ S1, ;Terminate buffer with a null
IDPB S1,T2
MOVE S1,T3 ;Return count in S1
$RETT
SUBTTL Dispatch for Parser Save Routines
;THE ROUTINES ON THE NEXT FEW PAGES SAVE THE OUTPUT OF THE PARSER IN
;A FORM USABLE BY THE EVENT PROCESSOR. THE ACTUAL DATA STRUCTURE IS
;DOCUMENTED IN PARSER.RNO
;THIS IS THE DISPATCH TABLE FOR THE VARIOUS SAVE ROUTINES, ONE FOR
;EACH TYPE OF FIELD THE COMND JSYS CAN PARSE. THESE ROUTINES ARE CALLED
;ON EACH SUCCESSFUL RETURN FROM THE COMND JSYS
;ALL ROUTINES ARE CALLED WITH
; S1/ LENGTH OF BLOCK
; S2/ ADDRESS OF COMND INFO
PARTAB: SAVKEY ;KEYWORD (.CMKEY)
SAVNUM ;NUMBER (.CMNUM)
.POPJ ;NOISE WORD (.CMNOI) (NO PROCESSING)
SAVSWI ;SWITCH (.CMSWI)
SAVFIL ;INPUT FILE SPEC (.CMIFI)
SAVOFI ;OUTPUT FILE SPEC (.CMOFI)
SAVFIL ;GENERAL FILE SPEC (.CMFIL)
SAVATM ;ARBITRARY FIELD (.CMFLD)
SAVZER ;CONFIRM (.CMCFM)
SAVRES ;DIRECTORY (.CMDIR)
SAVRES ;USER NAME (.CMUSR)
SAVZER ;COMMA (.CMCMA)
SAVINI ;INITIALIZATION (.CMINI)
;THIS IS CALLED TO INITIALIZE SAVE STUFF
SAVRES ;FLOATING POINT NUMBER (.CMFLT)
SAVDEV ;DEVICE NAME (.CMDEV)
SAVATM ;TEXT TO CARRAIGE RETURN (.CMTXT)
SAVRES ;DATE AND TIME (.CMTAD)
SAVATM ;QUOTED STRING (.CMQST)
SAVUQS ;UNQUOTED STRING (.CMUQS)
SAVTOK ;TOKEN (.CMTOK)
SAVNUM ;NUMBER (ARBITRARY TERMINATOR) (.CMNUX)
SAVATM ;(.CMACT)
SAVNOD ;NODE NAME (.CMNOD)
SUBTTL SAVKEY/SAVSWI Save a switch or keyword
;THIS ROUTINE WILL SAVE THE SWITCH OR KEYWORD VALUE IN THE
;COMMAND MESSAGE. THE FIRST WORD WILL BE HEADER AND SECOND WORD
;WILL BE THE DATA VALUE
SAVKEY:
SAVSWI: LOAD T1,CR.COD(S2) ;GET THE FUNCTION CODE
STORE T1,@ARGFRE,PF.TYP ;SAVE TYPE IN HEADER
MOVEI T1,PFD.D1+1 ;LENGTH OF FIELD
STORE T1,@ARGFRE,PF.LEN ;SAVE LENGTH IN HEADER
AOS ARGFRE ;BUMP THE POINTER
MOVE T1,CR.RES(S2) ;GET RESULT FROM COMND
LOAD S1,CMDRET+CR.PDB,RHMASK ;GET THE USED PDB FROM PARSE
HRRZ T1,(T1) ;GET RESULT(INDIRECT ADDRESS)
$CALL P$PNXT ;IS THERE A NEXT FIELD?
SKIPT ;YES, USE CURRENT DATA
HLRZ T1,(T1) ;NO,,GET CODE FROM COMND
MOVEM T1,@ARGFRE ;SAVE THE VALUE IN BLOCK
AOS ARGFRE ;BUMP THE POINTER
$RET ;RETURN
SUBTTL SAVFIL Save a filespec
;THIS ROUTINE WILL SAVE A FILESPEC IN THE FORM OF A GALAXY FD
;AS DESCRIBED IN GLXMAC
TOPS20 <
SAVOFI: MOVE T1,[111100,,1] ;OUTPUT ALL UP TO PROTECTION
SKIPA ;OUTPUT THE FILE
SAVFIL: MOVE T1,[111110,,1] ;OUTPUT ALL UP TO PROTECTION
DMOVE T3,S1 ;SAVE THE ARGUMENT BLOCKS
MOVE T2,ARGFRE ;START OF THE BLOCK
HRROI S1,PFD.D1(T2) ;POINTER TO START OF DATA
MOVE S2,CR.RES(S2) ;GET THE JFN
JFNS ;MAKE JFN INTO A STRING
IBP S1 ;STEP PAST NULL AT END OF STRING
HRRZI S2,1(S1) ;POINT S2 AT FIRST FREE ARGUMENT
EXCH S2,ARGFRE ;UPDATE THE POINTER
HRRZS S1 ;MAKE AN ADDRESS ONLY
SUBI S1,-1(S2) ;GET LENGTH OF THE FD
STORE S1,PFD.HD(T2),PF.LEN ;SAVE LENGTH OF ARGUMENT
LOAD S1,CR.COD(T4) ;GET THE COMND TYPE
STORE S1,PFD.HD(T2),PF.TYP ;SAVE THE HEADER WORD
MOVE S1,[GJFBLK,,GJFBLK+1] ;SET UP TO CLEAR GTJFN BLOCK
SETZM GJFBLK ;CLEAR FIRST WORD
BLT S1,GJFBLK+GJFSIZ-1 ;CLEAR THE BLOCK
MOVE S1,CR.RES(T4) ;GET THE JFN
RLJFN ;RELEASE THE JFN
JRST [MOVEI S2,[ASCIZ/Error releasing command file JFN/]
$RETF] ;RETURN FALSE
$RET ;RETURN
> ;End TOPS20
TOPS10 <
SAVOFI:
SAVFIL: MOVE T1,ARGFRE ;WHERE TO COPY TO
HRL T1,CR.RES(S2) ;WHERE TO COPY FROM
MOVE T4,CR.RES(S2) ;GET THE RESULT
LOAD T2,.FDLEN(T4),FD.LEN ;GET THE LENGTH OF FD
STORE T2,@ARGFRE,PF.LEN ;SAVE LENGTH OF BLOCK
ADDI T2,-1(T1) ;GET THE ENDING ADDRESS OF FD
BLT T1,(T2) ;MOVE THE FD
LOAD T4,CR.COD(S2) ;GET THE CODE OF FUNCTION
STORE T4,@ARGFRE,PF.TYP ;SAVE CODE AND LENGTH
MOVEI T3,1(T2) ;COMPUTE NEXT FREE LOCATION
EXCH T3,ARGFRE ;UPDATE IT
MOVE S1,[GJFBLK,,GJFBLK+1] ;SET UP TO CLEAR GTJFN BLOCK
SETZM GJFBLK ;CLEAR FIRST WORD
BLT S1,GJFBLK+GJFSIZ-1 ;CLEAR THE BLOCK
$RET ;RETURN
> ;End TOPS10
SUBTTL SAVNUM Save a number
;THIS ROUTINE WILL SAVE A NUMBER BLOCK WITH THE NUMBER
;IN THE FIRST DATA WORD AND THE RADIX IN THE SECOND
SAVNUM: LOAD T2,CR.COD(S2) ;GET THE COMND TYPE
STORE T2,@ARGFRE,PF.TYP ;SAVE THE FUNCTION CODE
MOVEI T2,PFD.SZ ;SIZE OF THE BLOCK
STORE T2,@ARGFRE,PF.LEN ;SAVE THE HEADER
AOS ARGFRE ;BUMP TO NEXT LOCATION
MOVE T2,CR.RES(S2) ;GET THE DATA FIELD
STORE T2,@ARGFRE ;SAVE THE NUMBER IN BLOCK
AOS ARGFRE ;BUMP TO NEXT LOCATION
LOAD T2,CR.PDB(S2),RHMASK ;LAST PDB USED BY COMMAND
LOAD T2,.CMDAT(T2) ;GET THE RADIX
STORE T2,@ARGFRE ;SAVE THE RADIX
AOS ARGFRE ;BUMP TO NEXT LOCATION
$RET ;RETURN
SUBTTL SAVZER Save a COMMA or CONFRM
;THIS ROUTINE WILL SAVE THE FUNCTION VALUE AND A LENGTH OF 1
SAVZER: LOAD T1,CR.COD(S2) ;GET THE FUNCTION CODE
STORE T1,@ARGFRE,PF.TYP ;SAVE THE TYPE CODE
MOVEI T1,PFD.D1 ;SIZE OF THE BLOCK
STORE T1,@ARGFRE,PF.LEN ;SAVE THE VALUE
AOS ARGFRE ;BUMP TO NEXT LOCATION
$RET ;RETURN
SUBTTL SAVUQS Save an unquoted string
;THIS ROUTINE WILL BUILD BLOCK WITH TEXT FROM UNQUOTED STRING FUNCTION
SAVUQS: MOVE T2,ARGFRE ;POINTER TO FREE LOCATION
ADDI T2,1 ;BUMP BY 1 PASSED HEADER
HRLI T2,(POINT 7,0) ;MAKE INTO A BYTE POINTER
MOVE T1,CURPTR ;USE THE BUFFER POINTER FIELD
CAME T1,CMDBLK+.CMPTR ;WERE THEY EQUAL AT THE START
JRST SAVU.1 ;SAVE A NULL AND RETURN
SETZ T3,0 ;MAKE A NULL
JRST SAVU.2 ;SAVE THE NULL AND RETURN
SAVU.1: ILDB T3,T1 ;GET A CHARACTER FROM THE SOURCE
CAMN T1,CMDBLK+.CMPTR ;AT END OF FIELD?
JRST SAVU.2 ;YES, FINISH OFF TEXT
IDPB T3,T2 ;SAVE IT IN THE DESTINATION
JRST SAVU.1 ;LOOP TILL HIT END OF TEXT
SAVU.2: IDPB T3,T2 ;SAVE THE BYTE
JRST SAVA.2 ;FINISH OFF TEXT
SUBTTL SAVATM Save the atom as the argument
;THIS SAVE ROUTINE WILL COPY DATA FROM THE ATOM BUFFER
;TO THE COMMAND MESSAGE
;THIS ROUTINE IS USED BY .CMFLD, .CMTXT, .CMQST
SAVATM: MOVE T2,ARGFRE ;POINTER TO FREE LOCATION
ADDI T2,1 ;BUMP BY 1 PASSED HEADER
HRLI T2,(POINT 7,0) ;MAKE INTO A BYTE POINTER
HRLZI T1,(POINT 7,0) ;MAKE SOURCE BYTE POINTER
HRRI T1,ATMBFR ;SOURCE OF DATA
SAVA.1: ILDB T3,T1 ;GET A CHARACTER FROM THE SOURCE
IDPB T3,T2 ;SAVE IT IN THE DESTINATION
JUMPN T3,SAVA.1 ;LOOP IF MORE ...NON-ZERO
SAVA.2: HRRZI T2,1(T2) ;GET NEXT LOCATION AND CLEAR LH
MOVE T1,T2 ;SAVE VALUE IN T1
SUB T2,ARGFRE ;GET LENGTH OF BLOCK
STORE T2,@ARGFRE,PF.LEN ;SAVE THE LENGTH
LOAD T2,CR.COD(S2) ;GET THE CODE VALUE
STORE T2,@ARGFRE,PF.TYP ;SAVE AS HEADER FOR BLOCK
EXCH T1,ARGFRE ;UPDATE THE FREE POINTER
$RET ;RETURN
SUBTTL SAVRES Save a 2 word argument
;THIS ROUTINE WILL CREATE A BLOCK WITH ONE DATA ELEMENT IN IT
;TO STORE THE RESULT RETURNED BY COMND
SAVRES: LOAD T2,CR.COD(S2) ;GET CODE IN LEFT HALF
STORE T2,@ARGFRE,PF.TYP ;SAVE TYPE IN HEADER
MOVEI T2,PFD.D2 ;SIZE OF THE BLOCK
STORE T2,@ARGFRE,PF.LEN ;SAVE THE HEADER VALUE
AOS ARGFRE ;BUMP TO NEXT LOCATION
MOVE T2,CR.RES(S2) ;GET THE RESULT
STORE T2,@ARGFRE ;SAVE THE VALUE
AOS ARGFRE ;BUMP TO NEXT LOCATION
$RET ;RETURN
SUBTTL SAVDEV Save routine for a device
;THIS ROUTINE WILL STORE A STRING IN THE BLOCK FOR .CMDEV
TOPS20 <
SAVDEV: LOAD T1,CR.PDB(S2),RHMASK ;GET PDB USED
TXNN T1,CM%PO ;WAS IT PARSE ONLY
JRST SAVATM ;YES, PROCESS AS SAVE ATOM
DMOVE T1,S1 ;SAVE THE CALLING ARGUMENTS
HRRO S1,ARGFRE ;GET POINTER FOR STRING
ADDI S1,1 ;SKIP OVER THE HEADER
MOVE S2,CR.RES(S2) ;GET THE DEVICE DESIGNATOR
DEVST ;CONVERT TO A STRING
$STOP(DDC,DEVICE DESIGNATOR CONVERSION ERROR)
HRRZI S2,1(S1) ;GET NEXT LOCATION AND CLEAR LEFT HALF
MOVE T3,S2 ;SAVE THE LOCATION
SUB S2,ARGFRE ;GET THE LENGTH
STORE S2,@ARGFRE,PF.LEN ;SAVE THE LENGTH IN BLOCK
LOAD S2,CR.COD(T2) ;GET THE FUNCTION CODE
STORE S2,@ARGFRE,PF.TYP ;SAVE TYPE IN BLOCK
EXCH T3,ARGFRE ;UPDATE FREE POINTER
$RETT ;RETURN TRUE
> ;End TOPS20
TOPS10 <
SAVDEV==SAVATM
> ;End TOPS10
SUBTTL SAVTOK Save routine to save a token
;THIS ROUTINE WILL SAVE A TOKEN IN THE COMMAND MESSAGE
SAVTOK: LOAD T1,CR.PDB(S2),RHMASK ;PDB USED BY COMMAND
LOAD S1,.CMDAT(T1) ;DATA USED BY COMND
MOVE T1,S2 ;SAVE S2
$CALL MAKPTR ;MAKE A POINTER..RETURNED IN S2
EXCH T1,S2 ;POINTER IN T1 AND BLOCK ADDRESS IN S2
MOVE T2,ARGFRE ;GET DESTINATION POINTER
ADDI T2,1 ;BUMP BY 1 PASSED HEADER
HRLI T2,(POINT 7,0) ;MAKE DESTINATION POINTER
PJRST SAVA.1 ;USE SAVE ATOM ROUTINE
SUBTTL SAVNOD Save node specification
;THIS ROUTINE WILL SAVE ANODE SPECIFICATION IN THE COMMAND
;MESSAGE
TOPS20 <
SAVNOD: PJRST SAVATM ;SAVE THE ATOM FOR TOPS-20
> ;End TOPS20
TOPS10 <
SAVNOD: PJRST SAVRES ;SAVE AS NUMBER WITH NO RADIX
> ;End TOPS10
SUBTTL SAVINI Initialize the returned arguments
;THIS ROUTINE IS CALLED TO INITIALIZE THE SAVE ROUTINES FOR THE PARSER
;IT IS THE FUNCTION DEPENDENT ROUTINE FOR THE .CMINI FUNCTION
SAVINI: MOVE S1,PARDAT ;GET PAGE ADDRESS
MOVE T1,COM.PB(S1) ;GET PARSER START OFFSET
ADDI T1,(S1) ;CONVERT TO FULL ADDRESS
MOVEM T1,ARGFRE ;SAVE AS START OF ARGUMENT AREA
$RET ;AND RETURN
SUBTTL REPARS Set up for COMND reparse
;THIS ROUTINE IS GOTTEN TO BY THE COMND JSYS CHANGING THE PC WHEN
;A USER RUBS OUT ACROSS A FIELD. IT JUST CLEARS OUT THE TEMPORARY
;STORAGE USED BY COMND AND RESTARTS THE PARSER
REPARS: $CALL @.CMINI+PARTAB ;TELL SAVE ROUTINES TO FORGET IT
MOVX S1,P.NPRO ;GET THE NO PROCESS FLAGS
ANDCAM S1,FLAGS ;CLEAR FLAG TO BE SAFE
MOVE S1,[GJFBLK,,GJFBLK+1] ;SET UP TO CLEAR GTJFN BLOCK
SETZM GJFBLK ;CLEAR FIRST WORD
BLT S1,GJFBLK+GJFSIZ-1 ;CLEAR THE BLOCK
MOVE S1,ARGSAV+PAR.TB ;GET THE ORIGINAL TABLES FROM CALL
AOS S1 ;POSITION TO THE FDB
LOAD T1,.CMFNP(S1),CM%FNC ;GET THE FUNCTION CODE
CAIE T1,.CMINI ;MAKE SURE NOT A .CMINI
JRST REPA.1 ;NOT .CMINI.... O.K.
$CALL P$PNXT ;GET NEXT PDB
AOS S1 ;BUMP TO ACTUAL PDB
REPA.1: STORE S1,CMDRET+CR.PDB,RHMASK ;SAVE THE NEW PDB
JRST PARCMD ;JUST RESTART PARSER
SUBTTL FILDEF Fill in defaults for COMND
;THIS ROUTINE WILL FILL IN DEFAULTS BEFORE THE PDB IS PROCESSED
;
;CALL S1/ SIZE OF BLOCK
; S2/ ADDRESS OF THE BLOCK
;
;RETURN TRUE: CHECK NEXT ALTERNATE AND RETURN
;
;RETURN FALSE: S1/ ERROR CODE IF ANY
; S2/ ADDRESS OF THE STRING
FILDEF: LOAD S1,CMDRET+CR.PDB,RHMASK ;GET CURRENT PDB
FILD.1: MOVEM S1,CURPDB ;SAVE THE CURRENT PDB
$CALL P$PDEF ;IS THERE A DEFAULT ROUTINE
JUMPF FILD.2 ;NO, TRY NEXT PDB
MOVE T2,S1 ;SAVE THE ACTION ROUTINE
MOVEI S1,PC.SIZ ;SIZE OF THE BLOCK
MOVEI S2,CMDRET ;COMMAND RETURN BLOCK
$CALL (T2) ;CALL THE DEFAULT FILLER
JUMPT FILD.2 ;O.K..CONTINUE ON
SKIPN S2 ;IF S2 HAS ERROR SET..SKIP
MOVEI S2,[ASCIZ/Error during default filling routine/]
MOVX T2,P.DERR ;DEFAULT ROUTINE ERROR
IORM T2,FLAGS ;SAVE IN THE FLAGS
MOVEM S1,PARBLK+PRT.EC ;SAVE ANY CODE FOR CALLER
$RETF ;RETURN FALSE
FILD.2: MOVE S1,CURPDB ;GET THE CURRENT PDB
LOAD S1,.CMFNP(S1),CM%LST ;GET THE ADDR OF NEXT PDB IN LIST
JUMPN S1,FILD.1 ;LOOP ON NEXT ONE
$RETT ;RETURN
SUBTTL PDBCPY Copy a switch table
;THIS ROUTINE IS CALLED AS A SPECIAL ROUTINE TO COPY
;THE CURRENT SWITCH TABLE TO TEMFDB SO THAT THE TABLE
;ENTRIES CAN BE DELETED AS USED.
C.SWIT==1B0 ;FLAG FOR SWITCH
PDBCPY: MOVE T3,S2 ;SAVE THE ARGUMENT BLOCK POINTER
LOAD S1,CR.PDB(T3),RHMASK ;GET THE LAST USED PDB
MOVE T2,CR.RES(T3) ;GET RESULT IN T2
$CALL P$PACT ;GET THE ACTION ROUTINE ADDRESS
TXNN S1,C.SWIT ;SPECIAL SWITCH SET
JRST PDBC.1 ;NO, ALREADY SETUP TEMP
HRRZ T1,CR.PDB(T3) ;CURRENT FDB ADDRESS
SUBI T1,1 ;INCLUDE THE HEADER FOR THE PDB
HRLZS T1,T1 ;NOW PLACE IN THE LEFT HALF
HRRI T1,TEMFDB ;NEW FDB AREA
BLT T1,TEMFDB+PDB.SZ-1 ;MOVE THE PDB
MOVEI S1,TEMFDB+1 ;GET THE CURRENT PDB
$CALL P$GPDB ;GET THE PDB ADDRESS
MOVX T1,C.SWIT ;GET SPECIAL SWITCH
ANDCAM T1,PB%RTN(S1) ;CLEAR THE BIT IN PDB
HRLZ T1,TEMFDB+1+.CMDAT ;GET TABLE ADDRESS
HRRI T1,TEMTAB ;GET TEMPORARY TABLE
HRRZ T2,@TEMFDB+1+.CMDAT ;GET COUNT OF TABLE
CAILE T2,TEMTSZ ;WITHIN TABLE SIZE
$STOP(STS,<SHARED SWITCH TABLE SIZE OF ^D/[TEMTSZ]/ TOO SMALL FOR TABLE OF SIZE ^D/T2/>)
BLT T1,TEMTAB(T2) ;MOVE THE TABLE
MOVEI T1,TEMTAB ;ADDRESS OF TABLE
MOVEM T1,TEMFDB+.CMDAT+1 ;SAVE DATA IN TABLE
MOVE T4,CR.RES(T3) ;GET THE RESULT
HRRZ T1,CR.PDB(T3) ;GET USED PDB FOR PARSE
SUB T4,.CMDAT(T1) ;GET OFFSET
MOVEI T2,TEMTAB(T4) ;GET NEW OFFSET
PDBC.1: MOVEI T1,TEMTAB ;TABLE ADDRESS IN T1
DMOVEM T1,DENTRY ;SAVE ARGUMENTS
SETOM DFLAGS ;TURN ON DELETE FLAG
$RET ;RETURN
SUBTTL STBDEL Delete a local switch table entry
;THIS ROUTINE IS CALLED BY THE MAIN PARSER TO DELETE
;THE CURRENT SWITCH VALUE FROM THE TEMFDB TABLE.
;IF ALL ENTRIES ARE GONE IT WILL TURN OF THE DEFAULT HELP
;TEXT TO COMMAND.
STBDEL: SETZM DFLAGS ;CLEAR THE FLAG
DMOVE S1,DENTRY ;GET DELETE AC'S
HLRZ T2,0(S1) ;GET USED COUNT
MOVE T1,T2 ;PLACE IN T1
SOSGE T1 ;DECREMENT..SKIP IF NOT ZERO
$RETF ;FALSE RETURN
ADD T2,S1 ;COMPUTE END OF TABLE
CAILE S2,(S1) ;ENTRY IN TABLE
CAMLE S2,T2 ;MAKE SURE
$STOP (TDE,TABLE DELETE ERROR)
HRLM T1,0(S1) ;SAVE COUNT
JUMPE T1,STBD.2 ;TABLE EMPTY
HRLI S2,1(S2) ;COMPACT TABLE
BLT S2,-1(T2) ;MOVE THE TABLE
STBD.1: SETZM 0(T2) ;CLEAR EMPTY WORD AT END
$RETT ;RETURN TRUE
STBD.2: MOVX S1,CM%SDH ;SUPPRESS DEFAULT HELP MESSAGE
IORM S1,TEMFDB+1+.CMFNP ;TURN ON IN TABLE
JRST STBD.1 ;FINISH UP TABLE OPERATION
SUBTTL TXTINP Multiple line text input routines
;THIS ROUTINE WILL CHECK IF THE PRIMARY OUTPUT IS TO THE
;TERMINAL AND IF SO DISPLAY A TEXT STRING. THE ROUTINE
;WILL THEN BRANCH TO GETTXT TO INPUT THE DATA
TXTINP: HRRZ T1,CMDBLK+.CMIOJ ;GET THE OUTPUT DESIGNATOR
CAIN T1,.PRIOU ;NOT TO THE TERMINAL
$TEXT (T%TTY,<Enter text and terminate with ^^Z>)
JRST GETTXT ;GET THE TEXT
SUBTTL GETTXT Get multiple lines of text
;THIS ROUTINE WILL ACCEPT TEXT AND TERMINATE ON A ^Z OR
;RETURN TO THE ORIGINAL COMMAND IF RUBOUT TO BEGINNING
;OF THE BUFFER.
GETTXT: MOVE T1,ARGFRE ;GET NEXT FREE LOCATION
MOVE T2,T1 ;SAVE IN T2
SOS T2 ;DECREMENT T2
LOAD T3,PFD.HD(T2),PF.TYP ;GET FIELD TYPE
CAIE T3,.CMCFM ;CHECK IF CONFIRM TYPED
JRST GETE.0 ;NO - ERROR IN BLOCK
MOVE T1,T2 ;OVERLAY CONFIRM BLOCK
STORE T1,ARGFRE ;SAVE AS CURRENT POINTER
ADDI T1,1 ;BUMP IT BY 1 FOR HEADER
MOVE T2,T1 ;SAVE ADDRESS IN T2
HRLI T1,(POINT 7,0) ;MAKE A BYTE POINTER
MOVEM T1,TXTDAT+.RDDBP ;POINTER TO SAVE INPUT
MOVEM T1,TXTDAT+.RDBFP ;POINTER TO BEGINNING OF BUFFER
SUB T2,PARDAT ;ARGFRE-START OF MESSAGE
ADDI T2,BUFSIZ-100 ;COMPUTE REMAINING LENGTH-100
IMULI T2,NCHPW ;NUMBER OF CHARACTERS PER WORD
MOVEM T2,TXTDAT+.RDDBC ;MAXIMUM SIZE OF INPUT
LOAD T1,CMDBLK+.CMIOJ ;GET JFNS FROM COMMAND
MOVEM T1,TXTDAT+.RDIOJ ;SAVE IN TEXT ARGUMENT BLOCK
MOVX T1,RD%JFN+RD%RND ;USING JFNS AND BREAKOUT ON
;RUBOUT TO BEGINNING OF BUFFER
MOVEM T1,TXTDAT+.RDFLG ;SAVE THE FLAGS
MOVEI T1,[EXP 1B26,0,0,0] ;BREAK TABLE FOR INPUT
MOVEM T1,TXTDAT+.RDBRK ;SAVE IN ARGUMENT BLOCK
ZERO TXTDAT+.RDRTY ;NO RETRY POINTER
MOVEI T1,.RDBRK ;SIZE OF THE BLOCK
MOVEM T1,TXTDAT+.RDCWB ;SAVE LENGTH IN BLOCK
MOVEI S1,TXTDAT ;ADDRESS OF THE BLOCK
$CALL K%TXTI ;INPUT THE DATA
JUMPF GETE.1 ;ERROR RETURN - RETURN
MOVX S1,RD%BFE ;BACK OVER BUFFER BEGINNING
TDNE S1,TXTDAT+.RDFLG ;WAS THIS THE REASON
PJRST GETT.1 ;YES - RESET THE COMMAND DATA
MOVX S1,RD%BTM ;BREAK TERMINATE INPUT
TDNE S1,TXTDAT+.RDFLG ;WAS THIS THE REASON
PJRST GETT.3 ;YES - FINISH STRING AND RETURN
PJRST GETE.2 ;TOO MUCH TEXT - TRUNCATED
GETT.1: SETZ S1, ;SETUP A NULL
MOVNI S2,2 ;ADJUST POINTER BACK TWO
MOVE S2,CMDBLK+.CMPTR ;GET NEW POINTER
SUBI S2,1 ;BACK UP 1 WORD
IBP S2 ;BUMP UP ONE BYTE
IBP S2 ;ONE MORE
IBP S2 ;ONE MORE SAME AS BACKING UP 2
IDPB S1,S2 ;REPLACE CR WITH NULL
IDPB S1,S2 ;REPLACE LF WITH NULL
MOVEI S1,BUFSIZ*NCHPW-2 ;SIZE OF BUFFER
SUB S1,CMDBLK+.CMCNT ;GET CHARACTERS IN BUFFER
MOVEM S1,CMDBLK+.CMINC ;SAVE IN COMMAND BLOCK
HRROI S1,BUFFER ;POINTER TO THE BUFFER
MOVEM S1,CMDBLK+.CMBFP ;RESET START OF TEXT BUFFER
MOVEM S1,CMDBLK+.CMPTR ;SAVE THE TEXT POINTER
MOVEI S1,BUFSIZ*NCHPW ;SIZE OF THE BUFFER
MOVEM S1,CMDBLK+.CMCNT ;RESET THE COUNT
MOVX S1,P.REPA ;SET FOR REPARSE
IORM S1,FLAGS ;SAVE FOR PARSER FLAGS
GETT.2: HRRZ T1,CMDBLK+.CMIOJ ;GET OUTPUT DESIGNATOR
CAIN T1,.PRIOU ;IS IT TERMINAL OUTPUT
$TEXT (T%TTY,<^Q/CURPMT/^T/BUFFER/^A>)
$RETF ;EXIT ACTION ROUTINE - repARSE
GETT.3: SETZ S1, ;CLEAR S1 FOR NULL
DPB S1,TXTDAT+.RDDBP ;REPLACE BREAK WITH NULL
MOVE S1,CMDBLK+.CMPTR ;BYTE POINTER OF STRING
MOVEM S1,TEMPTR ;SAVE IN TEMPTR
MOVE T2,ARGFRE ;ARGUMENT HEADER
AOS T2 ;POINT TO THE TEXT
$TEXT (GETOUT,<^T/(T2)/>) ;ADD TO THE BUFFER
MOVEI S1,0 ;GET A NULL
IDPB S1,TEMPTR ;SAVE THE NULL
HRRZ S1,TXTDAT+.RDDBP ;LAST USED ADDRESS
ADDI S1,1 ;BUMP TO NEXT FREE
MOVE S2,S1 ;SAVE IN S2
SUB S2,ARGFRE ;GET USED LENGTH
STORE S2,@ARGFRE,PF.LEN ;SAVE LENGTH IN HEADER
MOVEI S2,.CMTXT ;TEXT TYPE IN LEFT HALF
STORE S2,@ARGFRE,PF.TYP ;SAVE TYPE IN MESSAGE
EXCH S1,ARGFRE ;RESET NEXT FREE LOCATION
MOVEI S2,.CMCFM ;CONFIRM BLOCK
STORE S2,@ARGFRE,PF.TYP ;SAVE TYPE IN MESSAGE
MOVEI S2,1 ;ONLY ONE WORD
STORE S2,@ARGFRE,PF.LEN ;SAVE LENGTH IN HEADER
AOS ARGFRE ;BUMP TO NEXT
$RETT ;RETURN TRUE
GETE.0: MOVEI S2,[ASCIZ/Bad argument in message - expected confirm/]
$RETF ;RETURN FALSE
GETE.1: MOVEI S2,[ASCIZ/Error during text input/]
$RETF
GETE.2: HRR T1,CMDBLK+.CMIOJ ;GET THE OUTPUT DESIGNATOR
CAIN T1,.PRIOU ;NOT TO THE TERMINAL
$WARN (Message truncated - text exceeded buffer capacity)
JRST GETT.3 ;FINISH OFF THE MESSAGE
GETOUT: IDPB S1,TEMPTR ;SAVE THE CHARACTER
$RETT ;RETURN TRUE
SUBTTL TAKFDB TAKE command tables
TAKFDB: $NOISE(TAK001,<commands from>)
TAK001: $FILE(TAK002,<input filespec>,<$PREFILL(TAKDEF),$ACTION(TAKRTN),$ERROR(BADIFI)>)
TAK002: $SWITCH(,TAK003,<$ALTER(TAK004)>)
TAK003: $STAB
ORNSDP (TAK004,<DISPLAY>,DSP)
ORNSDP (TAK004,<NODISPLAY>,NDP)
$ETAB
TAK004: $CRLF (<$ACTION(TAKE)>)
BADIFI: SETZM S2 ;CLEAR THE ERROR CODE
$RETF ;BAD INPUT FILE
SUBTTL TAKDEF Take default setting
TOPS20 <
TAKDEF: MOVE S1,[GJFBLK,,GJFBLK+1] ;SET UP TO CLEAR BLOCK
SETZM GJFBLK ;CLEAR FIRST WORD
BLT S1,GJFBLK+GJFSIZ-1 ;CLEAR THE BLOCK
MOVX S1,GJ%OLD ;FILE MUST EXIST
MOVEM S1,GJFBLK+.GJGEN ;INTO FLAGS WORD
MOVE S1,[XWD .NULIO,.NULIO] ;SUPPLY NO JFNS
MOVEM S1,GJFBLK+.GJSRC ;INTO BLOCK
HRROI S1,[ASCIZ/SYSTEM/] ;POINT AT DEFAULT FILE NAME
MOVEM S1,GJFBLK+.GJNAM ;SAVE FOR GTJFN
HRROI S1,[ASCIZ/CMD/] ;DEFAULT EXTENSION
MOVEM S1,GJFBLK+.GJEXT ;SAVE IN GTJFN BLOCK
HRROI S1,[ASCIZ/DSK/] ;GET THE DEFAULT STRUCTURE
MOVEM S1,GJFBLK+.GJDEV ;SAVE THE DEVICE
$RET ;AND RETURN
> ;End TOPS20
TOPS10 <
TAKDEF: MOVE S1,[GJFBLK,,GJFBLK+1] ;SET UP TO CLEAR BLOCK
SETZM GJFBLK ;CLEAR FIRST WORD
BLT S1,GJFBLK+GJFSIZ-1 ;CLEAR THE BLOCK
MOVE S1,[SIXBIT/SYSTEM/] ;GET FILE NAME
STORE S1,GJFBLK+.FDNAM ;SAVE IN DEFAULT BLOCK
MOVSI S1,'CMD' ;GET DEFAULT EXTENSION
STORE S1,GJFBLK+.FDEXT ;SAVE IN BLOCK
MOVSI S1,'DSK' ;GET STRUCTURE NAME
STORE S1,GJFBLK+.FDSTR ;SAVE THE STRUCTURE
$RET ;AND RETURN
> ;End TOPS10
SUBTTL TAKRTN Special routines for TAKE commands
;INCLUDED HERE ARE THE SPECIAL ROUTINES NEEDED FOR THE
;PROPER SETUP FOR TAKE COMMANDS. THESE ROUTINES ARE
;CALLED AS SPECIAL ACTION ROUTINES BY THE PARSER
TAKRTN: SKIPN TAKFLG ;PROCESSING A TAKE COMMAND
$RET ;NO, JUST RETURN
MOVEI S1,0 ;CLEAR FLAG AC
MOVEI S2,[ASCIZ/TAKE command is illegal in a command file/]
$RETF ;FALSE RETURN TO ABORT COMMAND
TAKE: SETOM TAKFLG ;SET FLAG FOR PROCESSING TAKE
MOVX T1,P.DSPT ;GET FLAG TO DISPLAY COMMAND
ANDCAM T1,FLAGS ;CLEAR THE FLAG
SKIPE OPRTAK ;DISPLAY TAKE OUTPUT
IORM T1,FLAGS ;SET THE FLAG
MOVE T4,PARDAT ;GET THE PAGE ADDRESS
MOVE S1,COM.PB(T4) ;GET POINTER TO PARSER BLOCK
ADDI S1,(T4) ;GET OFFSET FOR PARSER DATA
$CALL P$SETU ;SETUP THE POINTER
$CALL P$KEYW ;GET THE NEXT FIELD
JUMPF TAKE.1 ;ERROR..RETURN
CAIE S1,.KYTAK ;IS IT A TAKE COMMAND
PJRST TAKE.1 ;INVALID TAKE COMMAND
$CALL P$FILE ;IS IT A FILE SPEC
JUMPF TAKE.2 ;NO, ERROR
MOVE T2,S1 ;ADDRESS OF THE BLOCK
$CALL P$CFM ;CHECK FOR CONFIRM
JUMPT TAK.1 ;YES, DON'T CHECK SWITCHES
$CALL TAKDSP ;CHECK TAKE DISPLAY SWITCHES
$RETIF ;FALSE..PASS ERRORS UP
$CALL P$CFM ;CHECK FOR A CONFIRM
JUMPF TAKE.1 ;ERROR...RETURN
TAK.1: MOVX S1,P.TAKE ;SAY WE ARE DOING TAKE COMMAND
IORM S1,FLAGS
MOVE S1,T2 ;COMMAND FD TO S1
SETZM S2 ;NO LOGGING FD
$CALL P$TAKE ;OPEN THE FILES
JUMPF TAKE.3 ;OPEN ERROR ON FILE
$RETT ;RETURN TRUE
TAKDSP: $CALL P$SWIT ;CHECK FOR A SWITCH
JUMPF TAKE.4 ;NO, GIVE ERROR RETURN
CAIE S1,.SWDSP ;DISPLAY COMMAND OUTPUT
JRST TAKD.1 ;TRY OTHER FLAGS
SETOM DSPTAK ;SET DISPLAY TAKE COMMANDS
$RETT ;RETURN TRUE
TAKD.1: CAIE S1,.SWNDP ;NO DISPLAY
JRST TAKE.4 ;INVALID ARGUMENT..ERROR
SETZM DSPTAK ;CLEAR TAKE DISPLAY
$RETT ;RETURN
TAKE.1: MOVEI S2,[ASCIZ/Invalid TAKE command/]
JRST TAKERR ;TAKE ERROR EXIT
TAKE.2: MOVEI S2,[ASCIZ/No input file specified in TAKE command/]
JRST TAKERR ;TAKE ERROR EXIT
TAKE.3: MOVEI S2,[ASCIZ/Can't open TAKE command file/]
JRST TAKERR ;TAKE ERROR EXIT
TAKE.4: MOVEI S2,[ASCIZ/Invalid argument in TAKE command/]
JRST TAKERR ;TAKE ERROR EXIT
TAKERR: SETZM TAKFLG ;CLEAR THE TAKE FLAG ON ERROR
SETZM DSPTAK ;Always zero display flag
$RETF ;RETURN FALSE
SUBTTL WAIFDB WAIT command tables
;This Command will sleep for a specified amount of time and wait
;and/or wait for an interrupt to proceed.
WAIFDB: $NOISE(WAI010,<for>)
WAI010: $NUMBER(WAI020,^D10,<Number of seconds to wait between 1 and 60>)
WAI020: $NOISE(WAI030,<seconds>)
WAI030: $CRLF(<$ACTION(WAITRN)>)
WAITRN: MOVE T4,PARDAT ;GET THE PARSER PAGE ADDRESS
MOVE S1,COM.PB(T4) ;OFFSET TO PARSER DATA
ADDI S1,(T4) ;SETUP PB PROPERLY
$CALL P$SETU ;SETUP THE POINTER
$CALL P$KEYW ;CHECK FOR A KEYWORD
JUMPF WAITE1 ;ERROR .. NO WAIT KEYWORD
CAIE S1,.KYWAI ;WAS IT WAIT?
PJRST WAITE1 ;NO, ERROR
WAIT.1: $CALL P$NUM ;WAS IT A NUMBER
JUMPF WAITE1 ;NO GENERATE AN ERROR
MOVE T3,S1 ;SAVE THE TIME
CAIG S1,^D60 ;60 SECOND LIMIT ON SLEEP
SKIPG S1 ;VALID TIME
PJRST WAITE2 ;INVALID WAIT VALUE
WAIT.2: $CALL P$NPRO ;NO PROCESSING FLAG AND RETURN
MOVE S1,T3 ;GET THE TIME
WAITSL: SKIPG S1 ;IF A NEGATIVE NUMBER,
MOVEI S1,1 ;SLEEP FOR A SECOND
CAILE S1,^D60 ;IF MORE THAN A MINUTE
MOVEI S1,^D60 ;SLEEP FOR A MINUTE
TOPS10 <
SLEEP S1, ;SLEEP
JFCL ;IGNORE ERRORS
$RETT ;RETURN AFTER SLEEPING
> ;End TOPS10 CONDITIONAL
TOPS20 <
IMULI S1,^D1000 ;CONVERT SECONDS TO MILLISECONDS
DISMS ;ELSE SLEEP FOR SPECIFIED SECONDS
JFCL ;USE A LOCATION
$RETT ;RETURN TO CALLER
> ;End TOPS20 CONDITIONAL
WAITE1: MOVEI S2,[ASCIZ/Invalid WAIT command/]
$RETF ;RETURN FALSE
WAITE2: MOVEI S2,[ASCIZ/Wait time must be a positive number between 1 and 60/]
$RETF ;RETURN FALSE
SUBTTL P$STAK Setup TAKE command
;THIS COMMAND WILL ACCEPT A JFN FOR THE TAKE FILE TO BE USED
;AND UPDATE THE NECESSARY OPRPAR DATA BASE TO MAKE ALL OTHER
;FUNCTION WORK CORRECTLY
;
;CALL S1/ JFN (IFN ON TOPS10) FOR THE COMMAND FILE
;
TOPS10 <
P$STAK: SETOM TAKFLG ;SET FLAG FOR PROCESSING TAKE
MOVEM S1,CMDIFN ;SAVE THE IFN
MOVEM S1,CMDJFN ;SAVE AS JFN ALSO
$RETT
> ;End TOPS10
TOPS20 <
P$STAK: $CALL .SAVET ;Preserve temporaries
STKVAR <<CMDFD,^D20>> ;Get some space to build FD
MOVE S2,S1 ;Put JFN in S2
MOVSI S1,^D20 ;Setup FD header
MOVEM S1,CMDFD
HRROI S1,1+CMDFD ;Point to storage for string
MOVX T1,1B2+1B5+1B8+1B11+1B14+JS%PAF ;Request all fields
JFNS
ERJMP .RETF
MOVE S1,S2 ;Close the file
CLOSF
ERJMP .RETF
MOVEI S1,CMDFD ;Point to the file spec
SETZM S2 ;No logging file wanted
PJRST P$TAKE ;Setup for TAKE
> ;End TOPS20
SUBTTL P$TAKE Routine to setup a TAKE command
;THIS ROUTINE ACCEPTS TWO FDS FOR THE TAKE COMMAND TO BE
;USED AND WILL OPEN THE FILES AND UPDATE THE DATA BASE TO
;MAKE ALL OTHER FUNCTIONS OPERATE CORRECTLY
;CALL S1/ ADDRESS OF COMMAND FILE FD
; S2/ ADDRESS OF LOG FILE FD
; On failure, release all IFN's and return false
P$TAKE: STKVAR <<CMDFOB,FOB.MZ>,<LOGFOB,FOB.MZ>>
MOVEM S1,FOB.FD+CMDFOB ;Save address of command FD
MOVEM S2,FOB.FD+LOGFOB ;Save address of logging FD
MOVX S1,FLD(7,FB.BSZ)+FLD(1,FB.LSN)
MOVEM S1,FOB.CW+CMDFOB ;Strip LSN and open as ascii
MOVEI S1,FOB.MZ ;Size of the FOB
MOVEI S2,CMDFOB ;Address of the FOB
$CALL F%IOPN ;Open the file
$RETIF ;Return the error on failure
MOVEM S1,CMDIFN ;Save the IFN
SETOM TAKFLG ;Remember we are doing a TAKE
TOPS20 <
MOVEI S2,FI.CHN ;Get the JFN for TOPS20
$CALL F%INFO
$RETIF ;Return the error on failure
; The error must indicate bad IFN
MOVEM S1,CMDJFN ;Save proper file index
TXO S1,CO%NRJ+CZ%NUD ;Close but don't release JFN
CLOSF
JRST P$TAK3 ;Should never happen
MOVE S1,CMDJFN ;Reclaim the JFN
MOVX S2,FLD(7,OF%BSZ)+OF%RD ;Reopen in proper mode
OPENF
JRST P$TAK3 ;Should never happen
SKIPA ;Already saved JFN
> ;End TOPS20
MOVEM S1,CMDJFN ;Save the proper file index
SKIPG FOB.FD+LOGFOB ;Logging file wanted?
JRST [MOVEI S1,.NULIO ;No, then set nulio
MOVEM S1,LOGIFN
MOVEM S1,LOGJFN
JRST P$TAK1]
MOVX S1,FLD(7,FB.BSZ) ;Open log file as ascii
MOVEM S1,FOB.CW+LOGFOB
MOVEI S1,FOB.MZ
MOVEI S2,LOGFOB
$CALL F%OOPN
JUMPF P$TAK4 ;Return error after cleanup
MOVEM S1,LOGIFN ;Save the IFN
TOPS20 <
MOVEI S2,FI.CHN ;Get the JFN for TOPS20
$CALL F%INFO
JUMPF P$TAK4 ;Return error after cleanup
MOVEM S1,LOGJFN ;Save the JFN
TXO S1,CO%NRJ+CZ%NUD ;Close but don't release JFN
CLOSF
JRST P$TAK2 ;Should never happen
MOVE S1,LOGJFN ;Reclaim proper JFN
MOVX S2,FLD(7,OF%BSZ)+OF%WR ;Reopen in proper mode
OPENF
JRST P$TAK2 ;Should never happen
SKIPA ;Already saved JFN
> ;End TOPS20
MOVEM S1,LOGJFN ;Save the logging JFN
P$TAK1: MOVE S1,CMDIFN ;Return command IFN
MOVE S2,LOGIFN ; and logging IFN
$RETT
; Cleanup after failure
P$TAK2: MOVE S1,LOGJFN ;Want to release log file
$CALL F%REL ;And don't care about errors
P$TAK3: MOVX S1,ERUSE$ ;Error code
P$TAK4: EXCH S1,CMDIFN ;Get the command file IFN
; Saving S1 just in case
$CALL F%REL ;Close and release it
;Don't care about false returns
MOVE S1,CMDIFN ;Remember S1 if worth remembering
SETZM CMDIFN ;Forget about it
SETZM LOGIFN ;Forget about it
SETZM TAKFLG ;No takes either
$RETF ;Tell the user tuff luck
SUBTTL P$SETU Setup the parser block pointer address
;THIS ROUTINE WILL TAKE THE ADDRESS AND USE IT FOR THE POINTER TO
;THE PARSER BLOCK
;
;CALL S1/ PARSER BLOCK ADDRESS
;
;RETURN TRUE: ALWAYS
P$SETU: MOVEM S1,CURRPB ;SAVE AS THE CURRENT POINTER
SETZM PREVPB ;CLEAR PREVIOUS POINTER
$RETT
SUBTTL P$CURR Get the address of the current entry
;THIS ROUTINE WILL RETURN THE ADDRESS OF CURRENT ENTRY TO
;BE PARSED
;RETURN TRUE: S1/ ADDRESS OF CURRENT PARSER ADDRESS
P$CURR: MOVE S1,CURRPB ;GET THE CURRENT PARSER POINTER
$RETT ;RETURN TRUE
SUBTTL P$PREV Position to previous parser entry
;THIS ROUTINE WILL CHANGE THE PARSER BLOCK TO THE PREVIOUS
;ENTRY THAT WAS PROCESSED.
;IT WILL ONLY GO BACK ONE BLOCK.
;
;RETURN TRUE: S1/ ADDRESS OF PREVIOUS.. NOW CURRENT
;
;RETURN FALSE: NO PREVIOUS ENTRY
P$PREV: SKIPN S1,PREVPB ;GET THE PREVIOUS POINTER
$RETF ;RETURN FALSE .. NONE SET
MOVEM S1,CURRPB ;SAVE AS THE CURRENT
$RETT ;RETURN TRUE
SUBTTL P$NEXT Bump the pointer to next field
;THIS ROUTINE WILL BUMP TO NEXT DATA FIELD AND RETURN TRUE.
;S1 AND S2 WILL HAVE THE DATA TO RETURN TO THE CALLER
P$NEXT: MOVE TF,CURRPB ;GET THE CURRENT PB
MOVEM TF,PREVPB ;SAVE AS THE PREVIOUS POINTER
LOAD TF,@CURRPB,PF.LEN ;GET THE LENGTH
ADDM TF,CURRPB ;ADD TO CURRENT LOCATION
$RETT ;RETURN TRUE
SUBTTL P$NFLD Get header and data for a parser element
;THIS ROUTINE WILL RETURN THE ARGUMENT TYPE FOR THE CURRENT ENTRY
;AND THE ADDRESS OF THE CURRENT ENTRY
;
;RETURNS TRUE: S1/ ARGUMENT TYPE
; S2/ ADDRESS OF BLOCK
;
;RETURNS FALSE: ;NO MORE ARGUMENTS .. NOT IMPLEMENTED YET
P$NFLD: MOVE S2,CURRPB ;GET THE CURRENT PB
LOAD S1,PFD.HD(S2),PF.TYP ;GET THE TYPE FIELD
PJRST P$NEXT ;BUMP TO NEXT ONE
P$NARG: MOVE S2,CURRPB ;GET THE CURRENT PB
LOAD S1,PFD.HD(S2),PF.TYP ;GET THE TYPE FIELD
$RETT ;RETURN
SUBTTL P$CFM Check for a confirm in next block
;THIS ROUTINE WILL CHECK THE NEXT FIELD FOR A CONFIRM
;RETURN TRUE: ON CONFIRM AND UPDATE PB
;
;RETURN FALSE: S1/CODE FOUND
P$CFM: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMCFM ;WAS IT A CONFIRM
$RETF ;NO, RETURN FALSE
PJRST P$NEXT ;ADVANCE PB AND RETURN
SUBTTL P$COMMA Check for a comma in next block
;THIS ROUTINE WILL CHECK THE NEXT FIELD FOR A COMMA
;RETURN TRUE: ON COMMA AND UPDATE PB
;
;RETURN FALSE: S1/CODE FOUND
P$COMMA: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMCMA ;WAS IT A COMMA
$RETF ;NO, RETURN FALSE
PJRST P$NEXT ;ADVANCE PB AND RETURN
SUBTTL P$KEYW Get a keyword from the parsed data
;THIS ROUTINE WILL TRY TO GET A KEYWORD FROM THE NEXT ELEMENT
;IN THE PARSER DATA BLOCK POINTED TO BY PB
;
;RETURNS TRUE: S1/ KEYWORD FOUND
;
;RETURNS FALSE: S1/ DATA TYPE FOUND
P$KEYW: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMKEY ;WAS IT A KEYWORD
$RETF ;NO RETURN WITH TYPE FOUND
GETVAL: MOVE S1,PFD.D1(S2) ;GET THE DATA
PJRST P$NEXT ;RETURN AND ADVANCE PB
SUBTTL P$SWIT Get a switch from the parsed data
;THIS ROUTINE WILL TRY TO GET A SWITCH FROM THE NEXT ELEMENT
;IN THE PARSER DATA BLOCK POINTED TO BY PB
;
;RETURNS TRUE: S1/ SWITCH FOUND
;
;RETURNS FALSE: S1/ DATA TYPE FOUND
P$SWIT: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMSWI ;WAS IT A SWITCH
$RETF ;NO RETURN WITH TYPE FOUND
MOVE S1,PFD.D1(S2) ;GET THE DATA
PJRST P$NEXT ;RETURN AND ADVANCE PB
SUBTTL P$USER Get the user id field
;THIS ROUTINE WILL RETURN USER NUMBER OR PPN FOR THE
;.CMUSR FUNCTION
;
;RETURNS TRUE: S1/ USER NUMBER OR PPN
;
;RETURN FALSE S1/ DATA TYPE FOUND
;
P$USER: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMUSR ;IS IT USER ID?
$RETF ;NO, RETURN FALSE
PJRST GETVAL ;YES, GET AND RETURN VALUE
SUBTTL P$FLOT Get the floating point number
;THIS ROUTINE WILL RETURN A FLOATING POINT NUMBER FOR THE .CMFLT
;FUNCTION
;
;RETURNS TRUE: S1/ FLOATING POINT NUMBER
;
;RETURN FALSE S1/ DATA TYPE FOUND
;
P$FLOT: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMFLT ;IS IT A FLOATING POINT NUMBER?
$RETF ;NO, RETURN FALSE
PJRST GETVAL ;YES, GET AND RETURN VALUE
SUBTTL P$DIR Get the directory field
;THIS ROUTINE WILL RETURN DIRECTORY NUMBER OR PPN FOR THE
;.CMDIR FUNCTION
;
;RETURNS TRUE: S1/ DIRECTORY NUMBER OR PPN
;
;RETURN FALSE S1/ DATA TYPE FOUND
;
P$DIR: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMDIR ;IS IT DIRECTORY NUMBER?
$RETF ;NO, RETURN FALSE
PJRST GETVAL ;YES, GET AND RETURN VALUE
SUBTTL P$TIME Get the time/date field
;THIS ROUTINE WILL RETURN THE TIME/DATE FROM THE
;.CMTAD FUNCTION
;
;RETURNS TRUE: S1/ TIME/DATE IN UDT
;
;RETURN FALSE S1/ DATA TYPE FOUND
;
P$TIME: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMTAD ;IS IT TIME/DATE?
$RETF ;NO, RETURN FALSE
PJRST GETVAL ;YES, GET AND RETURN VALUE
SUBTTL P$NUM Get a number from the parser block
;ON RETURN TRUE: S1/ NUMBER
; S2/ RADIX
;
;ON RETURN FALSE: S1/ DATA TYPE FOUND
P$NUM: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMNUM ;CHECK IF A NUMBER
CAIN S1,.CMNUX ; OR TERMINATED BY NON-DIGIT?
SKIPA ;YES TO EITHER
$RETF ;LOSER
DMOVE S1,PFD.D1(S2) ;S1:= NUMBER, S2:= RADIX
PJRST P$NEXT ;ADVANCE TO NEXT FIELD AND RETURN
SUBTTL P$FILE Get a filespec from the parser block
;ON RETURN TRUE: S1/ ADDRESS OF FD
; S2/ LENGTH OF FD AND HEADER
;
;ON RETURN FALSE: S1/ DATA TYPE FOUND
P$FILE: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMFIL ;CHECK IF A GENERAL FILE
$RETF ;NO, RETURN FALSE
JRST GETFD ;GET THE FD
P$IFIL: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMIFI ;CHECK IF A INPUT FILE
$RETF ;NO, RETURN FALSE
JRST GETFD ;GET AN FD
P$OFIL: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMOFI ;CHECK IF A OUTPUT FILE
$RETF ;NO, RETURN FALSE
GETFD: MOVE S1,CURRPB ;GET ADDRESS OF THE BLOCK
LOAD S2,PFD.HD(S1),PF.LEN ;LENGTH OF THE FD AND HEADER
PJRST P$NEXT ;ADVANCE TO NEXT FIELD
SUBTTL P$FLD Get a text field from block
;ON RETURN TRUE: S1/ ADDRESS OF FIELD
; S1/ LENGTH OF THE BLOCK
;
;ON RETURN FALSE: S1/ DATA TYPE FOUND
P$FLD: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMFLD ;IS IT A FIELD?
$RETF ;NO, RETURN FALSE
GETF.1: MOVE S1,CURRPB ;ADDRESS OF THE DATA
LOAD S2,PFD.HD(S1),PF.LEN ;GET THE LENGTH
PJRST P$NEXT ;BUMP TO NEXT FIELD
P$TOK: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMTOK ;IS IT A TOKEN
$RETF ;NO, RETURN FALSE
PJRST GETF.1 ;SETUP DATA AND RETURN
SUBTTL P$NODE Get a node from block
;ON RETURN TRUE: S1/ NODE NAME OR NUMBER
;
;ON RETURN FALSE: S1/ DATA TYPE FOUND
P$NODE: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMNOD ;WAS IT A NODE TYPE
$RETF ;NO, RETURN FALSE
MOVE S1,PFD.D1(S2) ;GET THE DATA
TOPS20 <
TLNN S1,770000 ;CHECK IF SIXBIT..DATA IN FIRST
;6 BITS
> ;End TOPS20
PJRST P$NEXT ;ADVANCE THE PB PTR AND RETURN
GETN.0: HRLI T1,(POINT 7,) ;BYTE POINTER
HRRI T1,PFD.D1(S2) ;GET THE ADDRESS
MOVE T2,[POINT 6,T3] ;SAVE IN T3
SETZM T3 ;CLEAR T3
GETN.1: ILDB S1,T1 ;GET A BYTE
JUMPE S1,GETN.2 ;END OF STRING..JUMP
CAIG S1,172 ;LOWER CASE Z
CAIGE S1,141 ;LOWER CASE A
SKIPA ;NO NEED TO CONVERT
SUBI S1,40 ;CONVERT TO UPPER CASE
SUBI S1,"A"-'A' ;CONVERT TO SIXBIT
TLNE T2,770000 ;ENOUGH SAVED??
IDPB S1,T2 ;NO, SAVE IT AWAY
JRST GETN.1 ;LOOP FOR MORE
GETN.2: MOVE S1,T3 ;PLACE NODE NAME IN S1
PJRST P$NEXT ;ADVANCE THE POINTER
SUBTTL P$SIXF Get a sixbit field type
;ON RETURN TRUE: S1/ SIXBIT FIELD
;
;ON RETURN FALSE: S1/ DATA TYPE FOUND
P$SIXF: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMFLD ;IS IT A FIELD TYPE
$RETF ;NO, RETURN FALSE
PJRST GETN.0 ;PROCESS THE FIELD AND RETURN
SUBTTL P$RNGE Get a range back
;ON RETURN TRUE: S1/ LOW RANGE
; S2/ HIGH RANGE
;
;ON RETURN FALSE: S1/ DATA TYPE FOUND
P$RNGE: $CALL P$NUM ;GET A NUMBER
$RETIF ;ERROR..RETURN
MOVE T4,S1 ;SAVE NUMBER
$CALL P$TOK ;TRY FOR A TOKEN
JUMPF GETR.1 ;ERROR..RETURN
$CALL P$NUM ;GET HIGH RANGE
$RETIF ;ERROR..RETURN
MOVE S2,S1 ;PLACE NUMBER IN S2 FOR HIGH
MOVE S1,T4 ;SETUP LOW VALUE
$RETT ;RETURN TRUE
GETR.1: MOVEI S1,0 ;0 THE LOW RANGE
MOVE S2,T4 ;PUT NUMBER AS HIGH RANGE
$RETT ;RETURN TRUE
SUBTTL P$TEXT Get a text address and length
;ON RETURN TRUE: S1/ ADDRESS OF TEXT BLOCK
; S2/ NUMBER OF WORDS OF TEXT
;
;ON RETURN FALSE: S1/ DATA TYPE FOUND
P$TEXT: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMTXT ;IS IT TEXT
$RETF ;NO, RETURN FALSE
LOAD S2,PFD.HD(S2),PF.LEN ;GET THE LENGTH IN S2
MOVE S1,CURRPB ;ADDRESS OF THE HEADER
PJRST P$NEXT ;BUMP TO THEE NEXT FIELD
SUBTTL P$DEV Get a device address and length
;ON RETURN TRUE: S1/ ADDRESS OF DEVICE BLOCK
; S2/ NUMBER OF WORDS OF DEVICE BLOCK
;
;ON RETURN FALSE: S1/ DATA TYPE FOUND
P$DEV: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMDEV ;IS IT TEXT
$RETF ;NO, RETURN FALSE
LOAD S2,PFD.HD(S2),PF.LEN ;GET THE LENGTH IN S2
MOVE S1,CURRPB ;ADDRESS OF THE HEADER
PJRST P$NEXT ;BUMP TO THEE NEXT FIELD
SUBTTL P$QSTR Get a quoted string
;ON RETURN TRUE: S1/ ADDRESS OF TEXT BLOCK
; S2/ NUMBER OF WORDS
;
;ON RETURN FALSE: S1/ DATA TYPE FOUND
P$QSTR: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMQST ;IS IT TEXT
$RETF ;NO, RETURN FALSE
LOAD S2,PFD.HD(S2),PF.LEN ;GET THE LENGTH IN S2
MOVE S1,CURRPB ;ADDRESS OF THE HEADER
PJRST P$NEXT ;BUMP TO THEE NEXT FIELD
SUBTTL P$UQSTR Get an unquoted string
;ON RETURN TRUE: S1/ ADDRESS OF TEXT BLOCK
; S2/ NUMBER OF WORDS
;
;ON RETURN FALSE: S1/ DATA TYPE FOUND
P$UQSTR: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMUQS ;IS IT TEXT
$RETF ;NO, RETURN FALSE
LOAD S2,PFD.HD(S2),PF.LEN ;GET THE LENGTH IN S2
MOVE S1,CURRPB ;ADDRESS OF THE HEADER
PJRST P$NEXT ;BUMP TO THEE NEXT FIELD
SUBTTL P$ACCT Get an account string
;ON RETURN TRUE: S1/ ADDRESS OF TEXT BLOCK
; S2/ NUMBER OF WORDS
;
;ON RETURN FALSE: S1/ DATA TYPE FOUND
P$ACCT: $CALL P$NARG ;GET THE TYPE ELEMENT
CAIE S1,.CMACT ;IS IT TEXT
$RETF ;NO, RETURN FALSE
LOAD S2,PFD.HD(S2),PF.LEN ;GET THE LENGTH IN S2
MOVE S1,CURRPB ;ADDRESS OF THE HEADER
PJRST P$NEXT ;BUMP TO THEE NEXT FIELD
SUBTTL P$NPRO No processing required
;Set No Processing Required in the Parser Flags
P$NPRO: MOVX S1,P.NPRO ;NO PROCESSING REQUIRED
IORM S1,FLAGS ;SAVE IN FLAGS OF PARSER
$RETT ;RETURN TRUE
SUBTTL P$GPDB Get the PDB address if any data
;THIS ROUTINE WILL GET THE ADDRESS OF THE PDB FOR THE BLOCK
;
;CALL S1/ ADDRESS OF THE FDB
;
;RETURN TRUE: S1/ ADDRESS OF THE PDB DATA
; S2/ LENGTH OF THE PDB
;
;RETURN FALSE: NO NEXT PDB
P$GPDB: SUBI S1,1 ;POINT TO THE HEADER FOR PDB
SKIPN (S1) ;PDB O.K.
$STOP(IPP,Invalid PDB Header in Parse Block)
LOAD TF,PB%HDR(S1),PB.FDB ;GET THE LENGTH OF THE FDB
LOAD S2,PB%HDR(S1),PB.PDB ;GET THE LENGTH OF THE PDB
CAMN S2,TF ;ARE THEY THE SAME
$RETF ;RETURN FALSE .. NONE SPECIFIED
ADD S1,TF ;POSITION TO THE PDB
SUB S2,TF ;GET LENGTH OF THE PDB
$RETT ;RETURN TRUE
SUBTTL P$PNXT Get next PDB given a PDB block
;THIS ROUTINE WILL RETURN INFORMATION FROM A PDB
;CALL S1/ ADDRESS OF THE PDB
;
;RETURN TRUE: S1/ ADDRESS OF THE NEXT PDB
;
;RETURN FALSE: NO NEXT PDB
P$PNXT: $CALL P$GPDB ;GET THE PDB DATA
$RETIF ;ERROR..RETURN
CAIG S2,PB%NXT ;IS THERE A NEXT FIELD
$RETF ;NO, RETURN FALSE
SKIPE S1,PB%NXT(S1) ;GET THE VALUE AND RETURN
$RETT ;YES, O.K.
$RETF ;RETURN FALSE
SUBTTL P$PERR Get error routine given a PDB block
;THIS ROUTINE WILL RETURN INFORMATION FROM A PDB
;CALL S1/ ADDRESS OF THE PDB
;
;RETURN TRUE: S1/ ADDRESS OF THE ERROR ROUTINE
;
;RETURN FALSE: NO ERROR PDB
P$PERR: $CALL P$GPDB ;GET THE PDB DATA
$RETIF ;ERROR..RETURN
CAIG S2,PB%ERR ;IS THERE AN ERROR FIELD
$RETF ;NO, RETURN FALSE
SKIPE S1,PB%ERR(S1) ;GET THE VALUE AND RETURN
$RETT ;YES, O.K.
$RETF ;RETURN FALSE
SUBTTL P$PDEF Get default filler routine given a PDB block
;THIS ROUTINE WILL RETURN INFORMATION FROM A PDB
;CALL S1/ ADDRES OF THE PDB
;
;RETURN TRUE: S1/ ADDRESS OF THE DEFAULT FILLER ROUTINE
;
;RETURN FALSE: NO DEFAULT FILLER PDB
P$PDEF: $CALL P$GPDB ;GET THE PDB DATA
$RETIF ;ERROR..RETURN
CAIG S2,PB%DEF ;IS THERE A DEFAULT FIELD
$RETF ;NO, RETURN FALSE
SKIPE S1,PB%DEF(S1) ;GET THE VALUE AND RETURN
$RETT ;YES, O.K.
$RETF ;RETURN FALSE
SUBTTL P$PACT Get action routine given a PDB block
;THIS ROUTINE WILL RETURN INFORMATION FROM A PDB
;CALL S1/ ADDRESS OF THE PDB
;
;RETURN TRUE: S1/ ADDRESS OF THE ACTION ROUTINE
;
;RETURN FALSE: NO NEXT PDB
P$PACT: $CALL P$GPDB ;GET THE PDB DATA
$RETIF ;ERROR..RETURN
CAIG S2,PB%RTN ;IS THERE A ACTION ROUTINE
$RETF ;NO, RETURN FALSE
SKIPE S1,PB%RTN(S1) ;GET THE VALUE AND RETURN
$RETT ;YES, O.K.
$RETF ;RETURN FALSE
SUBTTL P$INTR Interrupt support code
;THIS ROUTINE WILL DETERMINE IF A BREAKOUT FROM THE PARSER
;SHOULD BE DONE AND IF SO RESET THE PC
P$INTR: SKIPE TAKFLG ;IN A TAKE COMMAND?
$RETT ;YES, JUST RETURN
MOVE S1,@TIMPC ;GET THE PC
$CALL S%INTR ;FLAG THE INTERRUPT
JUMPF .RETT ;NOT IN COMMAND
TOPS20 <
$CALL CNTCHR ;COUNT THE CHARACTERS
MOVE T1,S1 ;SAVE CHARACTER COUNT
$CALL K%TPOS ;ARE WE AT PROPER MARGIN
CAME S1,PRMTSZ ;SIZE OF THE PROMPT
JRST INTR.2 ;CHECK TIMER
SKIPE T1 ;ANY CHARACTERS IN BUFFER?
JRST INTR.2 ;YES, CHECK TIMER
;COVER A ^U ..DO THE RESET IF AT THE PROMPTS
MOVEI T1,NCHPW*BUFSIZ ;GET SIZE OF BUFFER
MOVEM T1,CMDBLK+.CMCNT ;RESET THE COUNT
SETZM S1,CMDBLK+.CMINC ;NO, SAVE THE COUNT
HRROI S1,BUFFER ;POINTER TO NEXT FIELD
MOVEM S1,CMDBLK+.CMPTR ;SAVE THE POINTER
> ;End TOPS20
TOPS10 <
INTR.1: MOVEI S2,BUFSIZ*NCHPW ;GET COMMAND BUFFER SIZE
CAME S1,S2 ;BUFFER EMPTY
JRST INTR.2 ;CHECK THE TIMER
> ;End TOPS10
MOVEI S1,S%EXIT ;ADDRESS OF RETURN PC
MOVEM S1,@TIMPC ;SAVE THE NEW PC
$RETT ;RETURN
INTR.2: SKIPN TIMCHK ;TIMER TRAPS IN USE
$RETT ;NO, JUST RETURN
$CALL SETTIM ;SET THE TIMER
$RETT ;RETURN
SUBTTL SETTIM Setup the timer function
;THIS ROUTINE WILL SETUP A TIMER TO WAKEUP THE PARSER
;AFTER N SECONDS TO CHECK THE STATE WHEN A BREAKOUT WAS
;NOT DONE
SETTIM:
TOPS20 <
$CALL I%NOW ;GET THE CURRENT TIME
MOVE S2,S1 ;PUT TIME IN S2
ADDI S2,^D3*^D60 ;REQUEST INTERRUPT IN 60 SECONDS
MOVEM S2,TIMSET ;REMEMBER IN CASE WE HAVE TO CLEAR IT
MOVSI S1,.FHSLF ;GET THE FORK HANDLE
HRRI S1,.TIMDT ;GET TIMER FUNCTION
HRRZ T1,TIMDAT ;GET THE TIMER CHANNEL
TIMER ;DO THE FUNCTION
ERJMP SETT.1 ;TRAP ERROR
$RETT ;RETURN
SETT.1: $TEXT(,<
?Timer Setup Failed for ^E/s1/>)
$RETT ;RETURN
> ;End TOPS20
TOPS10 <
$RETT
> ;End TOPS10
SUBTTL CLRTIM Clear the timer function
;THIS ROUTINE WILL CLEAR THE TIMER IF PROCESS HAS ALREADY AWOKEN
CLRTIM:
TOPS20 <
SKIPN S2,TIMSET ;TIMER INTERRUPT SET?
$RETT ;NO, JUST RETURN
MOVSI S1,.FHSLF ;GET THE FORK HANDLE
HRRI S1,.TIMDD ;GET TIMER FUNCTION
HRRZ T1,TIMDAT ;GET THE INTERRUPT CHANNEL
TIMER ;DO THE FUNCTION
ERJMP .+1 ;TRAP ERROR
SETZM TIMSET ;CLEAR THE TIMER FLAG
$RETT ;RETURN
> ;End TOPS20
TOPS10 <
$RETT
> ;End TOPS10
SUBTTL P$TINT Timer interrupt routine
;THIS ROUTINE IS GIVEN CONTROL ON A TIMER INTERRUPT
TOPS20 <
P$TINT: $BGINT 1 ;LEVEL NUMBER
SKIPE TIMSTI ;TIMER STORE CHARACTER
JRST TINT.1 ;CHECK IT OUT
SKIPN TIMCHK ;TIMER SETUP
$DEBRK ;NO, JUST EXIT
SKIPN TIMSET ;WAS TIMER SET
$DEBRK ;NO JUST EXIT
SETZM TIMSET ;CLEAR TIMER FLAG
MOVE S1,@TIMPC ;GET THE PC
$CALL S%INTR ;STILL IN COMMAND
SKIPT ;YES, GET OUT NOW
$DEBRK ;NO .. RETURN
SETOM TIMSTI ;SETUP TERMINAL WAKEUP
HRLZI S1,.TICCB ;SETUP THE CHARACTER
HRR S1,TIMDAT ;GET THE CHANNEL
ATI ;ATTACH IT
MOVX S1,RT%DIM ;GET DEFERRED TERMINAL INTERRUPTS
HRRI S1,.FHSLF ;FOR MY PROCESS
RTIW ;READ THE VALUES.. T1 HAS MASK
MOVX S1,ST%DIM ;SET DEFERRED WAKEUP CHARACTERS
HRRI S1,.FHSLF ;FOR MY PROCESS
TXO T1,1B<.CHCNB> ;TURN ON CONTROL B
STIW ;SET THE MASK
HLRZ S1,CMDBLK+.CMIOJ ;GET THE JFN
MOVEI S2,.CHCNB ;CTRL/B
STI ;SET THE CHARACTER
$DEBRK ;RETURN ..WAIT FOR CHARACTER
TINT.1: SETZM TIMSTI ;CLEAR THE FLAG
MOVEI S1,.TICCB ;SETUP CONTROL B
DTI ;DETACH IT
$CALL CNTCHR ;GET THE POSITION
MOVEI T1,NCHPW*BUFSIZ ;GET SIZE OF BUFFER
MOVEM T1,CMDBLK+.CMCNT ;RESET THE COUNT
MOVEM S1,CMDBLK+.CMINC ;NO, SAVE THE COUNT
HRROI S1,BUFFER ;POINTER TO NEXT FIELD
MOVEM S1,CMDBLK+.CMPTR ;SAVE THE POINTER
TINT.2: MOVE S1,@TIMPC ;GET THE PC
$CALL S%INTR ;FLAG THE INTERRUPT
MOVEI S1,S%EXIT ;GET THE PC
MOVEM S1,@TIMPC ;SAVE THE PC
SETOM TIMINT ;SETUP INTERRUPT FLAG
$DEBRK ;DEBRK
> ;End TOPS20
TOPS10 <
P$TINT: $BGINT 1 ;LEVEL NUMBER
$DEBRK ;NO, JUST EXIT
> ;End TOPS10
SUBTTL CNTCHR Count characters in the buffer
;THIS ROUTINE WILL COUNT THE CHARACTERS IN THE COMMAND INPUT
;BUFFER UP TO THE NULL.
;
;RETURN S1/ COUNT OF CHARACTERS
CNTCHR: HRLI S2,(POINT 7,) ;SETUP BYTE POINTER
HRRI S2,BUFFER ;TO THE TEXT
SETZM S1 ;CLEAR COUNTER
CNTC.1: ILDB T1,S2 ;GET A BYTE
JUMPE T1,.RETT ;NULL?..RETURN
AOJA S1,CNTC.1 ;NO, GET NEXT ONE
SUBTTL REPRMT Do reprompt of command
;THIS ROUTINE WILL DO A REPROMPT BY PLACING A ^R IN THE TERMINALS
;INPUT BUFFER
REPRMT:
TOPS20 <
$CALL GETT.2 ;REPROMPT THE STRING
$RETT ;RETURN
> ;End TOPS20
TOPS10 <
$RETT ;RETURN
> ;End TOPS10
SUBTTL P$HELP Routine to display help from file
;Local storage for P$HELP
STRLEN==^D80/5 ;Max length of a string
TXTLEN==^D80/5 ;Length of text buffer
BYTCLC==TXTLEN*5-1 ;MAXIMUM BYTES FOR TEXT LESS
; ONE FOR THE NULL
DEFINE $TDATA(NAME,SIZE) <
..TRR==10 ;;REMEMBER RADIX
RADIX 8
..NV==1 ;;INIT THE FRAME COUNT
.TRV1<NAME,SIZE> ;;ALLOCATE FIRST ARG
DEFINE $TDATA(NAM,SIZ) <
.TRV1<NAM,SIZ>>> ;;REDEFINE $TDATA CALLS
DEFINE $TRVAR <
IFDEF ..NV,<
PUSHJ P,.TRSET ;;Call the allocator
XWD ..NV,..NV ;;Set length argument
PURGE ..TRR,..NV>> ;;Purge the symbols
$TDATA HLPIFN,1 ;STORAGE FOR HELP FILE IFN
$TDATA HLPFOB,FOB.MZ ;RESERVE AREA FOR FOB
$TDATA HLPCNT,1 ;NUMBER OF STRINGS FOUND
$TDATA SRCSTR,STRLEN ;CURRENT SEARCH DATA
$TDATA HLPSTR,STRLEN ;HELP STRING
$TDATA SCHARG,1 ;SEARCH ARGUMENT
$TDATA BYTECT,1 ;NUMBER OF BYTES REMAINING
$TDATA BYTEBP,1 ;POINTER TO LAST BYTE STORED
$TDATA HLPTXT,TXTLEN ;START OF TEXT
;Flag definitions for P$HELP (T4 is flag AC)
FL.DSP==1B0 ;Display this line
FL.DSS==1B1 ;Display scratch flag
FL.EOF==1B2 ;End of file seen
FL.CRL==1B3 ;We just saw CRLF
FL.WLD==1B4 ;We saw an "*" for this field
FL.NUL==1B5 ;We were called with a null string
FL.QUA==1B6 ;We saw a "/" for this field
;P$HELP is a subroutine to search for specified help text entry
; in the system help file and output it to the user's
; terminal. (Via the default text output routine the user
; specified in their library initialization)
;Call: S1/ Address of Help file FD
; S2/ Pointer to search string
;True return: No returned arguments
; Help text has been displayed
;False return: Error message has been displayed
;The possible error conditions that may be returned are:
; 1) No Help file available
; 2) Specified keyword not found
; 3) IO error reading Help file
ENTRY P$HELP
P$HELP: $SAVE <T1,T2,T3,T4,P1>
$TRVAR ;ALLOCATE LOCAL STORAGE
SETZM BYTECT ;CLEAR REMAINING BYTE COUNT
SETZM HLPTXT ;CLEAR FIRST WORD OF TEXT
MOVEM S1,FOB.FD+HLPFOB ;SAVE ADDRESS OF FD
TLCE S2,777777 ;Make real pointer
TLCN S2,777777
HRLI S2,(POINT 7)
MOVEM S2,SCHARG ;SAVE STRING POINTER
MOVX S1,FLD(7,FB.BSZ)+FLD(1,FB.LSN)
MOVEM S1,FOB.CW+HLPFOB ;SETUP BYTESIZE
MOVEI S1,FOB.MZ ;SETUP FOR OPEN
MOVEI S2,HLPFOB
$CALL F%IOPN ;OPEN THE HELP FILE
JUMPF [MOVEI S2,HLPFNF ;POINT TO ERROR TEXT
SETOM HLPIFN ;SET FILE NOT OPEN FLAG
JRST HELPRT]
MOVEM S1,HLPIFN ;SAVE THE IFN
SETOM S2 ;GET ACTUAL FILE NAME
$CALL F%FD
MOVEM S1,FOB.FD+HLPFOB ;SAVE IN CASE OF ERROR
MOVE S1,SCHARG ;GET POINTER TO DESIRED HELP
MOVE S2,[POINT 7,HLPSTR] ;STORE IN A SAFE PLACE
SETZ P1, ;Say we have no pointer yet
HELP.1: ILDB T1,S1 ;Get a character
CAIE T1," " ;Have a space?
CAIN T1,11 ;Or a tab?
JRST [SKIPN P1 ;Yes, have one previously?
MOVE P1,S2 ;No, save current location
JRST HELP.2] ;Go save it
CAIG T1," " ;Good character?
JRST HELP.3 ;No, go finish
SETZ P1, ;Real character, say no pointer
; Save current character
HELP.2: IDPB T1,S2 ;Save it
JRST HELP.1 ;Go for more
HELP.3: SKIPE P1 ;Any adjustment?
MOVE S2,P1 ;Yes, get real pointer
SETZ T1, ;TERMINATE STRING WITH A NULL
IDPB T1,S2
$CALL GETHLP ;CALL MAIN WORKING CODE
;AS A SUBROUTINE.
SKIPF ;ANYTHING FAIL?
SETZ S2,0 ;NO, SO CLEAR ERROR MESSAGE
HELPRT: SETZ S1,0 ;ALWAYS RETURN ERROR BLOCK
;ADDRESS REGISTER
DMOVE T1,S1 ;RELOCATE ERROR ARGUMENTS
SKIPE S2 ;ALL OK?
$TEXT (,^I/0(S2)/) ;NO, DISPLAY ERROR
SKIPL S1,HLPIFN ;GET THE IFN IF ANY
$CALL F%REL ;RELEASE THE FILE
SKIPN S2,T2 ;STATUS
$RETT
$RETF
HLPFNF: ITEXT<%Help file "^F/@FOB.FD+HLPFOB/" not found>
;GETHLP is herein defined as a subroutine only for the purpose of
; clarifying the code. The subroutine does all of the
; "work" involved in searching the data file for the
; specified ASCII string and displaying it on the terminal.
;Call: No calling arguments. T3 contains address of
; dynamic page
;True return: No arguments returned
;False return: S2 contains address of error message
GETHLP: SETZM HLPCNT ;COUNT NUMBER OF ENTRIES
SETZM T4 ;CLEAR THE FLAGS
MOVE S1,SCHARG ;Get calling pointer
ILDB S2,S1 ;Get the first byte
CAIN S2,.CHNUL ;Null string?
TXO T4,FL.DSP!FL.NUL ;YES, display and remember
CAIN S2,"/" ;Qualifier?
JRST [TXO T4,FL.QUA ;YES, remember it
ILDB S2,S1 ;Get the next byte
JRST .+1]
CAIN S2,"*" ;Wild card?
TXO T4,FL.WLD ;YES, match all
HELP.A: TXNE T4,FL.EOF ;End of file?
JRST HELP.C ;YES, return
$CALL GETBYT ;Get a byte from help file
JUMPF HELP.C ;Assume EOF
CAIE S2,"*" ;Want to check display?
JRST HELP.B ;No, skip this
SKIPE HLPCNT ;Yes, but displayed any entry yet?
JRST [TXNE T4,FL.WLD ;Yes, but are we displaying all?
JRST .+1 ;Yes, continue displaying
JRST HELP.C] ;No, terminate searching
$CALL HLPCHK ;No display yet or all, go and check
JRST HELP.A
HELP.B: CAIN S2,"!" ;Is this a comment?
JRST [$CALL HLPCOM ;Yes
JRST HELP.A]
CAIN S2,"@" ;Indirecting?
JRST [$CALL HLPIND ;Yes
JRST HELP.A]
CAIN S2,"/" ;Qualifier?
JRST [$CALL HLPQUA ;Yes
JRST HELP.A]
TXNE T4,FL.DSP ;Are we displaying?
AOS HLPCNT ;YES, remember it
$CALL HLPEOL ;Process this line
JRST HELP.A ;Do the next line
HELP.C: SKIPE HLPCNT ;ANY HELP FOUND?
JRST HELP.D ;YES, FORCE OUT LAST LINE
MOVEI S2,HLPNHA ;NO, RETURN AN ERROR
$RETF
HELP.D: MOVEI S2,.CHNUL ;Get a null
$CALL PUTBYT
$TEXT (,^T/HLPTXT/^A) ;Force out the buffer
$RETT
HLPNHA: ITEXT<%No help available for "^Q/SCHARG/">
;Routine to process a help file line
HLPQUA: PJRST HLPEOL ;Process this line
HLPCOM: TXZE T4,FL.DSP+FL.DSS ;Clear and check display flag
TXO T4,FL.DSS ;Remember it was set
HLPLIN: $CALL GETBYT ;Read a byte from file
JUMPF HLPEOF ;Check for error or EOF
HLPEOL: TXNE T4,FL.DSP ;Want to display?
$CALL PUTBYT ;Yes
CAIE S2,.CHCRT ;Was it a Carriage return?
JRST HLPLIN ;NO, loop until we find one
$CALL GETBYT ;Read another byte
JUMPF HLPEOF ;Check for error or EOF
TXNE T4,FL.DSP ;Want to display?
$CALL PUTBYT ;Yes
CAIE S2,.CHLFD ;Was it a line feed?
JRST HLPLIN ;NO, loop until we find CRLF
TXZE T4,FL.DSS ;Need to restore display flag?
TXO T4,FL.DSP ;YES, set it again
TXO T4,FL.CRL ;Say we just say CRLF
$RETT ;Return
HLPIND: $CALL HLPCOM ;Treat indirect as a comment
$RETT
HLPEOF: TXO T4,FL.EOF ;Set end of file
CAIN S1,EREOF$ ;Really end of file?
$RETF ;YES, just return
HLPERR: MOVEI S2,HLPERF ;NO, error reading file
$RETF
HLPERF: ITEXT<?Error reading help file "^F/@FOB.FD+HLPFOB/">
;HLPCHK is called when an "*" is seen in column 1 of the help file
; It checks to see if the remaining keyword text should
; be displayed.
HLPCHK: TXNE T4,FL.WLD ;Wild field?
JRST [TXO T4,FL.DSP ;Yes
$RETT]
MOVE T1,[POINT 7,SRCSTR] ;Point to storage
TXZ T4,FL.DSP ;Clear display flag
HLPC.A: $CALL GETBYT ;Get a byte from help file
JUMPF HLPEOF ;Check for error or EOF
IDPB S2,T1 ;Store the byte
CAIE S2,.CHCRT ;Was it a carriage return?
JRST HLPC.A ;NO, get the next byte
MOVEI S2,.CHNUL ;YES, replace it with a null
DPB S2,T1
$CALL GETBYT ;Insist on CRLF
JUMPF HLPEOF ;Check for error or EOF
CAIE S2,.CHLFD
$RETF ;Oops..the help file is bad
HLPC.B: HRROI S1,HLPSTR ;Point to desired string
HRROI S2,SRCSTR ;Point to help string
$CALL S%SCMP ;See if they match
SKIPE S1 ;Do they match?
TXNE S1,SC%SUB ; or almost match?
TXO T4,FL.DSP ;YES, display subsequent help
TXNE S1,SC%LSS ;Looked at enough?
TXO T4,FL.EOF ;YES, End the search
$RETT
;Subroutine to get a byte from the help file.
;Call: T4/ FL.DSP if byte is to be displayed
;Return: TRUE S2/ Byte from file
; FALSE S1/ Error code (Most likely end of file)
GETBYT: MOVE S1,HLPIFN ;Point to the file
$CALL F%IBYT ;Get the byte
CAIE S2,.CHLFD ;Line feed or Form feed?
CAIN S2,.CHFFD
$RET ;YES, just return
TXZ T4,FL.CRL ;NO, clear CRLF seen
$RET
;Subroutine to output data to our preallocated page. If overflow
; occurs the page is immediately output, the pointers are
; reset, and the page is reused.
;Call: S2 contains ASCII byte
;Return: Always to .+1
PUTBYT: SOSGE BYTECT ;ANY ROOM LEFT?
JRST PUTOUT ;NOPE
IDPB S2,BYTEBP ;YUP, PLANT THE CHARACTER
$RET
PUTOUT: PUSH P,S1 ;SAVE THE CHARACTER REGISTER
PUSH P,S2
$TEXT (,^T/HLPTXT/^A) ;TYPE THE DATA
MOVEI S1,BYTCLC ;RESET THE COUNT
MOVEM S1,BYTECT ;..
MOVE S2,[POINT 7,HLPTXT] ;AND THE BP
MOVEM S2,BYTEBP
POP P,S2
POP P,S1
JRST PUTBYT
SUBTTL End
XLIST ;TURN LISTING OFF
LIT ;DUMP LITERALS
LIST ;TURN LISTING ON
END