Google
 

Trailing-Edge - PDP-10 Archives - decuslib20-07 - decus/20-0161/parse.mac
There are 11 other files named parse.mac in the archive. Click here to see a list.
;<P.HURLEY.2>PARSE.MAC.2, 27-Jul-79 08:45:02, EDIT BY HURLEY

	TITLE PARSE - ROUTINE TO PARSE COMMANDS
	ENTRY PARSE
	SALL
	SEARCH MONSYM,MACSYM,PARUNV
	.REQUIRE SYS:MACREL

	T1=1
	T2=2
	T3=3
	T4=4
	Q1=5
	Q2=6
	Q3=7
	P1=10
	P2=11
	P3=12
	P4=13
	P5=14
	P6=15
	CX=16
	P=17

;DEFINITIONS

DEFINE SAVEPQ <
	JSP CX,SAVPQ>

DEFINE SAVEP <
	JSP CX,SAVP>

;DEFSTR DEFINITIONS

MSKSTR (CMFNC,.CMFNP,CM%FNC)	;COMMAND FUNCTION CODE
MSKSTR (CMLST,.CMFNP,CM%LST)	;ADR OF FUNCTION DESCRIPTOR BLOCK
DEFSTR (CMDAT,.CMDAT,35,36)	;COMMAND DATA

DEFSTR (PDBER,PDB.ER,35,36)	;ERROR MESSAGE ROUTINE ADDRESS
DEFSTR (PDBNX,PDB.NX,35,36)	;ADR OF NEXT PDB
DEFSTR (PDBDF,PDB.DF,35,36)	;ADR OF DEFAULT FILLING ROUTINE

	SUBTTL Constant Definitions

NCHPW==5			;NUMBER OF ASCII CHARACTERS PER WORD
BUFSIZ==200			;SIZE OF INPUT TEXT BUFFER
ATMSIZ==BUFSIZ			;SIZE OF ATOM BUFFER FOR COMND JSYS
GJFSIZ==.GJRTY+2		;SIZE OF GTJFN BLOCK USED BY COMND JSYS
FDBSIZ==.CMDEF+2		;SIZE OF FUNCTION DESCRIPTOR BLOCK
	SUBTTL Local Storage

;STORAGE FOR PARSER TO EVENT PROCESSOR COMMUNICATION

ZERBEG==.			;START OF AREA TO BE ZEROED

PARFRE:	BLOCK 1			;POINTER TO FIRST FREE IN COMM BLOCK
ARGFRE:	BLOCK 1			;POINTER TO FIRST FREE WORD IN ARG SPACE
JFNFRE:	BLOCK 1			;IOWD POINTER TO JFN STACK

	JFNSTL==40		;LENGTH OF JFNSTK
JFNSTK:	BLOCK JFNSTL		;LIST OF ALL STACKED JFNS

PARBLK:	BLOCK 50		;SPACE FOR COMM BLOCK
ARGBLK:	BLOCK 400		;SPACE FOR ARGUMENTS (ASCIZ, ETC.)
ARGEND==.-1			;WHERE TO STOP ZEROING

;STORAGE FOR THE PARSER

CMDBLK:	BLOCK .CMGJB+5		;COMMAND STATE BLOCK FOR COMND JSYS
BUFFER:	BLOCK BUFSIZ		;INPUT TEXT STORED HERE
ATMBFR:	BLOCK ATMSIZ		;ATOM BUFFER FOR COMND JSYS
GJFBLK:	BLOCK GJFSIZ		;GTJFN BLOCK FOR COMND JSYS

ZEREND==.			;END OF AREA TO BE ZEROED
	SUBTTL Main ROUTINE

;ROUTINE TO PARSE A COMMAND
;ACCEPTS IN T1/	STRING POINTER TO PROMPT
;	    T2/	POINTER TO THE COMMAND "PDB" CHAIN
;	    T3/	ADDRESS OF WHERE TO STORE THE PARSED COMMAND
;	CALL PARSE
;RETURNS +1:	FAILED - COMMAND "PDB" BLOCK DID NOT START WITH A .CMINI
;	 +2:	OK, PARSED COMMAND IS STORED IN BLOCK GIVEN IN T3
;		T1/	POINTER TO THE COMMAND STRING
;		T2/	FIRST UNUSED WORD IN ANSWER BLOCK

PARSE::	SAVEPQ			;SAVE ALL PERMANENT ACS
	STKVAR <PARCMT,PARADR>
	MOVEM T2,PARCMT		;SAVE POINTER TO THE COMMAND TABLE
	MOVEM T3,PARADR		;SAVE POINTER TO WHERE TO BUILD THE PARAMETER BLOCK
	LOAD T4,CMFNC,(T2)	;GET THE FIRST FUNCTION CODE
	CAIE T4,.CMINI		;IT MUST BE AN INI FUNCTION
	RET			;IF NOT, THEN GIVE ERROR RETURN

;NOW SET UP THE COMMAND STATE BLOCK

	MOVE T4,[ZERBEG,,ZERBEG+1]
	SETZM ZERBEG		;FIRST ZERO ALL STORAGE USED
	BLT T4,ZEREND-1
	MOVEM T1,CMDBLK+.CMRTY	;PUT RE-TYPE PROMPT POINTER IN STATE BLOCK
	HRROI T1,BUFFER		;GET POINTER TO INPUT TEXT BUFFER
	MOVEM T1,CMDBLK+.CMPTR	;SAVE POINTER TO COMMAND STRING
	MOVEM T1,CMDBLK+.CMBFP	;SAVE POINTER TO START-OF-BUFFER
	MOVE T1,[.PRIIN,,.PRIOU] ;GET PRIMARY INPUT,, OUTPUT JFN'S
	MOVEM T1,CMDBLK+.CMIOJ	;SAVE PRIMARY JFN'S
	MOVEI T1,REPARS		;GET RE-PARSE ADDRESS
	MOVEM T1,CMDBLK+.CMFLG	;SAVE RE-PARSE ADDRESS
	SETZM CMDBLK+.CMINC	;INITIALIZE # OF CHARACTERS AFTER POINTER
	MOVEI T1,BUFSIZ*NCHPW	;GET # OF CHARACTERS IN BUFFER AREA
	MOVEM T1,CMDBLK+.CMCNT	;SAVE INITIAL # OF FREE CHARACTER POSITIONS
	HRROI T1,ATMBFR		;GET POINTER TO ATOM BUFFER
	MOVEM T1,CMDBLK+.CMABP	;SAVE POINTER TO LAST ATOM INPUT
	MOVEI T1,ATMSIZ*NCHPW	;GET # OF CHARACTERS IN ATOM BUFFER
	MOVEM T1,CMDBLK+.CMABC	;SAVE COUNT OF SPACE LEFT IN ATOM BUFFER
	MOVEI T1,GJFBLK		;GET ADDRESS OF GTJFN BLOCK
	MOVEM T1,CMDBLK+.CMGJB	;SAVE IN COMMAND STATE BLOCK
	MOVE T1,[IOWD JFNSTL,JFNSTK]
	MOVEM T1,JFNFRE		;SET UP POINTER TO JFN STACK
PARSER:	MOVEI P1,CMDBLK		;COMND STATE BLOCK
	MOVE P2,PARCMT		;INITIAL PDB TO FEED TO COMND
	CALL RELJFN		;RELEASE ALL JFNS ON THE STACK
PARS.1:	DMOVE T1,P1		;COPY THE COMND ARGS
	COMND			;PARSE NEXT FIELD
	  ERJMP CMDERR		;ERROR, SEE WHY
	TXNN T1,CM%NOP		;VALID COMMAND ENTERED ?
	JRST PARS.3		;YES, GO DISPATCH TO PROCESSING ROUTINE
	LOAD P2,PDBER,(P2)	;GET ADDR OF SPECIAL ERROR ROUTINE
	JUMPE P2,PARS.2		;IF NO ROUTINE JUST TYPE COMMAND ERROR
	CALL (P2)		;CALL THE ROUTINE
	JRST PARSER		;GO TRY TO GET A COMMAND AGAIN
PARS.2:	HRROI T1,[ASCIZ/
?COMMAND ERROR: /]
	PSOUT
	MOVX T1,.PRIOU		;TO PRIMARY OUTPUT
	MOVE T2,[.FHSLF,,-1]	;OUR LAST ERROR
	ERSTR			;TYPE OUT THE ERROR STRING
	 JRST [	CALL ERRUEN	;UNDEFINED ERROR NUMBER
		JRST PARSER]
	 JRST [	CALL ERRBDD	;BAD DESTINATION DESIGNATOR
		JRST PARSER]
	JRST PARSER		;AND TRY AGAIN


;HERE ON SUCCESSFUL PARSE FROM COMMAND JSYS

PARS.3:	MOVE P2,T2		;COPY DATA TO P2
	MOVE P4,T3		;SAVE POINTER TO FUNCTION BLOCK
	LOAD P3,CMFNC,(P4)	;GET THE COMMAND FUNCTION CODE
	MOVE T1,P3		;COPY FUNCTION TO T1
	MOVE T2,P2		;AND DATA TO T2
	CALL @PARTAB(T1)	;DISPATCH OFF FUNCTION
	MOVE T1,P3		;COPY FUNCTION TO T1
	MOVE T2,P2		;AND DATA TO T2
	SKIPE T4,PDB.RT(P4)	;GET SPECIAL ROUTINE ADDRESS FROM PDB
	CALL (T4)		;CALL THE SPECIAL ROUTINE IF THERE
	HRRZ P2,(P2)		;GET CONTENTS OF RETURNED DATA
	LOAD T1,PDBNX,(P4)	;GET NEXT FDB IF ANY
	JUMPN T1,PARS.4		;USE IT IF ONE IS SPECIFIED
	CAIE P3,.CMKEY		;KEYWORD
	CAIN P3,.CMSWI		;OR SWITCH ?
	SKIPA T1,(P2)		;YES, USE DATA IN KEYTAB AS FDB ADR
	LOAD T1,PDBNX,(P4)	;NO, GET NEXT FDB FROM CURRENT
	JUMPE T1,PARS.5		;IF NO NEXT PDB, GO BUILD ANSWER
PARS.4:	HRRZS P2,T1		;PASS ONLY RIGHT HALF
	CALL FILDEF		;GO FILL IN ANY DEFAULTS NEEDED
	JRST PARS.1		;AND FINISH COMMAND
PARS.5:	MOVE T1,PARADR		;GET ADR OF WHERE TO BUILD BLOCK
	CALL BLDCOM		;GO BUILD A COMMAND MESSAGE
	MOVE T2,T1		;SAVE FIRST FREE WORD
	MOVE T1,[POINT 7,BUFFER] ;RETURN POINTER TO THE COMMAND
	RETSKP			;DONE
	SUBTTL Routine to Take a Parser Block and Build a Command Message

;ROUTINE TO BUILD THE PARSED BLOCK
;ACCEPTS IN T1/	ADR OF WHERE TO PUT THE BUILT BLOCK
;	ASSMUES ALL DATA IS SET UP IN AGRBLK
;RETURNS +1:	ALWAYS
;		T1/	FIRST UNUSED WORD IN ANSWER BLOCK

BLDCOM:	SAVEP			;SAVE NEEDED AC'S
	MOVE P1,PARFRE		;COMPUTE LENGTH OF
	SUBI P1,PARBLK		;PARSER BLOCK
	MOVE P2,ARGFRE		;GET END OF ARG SPACE
	SUBI P2,ARGBLK		;COMPUTE LENGTH
	MOVE P3,P1		;TAKE COPY OF PARSER BLOCK LENGTH
	MOVNS P1		;MAKE P1 NEGATIVE FOR AOBJN
	HRLS P1			;MAKE AOBJN POINTER
	HRRI P1,PARBLK		;POINT TO PARBLK (PARSER DATA BLOCK)
BLDC.1:	MOVE T4,(P1)		;GET DATA
	HLRZ Q1,T4		;GET CODE
	CAIE Q1,.CMSWI		;SWITCH?
	CAIN Q1,.CMKEY		;OR KEYWORD?
	JRST BLDC.2		;YES, NO OFFSET NEEDED
	CAIE Q1,.CMCFM		;CONFIRM?
	CAIN Q1,.CMCMA		;OR COMMA?
	JRST BLDC.2		;YES, NO OFFSET NEEDED
	ADD T4,P3		;ADD IN OFFSET
BLDC.2:	MOVEM T4,(T1)		;COPY TO IPCF PAGE
	ADDI T1,1		;INCREMENT IPCF PAGE POINTER
	AOBJN P1,BLDC.1		;LOOP FOR ALL
	MOVNS P2		;GET NEGATIVE LENGTH OF DATA AREA
	HRLZS P2		;MAKE AN AOBJN POINTER
BLDC.3:	MOVE T4,ARGBLK(P2)	;GET CURRENT WORD INTO T4
	MOVEM T4,(T1)		;SAVE IN MESSAGE BEING BUILT
	ADDI T1,1		;INCREMENT POINTER TO MESSAGE
	AOBJN P2,BLDC.3		;AND STEP THRU DATA AREA
	RET			;AND RETURN
	SUBTTL Routine to 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 RELJFN		;RELEASE ALL JFNS SO FAR
	CALL @.CMINI+PARTAB	;TELL SAVE ROUTINES TO FORGET IT
	MOVE T1,[GJFBLK,,GJFBLK+1] ;SET UP TO CLEAR GTJFN BLOCK
	SETZM GJFBLK		;CLEAR FIRST WORD
	BLT T1,GJFBLK+GJFSIZ-1	;CLEAR THE BLOCK
	MOVEI P1,CMDBLK		;GET STATE BLOCK ADDRESS
	MOVE P2,PARCMT		;GET INITIAL COMMAND TABLE POINTER
	LOAD P2,PDBNX,(P2)	;STEP TO BLOCK AFTER .CMINI
	JRST PARS.1		;JUST RESTART PARSER


;ROUTINE TO RELEASE ALL JFNS STACKED SO FAR

RELJFN:	MOVSI T4,JFNSTL		;SET UP AN AOBJN POINTER TO JFN STACK
RELJFL:	SKIPE T1,JFNSTK(T4)	;IS THERE A JFN HERE?
	RLJFN			;YES, RELEASE IT
	 JFCL
	SETZM JFNSTK(T4)	;ZERO THE STACK
	AOBJN T4,RELJFL		;LOOP BACK FOR ALL OF THEM
	MOVE T1,[IOWD JFNSTL,JFNSTK]
	MOVEM T1,JFNFRE		;INIT STACK POINTER
	RET			;DONE
	SUBTTL Routine To Fill in Defaults for COMND

;ROUTINE TO FILL IN DEFAULTS IF NEEDED
;CALLED WITH P2 POINTING TO PDB ABOUT TO BE FED TO COMND
;FILLS IN ALL DEFAULTS FOR THE NEXT SET OF LINKED PDB'S

FILDEF:	MOVE T1,P2		;COPY THE PDB ADDRESS
FILD.1:	LOAD T2,PDBDF,(T1)	;GET THE ADDR OF THE DEFAULT FILLING ROUTINE
	JUMPE T2,FILD.2		;NONE THERE, LOOK FOR LINKED PDB'S
	PUSH P,T1		;SAVE ADR OF PDB
	CALL (T2)		;CALL THE DEFAULT FILLER
	POP P,T1
FILD.2:	LOAD T1,CMLST,(T1)	;GET THE ADDR OF NEXT PDB IN LIST
	JUMPN T1,FILD.1		;LOOP IF THERE IS ONE
	RET			;AND RETURN
;CMDERR - ROUTINE TO PROCESS ERRORS ON EXECUTING A COMND JSYS
;	  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 CMDERR

CMDERR:	HRROI T1,[ASCIZ/
?COMMAND ERROR: /]
	PSOUT
	MOVX T1,.PRIOU		;TO PRIMARY OUTPUT
	MOVE T2,[.FHSLF,,-1]	;OUR LAST ERROR
	ERSTR			;TYPE OUT THE ERROR STRING
	 JRST [	CALL ERRUEN	;UNDEFINED ERROR NUMBER
		JRST PARSER]
	 JRST [	CALL ERRBDD	;BAD DESTINATION DESIGNATOR
		JRST PARSER]
	JRST PARSER		;GO START OVER AGAIN
	SUBTTL ERROR ROUTINES

BADCOM::	HRROI T1,[ASCIZ/
?INVALID COMMAND "/]
	PSOUT
	HRROI T1,ATMBFR
	PSOUT
	HRROI T1,[ASCIZ/" /]
	PSOUT
	RET
BADIFI:: MOVX T1,GJ%OFG		;PARSE-ONLY GTJFN
	MOVEM T1,GJFBLK+.GJGEN	;IN FLAGS WORD
	MOVE T1,[XWD .NULIO,.NULIO] ;SUPPLY NO JFNS
	MOVEM T1,GJFBLK+.GJSRC	;INTO BLOCK
	MOVEI T1,GJFBLK		;GTJFN BLOCK ADDRESS
	HRROI T2,ATMBFR		;STRING POINTER TO ATOM BUFFER
	GTJFN			;GET A JFN
	  JRST BADI.1		;JUST DO THE ERSTR
	HRROI T1,[ASCIZ/
?CAN'T FIND FILE "/]
	PSOUT
	HRRZ T2,T1		;MOVE JFN TO T2 FOR JFNS
	MOVEI T1,.PRIOU		;TO PRIMARY OUTPUT
	MOVE T3,[111100,,1]	;GET OUT EVERYTHING UP TO THE PROTECTION
	JFNS			;MAKE THE JFN INTO A STRING
	HRROI T1,[ASCIZ/"
	/]
	PSOUT
BADI.1:	MOVX T1,.PRIOU		;TO PRIMARY OUTPUT
	MOVE T2,[.FHSLF,,-1]	;OUR LAST ERROR
	ERSTR			;TYPE OUT THE ERROR STRING
	 CALLRET ERRUEN		;UNDEFINED ERROR NUMBER
	 CALLRET ERRBDD		;BAD DESTINATION DESIGNATOR
	RET

;ERSTR JSYS FAILURE ROUTINES

ERRBDD:	SKIPA T1,[-1,,[ASCIZ/ERSTR Jsys Failure, Bad Destination Designator/]]
ERRUEN:	HRROI T1,[ASCIZ/ERSTR Jsys Failure, Undefined Error Number/]
	PSOUT
	RET
	SUBTTL Dispatch for Parser Save Routines

COMMENT \

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 THESE ROUTINES ARE CALLED WITH T1 CONTAINING THE COMND FUNCTION CODE
;USED TO PARSE THE LAST FIELD AND T2 CONTAINING THE DATA RETURNED BY COMND
;T3 MUST CONTAIN THE ADDRESS OF THE FDB USED BY COMND TO PARSE THE FIELD

PARTAB:	SAVIND			;KEYWORD (.CMKEY)
	SAVNUM			;NUMBER  (.CMNUM)
	R			;NOISE WORD (.CMNOI) (NO PROCESSING)
	SAVIND			;SWITCH (.CMSWI)
	SAVJFN			;INPUT FILE SPEC (.CMIFI)
	SAVJFN			;OUTPUT FILE SPEC (.CMOFI)
	SAVJFN			;GENERAL FILE SPEC (.CMFIL)
	SAVATM			;ARBITRARY FIELD (.CMFLD)
	SAVZER			;CONFIRM (.CMCFM)
	SAVRSS			;DIRECTORY (.CMDIR)
	SAVRSS			;USER NAME (.CMUSR)
	SAVZER			;COMMA (.CMCMA)
	SAVINI			;INITIALIZATION (.CMINI)
				;THIS IS CALLED TO INITIALIZE SAVE STUFF
	SAVRES			;FLOATING POINT NUMBER (.CMFLT)
	SAVRES			;DEVICE NAME (.CMDEV)
	SAVATM			;TEXT TO CARRAIGE RETURN (.CMTXT)
	SAVRES			;DATE AND TIME (.CMTAD)
	SAVATM			;QUOTED STRING (.CMQST)
	R			;***RET FOR NOW***;UNQUOTED STRING (.CMUQS)
	SAVTOK			;TOKEN (.CMTOK)
	SAVNUM			;NUMBER (ARBITRARY TERMINATOR) (.CMNUX)
	R			;(.CMACT)
	SAVATM			;NODE NAME(.CMNOD)
	SUBTTL Save Routines

;DATA RETURNED IS A POINTER INTO A TABLE (SWITCH OR KEYWORD)
SAVIND:	HRRZ T2,(T2)		;GET INDIRECT ADDRESS
	LOAD T4,PDBNX,(T3)	;GET THE NEXT FDB FROM THIS ONE
	SKIPN T4		;IF ONE THERE, STORE ADDRESS INSTEAD
	HLRZ T2,(T2)		;FETCH CODE SET UP BY KEYTAB MACRO
	JRST MAKENT		;AND MAKE THE ENTRY

;SAVE ROUTINES FOR FUNCTIONS WHICH COPY VALUE TO ATOM BUFFER
;(.CMFLD, .CMTXT, .CMQST)
SAVATM:	SAVEP			;SAVE NEEDED REGS
	MOVE T2,ARGFRE		;GET FIRST FREE ARG LOCATION
	HRLI T2,(POINT 7,)	;MAKE T2 A BYTE POINTER
	MOVE P1,[POINT 7,ATMBFR] ;POINT AT THE ATOM BUFFER
SAVA.1:	ILDB P2,P1		;GET A CHARACTER FROM THE ATOM BUFFER
	IDPB P2,T2		;SAVE IT IN THE ARGUMENT SPACE
	JUMPN P2,SAVA.1		;AND LOOP IF MORE
	HRRZI T2,1(T2)		;STEP TO NEXT LOC AND CLEAR LH
	EXCH T2,ARGFRE		;STORE NEXT FREE AND GET FIRST USED
	SUBI T2,ARGBLK		;CONVERT TO RELATIVE ADDRESS
	JRST MAKENT		;AND MAKE THE ENTRY

;SAVE A ZERO (CONFIRM OR COMMA, FUNCTION TELLS ALL)
SAVZER:	SETZ T2,		;JUST A ZERO
	JRST MAKENT		;GO MAKE AN ENTRY

;SAVE ROUTINE FOR NUMBERS
SAVNUM:	SAVEP			;SAVE AN AC
	LOAD P1,CMDAT,(T3)	;GET THE RADIX USED
	DPB P1,[POINT 9,T1,26]	;SAVE IT WITH FUNCTION
;AND FALL INTO SAVRES

;ROUTINE TO STACK A JFN

SAVJFN:	MOVE T4,JFNFRE		;GET POINTER TO JFN STACK
	PUSH T4,T2		;STACK THE JFN
	MOVEM T4,JFNFRE		;STORE THE UPDATED STACK POINTER
	JRST SAVRES		;GO SAVE THE JFN IN THE ANSWER BLOCK

;SAVE ROUTINES WHICH SAVE A POINTER TO WHAT COMND RETURNS IN AC2
;(FLOATING NUMBER, DATE/TIME, DEVICE, FILE SPECS)
SAVRES:	SAVEP			;SAVE A WORKING REG
	MOVE P1,ARGFRE		;GET THE NEXT FREE ARG BLOCK WORD
	MOVEM T2,(P1)		;SAVE THE RESULT OF COMND THERE
	MOVE T2,P1		;GET ADDR USED INTO T2
	SUBI T2,ARGBLK		;MAKE IT THE OFFSET INTO ARGBLK
	AOS ARGFRE		;STEP FREE LOC UP ONE
	JRST MAKENT		;AND GO MAKE THE ENTRY

;ROUTINE TO SAVE ANSWER AND ATOM BUFFER
;(USER, DIRECTORY)
SAVRSS:	SAVEP			;SAVE A WORKING REG
	MOVE P1,ARGFRE		;GET THE NEXT FREE ARG BLOCK WORD
	MOVEM T2,(P1)		;SAVE THE RESULT OF COMND THERE
	AOS T2,ARGFRE		;STEP FREE LOC UP ONE
	HRLI T2,(POINT 7,)	;MAKE T2 A BYTE POINTER
	MOVE P1,[POINT 7,ATMBFR] ;POINT AT THE ATOM BUFFER
SAVR.1:	ILDB P2,P1		;GET A CHARACTER FROM THE ATOM BUFFER
	IDPB P2,T2		;SAVE IT IN THE ARGUMENT SPACE
	JUMPN P2,SAVR.1		;AND LOOP IF MORE
	HRRZI T2,1(T2)		;STEP TO NEXT LOC AND CLEAR LH
	EXCH T2,ARGFRE		;STORE NEXT FREE AND GET FIRST USED
	SUBI T2,ARGBLK+1	;CONVERT TO RELATIVE ADDRESS
	JRST MAKENT		;AND MAKE THE ENTRY

;SAVE A TOKEN
SAVTOK:	SAVEP			;SAVE SOME WORKING SPACE
	MOVE T2,ARGFRE		;GET SPACE TO STORE ARG TO T2
	HRLI T2,(POINT 7,)	;MAKE IT A BYTE POINTER
	LOAD P2,CMDAT,+PDB.FD(T2) ;GET THE DATA USED BY COMND
	HRLI P2,(POINT 7,)	;MAKE IT A BYTE POINTER
SAVT.1:	ILDB P1,P2		;GET A CHARACTER
	IDPB P1,T2		;AND SAVE IT AWAY
	JUMPN P1,SAVT.1		;LOOP IF NOT DONE
	HRRZI T2,1(T2)		;POINT T2 TO FIRST FREE LOC
	EXCH T2,ARGFRE		;AND CHANGE IT WITH FIRST USED
	SUBI T2,ARGBLK		;CONVERT TO RELATIVE ADDRESS
	JRST MAKENT		;AND GO MAKE ENTRY
	SUBTTL Initialization for Parser Save Routines

;THIS ROUTINE IS CALLED TO INITIALIZE THE SAVE ROUTINES FOR THE PARSER
;IT IS THE FUNCTION DEPENDENT ROUTINE FOR THE .CMINI FUNCTION

SAVINI:	MOVEI T1,ARGBLK		;GET THE ADDRESS OF THE ARGUMENT STORAGE
	MOVEM T1,ARGFRE		;SAVE AS FIRST FREE PLACE TO SAVE STUFF
	MOVEI T1,PARBLK		;GET ADDRESS OF PARSER COMMUNICATIONS BLOCK
	MOVEM T1,PARFRE		;SAVE AS FIRST FREE LOC IN THAT BLOCK
	MOVE T1,[PARBLK,,PARBLK+1] ;GET START OF BLOCK TO CLEAR
	SETZM (T1)		;CLEAR FIRST WORD
	BLT T1,ARGEND		;CLEAR TO END OF ARGUMENT SPACE
	RET			;AND RETURN
	SUBTTL MAKENT  --  Routine To Make an Entry for Parser Save Routines

;THIS ROUTINE IS CALLED WITH T2 CONTAINING WHAT WILL BE THE RIGHT HALF
;OF THE ENTRY AND T1 CONTAINING THE LEFT HALF.

MAKENT:	HRRZM T2,@PARFRE	;SAVE THE RIGHT HALF
	HRLM T1,@PARFRE		;SAVE THE LEFT HALF
	AOS PARFRE		;UPDATE THE FREE POINTER
	RET			;RETURN
;SUPPORT ROUTINES

SAVPQ:	PUSH P,Q1
	PUSH P,Q2
	PUSH P,Q3
	PUSH P,P1
	PUSH P,P2
	PUSH P,P3
	PUSH P,P4
	PUSH P,P5
	PUSH P,P6
	CALL 0(CX)
	 SKIPA
	AOS -11(P)
	POP P,P6
	POP P,P5
	POP P,P4
	POP P,P3
	POP P,P2
	POP P,P1
	POP P,Q3
	POP P,Q2
	POP P,Q1
	RET

SAVP:	PUSH P,P1
	PUSH P,P2
	PUSH P,P3
	PUSH P,P4
	PUSH P,P5
	PUSH P,P6
	CALL 0(CX)
	 SKIPA
	AOS -6(P)
	POP P,P6
	POP P,P5
	POP P,P4
	POP P,P3
	POP P,P2
	POP P,P1
	RET

	END