Trailing-Edge
-
PDP-10 Archives
-
klad_sources
-
klad.sources/gscn.mac
There is 1 other file named gscn.mac in the archive. Click here to see a list.
TITLE GSCN -- Command Scanner Interface for DIAGNOSTICS
SEARCH GLXMAC ;OPEN SYMBOLS NEEDED
SEARCH MACTEN
SEARCH UUOSYM
SALL
;This module emulates the command scanning and text input routines found
; in the TOPS-20 operating system. (Somewhat)
;SPECIAL DIAGNOSTIC DEFINITIONS, OVERRIDE GLXMAC
.PRIIN=100
.PRIOU=101
.FDSTR=2 ;STRUCTURE
.FDPPN=3 ;PPN
.FDNAM=4 ;NAME
.FDEXT=5 ;EXT
GJ%OLD=1B2
OPDEF GO [PUSHJ P,]
OPDEF RTN [POPJ P,]
OPDEF PUT [PUSH P,]
OPDEF GETIT [POP P,]
EXTERN $CCLIN
SUBTTL Table of Contents
; TABLE OF CONTENTS FOR GLXSCN
;
;
; SECTION PAGE
; 1. Table of Contents......................................... 2
; 2. Local Definitions......................................... 3
; 3. Module Storage............................................ 4
; 4. S%INIT -- Initialization of the Scanning Module......... 5
; 5. S%RCOC -- Read Character Output Control table.......... 6
; 6. S%WCOC -- Write Character Output Control table......... 6
; 7. S%STYP -- Set terminal type............................. 7
; 8. S%TXTI -- Handle Terminal Input......................... 8
; 9. TXTL -- Loop for inputting text......................... 9
; 10. Utilities for text handling............................... 10
; 11. SPCHK -- Check for special characters................... 15
; 12. CCU -- Handle ^U (Rubout entire line)................... 16
; 13. CCR -- Handle ^R (Re-type the line)..................... 17
; 14. CCDEL -- Handle Rubout (Delete one character)........... 18
; 15. CCW -- Handle ^W (Delete back to punctuation character). 19
; 16. BEGBUF -- Handle rubouts to beginning of buffer......... 19
SUBTTL Revision History
COMMENT \
Edit SPR/QAR/GCO Reason
---- ----------- -------------------------------------------
0001 Create GLXSCN module
0002 Fix a number of interrupt race problems and
start adding ESCape sequence code
0003 Add support for parsing of a string; fix bug in
.CMINI which caused prompts not at left margin
0004 TOTALLY HACKED UP FOR DIAGNOSTICS
\ ;END OF REVISION HISTORY
; Entry Points found in this module
ENTRY S%INIT ;INIT THE COMMAND SCANNER MODULE
ENTRY S%CMND ;SCAN A COMMAND
ENTRY S%SCMP ;COMPARE TWO STRINGS
ENTRY S%TBLK ;LOOK UP A STRING IN A TABLE
ENTRY S%ERR ;TYPE OUT SCANNER'S LAST ERROR
;SPECIAL DIAGNOSTICS MACROS
DEFINE $$DATA(NAM,SIZ<1>)<
NAM: BLOCK SIZ
>
DEFINE $$GDATA(NAM,SIZ<1>)<
NAM: BLOCK SIZ
>
SUBTTL Local Definitions
; Special Accumulator definitions
C==16 ;GLOBAL CHARACTER REGISTER
P5==P4+1 ;S%CMND NEEDS LOTS OF ACS
F==14 ;FLAG AC
Q1==15 ;
Q2==16 ;DON'T DEFINE Q3 OR Q4
; Special characters
.CHBSL=="\" ;BACKSLASH
; Control character former
DEFINE $C(A)<"A"-100> ;JUST ASCII MINUS LEAD BIT
; Bad parse return macro
DEFINE NOPARS(CODE,TEXT)<
MOVE T1,[XWD CODE,[ASCIZ /TEXT/]]
JRST XCOMNE > ;END OF NOPARS DEFINITION
; Special bit testing macros
DEFINE JXN(AC,FLD,ADDR)<
TXNN AC,FLD
SKIPA
JRST ADDR > ;END OF JXN DEFINITION
DEFINE JXE(AC,FLD,ADDR)<
TXNE AC,FLD
SKIPA
JRST ADDR > ;END OF JXE DEFINITION
DEFINE JXO(AC,FLD,ADDR)<
TXC AC,FLD
TXCN AC,FLD
JRST ADDR > ;END OF JXO DEFINITION
DEFINE RETSKP<JRST [AOS 0(P)
POPJ P,] >
; Bit table - 36. Words long with word N containing 1B<N>
XX==0
BITS: XLIST
REPEAT ^D36,<EXP 1B<XX>
XX==XX+1>
LIST
SUBTTL Module Storage
$$DATA RD,.RDSIZ ;INTERNAL ARGUMENT BLOCK
$$DATA PCALL ;PUSHDOWN LIST SAVE FOR COMND
$$DATA ATBPTR ;ATOM BUFFER POINTER (END)
$$DATA ATBSIZ ;ATOM BUFFER SIZE
$$DATA STKFEN ;FENCE FOR STACK RESTORATION
$$DATA FNARG ;FUNCTION ARGUMENT
$$DATA CMCCM,2 ;SAVED CC CODES
$$DATA CMRBRK ;POINTER TO BREAK SET TABLE
$$DATA CMCSF ;SAVED FLAGS
$$DATA CMCSAC,7 ;SAVED ACS DURING S%TXTI FROM S%CMND
$$DATA CMCSC ;
$$DATA CMCBLF ;
$$DATA TBA ;TABLE ARGUMENTS
$$DATA STRG ;TEMP STRING POINTER
$$DATA REMSTR ;"REMEMBER"ED STRING
$$DATA XXXPTR ;RE-USABLE STRING POINTER STORAGE
$$DATA CRBLK,CR.SIZ ;RETURNED BLOCK OF ANSWERS
$$DATA TABDON ;END OF TAB FOR "?"
$$DATA TABSIZ ;SIZE OF TAB LARGER THAN LARGEST KEYWORD
$$DATA LSTERR ;ERROR CODE RETURNED FROM NOPARS
$$DATA BIGSIZ ;LENGTH OF LONGEST KEYWORD
$$DATA KEYSIZ ;NOMINAL KEYWORD LENGTH
$$DATA PWIDTH ;TERMINAL'S WIDTH
$$DATA CURPOS ;LINE POSITION OF CURSOR
$$DATA Q3SAVE ;NO Q3 EXISTS
$$DATA IFOB ;INDIRECT FILESPEC FOB
$$DATA IIFN ;IFN OF INDIRECT FILE
$$DATA TI,.RDSIZ ;S%TXTI ARGUMENT BLOCK
$$DATA TRMUDX ;CONTROLLING TERMINAL'S UDX
$$DATA NODSIX ;SIXBIT NODE-ID
SUBTTL S%INIT -- Initialize the GLXSCN Module
IFN FTUUOS,<
S%INIT: MOVSI S1,'TTY' ;LOAD TTY NAME
IONDX. S1, ;GET THE I/O INDEX
JFCL ;IGNORE THE ERROR
MOVEM S1,TRMUDX ;AND STORE THE UDX
$RETT ;AND RETURN
> ;END IFN FTUUOS
IFN FTJSYS,<
S%INIT: $RETT ;RETURN
> ;END IFN FTJSYS
SUBTTL S%ERR - ERROR TYPEOUT ROUTINE
IFN FTUUOS,<;!!!BEGINNING OF TOPS10 ROUTINE
S%ERR: HRRZ S1,LSTERR ;GET ADDRESS OF ERROR
JUMPE S1,[POPJ P,0] ;RETURN IF NONE
OUTSTR [ASCIZ/
?/]
OUTSTR @S1
OUTSTR [ASCIZ /
/]
POPJ P,0
>; !!!END OF TOPS10 ROUTINE
IFN FTJSYS,<;!!!BEGINNING OF TOPS20 ROUTINE
S%ERR: MOVX S1,.PRIOU ;TO PRIMARY OUTPUT
MOVE S2,[.FHSLF,,-1] ;OUR LAST ERROR
ERSTR ;TYPE OUT THE ERROR STRING
HALTF ;UNDEFINED ERROR NUMBER
HALTF ;BAD DESTINATION DESIGNATOR
POPJ P,0
>;!!!END OF TOPS20 ROUTINE
SUBTTL S%CMND -- Scan a command
;The S%CMND routine provides a command scanner interface similar to the
; TOPS-20 COMND JSYS.
;CALL IS: S1/ Pointer to Command State Block
; S2/ Pointer to list of Function Descriptor Blocks
; See GLXMAC or MONSYM for a description of these
;TRUE RETURN: ALWAYS,
; S1/ Length of Command Reply block
; S2/ Address of the Command Reply block
;LOCAL FLAGS (RH OF F)
CMQUES==1B18 ;? TYPED
CMSWF==1B19 ;BEG OF SWITCH SEEN
CMUSRF==1B20 ;USER NAME REQUIRED
CMDEFF==1B21 ;DEFAULT FIELD GIVEN
CMCFF==1B22 ;^F RECOGNIZED FIELD
CMQUE2==1B23 ;IN SECOND OR SUBSEQUENT HELP POSSIBILITY
CMBOL==1B24 ;FIELD IS AT BEG OF LINE
CMTF1==1B25 ;INTERNAL TEMP FLAG
CMINDF==1B26 ;DOING GTJFN ON INDIRECT FILE
;FLAGS IN FUNCTION DISPATCH TABLE
CMNOD==1B0 ;NO DEFAULT POSSIBLE
NOIBCH=="(" ;NOISE WORD BEG CHARACTER
NOIECH==")" ;NOISE WORD END CHARACTER
CMSWCH=="/" ;SWITCH CHARACTER
CMSWTM==":" ;SWITCH TERMINATOR
CMHLPC=="?" ;HELP CHARACTER
CMCOM1=="!" ;COMMENT CHARACTER
CMCOM2==";" ;FULL LINE COMMENT CHARACTER
CMDEFC=="#" ;DEFAULT FIELD CHARACTER
CMFREC=="F"-100 ;FIELD RECOGNITION CHARACTER
CMINDC=="@" ;INDIRECT FILE CHARACTER
CMRDOC=="H"-100 ;REDO COMMAND CHARACTER
CMQTCH=="""" ;CHARACTER FOR QUOTED STRINGS
CMCONC=="-" ;LINE CONTINUATION CHARACTER
;NOPARSE ERROR CODES
NPXNSW==1
NPXNOM==2
NPXNUL==3
NPXINW==4
NPXNC==5
NPXICN==6
NPXIDT==7
NPXNQS==10
NPXAMB==11
NPXNMT==12
NPXCMA==13
NPXNNC==14 ;TOO MANY CHARACTERS IN NODE NAME
NPXNNI==15 ;ILLEGAL CHARACTER IN NODE NAME
NPXNSN==16 ;NO SUCH NODE
IFN FTJSYS,< ;BEGINNING OF COMND JSYS CALL
S%CMND: COMND
ERJMP .RETF
MOVEM S1,CRBLK+CR.FLG
MOVEM S2,CRBLK+CR.RES
MOVEM T1,CRBLK+CR.FNB
MOVEI S1,CR.SIZ
MOVEI S2,CRBLK
$RETT
>;END OF COMND JSYS CALL
;DIAGNOSTICS COMND JSYS EQUIVELANT
S%CMND: PUSHJ P,.S%CMND
MOVE 1,CRBLK+CR.FLG
MOVE 2,CRBLK+CR.RES
MOVE 3,CRBLK+CR.FNB
POPJ P,
F%IBYT: GO $CCLIN ;GET CHAR FROM TAKE FILE
$RETT
F%IOPN: $STOP(FSO,F%IOPN ERROR)
F%REL: $STOP(FSR,F%REL ERROR)
IFN FTUUOS,<;BEGINNING OF TOPS-10 COMND CALL ROUTINE
;!!!!!NOTE WELL - THIS CONDITIONAL RUNS TO THE END OF COMND ROUTINE
.S%CMND:HRRZM P,PCALL ;SAVE STACK POINTER
PUSHJ P,.SAVE4 ;SAVE P REGS
SAVE P5 ;P5 WON'T BE SAVED BY THAT
PUSHJ P,.SAVET ;AND T REGS
SAVE Q1 ;AND Q REGS
SAVE Q2
SAVE F ;AND F REGISTER
PUSHJ P,XCOMND ;DO THE WORK
HRRZ T4,.CMFLG(P2) ;GET REPARSE DISPATCH ADDRESS IF ANY
JUMPE T4,COMN1
TXNE F,CM%RPT ;REPARSE NEEDED?
HRRM T4,@PCALL ;YES, EFFECT TRANSFER
COMN1: POPJ P,0 ;NO RETURN
XCOMND::MOVEM S1,P2 ;SAVE BLOCK PTR
MOVEM S2,P1 ;SAVE FN BLOCK PTR
HRL P1,P1 ;SAVE COPY OF ORIGINAL
MOVEM P,STKFEN ;SAVE CURRENT STACK AS FENCE
MOVEI T1,[.CMRTY ;LIST OF BYTE POINTERS TO CHECK
.CMBFP
.CMPTR
.CMABP
0] ;MARK OF END OF LIST
PUSHJ P,CHKABP ;CHECK ALL BYTE PTRS
MOVE P3,.CMCNT(P2) ;SETUP ACTIVE VARIABLES
MOVE P4,.CMPTR(P2)
MOVE P5,.CMINC(P2)
HLLZ F,.CMFLG(P2) ;GET 'GIVEN' FLAGS
TXZ F,CM%PFE
TXZE F,CM%ESC ;PREVIOUS FIELD HAD ESC?
TXO F,CM%PFE ;YES
PUSHJ P,K%RCOC ;GET COC MODES
DMOVEM S1,CMCCM ;SAVE THEM
TXZ S1,3B<CMFREC*2+1> ;NO ECHO ^F
TXZ S1,3B<CMRDOC*2+1> ;OR ^H
TXO S1,3B<.CHLFD*2+1> ;PROPER HANDLING OF NL
TXZ S2,3B<.CHESC*2+1-^D36> ;SET ESC TO NO ECHO
PUSHJ P,K%WCOC ;AND WRITE THEM BACK
; ..
; ..
XCOMN0: MOVE P,STKFEN ;NORMALIZE STACK IN CASE ABORTED ROUTINES
TXZ F,CM%ESC+CM%NOP+CM%EOC+CM%RPT+CM%SWT+CMBOL+CMCFF+CMDEFF+CMINDF ;INIT FLAGS
CAMN P4,.CMBFP(P2) ;AT BEG OF LINE?
TXO F,CMBOL ;YES
XCOM1: LOAD T1,.CMFNP(P1),CM%FFL ;GET FUNCTION FLAGS
STORE T1,F,CM%FFL ;KEEP WITH OTHER FLAGS
HLRZ Q1,P1 ;GET CM%DPP FLAG FROM FIRST BLOCK ONLY
XOR F,.CMFNP(Q1)
TXZ F,CM%DPP
XOR F,.CMFNP(Q1)
MOVE T1,.CMDAT(P1) ;GET FUNCTION DATA IF ANY
MOVEM T1,FNARG ;KEEP LOCALLY
LOAD T1,.CMFNP(P1),CM%FNC ;GET FUNCTION CODE
CAIL T1,0 ;VALIDATE FN CODE
CAIL T1,MAXCFN
$STOP(BFC,Bad function code)
MOVE T1,CFNTAB(T1) ;GET TABLE ENTRY FOR IT
JXN T1,CMNOD,XCOM3 ;DISPATCH NOW IF NO DEFAULT POSSIBLE
PUSHJ P,INILCH ;SKIP SPACES AND INIT ATOM BUFFER
PUSHJ P,CMCIN ;GET INITIAL INPUT
CAIN T1,CMCONC ;POSSIBLE LINE CONTINUATION?
JRST [PUSHJ P,CMCIN ;YES, SEE IF NL FOLLOWS
CAIE T1,.CHLFD
PUSHJ P,CMRSET ;NO, RESET FIELD
PUSHJ P,CMCIN ;RE-READ FIRST CHAR
JRST .+1] ;CONTINUE
CAIN T1,CMCOM2 ;COMMENT?
JRST CMCMT2 ;YES
CAIN T1,CMCOM1
JRST CMCMT1 ;YES
CAIN T1,CMINDC ;INDIRECT INDICATOR?
JRST [TXNN F,CM%XIF ;YES, INDIRECT FILES ALLOWED?
JRST CMIND ;YES, DO IT
JRST .+1] ;NO, KEEP CHARACTER AS ORDINARY INPUT
CAIN T1,.CHLFD ;EOL BEGINS FIELD?
JRST [PUSHJ P,CMDIP ;YES, PUT IT BACK
LOAD T1,.CMFNP(P1),CM%FNC ;GET FUNCTION CODE
CAIN T1,.CMCFM ;CONFIRM?
JRST XCOM3 ;YES, DO IT
TXNE F,CM%DPP ;HAVE DEFAULT?
JRST XCOM5 ;YES, USE IT
TXNN F,CMBOL ;AT BGN OF BFR?
JRST XCOM3 ;NO, TRY NULL FIELD
PUSHJ P,CMRSET
SETZ P5,0 ;YES, EMPTY LINE. IGNORE
PUSHJ P,CMRTY1 ;REDO PROMPT
JRST XCOMN0] ;TRY AGAIN
CAIE T1,.CHESC ;ESC AT BEG OF FIELD?
CAIN T1,CMFREC
JRST XCOM4 ;^F AT BEG OF FIELD
; CAIN T1,CMDEFC ;OR DEFAULT REQUEST?
; JRST XCOM4 ;YES
XCOM2: PUSHJ P,CMDIP ;PUT CHAR BACK
XCOM3: LOAD T1,.CMFNP(P1),CM%FNC ;GET FUNCTION CODE
JRST @CFNTAB(T1) ;DO IT
;ESC OR ^F AT BEG OF FIELD
XCOM4: TXNN F,CM%DPP ;YES, HAVE DEFAULT STRING?
JRST XCOM2 ;NO
PUSHJ P,CMDCH ;FLUSH RECOG CHAR
XCOM5: HLRZ Q1,P1 ;GET PTR TO FIRST FLD BLOCK
MOVE T1,.CMDEF(Q1) ;GET DEFAULT STRING PTR
PUSHJ P,CHKBP ;CHECK POINTER
MOVEM T1,Q1
TXO F,CMDEFF ;NOTE FIELD ALREADY IN ATOM BFR
XCOM6: ILDB T1,Q1
JUMPE T1,[PUSHJ P,CHKLCH ;CHECK FOR NULL DEFAULT STRING
CAIG T1,0
$STOP(BDS,Bad Default String) ;NULL STRING ILLEGAL
PUSHJ P,TIELCH ;END OF STRING, TIE OFF ATOM BUFFER
TXNE F,CMCFF ;^F RECOG?
JRST XCOMRF ;YES, GO GET MORE INPUT
JXE F,CM%ESC,XCOM3 ;GO DIRECT TO FUNCTION IF NO RECOG
MOVEI T1,.CHESC
PUSHJ P,CMDIBQ ;YES, APPEND ESC TO BUFFER
PUSHJ P,CMRSET ;RESET LINE VARIABLES
JRST XCOMN0] ;TREAT AS ORDINARY INPUT
PUSHJ P,STOLCH ;STOR CHAR IN ATOM BUFFER
TXNE F,CM%ESC ;RECOGNIZING?
PUSHJ P,CMDIB ;YES, CHAR TO MAIN BUFFER ALSO
JRST XCOM6
;COMMENT
CMCMT2: SETO T1, ;SAY NO TERMINATOR OTHER THAN EOL
CMCMT1: MOVEM T1,Q2 ;REMEMBER MATCHING TERMINATOR
CMCOM: PUSHJ P,CMCIN ;GET NEXT CHAR
CAIN T1,CMCONC ;POSSIBLE LINE CONTINUATION?
JRST [PUSHJ P,CMCIN ;YES, CHECK FOR NL FOLLOWING
CAIN T1,.CHLFD
JRST CMCOM ;YES, STAY IN COMMENT
JRST .+1] ;NO, EXAMINE CHARACTER
CAIE T1,CMFREC ;RECOG REQUEST?
CAIN T1,.CHESC
JRST [PUSHJ P,CMAMB ;YES, DING
JRST CMCOM] ;KEEP GOING
CAIN T1,.CHLFD ;END OF LINE?
JRST [PUSHJ P,CMDIP ;YES, PUT IT BACK
JRST XCOM1] ;DO WHATEVER
CAMN T1,Q2 ;MATCHING TERMINATOR?
JRST XCOM1 ;YES, END OF COMMENT
JRST CMCOM ;NO, KEEP LOOKING
;TABLE OF COMND FUNCTIONS
CFNTAB: PHASE 0
.CMKEY::!XCMKEY ;KEYWORD
.CMNUM::!XCMNUM ;INTEGER
.CMNOI::!XCMNOI+CMNOD ;NOISE WORD
.CMSWI::!XCMSWI ;SWITCH
.CMIFI::!XCMIFI ;INPUT FILE
.CMOFI::!XCMOFI ;OUTPUT FILE
.CMFIL::!XCMFIL ;GENERAL FILESPEC
.CMFLD::!XCMFLD ;ARBITRARY FIELD
.CMCFM::!XCMCFM ;CONFIRM
.CMDIR::!XCMDIR ;DIRECTORY NAME
.CMUSR::!XCMUSR ;USER NAME
.CMCMA::!XCMCMA ;COMMA
.CMINI::!XCMINI+CMNOD ;INITIALIZE COMMAND
.CMFLT::!XCMFLT ;FLOATING POINT NUMBER
.CMDEV::!XCMDEV ;DEVICE NAME
.CMTXT::!XCMTXT ;TEXT
.CMTAD::!XCMTAD ;TIME AND DATE
.CMQST::!XCMQST ;QUOTED STRING
.CMUQS::!XCMUQS+CMNOD ;UNQUOTED STRING
.CMTOK::!XCMTOK ;TOKEN
.CMNUX::!XCMNUX ;NUMBER DELIMITED BY NON-DIGIT
.CMACT::!XCMACT ;ACCOUNT
.CMNOD::!XCMNOD ;NODE NAME
DEPHASE
MAXCFN==.-CFNTAB
;HERE TO GET MORE INPUT AND RETRY FIELD
XCOMRF: PUSHJ P,CMRSET ;RESET VARIABLES TO BEGINNING OF FIELD
PUSHJ P,CMCIN1 ;GET MORE INPUT
HLR P1,P1 ;RESET ALTERNATIVE LIST
JRST XCOMN0
;RESET VARIABLES TO BEGINNING OF CURRENT FIELD
CMRSET: SUB P5,P3 ;RESET VARIABLES TO BGN OF FIELD
ADD P5,.CMCNT(P2) ;KEEP ALL CURRENT INPUT
MOVE P3,.CMCNT(P2)
MOVE P4,.CMPTR(P2)
POPJ P,0
;STANDARD EXITS
;RETURN BECAUSE ENTIRE COMMAND DELETED
XCOMXL: TXO F,CM%RPT ;NOTE REPEAT PARSE NEEDED
MOVE T1,P4 ;BACK POINTER TO BEG OF BUFFER
MOVE T2,.CMBFP(P2)
MOVEM T2,P4
PUSHJ P,SUBBP ;SEE HOW MANY CHARS DELETED
ADDM T1,P3 ;UPDATE SPACE COUNT
SETZ P5, ;NOTE NO INPUT
PUSHJ P,CMRTY1 ;RETYPE PROMPT
JRST XCOMXI ;EXIT
;RETURN AND REPEAT PARSE BECAUSE USER DELETED BACK INTO ALREADY
;PARSED TEXT
XCOMRP: TXO F,CM%RPT ;REQUEST REPEAT
MOVE T1,P4 ;COMPUTE NUMBER CHARS IN BUFFER
MOVE T2,.CMBFP(P2)
MOVEM T2,P4 ;RESET PTR TO TOP OF BUFFER
PUSHJ P,SUBBP ;COMPUTE PTR-TOP
MOVEM T1,P5 ;SET AS NUMBER CHARS FOLLOWING PTR
ADDM T1,P3 ;RESET COUNT TO TOP OF BUFFER
JUMPE T1,XCOMXL ;JUMP IF LINE NOW EMPTY
JRST XCOMX1 ;OTHERWISE UPDATE VARIABLES AND EXIT
;GOOD RETURN
XCOMXR: TXNE F,CM%ESC ;RECOG CHARACTER TERMINATED?
PUSHJ P,CMDCH ;YES, FLUSH IT
XCOMXI: TXZN F,CM%ESC ;FIELD TERMINATED WITH RECOG?
JRST XCOMX1 ;NO
TXNE F,CMCFF ;^F RECOG?
JRST XCOMRF ;YES, GET MORE INPUT BEFORE RETURNING
TXO F,CM%ESC ;SET FLAG
MOVEI T1," " ;TERMINATE TYPESCRIPT WITH SPACE
PUSHJ P,CMDIB
XCOMX1: MOVEM P3,.CMCNT(P2) ;UPDATE VARIABLES
MOVEM P4,.CMPTR(P2)
MOVEM P5,.CMINC(P2)
XCOMX2: MOVE P,STKFEN ;RESET STACK
DMOVE S1,CMCCM ;GET SAVED CC MODES
PUSHJ P,K%WCOC ;RESTORE THEM
MOVEM P1,CRBLK+CR.FNB ;RETURN PTR TO FUNCTION BLOCK USED
TXZ F,CM%FFL ;FLUSH FUNCTION FLAGS
HLLM F,.CMFLG(P2) ;RETURN FLAGS
MOVEM P2,CRBLK+CR.FLG ;STORE BLK ADDRESS
HLLM F,CRBLK+CR.FLG ;AND THE FLAGS
MOVEI S1,CR.SIZ ;LOAD SIZE OF RETURNED BLOCK
MOVEI S2,CRBLK ;AND ITS LOCATION
$RETT ;AND TAKE A GOOD RETURN
;FAILURE RETURNS - FAILED TO PARSE
XCOMNE: MOVEM T1,LSTERR ;SAVE ERROR CODE
XCOMNP: JXN F,CMQUES,CMRTYP ;IF IN HELP, DON'T RETURN NOW
PUSHJ P,CMRSET ;RESET FIELD VARIABLES
MOVEM P5,.CMINC(P2) ;FIX USER BLOCK
LOAD T1,.CMFNP(P1),CM%LST ;GET PTR TO NEXT FN BLOCK
HRRM T1,P1 ;SAVE IT
JUMPN T1,XCOMN0 ;DISPATCH IF THERE IS ANOTHER FUNCTION
TXO F,CM%NOP ;NO OTHER POSSIBILITIES, SAY NO PARSE
JRST XCOMX2
;HERE AFTER EACH HELP OUTPUT
CMRTYP: PUSHJ P,CMRSET ;RESET FIELD VARIABLES
LOAD T1,.CMFNP(P1),CM%LST ;GET NEXT FUNCTION IN LIST
HRRM T1,P1
TXO F,CMQUES+CMQUE2 ;NOTE IN SECOND HELP POSSIBILITY
JUMPN T1,XCOMN0 ;DO SUBSEQUENT HELPS
MOVEI T1,.CHLFD ;START NEW LINE
PUSHJ P,CMCOUT
HLR P1,P1 ;END OF LIST, REINIT IT
SOS P5 ;FLUSH QMARK FROM INPUT
TXZ F,CMQUES+CMQUE2 ;NOTE NOT IN HELP
PUSHJ P,CMRTY1 ;RETYPE LINE
JRST XCOMN0 ;RESTART PARSE OF CURRENT FIELD
XCOMEO: TXO F,CM%NOP ;SET NO PARSE
MOVEI S2,CRBLK
MOVE P,STKFEN ;FIXUP STACK
$RETF
;RETYPE LINE INCLUDING ADVANCE INPUT IF ANY
CMRTY1:;** HRRZ T1,.CMIOJ(P2) ;GET OUT JFN
;** RFPOS
;** HRRZ T2,T2
;** JUMPE T2,CMRTY2 ;JUMP IF AT LEFT MARGIN
HRROI T1,[BYTE (7) .CHCRT,.CHLFD] ;NOT AT MARGIN, GIVE CRLF
PUSHJ P,CMSOUT ;
CMRTY2: SKIPE Q1,.CMRTY(P2) ;GET ^R PTR IF ANY
CMRTY3: CAMN Q1,.CMBFP(P2) ;UP TO TOP OF BFR?
JRST CMRTY4 ;DONE WITH ^R PTR
ILDB T1,Q1 ;TYPE ^R BFR
JUMPN T1,[PUSHJ P,CMCOUT
JRST CMRTY3]
CMRTY4: MOVE Q1,.CMBFP(P2) ;GET MAIN BFR PTR
CMRTY5: CAMN Q1,P4 ;UP TO CURRENT PTR?
JRST CMRTY6 ;YES, GO DO ADVANCE INPUT
ILDB T1,Q1 ;TYPE OUT COMMAND BFR
PUSHJ P,CMCOUT
JRST CMRTY5
CMRTY6: MOVE Q2,P5 ;GET INPUT COUNT
CMRTY7: SOJL Q2,[SETZ T1,0 ;ALL INPUT PRINTED, TIE OFF
IDPB T1,Q1 ;BUFFER
POPJ P,0]
ILDB T1,Q1
PUSHJ P,CMCOUT
JRST CMRTY7
;INDIRECT FILE HANDLING
CMIND: JXO F,CMQUE2,XCOMNP ;NO SECOND HELP POSSIBILITIES
PUSHJ P,CMATFI ;GET A JFN ON THE INDIRECT FILE
JRST CMINDE ;FAILED
PUSHJ P,CMCFM0 ;DO A CONFIRM
JRST [HRROI T1,[ASCIZ /
?Indirect file not confirmed.
/]
PUSHJ P,CMSOUT
TXO F,CM%NOP
JRST XCOMX2]
LOAD S1,.CMGJB(P2),CM%GJB ;GET ADDR OF FD
SKIPN S2,.FDSTR(S1) ;IF DEVICE HAS NOT BEEN SPECIFIED,
MOVSI S2,'DSK' ;DEFAULT TO DISK
MOVEM S2,.FDSTR(S1) ;
SKIPN S2,.FDEXT(S1) ;AND DEFAULT THE EXTENSION
MOVSI S2,'CMD' ;TO ".CMD"
MOVEM S2,.FDEXT(S1) ;
STORE S1,IFOB+FOB.FD ;STORE IT
MOVX S1,FB.LSN!<INSVL.(7,FB.BSZ)> ;IGNORE LINE NUMBERS
STORE S1,IFOB+FOB.CW ;STORE
MOVEI S1,2 ;SHORT FOB
MOVEI S2,IFOB ;AND ITS ADDRESS
PUSHJ P,F%IOPN ;OPEN FOR INPUT
JUMPF CMINDE ;IF FAILS,TELL WHY
MOVEM S1,IIFN ;STORE IFN
PUSHJ P,CMRSET ;FLUSH INDIRECT FILESPEC FROM BUFFER
CMIND1: MOVE S1,IIFN ;GET IFN
PUSHJ P,F%IBYT ;GET A BYTE
JUMPF CMIND2 ;IF FAILS FIND OUT WHY
CAIE S2,CMRDOC ;IGNORE ^H
CAIN S2,.CHCRT ;IGNORE CR
JRST CMIND1
CAIE S2,.CHLFD ;CONVERT EOL TO SPACE
CAIN S2,.CHESC ;DITTO ESC (BUT THERE SHOULDN'T BE ANY)
MOVEI S2," "
MOVE T1,S2 ;COPY CHARACTER
PUSHJ P,CMDIBQ ;PUT CHAR IN BUFFER WITHOUT TYPEOUT
JRST CMIND1
CMIND2: MOVE S1,IIFN ;CLOSE OFF THE FILE NOW
PUSHJ P,F%REL ;
MOVEI T1,.CHLFD ;TIE OFF LINE
PUSHJ P,CMDIBQ
JRST XCOMRP ;REPARSE LINE AS NOW CONSTITUTED
CMINDE: PUSHJ P,I%IOFF ;TURN OFF INTERRUPTS
PCRLF
MOVEI [ASCIZ/?PROBLEM WITH INDIRECT FILE:/]
PNTALF
PUSHJ P,I%ION ;THEN TURN THEM BACK ON
TXO F,CM%NOP ;RETURN FAILURE, NO CHECK ALTERNATIVES
JRST XCOMX2
;****************************************
;COMND - LOCAL SUBROUTINES
;****************************************
;READ NEXT FIELD ATOM
;ASSUMES ATOM BUFFER ALREADY SETUP
CMRATM: MOVEI T1,FLDBRK ;USE STANDARD FIELD BREAK SET
PJRST CMRFLD ;PARSE THE FIELD
FLDBRK: 777777,,777760 ;ALL CONTROL CHARS
777754,,001760 ;ALL EXCEPT - , NUMBERS
400000,,000760 ;ALL EXCEPT UC ALPHABETICS
400000,,000760 ;ALL EXCEPT LC ALPHABETICS
;READ FILESPEC FIELD - FILESPEC PUNCTUATION CHARACTERS
;ARE LEGAL ( :, <, >, ., ;)
CMRFIL: MOVEI T1,FILBRK ;USE FILE BREAK SET
PJRST CFRFLD
FILBRK: 777777,,777760 ;ALL CC
747504,,000520 ;PUNCT, NUMBERS
400000,,000260 ;UC, BRACKETS
400000,,000760 ;LC
;USERNAME BREAK SET. BREAKS ON EVERYTHING EXCEPT DOT AND ALPHABETICS.
USRBRK: -1,,777760 ;BREAK ON CONTROLS
777744,,001760 ;DON'T BREAK ON "-", ".", DIGITS
400000,,760 ;DON'T BREAK ON UPPERCASE LETTERS
400000,,760 ;OR LOWERCASE LETTERS
;READ TO END OF LINE
EOLBRK: 1B<.CHLFD> ;END OF LINE ONLY
EXP 0,0,0 ;THREE WORDS OF 0'S
;GENERAL FIELD PARSE ROUTINE - TAKES BREAK SET MASK
; T1/ ADDRESS OF 4-WORD BREAK SET MASK
; PUSHJ P,CMRFLD
; RETURNS +1, FIELD COPIED TO ATOM BUFFER, TERMINATOR BACKED UP
CMRFLD: MOVEM T1,CMRBRK ;SAVE BREAK TABLE ADDRESS
TXNE F,CMDEFF ;DEFAULT GIVEN?
JRST CMRATT ;YES, ALREADY IN BUFFER
CMRAT1: PUSHJ P,CMCIN ;GET A CHAR
CMRAT2: CAIE T1,CMFREC ;^F RECOGNITION?
CAIN T1,.CHESC ;ESC?
JRST [PUSHJ P,CHKLCH ;YES, RETURN IF ANYTHING NOW
JUMPG T1,CMRATT ;IN ATOM BFR
PUSHJ P,CMAMB ;NOTHING THERE, DING
JRST CMRAT1] ;KEEP TRYING
CAIE T1," " ;SPACE OR TAB?
CAIN T1,.CHTAB
JRST [PUSHJ P,CHKLCH ;YES, RETURN IF ANYTHING
JUMPG T1,CMRATT ;IN ATOM BFR
JRST CMRAT1] ;OTHERWISE IGNORE
CAIN T1,.CHLFD ;OR EOL?
JRST CMRATR ;YES
CAIN T1,CMHLPC ;HELP REQUEST?
JRST [TXO F,CMQUES ;YES, FLAG
JRST CMRATT]
move T2,t1 ;get copy of char
IDIVI T2,40 ;COMPUTE INDEX TO BIT MASK
MOVE T3,BITS(t3)
ADD T2,CMRBRK
TDNE T3,0(t2) ;BREAK CHARACTER?
JRST CMRATR ;YES
CMRAT3: PUSHJ P,STOLCH ;BUILD KEYWORD STRING
JRST CMRAT1
CMRATR: PUSHJ P,CMDIP ;PUT CHARACTER BACK IN BUFFER
CMRATT: PJRST TIELCH ;TIE OFF ATOM BUFFER AND RETURN
;FILE SPEC FIELD PARSE ROUTINE - TAKES BREAK SET MASK
; T1/ ADDRESS OF 4-WORD BREAK SET MASK
; PUSHJ P,CFRFLD
; RETURNS +1, FIELD COPIED TO ATOM BUFFER, TERMINATOR BACKED UP
CFRFLD: MOVEM T1,CMRBRK ;SAVE BREAK TABLE ADDRESS
TXNE F,CMDEFF ;DEFAULT GIVEN?
JRST CFRATT ;YES, ALREADY IN BUFFER
CFRAT1: PUSHJ P,CMCIN ;GET A CHAR
CFRAT2: CAIE T1,CMFREC ;^F RECOGNITION?
CAIN T1,.CHESC ;ESC?
JRST CFRATT ;YES
CAIE T1," " ;SPACE OR TAB?
CAIN T1,.CHTAB
JRST [PUSHJ P,CHKLCH ;YES, RETURN IF ANYTHING
JUMPG T1,CFRATT ;IN ATOM BFR
JRST CFRAT1] ;OTHERWISE IGNORE
CAIN T1,.CHLFD ;OR EOL?
JRST CFRATR ;YES
CAIN T1,CMHLPC ;HELP REQUEST?
JRST [TXO F,CMQUES ;YES, FLAG
JRST CFRATT]
move T2,t1 ;get copy of char
IDIVI T2,40 ;COMPUTE INDEX TO BIT MASK
MOVE T3,BITS(t3)
ADD T2,CMRBRK
TDNE T3,0(t2) ;BREAK CHARACTER?
JRST CFRATR ;YES
CFRAT3: PUSHJ P,STOLCH ;BUILD KEYWORD STRING
JRST CFRAT1
CFRATR: PUSHJ P,CMDIP ;PUT CHARACTER BACK IN BUFFER
CFRATT: PJRST TIELCH ;TIE OFF ATOM BUFFER AND RETURN
;ATOM READ FOR SPECIAL FIELDS - DOES NOT ALLOW RECOGNITION
;READ FIELD TO CR
CMRSTR: TXZA F,CMTF1 ;FLAG NO TERMINATE ON SPACE
; .. ;CONTINUE IN CMRSPC
;READ FIELD TO SPACE OR CR
CMRSPC: TXO F,CMTF1 ;FLAG TERMINATE ON SPACE
TXNE F,CMDEFF ;HAVE FIELD ALREADY?
POPJ P,0 ;YES
CMRSP1: PUSHJ P,CMCIN ;GET CHAR
CAIN T1,CMHLPC ;HELP?
JRST [TXO F,CMQUES ;YES
POPJ P,0]
CAIE T1,.CHESC ;RECOG REQUEST?
CAIN T1,CMFREC
JRST [PUSHJ P,CMAMB ;DING
JRST CMRSP1] ;CONTINUE
CAIE T1,.CHTAB
CAIN T1," " ;END OF FIELD?
JRST [JXE F,CMTF1,.+1 ;CONTINUE IF NOT TERMINATING ON BLANK
PUSHJ P,CHKLCH ;SEE IF ANY NON-BLANK SEEN
JUMPE T1,CMRSP1 ;JUMP IF LEADING BLANK
JRST CMRATT] ;TERMINATING BLANK
CAIN T1,.CHLFD ;END OF LINE?
JRST CMRATR ;YES
PUSHJ P,STOLCH ;NO, CHAR TO ATOM BUFFER
JRST CMRSP1 ;CONTINUE
;READ QUOTED STRING INTO ATOM BUFFER
;STRING DELIMITED BY ", "" MEANS LITERAL "
CMRQST: TXNE F,CMDEFF ;HAVE DEFAULT?
RETSKP ;YES
PUSHJ P,CMCIN ;GET FIRST CHAR
CAIN T1,CMHLPC ;FIRST CHAR IS HELP?
JRST [TXO F,CMQUES ;YES
RETSKP]
CAIE T1,CMQTCH ;START OF STRING?
POPJ P,0 ;NO, FAIL
CMRQS1: PUSHJ P,CMCIN ;READ NEXT CHAR
CAIN T1,.CHLFD ;LINE ENDED UNEXPECTEDLY?
JRST [PJRST CMDIP] ;YES, PUT LF BACK AND RETURN FAIL
CAIE T1,CMQTCH ;ANOTHER QUOTE?
JRST CMRQS2 ;NO, GO STORE CHARACTER
PUSHJ P,CMCIN ;YES, PEEK AT ONE AFTER
CAIN T1,CMQTCH ;PAIR OF QUOTES?
JRST CMRQS2 ;YES, STORE ONE
PUSHJ P,CMDIP ;NO, PUT BACK NEXT CHAR
PUSHJ P,TIELCH ;TIE OFF ATOM BUFFER
RETSKP ;GOOD
CMRQS2: PUSHJ P,STOLCH ;STOR CHAR IN ATOM BUFFER
JRST CMRQS1 ;KEEP LOOKING
;INIT ATOM BUFFER
INILCH: MOVE T1,.CMABP(P2) ;GET PTR
MOVEM T1,ATBPTR
MOVE T1,.CMABC(P2) ;GET SIZE
MOVEM T1,ATBSIZ
PJRST CMSKSP ;FLUSH INITIAL SPACES
;STORE CHARACTER IN ATOM BUFFER
STOLCH: SOSGE ATBSIZ ;ROOM?
$STOP(ABS,Atom buffer too small) ;NO
IDPB T1,ATBPTR
POPJ P,0
;CHECK NUMBER OF CHARACTERS IN ATOM BUFFER
CHKLCH: MOVE T1,.CMABC(P2) ;GET ORIG COUNT
SUB T1,ATBSIZ ;COMPUTE DIFFERENCE
POPJ P,0
;TIE OFF ATOM BUFFER
TIELCH: SKIPG ATBSIZ ;ROOM FOR NULL?
PUSHJ P,S..ABS ;NO, LOSE
SETZ T1,0
MOVE T3,ATBPTR ;GET POINTER
IDPB T1,T3 ;DEPOSIT WITHOUT CHANGING PTR
POPJ P,0
;GET NEXT INPUT CHARACTER FOR PROCESSING
;APPEND TEXT TO BUFFER IF NECESSARY WITH INTERNAL TEXTI
; PUSHJ P,CMCIN
; RETURNS +1 ALWAYS, T1/ CHARACTER
CMCIN: SOJL P5,[SETZ P5,0 ;MAKE INPUT EXACTLY EMPTY
PUSHJ P,CMCIN1 ;NONE LEFT, GO GET MORE
JRST CMCIN]
ILDB T1,P4 ;GET NEXT ONE
SOS P3 ;UPDATE FREE COUNT
CAIN T1,CMFREC ;^F?
JRST [TXO F,CM%ESC+CMCFF ;YES
POPJ P,0]
CAIN T1,.CHESC ;ESC?
JRST [TXO F,CM%ESC ;YES
POPJ P,0]
CAIN T1,.CHLFD ;END OF LINE?
TXO F,CM%EOC ;YES, MEANS END OF COMMAND
POPJ P,0
CMCIN1: MOVEM F,CMCSF ;SAVE F
SETZM CMCBLF ;INIT ACCUMULATED FLAGS
MOVE T1,[XWD P1,CMCSAC] ;PREPARE FOR BLT
BLT T1,CMCSAC+3 ;SAVE P1-P4
MOVX T1,RD%BRK+RD%PUN+RD%BEL+RD%CRF+RD%JFN+RD%BBG ;SETUP FLAGS
TXNE F,CM%NJF ;WERE JFN'S PASSED?
TXZ T1,RD%JFN ;NO, PASS THAT FACT
TXNE F,CM%RAI ;RAISE INPUT REQUESTED?
TXO T1,RD%RAI ;YES, PASS IT
MOVEM T1,TI+.RDFLG ;STORE FLAGS FOR TEXTI
MOVX T1,.RDBKL ;GET NUMBER OF WORDS TO PASS
MOVEM T1,TI+.RDCWB ;AND STORE IT
MOVE T1,.CMRTY(P2) ;SETUP ^R BUFFER
MOVEM T1,TI+.RDRTY ;FOR TXTI
MOVE T1,.CMBFP(P2) ;SETUP TOP OF BUFFER
MOVEM T1,TI+.RDBFP ;
SETZM TI+.RDBRK ;NO SPECIAL BREAK MASK
MOVEM P4,TI+.RDBKL ;STORE CURRENT PTR FOR BACK UP LIMIT
MOVEM P3,CMCSC ;SAVE CURRENT COUNT
SUB P3,P5 ;ADJUST COUNT FOR ADVANCE INPUT
MOVEM P3,TI+.RDDBC ;AND STORE FOR THE TEXT INPUT
SKIPE P5 ;PUSH POINTER PAST CURRENT INPUT
IBP P4 ;
SOJG P5,.-1 ;
MOVEM P4,TI+.RDDBP ;STORE FOR INPUT
MOVE S1,.CMIOJ(P2) ;GET THE JFNS
MOVEM S1,TI+.RDIOJ ;STORE FOR TEXTI
CMCIN2: SKIPG P3 ;ROOM IN BUFFER FOR MORE INPUT?
$STOP(TMT,Too much text) ;NO
MOVEI S1,TI ;GET LOCATION OF TEXTI BLOCK
PUSHJ P,K%TXTI ;DO INTERNAL TEXTI
JUMPF [MOVEI S1,EREOF$
JRST XCOMEO]
IOR F,TI+.RDFLG ;GET FLAGS
TXNE F,RD%BFE ;BUFFER EMPTY?
JRST CMCIN4 ;YES
IORB F,CMCBLF ;ACCUMULATE FLAGS (RD%BLR)
LDB T1,TI+.RDDBP ;GET LAST CHAR
MOVE P4,TI+.RDDBP ;REMEMBER POINTER
MOVE P3,TI+.RDDBC ;AND COUNT
CAIE T1,.CHLFD ;AN ACTION CHAR?
CAIN T1,.CHESC
JRST CMCIN3 ;YES
CAIE T1,CMHLPC
CAIN T1,CMFREC ;^F?
JRST CMCIN3 ;YES
JRST CMCIN2 ;NO, GET MORE INPUT
CMCIN3: TXNE F,RD%BLR ;BACKUP LIMIT REACHED?
JRST CMCIN4 ;YES, CLEANUP AND REPARSE
MOVE P5,CMCSC ;RECOVER PREVIOUS COUNT
SUB P5,P3 ;COMPUTE CHARACTERS JUST APPENDED
MOVSI T1,CMCSAC ;RESTORE ACS P1-P4, F
HRRI T1,P1
BLT T1,P4
MOVE F,CMCSF
POPJ P,0
;HERE ON RETURN FROM TEXTI WHICH REACHED BACKUP LIMIT OR WHICH RETURNED
;BECAUSE BUFFER EMPTY. MUST REPARSE LINE. RESTORE ACS, BUT LEAVE
;MAIN POINTER AS RETURNED BY TEXTI.
CMCIN4: DMOVE P1,CMCSAC ;RESTORE P1&P2
MOVE F,CMCSF ;RESTORE F
JRST XCOMRP ;RETURN REPEAT PARSE
;SKIP LEADING TABS OR SPACES
CMSKSP: PUSHJ P,CMCIN ;GET A CHAR
CAIE T1," " ;SPACE OR TAB?
CAIN T1,.CHTAB
JRST CMSKSP ;YES, KEEP LOOKING
PJRST CMDIP ;NO, PUT IT BACK
;LOCAL ROUTINE - SUBTRACT ASCII BYTE PTRS
; T1, T2/ ASCII BYTE PTRS
; PUSHJ P,SUBBP
; RETURNS +1 ALWAYS,
; T1/ T1-T2
SUBBP: HRRZ T3,T1 ;COMPUTE 5*(A1-A2)+(P2-P1)/7
SUBI T3,0(T2)
IMULI T3,5 ;COMPUTE NUMBER CHARS IN THOSE WORDS
LDB T1,[POINT 6,T1,5]
LDB T2,[POINT 6,T2,5]
SUBM T2,T1
IDIVI T1,7
ADD T1,T3
POPJ P,0
;LOCAL ROUTINE - DELETE LAST CHAR INPUT
CMDCH: MOVE T1,P4
PUSHJ P,DBP ;DECREMENT BYTE PTR
MOVEM T1,P4
AOS P3 ;ADJUST SPACE COUNT
SETZ P5,0 ;CAN'T BE ANY WAITING INPUT
POPJ P,0
;LOCAL ROUTINE - DECREMENT INPUT POINTER
CMDIP: LDB T1,P4 ;CHECK THE CHARACTER
CAIE T1,CMFREC ;A RECOG REQUEST CHAR?
CAIN T1,.CHESC
TXZ F,CM%ESC+CMCFF ;YES, RESET FLAGS
MOVE T1,P4 ;GET POINTER
PUSHJ P,DBP ;DECREMENT IT
MOVEM T1,P4 ;PUT IT BACK
AOS P5 ;ADJUST COUNTS
AOS P3
POPJ P,0
;LOCAL ROUTINE - DEPOSIT INTO INPUT BUFFER
CMDIB: PUSHJ P,CMCOUT ;TYPE THE CHAR
CMDIBQ: SETZ P5,0 ;CLEAR ADVANCE COUNT
SOSGE P3 ;ROOM?
PUSHJ P,S..ABS ;NO
IDPB T1,P4 ;APPEND BYTE TO USER'S BUFFER
POPJ P,0
;LOCAL ROUTINE - DECREMENT BYTE POINTER
DBP: SOS T1 ;BACK OFF ONE WORD
IBP T1 ;AND THEN GO FORWARD 4 TIMES
IBP T1
IBP T1
IBP T1
$RETT ;THEN RETURN
;APPEND CHARACTER TO INPUT BUFFER
; T1/ CHARACTER
CMAPC: MOVEM T1,T4 ;SAVE CHAR
MOVE T2,P5 ;ADVANCE COUNT
ADJBP T2,P4 ;COMPUTE POINTER TO END OF INPUT
IDPB T4,T2 ;APPEND THE CHAR
AOS P5 ;UPDATE ADVANCE COUNT
POPJ P,0
;DO CALLER-SUPPLIED HELP TEXT IF ANY
DOHLP: HRROI T1,[ASCIZ /
or/]
TXNE F,CMQUE2 ;IN ALTERNATE HELP POSSIBILITIES?
PUSHJ P,CMSOUT ;YES, NOT ALTERNATIVE
TXNN F,CM%HPP ;HAVE HELP POINTER?
POPJ P,0 ;NO
MOVEI T1," "
PUSHJ P,CMCOUT ;SPACE BEFORE USER TEXT
HRRZ T1,P1 ;LOAD ADDRESS
MOVE T1,.CMHLP(T1) ;YES, GET IT
PUSHJ P,CMUSOU ;YES, TYPE IT
POPJ P,0
;HANDLE AMBIGUOUS TYPEIN
CMAMB: TXZN F,CM%ESC ;ESC SEEN?
JRST [NOPARS (NPXAMB,UNRECOGNIZED CONTROL CHARACTER)] ;NO, SAME AS UNREC
PUSHJ P,CMDCH ;FLUSH RECOG CHAR FROM BUFFER
MOVEI T1,.CHBEL ;INDICATE AMBIGUOUS
PUSHJ P,CMCOUT
JRST XCOMRF ;GET MORE INPUT AND RESTART
;OUTPUT CHARACTER TO SPECIFIED DESTINATION
; T1/ CHAR
; PUSHJ P,CMCOUT
; RETURNS +1 ALWAYS
CMCOUT: OUTCHR T1 ;OUTPUT THE CHARACTER
POPJ P,0
;OUTPUT STRING FROM CURRENT CONTEXT
; T1/ STRING PTR
; PUSHJ P,CMSOUT
; RETURN +1 ALWAYS
CMUSOU:
CMSOUT: HLRZ S1,T1 ;GET LH OF POINTER TO S1
CAIN S1,-1 ;IS IT A -1?
MOVEI S1,(POINT 7,0) ;YES, MAKE IT POINT 7,
CAIN S1,(POINT 7,0) ;IS IT A WORD-ALIGNED POINTER?
JRST CMSO.2 ;YES, DO AN OUTSTR FOR EFFICIENCY
HRL T1,S1 ;NO, COMPLETE THE BYTE POINTER
CMSO.1: ILDB S1,T1 ;GET A CHARACTER
JUMPE S1,.POPJ ;TERMINATE ON NULL
OUTCHR S1 ;OUTPUT THE CHARACTER
JRST CMSO.1 ;AND LOOP FOR MORE
CMSO.2: OUTSTR 0(T1) ;TYPE OUT THE STRING
POPJ P, ;AND RETURN
;OUTPUT CHARACTER TO SPECIFIED DESTINATION
; T1/ CHAR
; PUSHJ P,XMCOUT
; RETURNS +1 ALWAYS
XMCOUT: OUTCHR T1
CAIN T1,^D9
JRST XMCS.1
JRST XMCS.2
;OUTPUT STRING FROM CURRENT CONTEXT
; T1/ STRING PTR
; PUSHJ P,XMSOUT
; RETURN +1 ALWAYS
XMSOUT: HLRZ S1,T1 ;GET LH OF POINTER TO S1
CAIN S1,-1 ;IS IT A -1?
HRLI T1,(POINT 7,0) ;YES, MAKE POINT 7
XMSO.1: ILDB S1,T1 ;GET A CHARACTER
JUMPE S1,.POPJ ;TERMINATE ON NULL
PUSHJ P,XMCSPC ;GO OUTPUT THE CHARACTER
JRST XMSO.1 ;AND LOOP FOR MORE
POPJ P,0
XMCSPC: OUTCHR S1 ;OUTPUT A CHARACTER
CAIE S1,^D9
JRST XMCS.2
XMCS.1: MOVE S1,CURPOS
ADDI S1,8
IDIVI S1,8
IMULI S1,8
MOVEM S1,CURPOS
SKIPA
XMCS.2: AOS CURPOS ;MAINTAIN POSITION
POPJ P,0
;CHECK ALL BYTE PTRS
; T1/ PTR TO LIST OF ADDRESSES, TERMINATED BY 0
CHKABP: SAVE Q1 ;SAVE ACS
SAVE Q2 ;THAT WE USE
MOVEM T1,Q1 ;SAVE LIST PTR
CHKAB1: MOVE Q2,0(Q1) ;GET NEXT ADDRESS
JUMPE Q2,.RETT ;DONE ON 0
ADDI Q2,0(P2) ;MAKE PTR TO BLOCK
MOVE T1,0(Q2) ;GET BYTE PTR
PUSHJ P,CHKBP ;CHECK AND NORMALIZE
MOVEM T1,0(Q2) ;PUT IT BACK
AOJA Q1,CHKAB1 ;DO NEXT
;CHECK A BYTE PTR
; T1/ BYTE PTR - IF LH IS -1, PTR IS FIXED
CHKBP: HLRZ T2,T1
CAIN T2,-1
HRLI T1,(POINT 7)
LDB T2,[POINT 6,T1,11] ;GET BYTE SIZE
IBP T1 ;INCREMENT AND DECREMENT TO NORMALIZE
PJRST DBP
;************************
;FUNCTIONS
;************************
;INITIALIZE LINE AND CHECK FOR REDO REQUEST
XCMINI: HRRZ T1,.CMIOJ(P2) ;DOING OUTPUT TO TERMINAL?
CAXE T1,.PRIOU ;..
JRST CMINI4 ;NO, SKIP REPAIR
MOVEI T1,[BYTE (7).CHCRT,.CHLFD] ;GET TO LEFT MARGIN
PUSHJ P,CMSOUT
CMINI1: SKIPE Q1,.CMRTY(P2) ;DO PROMPT IF ANY
CMINI2: CAMN Q1,.CMBFP(P2) ;STOP AT TOP OF BUFFER
JRST CMINI3
ILDB T1,Q1
JUMPN T1,[PUSHJ P,CMCOUT
JRST CMINI2]
CMINI3: CAMN P4,.CMBFP(P2) ;BUFFER EMPTY?
JRST CMINI4 ;YES, NO REDO POSSIBLE
LDB T1,P4 ;CHECK LAST CHAR
CAIN T1,.CHLFD ;END OF LINE?
JRST CMINI4 ;YES, LAST COMMAND OK, NO REDO
INCHRW T1 ;GET FIRST CHARACTER
CAIN T1,CMRDOC ;IS IT REDO?
JRST CMINI5 ;YES
MOVE T2,TRMUDX ;GET TERMINAL'S UDX
MOVE T4,T1 ;COPY CHARACTER
LSH T4,^D36-7 ;AND POSITION IT
MOVX T1,.TOTYP ;RE-INSERT INTO INPUT BUFFER
MOVEI T3,T4 ;POINT TO STRING
MOVE S1,[XWD 3,T1] ;POINT TO ARGUMENT BLOCK
TRMOP. S1, ;AND DO IT
$STOP(TRI,TRMOP RE-INSERT FAILURE)
CMINI4: MOVE T1,P4 ;RESET LINE VARIABLES
MOVE T2,.CMBFP(P2)
MOVEM T2,P4
PUSHJ P,SUBBP ;COMPUTE CHARACTERS IN LINE
ADDM T1,P3 ;UPDATE SPACE COUNT
SETZ P5,0 ;RESET ADVANCE COUNT
JRST XCOMXI ;RETURN GOOD
CMINI5: MOVE P3,.CMCNT(P2) ;RESET VARIABLES TO CURR FIELD
MOVE P4,.CMPTR(P2)
SETZ P5,0 ;NO INPUT
MOVEI T1,[BYTE (7).CHCRT,.CHLFD] ;START NEW LINE
PUSHJ P,CMSOUT ;
PUSHJ P,CMRTY1 ;RETYPE
JRST XCOMRP ;RETURN TO REPARSE
;SWITCH - LIKE KEYWORD BUT PRECEEDED BY SLASH
XCMSWI: TXO F,CMSWF ;NOTE DOING SWITCH
TXNE F,CMDEFF ;DEFAULT GIVEN?
JRST CMKEY0 ;YES, SLASH ALREADY ASSUMED
PUSHJ P,CMCIN ;GET FIRST CHAR
CAIE T1,CMFREC ;^F
CAIN T1,.CHESC ;ESC?
JRST [PUSHJ P,CMAMB ;YES, INDICATE AMBIGUOUS
JRST XCMSWI] ;TRY AGAIN
CAIN T1,CMHLPC ;HELP?
JRST [SETZ T1,0
MOVE T2,ATBPTR
IDPB T1,T2
MOVE T1,FNARG ;GET TABLE PTR
MOVEI T1,1(T1) ;POINT TO FIRST TABLE ENTRY
JRST CMQ2] ;TYPE OPTIONS
CAIE T1,CMSWCH ;THE SWITCH CHARACTER?
JRST [PUSHJ P,CMDIP ;NO, PUT IT BACK
NOPARS (NPXNSW,UNRECOGNIZABLE SWITCH CONSTRUCTION)] ;RETURN NO PARSE
JRST CMKEY0 ;CONTINUE LIKE KEYWORD
;KEYWORD LOOKUP FUNCTION
XCMKEY: TXZ F,CMSWF ;NOT SWITCH
CMKEY0:
KEYW1: PUSHJ P,CMRATM ;READ THE FIELD INTO LOCAL BUFFER
MOVE T1,FNARG ;GET TABLE HEADER ADDRESS
MOVE T2,.CMABP(P2) ;POINT TO KEYWORD BUFFER
PUSHJ P,XTLOOK ;LOOKUP
TXNE F,CMQUES ;HAD "?"
JRST CMQ1 ;YES, GO TYPE ALTERNATIVES
JXN T2,TL%NOM,[NOPARS (NPXNOM,NO KEYWORD MATCH)] ;NO MATCH
JXN T2,TL%AMB,[PUSHJ P,CMAMB ;AMBIGUOUS, DING OR FAIL
JRST KEYW1] ;GET MORE INPUT
MOVEM T1,T2 ;SAVE TABLE INDEX
MOVEM T1,CRBLK+CR.RES ;AS RESULT
JXE F,CM%ESC,KEYW4 ;DONE IF NO REC WANTED
MOVEM T3,Q1 ;SAVE PTR TO REMAINDER OF STRING
PUSHJ P,CMDCH ;FLUSH RECOG CHARACTER
KEYW2: ILDB T1,Q1 ;TYPE REMAINDER OF KEYWORD
JUMPE T1,KEYW3 ;DONE
PUSHJ P,CMDIB ;APPEND COMPLETION TO BUFFER
CAIN T1,CMSWTM ;A SWITCH TERMINATOR?
JRST [TXZ F,CM%ESC ;YES, OVERRIDES ESC
TXO F,CM%SWT ;NOTE SWITCH TERMINAOTR
TXNN F,CMSWF ;IN SWITCH?
PUSHJ P,CMDIP ;NO, PUT TERMINATOR BACK
JRST XCOMXI] ;DONE
JRST KEYW2
KEYW3: JXE F,CMSWF,XCOMXI ;DONE IF NOT SWITCH
MOVE Q1,FNARG ;CHECK FUNCTION FLAGS
JXE Q1,CM%VRQ,XCOMXI ;DONE IF NO VALUE REQUIRED
MOVEI T1,CMSWTM ;INCLUDE COLON IN RECOGNITION
PUSHJ P,CMDIB
TXO F,CM%SWT ;NOTE SWITCH TERMINATOR
JRST XCOMX1 ;INHIBIT ADDITIONAL SPACE
KEYW4: PUSHJ P,CHKLCH ;SEE IF ATOM NON-NULL
JUMPE T1,[NOPARS (NPXNUL,KEYWORD EXPECTED)] ;FAIL IF NULL
JXE F,CMSWF,XCOMXI ;DONE IF NOT SWITCH
PUSHJ P,CMSKSP ;SKIP SPACES
PUSHJ P,CMCIN ;GET NON-BLANK CHAR
CAIN T1,CMSWTM ;SWITCH TERMINATOR?
JRST [TXO F,CM%SWT ;YES, NOTE
JRST XCOMXI] ;DONE
PUSHJ P,CMDIP ;NO, PUT IT BACK
MOVE Q1,FNARG
JXN Q1,CM%VRQ,XCOMNP ;FAIL IF VALUE WAS REQUIRED
JRST XCOMXI ;OTHERWISE OK
;"?" TYPED, FIRST PARTIAL MATCH FOUND. TYPE ALL PARTIAL MATCHES
CMQ1: JXN T2,TL%NOM,[
JXN F,CMQUE2,CMRTYP ;DO NOTHING IF NOT FIRST ALTERNATIVE
HRROI T1,[ASCIZ / keyword (no defined keywords match this input)/]
PUSHJ P,CMSOUT ;TYPE MESSAGE
JRST CMRTYP] ;RETYPE LINE AND CONTINUE
CMQ2: MOVEM T1,Q2 ;SAVE TABLE INDEX
PUSHJ P,DOHLP ;DO USER HELP IF ANY
TXNE F,CM%SDH ;DEFAULT HELP SUPPRESSED?
JRST CMRTYP ;YES, DONE
MOVE T1,FNARG ;GET TABLE PTR
HLRZ Q1,0(T1) ;GET TABLE SIZE
ADDI Q1,1(T1) ;COMPUTE TABLE END ADDRESS FOR BELOW
HRROI T1,[ASCIZ / one of the following:
/]
PUSHJ P,CMSOUT
SETZM CURPOS ;CLEAR CURRENT POSITION
SOJ Q2,0 ;GETS INCREMENTED BEFORE EACH APPLICATION
MOVEM Q2,Q3SAVE ;SAVE SO IT CAN BE REINITIALIZED
SETZM TABSIZ ;START WITH TAB SIZE OF 0
SETOM PWIDTH ;MARK THAT WE DON'T KNOW WIDTH YET
CMTAB1: PUSHJ P,CMNXTE ;GET TO NEXT VALID KEYWORD IN TABLE
JRST CMTAB2 ;NO MORE IN TABLE
PUSHJ P,CMGTLN ;CALCULATE LENGTH OF KEYWORD
CAML T1,TABSIZ ;LONGEST SEEN SO FAR?
MOVEM T1,TABSIZ ;YES, REMEMBER IT
JRST CMTAB1 ;LOOK AT REST
CMTAB2: MOVE T1,TABSIZ
MOVEM T1,BIGSIZ ;REMEMBER LENGTH OF LONGEST KEYWORD
MOVEI T1,3+1 ;3 SPACES AFTER CRLF AND LEAVE AT LEAST
;ONE SPACE BETWEEN ITEMS
ADDM T1,TABSIZ
MOVE Q2,Q3SAVE ;RESTART TABLE POINTER FOR ACTUAL LISTING
CMQ3: PUSHJ P,CMNXTE ;GET TO NEXT KEYWORD
JRST CMRTYP ;NO MORE, REPEAT COMMAND SO FAR AND CONTINUE
PUSHJ P,KEYTAB ;JUSTIFY "TYPEBALL" FOR KEYWORD TYPEOUT
PUSHJ P,XMSOUT ;TYPE IT
JRST CMQ3 ;TRY NEXT
;ROUTINE WHICH TAKES POINTER TO TABLE IN Q2, POINTER TO END OF TABLE
;IN Q1, AND RETURNS POINTER TO KEYWORD NAME IN T1. SKIPS UNLESS TABLE
;IS EXHAUSTED. ONLY CONSIDERS PRINTABLE KEYWORDS, AND UPDATES Q2.
CMNXTE: AOS Q2 ;LOOK AT NEXT TABLE ENTRY
CAML Q2,Q1 ;BEYOND END OF TABLE?
POPJ P,0 ;YES, FINISHED LIST
HLRZ T2,0(Q2) ;GET STRING PTR FOR IT
PUSHJ P,CHKTBS ;GET FLAGS FROM STRING
JXN T1,CM%INV+CM%NOR,CMNXTE ;SKIP ENTRY IF INVISIBLE OR NOREC
MOVE T1,.CMABP(P2) ;PTR TO PARTIAL KEYWORD
PUSHJ P,USTCMP ;COMPARE
JUMPE T1,CMNXT1 ;OK IF EXACT MATCH
JXE T1,SC%SUB,.POPJ ;DONE IF NOT SUBSTRING
CMNXT1: HLRZ T2,0(Q2) ;GET PTR TO STRING FOR THIS ENTRY
PUSHJ P,CHKTBS
MOVE T1,T2
RETSKP
;ROUTINE TO CALL BEFORE TYPING KEYWORD IN RESPONSE TO "?". GIVE
;IT USER'S BYTE POINTER IN T1. IT DECIDES WHETHER KEYWORD WILL FIT
;ON THIS LINE, AND STARTS NEW LINE IF NOT. IT THEN OUTPUTS A TAB,
;FOLLOWED BY SWITCH DELIMITER (IF KEYWORD IS A SWITCH).
KEYTAB: PUSHJ P,.SAVET ;DON'T CLOBBER USER'S BYTE POINTER
PUSHJ P,CMGTLN ;COMPUTE LENGTH OF KEYWORD
MOVEM T1,KEYSIZ ;REMEMBER LENGTH
HRRZ T1,.CMIOJ(P2) ;GET OUTPUT CHANNEL
SKIPL PWIDTH ;DO WE ALREADY KNOW HOW WIDE PAPER IS?
JRST KEY2 ;YES, SO DON'T DO SYSTEM CALL
MOVEI T2,^D72 ;START DEFAULT
MOVEM T2,PWIDTH
MOVE T4,TRMUDX ;GET OUR UDX
MOVX T3,.TOWID ;FUNCTION FOR CARRIAGE POSITION
MOVE T2,[XWD 2,T3]
TRMOP. T2,0
; $STOP(TWF,TRMOP WIDTH FAILURE)
MOVEI T2,^D72 ;IF ERROR, MAKE WIDTH 72
KEY1: MOVEM T2,PWIDTH ;SAVE WIDTH, SO NO JSYS CALL NEXT TIME
JRST KEY4 ;FIRST TIME THROUGHM, ASSUME NO TAB NEEDED
KEY2: MOVE T2,CURPOS ;GET OUR CURRENT POSITION
PUSHJ P,[ CMTAB: ADD T2,TABSIZ ;FIGURE OUT MAXIMUM PLACE TAB CAN MOVE US TO
IDIV T2,TABSIZ ;SCALE DOWN TO REALLY WHERE
IMUL T2,TABSIZ ;TAB WILL BRING US TO
POPJ P,0]
ADD T2,BIGSIZ ;MAKE SURE WE HAVE ROOM FOR ANOTHER COLUMN
HRROI T1,[ASCIZ /
/]
CAMG T2,PWIDTH ;ROOM FOR ANOTHER KEYWORD ON THIS LINE?
JRST KEY3 ;YES, SO DON'T START NEW LINE
PUSHJ P,XMSOUT ;GET TO NEXT LINE
SETZM CURPOS ;CLEAR CURRENT POSITON
CAIA ;NO TAB NECESSARY AT BEGINNING OF LINE
KEY3: PUSHJ P,TYPTAB ;TYPE A TAB
KEY4: MOVX T1,CMSWCH
TXNE F,CMSWF ;IN SWITCH FIELD?
PUSHJ P,XMCOUT ;YES, TYPE SWITCH INDICATOR
POPJ P,0 ;READY TO TYPE KEYWORD ALL ON SAME LINE NOW
;ROUTINE TO TYPE TAB OF SIZE TABSIZ. IT ASSUMES HARDWARE TABS ARE OF
;SIZE 8 AND TRIES TO TYPE AS MANY REAL TABS AS IT CAN, AND THEN SPACES
;OVER REST OF THE WAY.
TYPTAB: MOVE T2,CURPOS ;SEE WHERE WE'RE STARTING ON LINE
PUSHJ P,CMTAB ;SEE WHERE WE WANT TO GET TO
MOVEM T2,TABDON ;REMEMBER WHERE WE WANT TO GET TO
TYPTB1: MOVE T1,CURPOS ;GET WHERE WE ARE
ADDI T1,8 ;HARDWARE TAB MIGHT GO THIS FAR
TRZ T1,7 ;BUT MAYBE NOT QUITE
CAMLE T1,TABDON ;WILL HARDWARE TAB GO TOO FAR?
JRST TYPTB2 ;YES
MOVEI T1,.CHTAB
PUSHJ P,XMCOUT ;AND TYPE IT
JRST TYPTB1 ;LOOP FOR AS MANY HARDWARE TABS AS WE CAN GET AWAY WITH
TYPTB2: MOVE T1,CURPOS
CAML T1,TABDON ;ARE WE THERE YET?
POPJ P,0 ;YES, SO TAB IS TYPED
MOVEI T1," " ;NO, SO SPACE OVER
PUSHJ P,XMCOUT
JRST TYPTB2 ;AND LOOP FOR REST OF SPACES
;ROUTINE TAKING POINTER TO KEYWORD IN T1. RETURNS KEYWORD LENGTH IN
;T1. GIVES EXTRA 1 FOR SWITCH, ASSUMING A SLASH WILL PREFIX ITS
;PRINTOUT.
CMGTLN: MOVEI T4,0 ;COUNT OF NUMBER OF CHARACTERS NEEDED FOR THIS KEYWORD
CMGT.1: ILDB T2,T1 ;PICK UP NEXT CHARACTER FROM KEYWORD
CAIE T2,0 ;ASSUME KEYWORD ENDS ON NULL
AOJA T4,CMGT.1 ;NOT OVER YET, ACCUMULATE ITS LENGTH
TXNE F,CMSWF ;IS THIS A SWITCH?
AOJ T4,0 ;YES, DELIMITER TAKES UP ANOTHER SPACE
MOVE T1,T4 ;RETURN LENGTH IN T1
POPJ P,0
;ARBITRARY TEXT TO ACTION CHARACTER
XCMTXT: PUSHJ P,CMRSTR ;READ STRING
JXN F,CMQUES,[PUSHJ P,DOHLP ;DO USER HELP
HRROI T1,[ASCIZ / text string/]
TXNN F,CM%SDH
PUSHJ P,CMSOUT ;TYPE HELP UNLESS SUPPRESSED
JRST CMRTYP] ;NO DEFAULT MESSAGE
JRST XCOMXI ;DONE
;NOISE WORD FUNCTION
XCMNOI: MOVE T1,FNARG ;GET STRING PTR
PUSHJ P,CHKBP ;CHECK AND NORMALIZE
MOVEM T1,XXXPTR
TXNN F,CM%PFE ;PREVIOUS FIELD ENDED WITH ESC?
JRST CMNOI3 ;NO
CMNOI1: TXO F,CM%ESC ;YES, MEANS THIS ONE DID TOO
MOVEI T1,NOIBCH ;TYPE NOISE BEG CHAR
PUSHJ P,CMDIB ; AND PUT IT IN BUFFER
CMNOI2: ILDB T1,XXXPTR ;GET NEXT NOISE CHAR
JUMPN T1,[PUSHJ P,CMDIB ;PUT IT IN BUFFER IF NOT END OF STRING
JRST CMNOI2]
MOVEI T1,NOIECH ;END OF STRING, TYPE END CHAR
PUSHJ P,CMDIB
JRST XCOMXI ;EXIT
;PREVIOUS FIELD NOT TERMINATED WITH ESC - PASS NOISE WORD IF TYPED
CMNOI3: PUSHJ P,CMSKSP ;BYPASS SPACES
PUSHJ P,CMCIN ;GET FIRST CHAR
CAIE T1,NOIBCH ;NOISE BEG CHAR?
JRST [PUSHJ P,CMDIP ;NO, NOT A NOISE WORD, PUT IT BACK
JRST XCOMXI] ;RETURN OK
CMNOI4: PUSHJ P,CMCIN ;GET NEXT NOISE CHAR
CAIE T1,CMFREC ;^F?
CAIN T1,.CHESC ;ESC?
JRST [PUSHJ P,CMDCH ;YES, FLUSH IT
JRST CMNOI2] ;COMPLETE NOISE WORD FOR USER
ILDB T2,XXXPTR ;COMPARE WITH GIVEN STRING
CAMN T1,T2
JRST CMNOI4 ;STILL SAME AS EXPECTED
CAIN T1,NOIECH ;NOT SAME, STRING ENDED TOGETHER?
JUMPE T2,XCOMXI ;YES, EXIT OK
NOPARS (NPXINW,BAD NOISE WORD) ;NO, PROBABLY BAD NOISE WORD
;CONFIRM
XCMCFM: PUSHJ P,CMCFM0 ;DO THE WORK
JRST [NOPARS (NPXNC,CONFIRMATION REQUIRED)] ;FAILED
JRST XCOMXI ;OK
CMCFM0: PUSHJ P,CMCIN ;GET CHAR
CAIE T1,.CHTAB ;BLANK?
CAIN T1," "
JRST CMCFM0 ;YES, IGNORE
CAIN T1,CMHLPC ;HELP?
JRST [PUSHJ P,DOHLP
HRROI T1,[ASCIZ / confirm with carriage return/]
TXNN F,CM%SDH
PUSHJ P,CMSOUT ;GIVE HELP MESSAGE
JRST CMRTYP] ;RETYPE AND TRY AGAIN
CAIE T1,CMFREC ;^F?
CAIN T1,.CHESC ;ESC?
JRST [PUSHJ P,CMAMB ;YES, DING
JRST CMCFM0] ;TRY AGAIN
CAIE T1,.CHLFD ;NL (NEW LINE, I.E. LINEFEED)
POPJ P,0 ;NO, FAIL
RETSKP ;YES
;FLOATING POINT NUMBER
XCMFLT: $STOP(SFP,Scanning floating point not implemented)
REPEAT 0,<
MOVEI T1,FLTBRK ;USE SPECIAL BREAK SET
PUSHJ P,CMRFLD ;READ FIELD
JXN F,CMQUES,[PUSHJ P,DOHLP
HRROI T1,[ASCIZ / number/]
TXNN F,CM%SDH ;SUPPRESS DEFAULT?
PUSHJ P,CMSOUT ;NO, DO IT
JRST CMRTYP]
MOVE T1,.CMABP(P2) ;NUMBER NOW IN ATOM BUFFER, GET PTR
MOVEM T1,T1
IMCALL .FLIN
JRST [MOVEM T3,T2 ;FAILED, RETURN ERROR CODE
JRST XCOMNP]
JRST CMNUMR ;DO NUMBER CLEANUP AND RETURN
;FLOATING POINT BREAK SET MASK, ALLOWS +, -, ., E, NUMBERS
FLTBRK: 777777,,777760
777644,,001760
400000,,000760
400000,,000760
>;END OF REPEAT 0
;NUMBER
XCMNUX: SKIPA T1,[NUXBRK] ;USE SPECIAL BREAK SET
XCMNUM: MOVEI T1,NUMBRK ;USE REGULAR BREAK SET
PUSHJ P,CMRFLD ;READ FIELD
TXNE F,CMQUES ;SAW "?"
JRST CMNUMH ;YES
MOVE T1,.CMABP(P2) ;SETUP NIN
MOVE T3,FNARG ;GET RADIX
PUSHJ P,NUMIN ;PARSE THE NUMBER
JRST CMNUM1 ;NO PARSE
CMNUMR: MOVEM T2,CRBLK+CR.RES ;STORE RESULT
MOVE T2,ATBPTR
IBP T2 ;BUMP PTR PAST TERMINATOR
CAMN T1,T2 ;NIN SAW WHOLE FIELD?
JRST [MOVE T2,CRBLK+CR.RES
JRST XCOMXR] ; YES, RECOVER RESULT AND RETURN
CMNUM1: NOPARS (NPXICN,NUMERIC CHARACTER EXPECTED) ;INVALID CHARACTER IN NUMBER
;NUMBER BREAK SET, ALLOWS +, -, NUMBERS
NUMBRK: 777777,,777760
777654,,001760
400000,,000760
400000,,000760
NUXBRK: 777777,,777760
777654,,001760
777777,,777760
777777,,777760
;NUMERIC INPUT ROUTINE
; T1/ BYTE POINTER TO STRING
; T3/ BASE TO USE
;
;RETURNS T1 UPDATED,T2 THE RESULT
NUMIN: SETZ S2,0 ;CLEAR MODIFIER
ILDB S1,T1 ;GET FIRST CHARACTER
CAIN S1," " ;A BLANK?
JRST NUMIN ;YES, IGNORE IT
CAIN S1,"-" ;IS IT MINUS SIGN?
MOVX S2,-1 ;YES, REMEMBER IT
CAIN S1,"+" ;IS IT PLUS SIGN?
MOVX S2,+1 ;YES, REMEMBER IT
SKIPE S2 ;IF WE HAD EITHER + OR -
ILDB S1,T1 ;GET NEXT BYTE
CAIG S1,"0"-1(T3) ;TOO BIG
CAIGE S1,"0" ;OR TOO SMALL?
POPJ P,0 ;YES, TAKE FAILURE RETURN
SETZ T2,0 ;CLEAR THE RESULT
NUMI.1: IMULI T2,0(T3) ;SHIFT OVER 1 DIGIT
ADDI T2,-"0"(S1) ;AND ADD IN THIS ONE
ILDB S1,T1 ;GET NEXT CHAR
CAIG S1,"0"-1(T3) ;IN RANGE?
CAIGE S1,"0"
JRST [SKIPE S2
IMUL T2,S2
RETSKP]
JRST NUMI.1 ;YES, REPEAT
CMNUMH: PUSHJ P,DOHLP ;DO USER SUPPLIED MESSAGE
JXN F,CM%SDH,CMRTYP ;SUPPRESS DEFAULT HELP IF REQUESTED
HRRZ T2,FNARG ;GET BASE
CAIL T2,^D2 ;LEGAL?
CAILE T2,^D10
$STOP(IBN,Illegal base for number)
CAIN T2,^D10 ;DECIMAL?
JRST CMNH10 ;YES
CAIN T2,^D8 ;OCTAL?
JRST CMNH8 ;YES
HRROI T1,[ASCIZ / a number in base /]
PUSHJ P,CMSOUT ;ARBITRARY BASE
HRRZ T1,.CMIOJ(P2)
HRRZ T2,FNARG
MOVEI T3,^D10
ADDI T2,"0" ;CONVERT BASE TO ASCII
OUTCHR T2 ;OUTPUT THE BASE
SUBI T2,"0" ;CONVERT IT BACK
JRST CMRTYP ;RETYPE LINE AND CONTINUE
CMNH8: HRROI T1,[ASCIZ / octal number/]
JRST CMNH
CMNH10: HRROI T1,[ASCIZ / decimal number/]
CMNH: PUSHJ P,CMSOUT
JRST CMRTYP
;DATE AND/OR TIME
;FLAGS IN ARG SPECIFY WHICH
XCMTAD: $STOP(SDT,Scanning date/time not implemented)
REPEAT 0,<
MOVE Q1,FNARG ;GET ARG
PUSHJ P,CMRSPC ;READ FIRST FIELD
JXN F,CMQUES,CMTADH ;DO HELP IF REQUESTED
JXN F,CMDEFF,CMTAD1 ;JUMP IF NOW HAVE FIELD DEFAULT
TXC Q1,CM%IDA+CM%ITM ;DATE AND TIME BOTH?
TXCN Q1,CM%IDA+CM%ITM
JRST [MOVEI T1," " ;YES, PUT SPACE IN ATOM BUFFER
PUSHJ P,STOLCH
PUSHJ P,CMRSPC ;READ SECOND FIELD
JXN F,CMQUES,CMTADH ;DO HELP
JRST .+1]
CMTAD1: MOVE T1,.CMABP(P2) ;POINT TO ATOM BUFFER
MOVEM T1,T1
MOVX T2,1B0+1B6 ;SETUP FLAGS FOR IDTNC
TXNE Q1,CM%IDA ;DATE WANTED?
TXZ T2,1B0 ;YES
TXNE Q1,CM%ITM ;TIME WANTED?
TXZ T2,1B6 ;YES
;** IMCALL .IDTNC
JRST XCOMNP ;FAILED
TXNE Q1,CM%NCI ;CONVERT TO INTERNAL FORMAT?
JRST [MOVSI T1,T2 ;NO, STORE DATA IN USER BLOCK
HRR T1,Q1
BLT T1,2(Q1)
JRST XCOMXR]
TXNN Q1,CM%IDA ;HAVE DATE?
JRST [SETO T2,0 ;NO, DEFAULT TO TODAY
SETZ T4,0
;** ODCNV ;GET TODAY
;** UMOVEM T3,T3
JRST .+1]
;** IMCALL .IDCNV ;CONVERT TO INTERNAL
JRST XCOMNP ;FAILED
MOVEM T2,CRBLK+CR.RES ;STORE RESULT
JRST XCOMXR ;OK, TAD ALREADY IN T2
;TIME/DATE HELP
CMTADH: PUSHJ P,DOHLP ;DO USER TEXT
JXN F,CM%SDH,CMRTYP ;CHECK SUPPRESS DEFAULT
LOAD T1,Q1,<CM%IDA+CM%ITM> ;GET FLAGS
HRRO T1,[[ASCIZ //]
[ASCIZ / time/]
[ASCIZ / date/]
[ASCIZ / date and time/]](T1)
PUSHJ P,CMSOUT ;PRINT APPROPRIATE MESSAGE
> ;END OF REPEAT 0
JRST CMRTYP
;DEVICE
XCMDEV: PUSHJ P,CMRATM ;GET THE FIELD
JXN F,CMQUES,CMDEVH ;HELP
JXN F,CM%ESC,[PUSHJ P,CMAMB ;NO ESC ALLOWED
JRST XCMDEV ] ;ON DEVICE
PUSHJ P,CMCIN ;CHECK TERMINATOR
CAIE T1,":" ;DEVICE?
JRST [NOPARS (NPXIDT,IMPROPER DEVICE SPECIFICATION)] ;NO, FAIL
CMDEV1: MOVE T1,.CMABP(P2) ;SETUP STDEV ARGS
MOVEM T1,XXXPTR ;STORE POINTER
PUSHJ P,FTOKEN ;GET TOKEN
JUMPE T1,XCOMNP ;IF NULL SPEC
CAIE T2,":" ; OR NOT TERMINATED WITH COLON
JRST XCOMNP ; THEN FAILED TO PARSE
MOVEM T1,CRBLK+CR.RES ;STORE RESULT
JXE F,CM%ESC,XCOMXR ;SUCCESS, DONE IF NO ESC
MOVEI T1,":" ;RECOG, APPEND TERMINATOR
PUSHJ P,CMDIB
JRST XCOMXI
CMDEVH: PUSHJ P,DOHLP ;DO USER HELP
HRROI T1,[ASCIZ / device name/]
TXNN F,CM%SDH ;SUPPRESS DEFAULT?
PUSHJ P,CMSOUT ;NO, DO IT
JRST CMRTYP
;QUOTED STRING
XCMQST: PUSHJ P,CMRQST ;READ THE STRING
JRST [NOPARS (NPXNQS,QUOTED STRING EXPECTED)] ;FAILED
JXN F,CMQUES,[PUSHJ P,DOHLP ;DO USER HELP
HRROI T1,[ASCIZ / quoted string/]
TXNN F,CM%SDH ;DEFAULT HELP?
PUSHJ P,CMSOUT ;YES
JRST CMRTYP]
JRST XCOMXI
;UNQUOTED STRING - TAKES BIT MASK (4 WORDS * 32 BITS) TO SPECIFY BREAKS.
XCMUQS:
CMUQS1: PUSHJ P,CMCIN ;GET A CHAR
IDIVI T1,^D32 ;COMPUTE INDEX TO BIT ARRAY
MOVE T2,BITS(T2)
ADD T1,FNARG
TDNN T2,0(T1) ;BIT ON?
JRST CMUQS1 ;NO, KEEP GOING
PUSHJ P,CMDIP ;YES, PUT CHAR BACK
JRST XCOMXI ;DONE
;ARBITRARY FIELD
XCMFLD: PUSHJ P,CMRATM
CMFLD1: TXNE F,CMQUES ;"?" SEEN?
JRST [PUSHJ P,DOHLP ;YES, DO USER MESSAGE
JRST CMRTYP]
JRST XCOMXR ;LEAVE FIELD IN ATOM BUFFER
;ACCOUNT
XCMACT: MOVEI T1,USRBRK ;SAME BREAK SET AS USER NAME FIELD
PUSHJ P,CMRFLD ;READ FIELD
JRST CMFLD1 ;FINISH LIKE ARBITRARY FIELD
;NODE NAME
XCMNOD: $STOP(NOD,SCANNING NODE NOT IMPLEMENTED)
REPEAT 0,<
PUSHJ P,CMRATM ;GET AN ATOM
JXN F,CMQUES,[PUSHJ P,DOHLP ;TYPE OUT USER'S HELP
HRROI T1,[ASCIZ / Node Name/] ;SET UP DEFAULT HELP
TXNN F,CM%SDH ;DOES USER NOT WANT IT
PUSHJ P,CMSOUT ;NO,TYPE IT
JRST CMRTYP] ;AND RETYPE COMMAND
MOVE T1,.CMABP(P2) ;POINT AT THE ATOM BUFFER
MOVEI T3,^D8 ;TRY AS AN OCTAL NUMBER
PUSHJ P,NUMIN ;READ IT
JRST XNOD1 ;LOST, TRY AS A SIXBIT NAME
MOVEM T2,CRBLK+CR.RES ;SAVE AS RESULT
MOVE T2,ATBPTR ;GET POINTER TO END OF ATOM BUFFER
IBP T2 ;POINT AT TERMINATOR
CAME T1,T2 ;OUR POINTER END THE SAME PLACE?
JRST XNOD1 ;NO, NOT A GOOD NUMBER
MOVE T3,CRBLK+CR.RES ;NODE NUMER WE JUST PARSED
TXNE F,CM%PO ;PARSE ONLY?
JRST [CAILE T3,77 ;ILLEGAL NODE NUMBER?
JRST XNOD1 ;YES, TRY A NAME
JRST XCOMXI] ;GOOD NODE NUMBER, RETURN
MOVE T1,[XWD .NDRNN,T2] ;CHECK TO MAKE SURE THAT THIS NODE NUMBER EXISTS
MOVEI T2,2 ;2 ARGS
NODE. T1, ;TRY IT FOR EXISTANCE
SKIPA ;NOT A NODE NUMBER, TRY AS A NAME
JRST XCOMXI ;A GOOD NODE NUMBER, RETURN
XNOD1: MOVE T1,.CMABP(P2) ;POINT AT THE ATOM BUFFER
MOVEI T2,6 ;GET MAX NUMBER OF CHARACTERS IN NAME
MOVE T4,[POINT 6,NODSIX]; BP TO NODE STORAGE
SETZM NODSIX ;START FRESH
XNOD2: ILDB T3,T1 ;GET NEXT CHARACTER FROM ATOM BUFFER
CAIL T3,"0" ;IS THE CHARACTER
CAILE T3,"Z" ;NUMERIC OR UPPER CASE?
JRST XNOD4 ;ITS NOT
CAILE T3,"9" ;...
CAIL T3,"A" ;...
CAIA ;GOOD CHARACTER, JUST SAVE IT
JRST XNOD4 ;TRY FOR LOWER CASE ALPHA
XNOD3: SUBI T3,"a"-"A" ;SIXBITIZE
IDPB T3,T4 ;FILL OUT SIXBIT NODE NAME
SOJGE T2,XNOD2 ;HAVE WE SEEN ENOUGH CHARACTERS?
NOPARS (NPXNNC,IMPROPER NODE NAME) ;TOO MANY CHARACTERS IN NODE NAME
XNOD4: CAIG T3,"z" ;BIGGER THAN LOWER CASE Z?
CAIGE T3,"a" ;OR LESS THAN LOWER CASE A?
JRST XNOD5 ;YES, GIVE ILLEGAL CHARACTER IN NODE NAME
SUBI T3,"a"-"A" ;CONVERT CHARACTER TO UPPER CASE
JRST XNOD3 ;SAVE IT AN LOOK FOR MORE
XNOD5: MOVE T2,ATBPTR ;GET POINTER TO END OF ATOM BUFFER
IBP T2 ;POINT AT TERMINATOR
CAMN T1,T2 ;OUR POINTER END THE SAME PLACE?
JRST XNOD6 ;GO DO NODE UUO
NOPARS (NPXNNI,NODE NAME EXPECTED) ;ILLEGAL CHARACTER IN NODE NAME
XNOD6: MOVEI T2,2 ;2 ARGS
MOVE T3,NODSIX
MOVE T1,[XWD .NDRNN,T2]
NODE. T1,0
JRST [NOPARS (NPXNSN,NO SUCH NODE)]
MOVEM T1,CRBLK+CR.RES ;STORE NUMBER
JRST XCOMXI ;AND RETURN
>
;INDIRECT FILESPEC (INTERNAL CALL)
CMATFI:
TXO F,CMINDF ;NOTE GETTING INDIRECT FILE
JRST XCMIFI ;AND HANDLE AS INPUT FILE
XCMOFI:
XCMIFI:
XCMFIL: PUSHJ P,CMRFIL ;GET FILE SPECIFICATION
JXN F,CMQUES,CMFHLP ;IF THEY WANT HELP, GIVE IT TO THEM
; JXN F,CM%ESC,[ PUSHJ P,CMAMB ;NO RECOGNITION AVAILABLE
; JRST XCMFIL]
PUSHJ P,FILIN ;GET FILE SPEC
JRST XCOMNP ;IF FAILS ITS A NO PARSE
MOVE T2,ATBPTR ;GET POINTER TO ATOM BUFFER END
IBP T2 ;BUMP PAST TERMINATOR
CAME T2,XXXPTR ;DOES IT MATCH?
JRST XCOMNP ;NO, TERMINATED PREMATURELY
TXZE F,CMINDF ;ARE WE DOING INDIRECT FILE?
RETSKP ;YES , RETURN FOR PROCESSING
JRST XCOMXI ;OTHERWISE, DONE
FILIN: SETZM DEVSUP#
SETZM PPNSUP#
PUSHJ P,.SAVE1 ;SAVE A REG
LOAD S2,.CMGJB(P2),CM%GJB ;GET ADDR OF FD
MOVEM S2,CRBLK+CR.RES ;SAVE IT FOR CALLER
MOVE P1,S2 ;AND REMEMBER IT
MOVX S1,FDXSIZ ;NOW ZERO IT OUT
STORE S1,.FDLEN(S2),FD.LEN ;STORE LENGTH INTO FD
MOVE T1,.CMABP(P2) ;GET ATOM BUFFER POINTER
MOVEM T1,XXXPTR ;STORE IT
PUSHJ P,FTOKEN ;GET FIRST FILE TOKEN
CAIE T2,':' ;IS FIRST PART A DEVICE
JRST FILI.1 ;NO
MOVEM T1,.FDSTR(P1) ;STORE STRUCTURE NAME
SETOM DEVSUP
PUSHJ P,FTOKEN ;YES, LOAD NEXT TOKEN
FILI.1: JUMPN T1,FILI.2 ;IF WE HAVE SOMETHING, IT MUST BE FILENAM
CAIE T2,'[' ;IF NOT, EXPECT A PPN HERE
CAIN T2,74 ;
SKIPA ;IT IS A PPN
JRST FILI.2 ;CHECK FOR SUFFICIENT FILE-SPEC
MOVE T1,XXXPTR ;GET POINTER TO PPN
PUSHJ P,DBP ;DECREMENT POINTER
MOVE T2,T1 ;GET INTO PLACE
PUSHJ P,PPNIN ;GET PPN
POPJ P, ;PASS ON FAILURE
MOVEM T1,XXXPTR ;STORE CORRECTED POINTER
STORE T2,.FDPPN(P1) ;STORE THE PPN NOW
SETOM PPNSUP
PUSHJ P,FTOKEN ;AND GET NEXT PART
FILI.2: SKIPN DEVSUP ;WAS DEVICE SUPPLIED ?
GO DEVSP1 ;NO, GET DEFAULT IF SUPPLIED
SKIPN PPNSUP ;WAS PPN SUPPLIED ?
GO PPNSP1 ;NO, GET DEFAULT IF SUPPLIED
SKIPN T1 ;ANY FILE NAME ?
GO NAMSP1 ;NO, GET DEFAULT
STORE T1,.FDNAM(P1) ;STORE NAME
CAIE T2,'.' ;IS THERE AN EXTENSION?
JRST EXTSUP ;NO, GET DEFAULT
PUSHJ P,FTOKEN ;GET EXTENSION
SKIPN T1 ;ANY EXT ?
GO EXTSP1 ;NO, GET DEFAULT IF SUPPLIED
STORE T1,.FDEXT(P1) ;AND STORE IT
FILI.3: CAIE T2,'[' ;HAVE WE GOT A PPN?
CAIN T2,74 ;NOW
SKIPA ;YES, WE HAVE
JRST FILI.4 ;CHECK FOR SUFFICIENT FILE-SPEC
MOVE T1,XXXPTR ;RELOAD THE POINTER
PUSHJ P,DBP ;DECREMENT IT
MOVE T2,T1 ;AND THEN PARSE THE
PUSHJ P,PPNIN ;PPN
POPJ P, ;RETURN A FAILURE
MOVEM T1,XXXPTR ;STORE CORRECTED POINTER
STORE T2,.FDPPN(P1) ;STORE PPN IF OK
IBP XXXPTR ;AND BUMP PAST IT
FILI.4: SKIPN S1,.FDSTR(P1) ;SEE IF USER SUPPLIED A DEFAULT DEVICE
MOVSI S1,'DSK' ;NO, SUPPLY DEFAULT DEVICE
STORE S1,.FDSTR(P1) ;STORE DEFAULT DEVICE
SKIPN .FDNAM(P1) ;MAKE SURE THERE IS A NAME
POPJ P, ;NO NAME, BAD FILE SPEC
RETSKP ;TAKE GOOD RETURN
;PROCESS FILE PARAMETER DEFAULTS
NAMSP1: HRRZ .FDNAM(P1) ;GET DEFAULT POINTER
SKIPN ;ANY SUPPLIED ?
$STOP(NNS,NO DEFAULT NAME SUPPLIED)
TLNE F,(CM%ESC) ;ESCAPE TERMINATE FIELD ?
PNTALF ;PRINT IT
PUT T2
PUT XXXPTR
HRRZ .FDNAM(P1)
HRLI 440700 ;MAKE BYTE POINTER
MOVEM XXXPTR
GO FTOKEN ;PROCESS FILE NAME
GETIT XXXPTR
GETIT T2
RTN
EXTSUP: SKIPN .FDEXT(P1) ;ANY DEFAULT EXT ?
JRST FILI.3
TLNE F,(CM%ESC) ;ESCAPE TERMINATE FIELD ?
PNTCIF "."
GO EXTSP1 ;PROCESS DEFAULT
JRST FILI.3-1
EXTSP1: HRRZ .FDEXT(P1) ;GET DEFAULT POINTER
TLNE F,(CM%ESC) ;ESCAPE TERMINATE FIELD ?
PNTALF ;PRINT IT
PUT T2
PUT XXXPTR
HRRZ .FDEXT(P1)
HRLI 440700 ;MAKE BYTE POINTER
MOVEM XXXPTR
GO FTOKEN ;PROCESS FILE EXT
GETIT XXXPTR
GETIT T2
RTN
DEVSP1: SKIPN .FDSTR(P1) ;ANY DEFAULT SUPPLIED ?
RTN ;NO
PUT T2
PUT XXXPTR
HRRZ .FDSTR(P1)
TLNE F,(CM%ESC) ;ESCAPE TERMINATE FIELD ?
PNTALF ;PRINT IT
HRRZ .FDSTR(P1)
HRLI 440700
MOVEM XXXPTR
GO FTOKEN ;PROCESS DEFAULT
STORE T1,.FDSTR(P1)
GETIT XXXPTR
GETIT T2
RTN
PPNSP1: SKIPN .FDPPN(P1) ;ANY DEFAULT SUPPLIED ?
RTN ;NO
PUT T1
PUT T2
HRRZ .FDPPN(P1)
TLNE F,(CM%ESC) ;ESCAPE TERMINATE FIELD ?
PNTALF ;PRINT IT
HRRZ .FDPPN(P1)
HRLI 440700
MOVEM T2
GO PPNIN ;PROCESS PPN
$STOP(DPP,DEFAULT PPN ERROR)
STORE T2,.FDPPN(P1)
GETIT T2
GETIT T1
RTN
FTOKEN: SETZM T1 ;CLEAR RESULT
MOVE T3,[POINT 6,T1] ;AND POINT TO STORAGE AREA
FTOK.1: ILDB T2,XXXPTR ;GET A BYTE
PUSHJ P,C7TO6 ;CONVERT TO SIXBIT
CAIG T2,'Z' ;IS IT IN RANGE?
CAIGE T2,'0' ;
POPJ P,0 ;NO
CAILE T2,'9' ;
CAIL T2,'A' ;
SKIPA
POPJ P,0
TXNE T3,<INSVL.(77,BP.POS)> ;IS THERE ROOM?
IDPB T2,T3 ;YES,STORE IT
JRST FTOK.1 ;TRY ANOTHER
C7TO6: CAIL T2,"a" ;IS IT LC?
SUBI T2,40 ;YES
SUBI T2," " ;CONVERT TO SIXBIT
ANDI T2,77 ;MASK IT AND
POPJ P, ;RETURN
;FILESPEC HELP
CMFHLP: JXO F,CMINDF,[HRROI T1,[ASCIZ / filespec of indirect file/]
JRST CMFH1] ;SPECIAL HELP IF INDIRECT FILESPEC
PUSHJ P,DOHLP ;DO USER MESSAGE
JXN F,CM%SDH,CMRTYP ;SUPPRESS DEFAULT HELP IF REQUESTED
; LOAD T2,.CMFNP(P1),CM%FNC ;GET FUNCTION CODE
; CAXE T2,.CMIFI ;INPUT FILE?
LOAD T2,.CMGJB(P2),CM%GJB ;GET ADDR OF FD
MOVE T2,(T2)
TLNN T2,(GJ%OLD)
SKIPA T1,[-1,,[ASCIZ / output filespec/]] ;NO, OUTPUT
HRROI T1,[ASCIZ \ input filespec\] ;YES,INPUT
CMFH1: PUSHJ P,CMSOUT
JRST CMRTYP
;TOKEN - ARBITRARY SYMBOL AS SPECIFIED BY FN DATA
XCMTOK: MOVE Q1,FNARG ;GET STRING ADDRESS
CMTOK1: ILDB Q2,Q1 ;GET NEXT CHAR IN STRING
JUMPE Q2,[PUSHJ P,TIELCH ;SUCCESS IF END OF STRING
JRST XCOMXI]
CMTOK2: PUSHJ P,CMCIN ;GET NEXT CHAR OF INPUT
CAMN T1,Q2 ;MATCH?
JRST [PUSHJ P,STOLCH ;YES, APPEND TO ATOM BUFFER
JRST CMTOK1] ;CONTINUE
CAIE T1,CMFREC ;RECOG REQUEST?
CAIN T1,.CHESC
JRST [PUSHJ P,CMAMB ;YES, CAN'T
JRST CMTOK2]
CAIN T1,CMHLPC ;HELP REQUEST?
JRST [PUSHJ P,DOHLP ;YES
JXN F,CM%SDH,CMRTYP
MOVEI T1,"""" ;TYPE "token"
PUSHJ P,CMCOUT
MOVE T1,FNARG
PUSHJ P,CMUSOU
MOVEI T1,""""
PUSHJ P,CMCOUT
JRST CMRTYP]
NOPARS (NPXNMT,INVALID TOKEN FOUND) ;NO MATCH OF TOKEN
; PPN (EITHER DIRECTORY OR USER NAME FUNCTION)
PPNBRK: 777777,,777760
777734,,007537
777777,,777277
777777,,777760
XCMDIR:
XCMUSR: ;EQUIVALENT
MOVEI T1,PPNBRK ;GET PROPER BREAK SET
PUSHJ P,CMRFLD ;GET FIELD
TXNE F,CMQUES ;HELP?
JRST CMDIRH ;YES
TXNE F,CM%ESC ;RECOGNITION WANTED?
JRST [ PUSHJ P,CMAMB ;YES, ALWAYS AMBIGOUS
JRST XCMUSR ]
MOVE T2,.CMABP(P2) ;PTR TO TYPEIN
PUSHJ P,PPNIN ;PARSE PPN
JRST XCOMNP ;ILLEGAL SYNTAX
MOVEM T2,CRBLK+CR.RES ;STORE RESULT
CAME T1,ATBPTR ;CHECK THAT WE SAW WHOLE FIELD
JRST XCOMNP ;IF NOT, PARSE FAILURE
JRST XCOMXI ;DONE NOW
;DIRECTORY/USER HELP
CMDIRH: PUSHJ P,DOHLP ;DO USER HELP
JXN F,CM%SDH,CMRTYP ;SUPPRESS DEFAULT HELP IF REQUESTED TO
HRROI T1,[ASCIZ / Project-Programmer number/]
PUSHJ P,CMSOUT
JRST CMRTYP ;RETYPE AND CONTINUE
PPNIN: PUSHJ P,.SAVE1 ;SAVE A REG
ILDB S1,T2 ;GET FIRST BYTE
CAIN S1," " ;SKIP LEADING BLANKS
JRST PPNIN ;
CAIE S1,74 ;BETTER BE A BRACKET OF SOME
CAIN S1,"[" ;KIND
SKIPA ;IT IS
POPJ P, ;IT IS NOT, FAIL NOW
MOVE T1,T2 ;COPY BP
MOVEI T3,^D8 ;AND MAKE IT OCTAL
PUSHJ P,NUMIN ;PARSE PROJECT NUMBER
POPJ P, ;IF IT FAILS, GIVE UP NOW
LDB S1,T1 ;GET TERMINATOR BYTE
CAIE S1,"," ;BETTER BE A COMMA
POPJ P, ;NOT, GIVE UP NOW
HRLZ P1,T2 ;REMEMBER PROJECT NR.
PUSHJ P,NUMIN ;GET 2ND HALF (PROGRAMMER NR.)
POPJ P, ;PASS ON FAILURE
HLL T2,P1 ;ASSEMBLE PPN
LDB S1,T1 ;GET TERMINATOR
CAIE S1,"]" ;AND CHECK IT
CAIN S1,76 ;FOR BRACKET
RETSKP ;ALL IS OK
POPJ P, ;OR FAIL
;COMMA, ARBITRARY CHARACTER
XCMCMA: MOVEI T1,"," ;SETUP COMMA AS CHARACTER TO FIND
MOVEM T1,FNARG
CMCHR: PUSHJ P,CMCIN ;GET A CHAR
CAIE T1,.CHTAB ;BLANK?
CAIN T1," "
JRST CMCHR ;YES, IGNORE
HRRZ T2,FNARG ;GET SPECIFIED CHAR
CAMN T1,T2 ;THE RIGHT ONE?
JRST XCOMXI ;YES, WIN
CAIE T1,CMFREC ;^F?
CAIN T1,.CHESC ;ESC?
JRST [PUSHJ P,CMAMB ;YES, DING
JRST CMCHR] ;TRY AGAIN
CAIN T1,CMHLPC ;HELP?
JRST [PUSHJ P,DOHLP
JXN F,CM%SDH,CMRTYP ;JUMP IF SUPPRESSING HELP
MOVEI T1,"""" ;TYPE "char"
PUSHJ P,CMCOUT
HRRZ T1,FNARG
PUSHJ P,CMCOUT
MOVEI T1,""""
PUSHJ P,CMCOUT
JRST CMRTYP]
NOPARS (NPXCMA,COMMA WAS EXPECTED) ;FAIL
;LOCAL ROUTINE TO SETUP BYTE PTR TO TABLE STRING AND GET FLAGS
; T2/ ADDRESS OF STRING
; PUSHJ P,CHKTBS
; T1/ FLAGS
; T2/ BYTE POINTER TO STRING
CHKTBS: HRLI T2,(POINT 7) ;SETUP P AND S FIELDS
SKIPE T1,0(T2) ;CHECK FIRST WORD OF STRING
TXNE T1,177B6 ;FIRST CHAR 0 AND WORD NOT ALL-0?
TDZA T1,T1 ;NO, MAKE FLAGS ALL 0
AOS T2 ;YES, HAVE FLAGS, ADJUST BYTE PTR
POPJ P,0
SUBTTL S%SCMP -- String Comparison Routine
;CALL IS: S1/ TEST STRING POINTER
; S2/ BASE STRING POINTER
;TRUE RETURN: S1/ COMPARE CODE:
; 1B0 (SC%LSS) - TEST STRING LESS THAN BASE STRING
; 1B1 (SC%SUB) - TEST STRING SUBSET OF BASE STRING
; 1B2 (SC%GTR) - TEST STRING GREATER THAN BASE STRING
; N.O.T.A. MEANS EXACT MATCH
; S2/ UPDATED BASE STRING POINTER, USEFUL IN CASE TEST STRING
; WAS SUBSET
S%SCMP: PUSHJ P,.SAVET ;SAVE T REGS
DMOVE T1,S1 ;COPY ARGUMENTS
HLRZ T3,T1
CAIN T3,-1
HRLI T1,(POINT 7)
HLRZ T3,T2
CAIN T3,-1
HRLI T2,(POINT 7)
PUSHJ P,USTCMP ;DO THE WORK
DMOVE S1,T1 ;PUT THE ARGUMENTS BACK
$RETT
;STRING COMPARE ROUTINE - REFERENCES PREVIOUS CONTEXT.
; T1/ TEST STRING POINTER
; T2/ BASE STRING POINTER
; PUSHJ P,USTCMP
;RETURN AS FOR .STCMP
USTCMP::ILDB T3,T1 ;GET NEXT BYTE FROM EACH STRING
CAIL T3,"A"+40 ;LC LETTER?
JRST [CAIG T3,"Z"+40
SUBI T3,40 ;YES, CONVERT TO UC
JRST .+1]
ILDB T4,T2
CAIL T4,"A"+40 ;LC LETTER?
JRST [CAIG T4,"Z"+40
SUBI T4,40 ;YES, CONVERT TO UC
JRST .+1]
CAME T3,T4 ;STILL EQUAL?
JRST STRC2 ;NO, GO SEE WHY
JUMPN T3,USTCMP ;KEEP GOING IF NOT END OF STRING
SETZ T1, ;STRINGS ENDED TOGETHER, EXACT MATCH.
POPJ P,0 ;RETURN 0
STRC2: JUMPE T3,[MOVX T1,SC%SUB ;TEST STRING ENDED, IS A SUBSET
ADD T2,[7B5] ;DECREMENT BASE POINTER ONE BYTE
POPJ P,0]
CAMG T3,T4 ;STRINGS UNEQUAL
SKIPA T1,[SC%LSS] ;TEST STRING LESS
MOVX T1,SC%GTR ;TEST STRING GREATER
POPJ P,0
SUBTTL S%TBLK -- Table lookup routine
;CALL IS: S1/ ADDRESS OF TABLE HEADER WORD
; S2/ STRING POINTER TO STRING TO BE FOUND
;
;TRUE RETURN: S1/ ADDRESS OF ENTRY WHICH MATCHED OR WHERE ENTRY WOULD BE
; IF IT WERE IN TABLE
; S2/ RECOGNITION CODE:
; 1B0 (TL%NOM) - NO MATCH
; 1B1 (TL%AMB) - AMBIGUOUS
; 1B2 (TL%ABR) - UNIQUE ABBREVIATION
; 1B3 (TL%EXM) - EXACT MATCH
S%TBLK: PUSHJ P,.SAVET ;SAVE SOME REGISTERS
DMOVE T1,S1 ;COPY INPUT ARGUMENTS
PUSHJ P,XTLOK0 ;DO THE WORK
DMOVE S1,T1 ;RE-COPY ARGUMENTS
$RETT ;AND RETURN
;WORKER ROUTINE - MAY BE CALLED INTERNALLY.
; RETURNS +1 SUCCESS, ACS AS ABOVE
;INTERNAL AC USAGE:
; T1/ TEST STRING FROM CALL
; T2/ STRING FROM TABLE
; T3/ CLOBBERED BY USTCMP
; T4/ " "
; P1/ CURRENT TABLE INDEX
; P2/ ADDRESS OF TABLE INDEXED BY P1 - USED FOR INDIRECTION
; P3/ INDEX INCREMENT FOR LOG SEARCH
; P4/ SIZE OF TABLE
XTLOOK:: PUSHJ P,.SAVE4 ;PRESERVE ACS
SAVE P5
XTLOK0: HLRZ T3,T2 ;CHECK STRING POINTER
CAIE T3,-1 ;LH 0 OR -1?
CAIN T3,0
HRLI T2,(POINT 7) ;YES, FILL IN
MOVEM T2,STRG
MOVEI P2,1(T1) ;CONSTRUCT ADDRESS OF FIRST ENTRY
HRLI P2,P1 ;MAKE IT INDEXED BY P1
HLRZ P4,0(T1) ;GET PRESENT SIZE
MOVE P3,P4 ;INITIAL INCREMENT IS SIZE
MOVE P1,P4 ;SET INITIAL INDEX TO SIZE/2
ASH P1,-1
JUMPE P4,TABLKX ;IF TABLE EMPTY THEN NO MATCH
TABLK0: HLRZ T2,@P2 ;GET STRING ADR FROM TABLE
PUSHJ P,CHKTBS ;CONSTRUCT POINTER
MOVE T1,STRG ;GET TEST STRING
PUSHJ P,USTCMP ;COMPARE
JUMPN T1,TABLK1 ;JUMP IF NOT EXACTLY EQUAL
TABLKF: HLRZ T2,@P2 ;GET STRING ADDRESS
PUSHJ P,CHKTBS ;GET FLAGS
JXN T1,CM%NOR,TABLKM ;MAKE IT AMBIG IF NOREC ENTRY
MOVX T2,TL%EXM ;EXACTLY EQUAL, RETURN CODE
JRST TABLKA
TABLKM: SKIPA T2,[TL%AMB] ;AMBIGUOUS RETURN
TABLKX: MOVX T2,TL%NOM ;NO MATCH RETURN
TABLKA: MOVEI T1,@P2 ;RETURN ADR WHERE ENTRY IS OR SHOULD BE
POPJ P,
;STRING MAY BE UNEQUAL OR A SUBSET, SEE WHICH
TABLK1: JXE T1,SC%SUB,TABLKN ;UNEQUAL, GO SETUP NEXT PROBE
TABLK3: MOVEM T2,REMSTR ;SUBSTRING, SAVE REMAINDER
JUMPE P1,TABLK2 ;JUMP IF THIS FIRST ENTRY IN TABLE
MOVEI T1,@P2 ;CHECK NEXT HIGHER ENTRY IN TABLE
HLRZ T2,-1(T1) ;GET ITS STRING ADDRESS
PUSHJ P,CHKTBS ;BUILD BYTE PTR
MOVE T1,STRG ;GET TEST STRING
PUSHJ P,USTCMP ;TEST PREVIOUS ENTRY
JUMPE T1,[SOJA P1,TABLKF] ;EXACTLY EQUAL, DONE. FIX INDEX.
JXN T1,SC%GTR,TABLK2 ;IF LESS THEN HAVE FOUND HIGHEST SUBSTR
SOJA P1,TABLK3 ;STILL A SUBSTR, CHECK HIGHER
;NOW POINT AT HIGHEST ENTRY WHICH IS A SUBSTR. IF THERE IS AN EXACT
;MATCH, IT IS BEFORE ALL SUBSETS AND HAS ALREADY BEEN FOUND
TABLK2: MOVEI T1,@P2 ;CHECK NEXT ENTRY FOR AMBIGUOUS
CAIL P1,-1(P4) ;NOW AT LAST ENTRY IN TABLE?
JRST TBLK2A ;YES, THIS ENTRY IS DISTINCT
HLRZ T2,1(T1) ;GET STRING ADR OF NEXT ENTRY
PUSHJ P,CHKTBS ;BUILD BYTE PTR
MOVE T1,STRG ;GET TEST STRING
PUSHJ P,USTCMP ;COMPARE NEXT LOWER ENTRY
JUMPE T1,[$STOP(BTF,Bad table format)] ;EXACT MATCH,TABLE IS BAD
JXN T1,SC%SUB,TABLKM ;NEXT ENTRY NOT DISTINCT, DO AMBIG RETURN
TBLK2A: HLRZ T2,@P2 ;CHECK FLAGS FOR THIS ENTRY
PUSHJ P,CHKTBS
JXN T1,CM%NOR,TABLKM ;FAIL IF NOREC BIT SET
MOVX T2,TL%ABR ;GIVE LEGAL ABBREVIATION RETURN
MOVE T3,REMSTR ;RETURN PTR TO REMAINDER OF STRING
JRST TABLKA
;HERE WHEN PROBE NOT EQUAL
TABLKN: CAIG P3,1 ;INCREMENT NOW 1?
JRST [JXN T1,SC%LSS,TABLKX ;YES, NO MATCH FOUND
AOJA P1,TABLKX] ;IF STRING GREATER, BUMP ADR FOR INSERT
AOS P3 ;NEXT INC = <INC+1>/2
ASH P3,-1
TXNE T1,SC%GTR ;IF LAST PROBE LOW, ADD INCREMENT
ADD P1,P3
TXNE T1,SC%LSS
SUB P1,P3 ;LAST PROBE HIGH, SUBTRACT INCR
TBLKN1: CAIL P1,0(P4) ;AFTER END OF TABLE?
JRST [MOVX T1,SC%LSS ;YES, FAKE PROBE TOO HIGH
JRST TABLKN]
JUMPGE P1,TABLK0 ;IF STILL WITHIN TABLE RANGE, GO PROBE
MOVX T1,SC%GTR ;BEFORE START OF TABLE, FAKE LOW PROBE
JRST TABLKN
SCN%L: ;LABEL THE LITERAL POOL
>;;!!!!!NOTE WELL - THIS CONDITIONAL STARTED AT LABEL S%CMND