Google
 

Trailing-Edge - PDP-10 Archives - decus_20tap2_198111 - decus/20-0028/c.366
There are 2 other files named c.366 in the archive. Click here to see a list.
TITLE COMMON SUBROUTINES FOR SNOBOL
	
SUBTTL BY LARRY WADE / THIS ASSEMBLY MADE WITH C.366
IFNDEF REENTR,<REENTR==1>
IFN REENTR,<
	TWOSEG
	RELOC ^O400000
>


	EXTERN FLOUT.
	EXTERN I	;INTEGER DATA TYPE
	EXTERN STYPE
	EXTERN JOBFF,JOBREL
	INTERN SPCINX,LOCSPR,APPEND,INTSPX,REALSX
	INTERN CPYPAX,INTDEV,INFMT
	EXTERN SYNTAB,SYNSIZ,PUTTAB,PUTSIZ
	EXTERN DATBUF
	INTERN INTCOR
	INTERN PDL
	EXTERN PDSTCK
PDSIZ=30
PDL:	IOWD PDSIZ,PDSTCK

	INTERN DATX
DATX:	CALLI	1,14		;GET THE DATE FROM THE MONITOR.
	IDIVI	1,^D31		;DIV. BY 31 TO OBTAIN THE DAY-1.
	AOS	2		;TO OBTAIN THE DAY.
	IDIVI	2,^D10		;CONVERT INTO TWO DEC. DIGITS.
	SKIPN	2		;IS THE DAY < 10?
	MOVNI	2,20		;YES, OUTPUT BLANK.
	MOVEI 0,DATBUF		;CREATE POINTER
	HRLI	0,440700	;TO DEPOSIT DATE
	JSP	4,SUB1		;DEPOSIT DAY
	IDIVI	1,^D12		;TO OBTAIN THE MONTH
	MOVE	3,[POINT 7,TABLE(2)] ;BYTE POINTER FOR MONTH
GETMON:	ILDB	4,3		;GET MONTH FROM THE TABLE
	IDPB	4,0		;DEPOSIT MONTH
	TLNE	3,760000	;ALL OF THE MONTH?
	JRST	GETMON		;NO, GET NEXT CHAR.
	MOVEI	2,^D64(1)	;YES, GET THE YEAR
	IDIVI	2,^D10		;CONVERT INTO TWO DEC. DIGITS
	JSP	4,SUB1		;DEPOSIT YEAR
	POPJ P,

;SUB1 CONVERTS THE DAY AND THE YEAR INTO ASCII CHARS, AND
;DEPOSITS THEM IN THE TWO WORD ARRAY.

SUB1:	ADDI	2,60		;CONVERT FIRST DIGIT TO ASCII
	IDPB	2,0		;DEPOSIT FIRST DIGIT
	ADDI	3,60		;CONVERT SECOND DIGIT TO ASCII
	IDPB	3,0		;DEPOSIT SECOND DIGIT
	JRST	(4)		;RETURN TO MAIN SEQ.

PAGE

TABLE:	ASCII	/-JAN-/
	ASCII	/-FEB-/
	ASCII	/-MAR-/
	ASCII	/-APR-/
	ASCII	/-MAY-/
	ASCII	/-JUN-/
	ASCII	/-JUL-/
	ASCII	/-AUG-/
	ASCII	/-SEP-/
	ASCII	/-OCT-/
	ASCII	/-NOV-/
	ASCII	/-DEC-/


	INTERN INFMT
INFMT:	ASCII \(16A5)\	;GENERALIZED FORMAT FOR ALL INPUT

	INTERN SOURCF,TITLEF

SOURCF:	ASCII \(1H0,'DIGITAL EQUIPMENT CORP., PDP-10'/)\

TITLEF:	ASCII \(1H1,'SNOBOL4 (VERSION 3.4.3,  JAN. 16, 1971)'/)\
			;AT COMPILER LEVEL.

	INTERN BUFPNT
	EXTERN BUFIN

BUFPNT:	POINT 7,BUFIN,

	EXTERN ALPHI.,ALPHO.
	INTERN TXPNT
	EXTERN TXBUF

TXPNT:	POINT 7,TXBUF,


			;ORDER TO INITIALIZE ARRAY0S AND BUFFERS
CPOPJ2:	AOS (P)
CPOPJ1:	AOS (P)
CPOPJ:	POPJ P,

PAGE

	INTERN RENCOM
	EXTERN SYSCUT,DMPCL,LISTCL
RENCOM:	SETOM DMPCL
	EXTERN NCTRLC,CUTFLG,JOBOPC

	SKIPN NCTRLC	;CAN WE INTERRUPT AT THIS POINT?
	JRST SYSCUT	;YES, SO DO IT

	EXTERN EOL.,FIN
; SINCE WE ARE SOMEWHERE IN FORSE DOING SOME I/O LET'S FORCE A
; FIN. UUO AND CAUSE AN EXIT

	MOVEM 0,CUTFLG
	MOVEI 0,RNCOM1
	EXCH 0,CUTFLG
	SETOM EOL.
	JRST FIN	;DO THE FIN. AND RETURN AT RNCOM1

RNCOM1:	SETZM CUTFLG
	JRST SYSCUT






;	CPYPAX IS CALLED BY "CPYPAT" MACRO
;	A1,A2...A6 CONTAIN THE ADDRESS OF DESCRIPTORES
;	D1,D2...D6 RESPECTIVELY

CPYPAX:	MOVE R1,(A1)
	MOVE R2,(A2)
	MOVE R3,(A6)
CPY3:	MOVE A0,2(R2)
	MOVEM A0,2(R1)
	MOVE A0,3(R2)
	MOVEM A0,3(R1)
	MOVE A0,2*D(R2)
	SKIPE A0
	ADD A0,(A4)	;F1(X)=X+4 IF X NOT EQUAL TO 0
	MOVEM A0,2*D(R1)
	HRRZ A0,2*D+1(R2)
	JUMPE A0,CPY1
	ADD A0,(A4)	;F2(X)=X+A4 IF X NE TO 0
	SKIPA
CPY1:	MOVE A0,(A5)	;F2(X)=A5 IF X=0
	MOVEM A0,2*D+1(R1)
	MOVE A0,3*D(R2)	;GET A9+A3
	ADD A0,(A3)
	MOVEM A0,3*D(R1)
	HRRZ A0,3*D+1(R2)	;GET V9+A3
	ADD A0,(A3)
	MOVEM A0,3*D+1(R1)
	HRRZ A0,D+1(R2)	;LOOK AT V7
	CAIE A0,3
	JRST CPY2	;THIS CHECK DIFFERENT FOR VER 3
	MOVE A0,4*D(R2)
	MOVEM A0,4*D(R1)
	MOVE A0,4*D+1(R2)
	MOVEM A0,4*D+1(R1)
CPY2:	HRRZ A0,D+1(R2)	;GET V7
	ADDI A0,1
	IMULI A0,D
	SUBI R3,(A0)	;GET NEW R3
	ADDI R1,(A0)
	ADDI R2,(A0)
	SKIPLE R3
	JRST CPY3
CPY4:	MOVEM R1,(A1)
	POPJ P,

;	INTEGER TO STRING CONVERSION ROUTINE
;	CALLED BY "INTSPC" MACRO
;	A0=ADDRESS OF OUTPUT SPECIFIER
;	A1=INTEGER TO BE CONVERTED

INTSPX:	SETZM SPECL(A0)	;SET LENGTH=0 INITIALLY
; CLEAR FLAG FIELD AND SET 'SPCFLG' TO UNIQUELY IDENTIFY
; THIS AS A SPECIFIER

	MOVSI A3,SPCFLG
	HLLM A3,SPECF(A0)
	MOVE A3,[POINT 7,BUFSPX,]
	HRRM A3,(A0)	;SET ADDRESS FIELD
	MOVEM A3,SPECO(A0)	;SET OFFSET FIELD
	JUMPGE A1,INTS1
	MOVN A1,A1	;NEGATIVE, SO FORCE POSITIVE
	MOVEI CH,"-"
	IDPB CH,A3
	AOS SPECL(A0)	;BUMP LENGTH
INTS1:	MOVEI A4,^O12	;RADIX 10
RDXPRT:	IDIVI A1,(A4)
	HRLM A2,0(P)	;STORE ON LEFT HALF OF LIST
	SKIPE A1	;DONE IF NUMERATOR GOES TO ZERO
	PUSHJ P,RDXPRT	;RECURISIVE CALL
	HLRZ CH,0(P)
	ADDI CH,"0"	;CONVERT TO ASCII
	IDPB CH,A3
	AOS SPECL(A0)
	POPJ P,	;EVENTUALLY RETURN TO CALLER

PAGE

	EXTERN BUFSPX

PAGE

	EXTERN FRSGPT,HDSGPT,TLSGP1,OCALIM

	;FREE SEGMENT POINTER,HEADER SEGMENT POINTER AND TAIL
	INTERN INTCOR

;	BECAUSE OF DESIGN DECISIONS IN SNOBOL, IT IS NECESSARY
;	TO REINITIALIZE MANY-MANY VARAIBLES AND CONSTANTS ON
;	EACH RESTART OF SNOBOL (EXCEPT THE FIRST, BUT WE DO IT
;	ANYWAY). THIS IS DUE TO THE FACT THAT SOME NECESSARY
;	CONSTANTS ARE IRREPARABLY CHANGED DURING EXECUTION.

;	SINCE THERE ARE SO MANY, WE KEEP THESE ON A DISK FILE
;	CALLED SNOBOL.INI AND READ THIS FILE INTO THE PROPER
;	CORE AREA (BOUNDED BY DTLIST AND ARTHNO).

;	SNOBOL.INI IS CREATED DURING SNOBOL GENERATION TIME
;	BY USING THE /C SWITCH (FOR CREATE).

	EXTERNAL DTLIST,ARTHNO
	INTERN CORCHN
CORCHN==^O16	;CHANNEL TO DO INPUT FROM SNOBOL.INI
	EXTERN INIST%,ILIST%

	EXTERN TOTAVL,STCORE,ICORE,NUMIOB
	EXTERN ERRSET
INTCOR:	JSA ^O16,ERRSET
	ARG ZERO	;TELL HIM WE DON'T WANT ANY ERROR PRINTOUT
	INIT CORCHN,17	;DUMP MODE,RANDOM CHANNEL
	SIXBIT/SYS/	;ASSIGN DSK SYS IF ON OWN AREA
	Z		;DUMP MODE,SO NO BUFFERS
	HALT .		;FBTSES
INTCR1:	SETZM INIST%+3
	LOOKUP CORCHN,INIST%
	JRST INTCR2
INTCR4:	SKIPN FRSTIM
	JRST ICOR11
	MOVEI A0,ARTHNO	;CALCULATE WC
	SUBI A0,DTLIST
	MOVNS A0
	HRLM A0,ILIST%
	MOVEI A0,DTLIST-1
	HRRM A0,ILIST%	;FIX UP IOWD
	SETZM ILIST%+1
	INPUT CORCHN,ILIST%	;INPUT IT
ICOR11:	RELEASE CORCHN,	;GIVE IT UP
ICOR1:	SETOM FRSTIM

	RELOC
FRSTIM:	Z
	RELOC

	MOVE A0,JOBREL	;NOW MAKE UP DYNAMIC STORAGE
	MOVEM A0,ICORE	;SAVE FOR LATER SHRINKAGE
	SUB A0,JOBFF	;GET AMOUNT OF FREE STORAGE
	IDIVI A0,^O1777	;CONVERT TO NUMBER OF 1K BLOCKS
	MOVEM A0,STCORE	;AMOUNT OF STARTING FREE CORE
	MOVEI A1,0	;FIND OUT HOW MUCH CORE WE HAVE
	CALLI A1,11	;CORE UUO
	JFCL
	IMULI A1,2000	;CONVERT TO RELATIVE ADDR
IFN REENTR,<
	EXTERN JOBHRL
	HLRZ A0,JOBHRL
	SUBI A1,(A0)	;ACCOUNT FOR HIGH SEG SIZE
>
	MOVEM A1,TOTAVL	;TOTAL AVAILABLE TO US
	MOVE A0,JOBREL
	SUBI A0,2*D	;SAFTEY FACTOR
	MOVEM A0,TLSGP1
	; /I SWITCH CODE FOR IO BUFFERING
	MOVE A0,NUMIOB	;NUMBER OF IO BUFFERS TO INCREASE TO
	IMULI A0,^O204*2
	ADDI A0,^O204*4
	ADD A0,JOBFF	;RELOCATE
	ADDI A0,10	;SAFTEY FACTOR
ICOR2:	MOVEM A0,FRSGPT	;FREE SEGMENT POINTER
	MOVEM A0,HDSGPT	;PERMANENT HEADER WORD
		EXTERN STRREF
	SETZM STRREF	;CLEAR THE PEG COUNTER
; GUARD AGAINST CORE BOUNDARIES BEING EXCEEDED AT THIS POINT

EXTRACARE:	ADDI A0,5*^O1777	;5K IS MAGIC EXCESS AMT
	CAMG A0,JOBREL	;HAVE WE EXCEED JOBREL?
	POPJ P,	;NO,SO RETURN
	CALLI A0,11	;GET THE NEEDED CORE
	EXTERN CORERR
	JRST CORERR	;NOT AVAILABLE, SO GIVE ERROR MSG
	MOVE A0,JOBREL
	SUBI A0,2*D	;FIX UP TLSGP1
	MOVEM A0,TLSGP1
	POPJ P,		;RETURN CAREFREE AND HAPPY!


PAGE

	INTERN NUMINP,NUMOUT
	EXTERN UNITI,UNITO

NUMINP:	EXP UNITI	;INPUT DEVICE NUMBER
NUMOUT:	EXP UNITO	;OUTPUT DEVICE NUMBER
NUMONE:	EXP 1		;ONE?
NUMTWO:	EXP 2		;TWO?
NUMSNS==^D29	;DEVICE NO. FOR SNOOL SAVE FILE OPERATIONS
NUM29:	EXP NUMSNS	;"SNS" DEVICE NUMBER

	EXTERN CSWSET
INTCR2:	SETZM INIST%+2
	SETZM INIST%+3
	RELEASE CORCHN,0
	INIT CORCHN,17
	SIXBIT /DSK/
	Z
	HALT .
	LOOKUP CORCHN,INIST%
	SKIPA
	JRST INTCR4
INTCR3:	RELEASE CORCHN,0
	PUSHJ P,CSWSET	;WRITE THE FILE ON DISK
	JFCL
	INIT CORCHN,17
	SIXBIT /DSK/
	Z
	HALT .
	JRST INTCR1	;AND CONTINUE

PAGE

INTDEV:	PUSHJ P,FIXLST
	PUSHJ P,FIXSRC
	POPJ P,

	INTERN FIXSRC
	EXTERN OFILE,IFILE,LSTFIL,SRCFIL
	INTERN INTDEV
	EXTERN OFILBF,IFFAIL,IFILBF

FIXLST:	SETZM OFILBF+3	;CLEAR OLD PPN
	MOVEI A0,6
	MOVE A1,[POINT 6,LSTFIL,]	;SOURCE
	MOVE A2,[POINT 7,OFILBF,]	;DESTINATION
	PUSHJ P,FIXNAM
	MOVEI A0,3
	MOVE A1,[POINT 6,LSTFIL+1,]
	PUSHJ P,FIXEXT
	MOVE A1,LSTFIL+2
	MOVEM A1,OFILBF+3	;TRANSFER PPN
	JSA Q,OFILE
	JUMP 0,NUMOUT
	JUMP 5,OFILBF
	JUMP 0,OFILBF+3
	POPJ P,

FIXSRC:	SETZM IFILBF+3
	MOVEI A0,6
	MOVE A1,[POINT 6,SRCFIL,]	;SOURCE
	MOVE A2,[POINT 7,IFILBF,]	;DESTINATION
	PUSHJ P,FIXNAM
	MOVEI A0,3
	MOVE A1,[POINT 6,SRCFIL+1,]
	PUSHJ P,FIXEXT

	MOVE A1,SRCFIL+2
	MOVEM A1,IFILBF+3	;TRANSFER PPN
; CHECK FOR A SNOBOL SAVE FILE

	HLRZ A0,SRCFIL+1	;GET EXTENSION
	CAIE A0,(SIXBIT .SNS.)
	JRST FIX1
	JSA Q,IFILE
	JUMP 0,NUM29
	JUMP 5,IFILBF	;READ THE FILE

	MOVEI A0,0	;CHECK FOR FILE NOT THERE
	EXCH A0,IFFAIL
	JUMPN A0,NOFILE

	PUSHJ PDP,BUFCLR	;CLEAR OUT OLD GARBAGE
FIXS1:	RTB. 0,NUMSNS	;READ THE CONTROL BLOCK FIRST
	SLIST. 0,BUFIN
	ARG 0,^D30
	FIN.

	MOVE A0,BUFIN	;FIND OLD JOBREL
	JUMPE A0,BADSNS	;BAD FORMAT ON INPUT FILE
	CALLI A0,^O11	;CORE UUO
	JRST FIX2
	MOVE A0,BUFIN+1	;FIND NO. OF WORDS TO READ
	HRRM A0,SIZEIN
	MOVE A0,BUFIN+2
	HRRM A0,FIX6	;STORE SIZE
	MOVE A0,BUFIN+3
	HRRM A0,FIX5	;STORE ADDRESS
	JRST FIX3

	RELOC	;SWITCH TO LOW SEGMENT
FIX3:	RTB. 0,NUMSNS
	SLIST. 0,DTLIST
SIZEIN:	ARG 0,7777	;FIXED UP AT RUN TIME
	FIN.

FIX5:	RTB. 0,NUMSNS
FIX6:	SLIST. 0,.	;FIXED UP AT RUN TIME
FIX7:	ARG 0,0
	FIN.
	JRST FIX4

	RELOC	;SWITCH BACK TO HIGH SEGMENT
FIX4:	MOVSI 17,BUFIN+3	;RESTORE ACS
	BLT 17,17
	EXTERN RETNUL
	EXTERN SAVECL

	MOVEI A0,1
	MOVEM A0,SAVECL
	POPJ PDP,		;RETURN TO THE POINT AFTER
				;WHERE 'SAVE' WAS ORIGINALLY CALLED

	MLON
FIX2:	TTCALL 3,[ASCIZ /CAN'T EXPAND CORE FOR SNOBOL SAVE FILE
/]
	JRST F4EXEC
	EXTERN F4EXEC
FIX1:

	JSA Q,IFILE	;SPECIFY INPUT FILE NAME
	JUMP 00,NUMINP	;FORTRAN INPUT NUMBER
	JUMP 05,IFILBF	;INPUT BUFFER FOR FILENAME
	JUMP 0,IFILBF+3
	SKIPE ETMCL	;DON'T CHECK IF IN INTERPRETER
	JRST CPOPJ
	MOVEI A0,0	;CHECK FOR FILE NOT THERE
	EXCH A0,IFFAIL
	JUMPN A0,NOFILE
	POPJ P,

FIXEXT:	MOVEI A3,"."
	IDPB A3,A2
FIXNAM:	ILDB A3,A1	;GET A SOURCE CHARACTER
	JUMPE A3,CPOPJ
	ADDI A3,40	;CONVERT TO ASCII
	IDPB A3,A2
	SOJG A0,FIXNAM
	POPJ P,


NOFILE:	TTCALL 3,[ASCIZ /?INPUT FILE NOT FOUND
/]
	JRST F4EXEC

BADSNS:	TTCALL 3,[ASCIZ /?BAD INPUT FORMAT ON SAVE FILE
/]
	JRST F4EXEC

PAGE


	EXTERN BINWR.,ERR.,FAIL,DTLIST
	INTERNAL SAVCOR

; THIS ROUTINE IMPLEMENTS THE SAVE(FILE) FUNCTION
; IT ASSUMES A FILE NAME OF THE FORM  FOO.SNS, WHERE
; 'SNS' SIGNIFIES THE SNOBOL SAVE FORMAT FILE DEFAULT
;
; CALLS OF THIS FUNCTION ARE OF THE FORM
;
;	SAVE('SNIP.SNS')	:F(HELP)
;
; CALL:	MOVEI A2,SPECIFIER ADDRESS
;	PUSHJ PDP,SAVCOR
;	SUCCESS RETURN

; THE LAYOUT OF THE CONTROL BLOCK IS 
;
; BUFIN+0	OLD JOBHRL,,OLD JOBREL
; BUFIN+1	SIZE OF BLOCK STARTING AT CUTFLG
	EXTERN JOBSA
; BUFIN+2	SIZE OF BLOCK STARTING AT C(LH(JOBSA))
; BUFIN+3 -BUFIN + 7	NOT USED
; BUFIN+10	AC SAV AREA


SAVCOR:	PUSHJ P,BUFCLR	;CLEAR THE OUTPUT BUFFER
	MOVE A0,JOBREL	;REMEMBER HOW MUCH CORE WE HAVE
	MOVEM A0,BUFIN

IFN REENTR,<
	MOVE A0,JOBHRL
	HRLM A0,BUFIN
>
	MOVEI A0,ARTHNO
	SUBI A0,CUTFLG
	MOVEM A0,BUFIN+1
	HRRM A0,LSTSIZ
	MOVE A0,JOBREL
	HLRZ A1,JOBSA
	HRRM A1,SAVC4
	SUB A0,A1
	MOVEM A0,BUFIN+2
	HRRM A0,SAVC5
	MOVEM A1,BUFIN+3
	MOVEI A1,BUFIN+10	;SAVE ACS ALSO
	BLT A1,BUFIN+10+17
; NOW WRITE OUT THE TWO AREAS, ONE A CONTROL BLOCK AND THE OTHER
; ALL OF THE ACTUAL VARIABLE DATA

	WTB. 0,NUMSNS	;SELECT UNIT 29
	SLIST. 0,BUFIN
	ARG 0,^D30
	FIN.
	JRST SAVC1
	RELOC	;SWITCH TO LOW SEGMENT

SAVC1:	WTB. 0,NUMSNS
	SLIST. 0,CUTFLG
LSTSIZ:	ARG 0,7777	;FIXED AT RUN TIME
	FIN.

SAVC3:	WTB. 0,NUMSNS
SAVC4:	SLIST. 0,.
SAVC5:	ARG 0,0
	FIN.
	JRST SAVC2

	RELOC	;SWITCH TO HIGH SEGMENT
SAVC2:	POPJ P,

PAGE


; CALLED FROM APDSP MACRO
; A0=ADDRESS OF STRING 1-STRING 2 IS APPENDED TO THIS STRING
; A1=ADDRESS OF STRING 2 SPECIFIER

APPEND:	MOVE A3,SPECO(A0)	;GET BYTE POINTER OF STRING1
	MOVE A4,SPECL(A0)	;CHECK FOR NULL STRING
APPEN3:	JUMPE A4,APPEN1
	CAIGE A4,5
	JRST APPEN2
	IDIVI A4,5
	ADD A3,A4
	MOVE A4,A5
APPEN2:	SKIPE A4
	IBP A3
	SOJG A4,.-1
; THE ABOVE CODE TO GET TO THE END OF A STRING WAS ADOPTED
; BECAUSE THE CODE 'DUPL('A',50000)' TOOK FOREVER TO EXECUTE

APPEN1:
	MOVE A4,SPECO(A1)	;GET POINTER TO STRING2
	MOVE A5,SPECL(A1)	;GET NUMBER OF CHARACTERS TO MOVE
	JUMPE A5,CPOPJ		;CHECK FOR NULL STRING
	ILDB CH,A4
	IDPB CH,A3		;MOVE IT
	SOJG A5,.-2		;MOVE ALL OF IT-
	MOVE A5,SPECL(A1)
	ADDM A5,SPECL(A0)	;INDICATE NEW LENGTH
	POPJ P,			;AND CALL IT QUITS

PAGE

; CALLED BY "LOCSP" MACRO
; A0=ADDRESS OF INPUT DESCRIPTOR
; A1=ADDRESS OF SPECIFIER

LOCSPR:	MOVE A2,(A0)	;GET "A"
	MOVSI A3,SPCFLG
	IORM A3,1(A1)	;UNIQUELY IDENTIFY AS A SPECIFIER
	JUMPE A2,LOCS1	;A=0 TEST
	MOVE A3,(A0)	;COPY DESCRIPTOR INTO SPECIFIER
	MOVEM A3,(A1)
	MOVE A3,1(A0)
	MOVEM A3,1(A1)
	MOVSI A3,SPCFLG	;UNIQUELY IDENTIFY AS A SPECIFIER
	IORM A3,1(A1)
	MOVEI A3,4*CPD/5	;CPD=NO. OF CHARACTERS/DESCRIPTOR
	HRLI A3,^O440700	;MAKE A BYTE POINTER OUT OF IT
	ADD A3,(A0)		;PUT IN ADDRESS PART
	MOVEM A3,SPECO(A1)	;STORE THE POINTER IN OFFSET FIELD
	HRRZ A3,1(A2)	;GET VALUE FIELD-"I"
	SKIPA
LOCS1:	MOVEI A3,0
	MOVEM A3,SPECL(A1)	;STORE LENGTH FIELD
	POPJ P,


PAGE

; CALL: PUSHJ P,STREAM
;	A0=BYTE POINTER TO INPUT STRING
;	A1= NUMBER OF CHARACTERS IN THE STRING
;	A3=TABLE ADDRESS
;	A4-ADDRESS OF SPECIFIER 1
;	A5=ADDRESS OF SPECIFIER 2
;	Z	;ERROR RETURN
;	Z	;RUNOUT RETURN
;	Z	;SUCCESS RETURN

PXPTR:	POINT 6,A2,35	;"PUT" FIELD CROSS INDEX
TXPTR:	POINT 6,A2,29	;"GOTO" CROSS INDEX

	INTERN STREEM
STREEM:	SETZM STYPE	;DESTROY THE HISTORY
	MOVE A0,SPECO(A5)
	MOVE A1,SPECL(A5)	;GET CHARACTER COUNT
	JUMPE A1,RUNOUT	;IF NO CHARACTERS, RUNOUT
STRM1:	MOVE A12,A0	;COPY THE BYTE PTR
	IBP A0
	SETZM A7	;FOR CARRY
	LDB A6,A0	;GET A CHARACTER
	LSHC A6,-1	;DIVIDE BY 2, SAVE REMAINDER
	ADDI A6,(A3)	;GET ADDRESS IN SYNTAX TABLE
	HRRZ A2,(A6)	;GUESS WHICH HALFWORD WE WANT
	TLNE A7,400000	;WAS THE CHAR. EVEN
	HLRZ A2,(A6)	;NO, GET THE LEFT HALF INSTEAD
	TRNE A2,STOP+STOPSH	;STOP OR STOP SHORT?
	JRST STPSH	;YES
	TRNE A2,CONTIN	;CONTINUE CODE?
	JRST CNTIN	;YES
	TRNE A2,ERROR
	JRST STRERR
	LDB A6,TXPTR	;GOTO A DIFF. SYNTAX TABLE?
	CAILE A6,SYNSIZ	;IN RANGE?
	POPJ P,		;NO,ERROR RETURN
	SKIPN A6
	JRST STRM2	;USE THE SAME TABLE
	SETZM STYPE	;START WITH A FRESH VALUE
	HRRZ A3,SYNTAB(A6) ;GET THE NEW TABLE ADDRESS
STRM2:
	LDB A6,PXPTR	;ANYTHING IN "PUT" FIELD?
	CAILE A6,PUTSIZ	;IN RANGE?
	POPJ P,		;NO,ERROR RETRUN
	HRRZ A6,PUTTAB(A6)
	SKIPE A6
	MOVEM A6,STYPE
CNTIN:	SOJG A1,STRM1	;CONTINUE IF MORE CHARS.
RUNOUT:	MOVSI A0,(A5)
	HRRI A0,(A4)
	BLT A0,SPECL(A4)
	SETZM SPECL(A5)
	JRST CPOPJ1	;NO,RUNNOUT RETURN

STRERR:	SETZM STYPE	;INDICATE ERROR
	MOVSI A0,(A5)	;"FROM"
	HRRI A0,(A4)	;"TO"
	BLT A0,SPECL(A4)
	POPJ P,		;ERROR RETURN
STPSH:	SUBI A1,1	;BRING J INTO SYNC
	LDB A6,PXPTR	;SEE IF "PUT" FIELD EMPTY
	CAILE A6,PUTSIZ	;IN RANGE?
	POPJ P,		;NO,ERROR RETURN
	HRRZ A6,PUTTAB(A6)	;GET VALUE
	SKIPE A6	;DON'T UPDATE UNLESS THE VALUE IS NEW
	MOVEM A6,STYPE	;ADD IN,IF ANY
	MOVSI A3,(A5)	;"FROM"
	HRRI A3,(A4)	;"TO"
	BLT A3,SPECL(A4)
	HRRZ A3,SPECL(A5)	;GET ORIG. NO. OF CHARACTERS
	SUBI A3,(A1)	;FORM "J"
	MOVN A3,A3
	TRNN A2,STOP
	JRST STRSH	;SO STOPSH CODE
	ADDM A3,SPECL(A5)	;FORM L-J
	MOVN A3,A3		;MAKE POSITIVE AGAIN
	HRRM A3,SPECL(A4)	;FORM J
	MOVEM A0,SPECO(A5)	;OFFSET+J+1
	JRST CPOPJ2	;SUCCESS RETURN

STRSH:	ADDM A3,SPECL(A5)
	AOS SPECL(A5)	;L-J+1
	MOVN A3,A3
	SUBI A3,1
	HRRM A3,SPECL(A4)	;J-1
	MOVEM A12,SPECO(A5)	;OFFSET+J
	JRST CPOPJ2	;SUCCESS RETURN


PAGE

	INTERN SPREAX
	EXTERN R,TBLP.  ;REAL DATA TYPE
;	CONVERT STRING TO A REAL NUMBER
;	A0=ADDRESS OF WHERE TO STORE RESULT
;	A1=ADDRESS OF STRING SPECIFIER

;TITLE FLIRT.  V.005 	FLOATING POINT INPUT	FORTRAN IV
;SUBTTL  29-MAY-67

;"FLIRT." IS A ROUTINE WHICH INPUTS A STRING OF ASCII CHARACTERS.
;THE CHARS. ARE RECEIVED IN ACO FROM "CHINN."; THE INPUT ITEM IS
;RETURNED IN THE SAME AC.  "IIB." IS AN EXTERNAL ROUTINE WHICH
;ADVANCES THE POINTER; "TBLP." IS AN EXTERNAL TABLE
;OF FLOATING POINT POWERS OF TEN.

;IF THE FLAG ILLEG. HAS BEEN SET (BY A CALL TO ILL), THE
;INPUT WORD WILL BE SET TO 0 IF ANY ILLEGAL CHARACTERS
;ARE SCANNED FOR THAT WORD.

;  CALLING SEQUENCE:
;	PUSHJ P,FLIRT.
;  2 RETURNS:
;	ILLEGAL CHARACTER
;	NORMAL
;  PUSHDOWN LIST CONTAINS:
;	1.  FORMAT WORD CONSTRUCTED AS FOLLOWS:
;	    BIT 0:  0=F TYPE CONVERSION
;	            1=E TYPE CONVERSION
;	    BIT 1:  1=G TYPE CONVERSION
;	    BITS 4-10:  D -- NO. OF DIGITS FOLLOWING THE DECIMAL POINT
;	    BITS 11-17:  W -- FIELD WIDTH; W=0, VARIABLE FIELD
;	    BITS 18-35:  N -- SCALE FACTOR
;	2.  PROGRAM COUNTER (RETURN ADDRESS)

;PARAMETER ASSIGNMENTS
	H=6		;INPUT WORD
	ACO=A11		;
			;RETURNS THE INPUT ITEM
	ACT=2		;CNTR FOR MULTIPLICATION FACTOR
	FL=0		;FLAG
	FMT=4		;FORMAT WORD
	ACNO=3		;FRACTION,EXPONENT
	W=5		;FIELD WIDTH
	PDP=17		;PUSHDOWN POINTER

;FLAGS
	EXP=1		;EXPONENT
	FRAC=2		;FRACTION
	FIRDIG=4		;FIRST DIGIT
	NEGFRA=10		;NEGATIVE FRACTION
	NEGEXP=20		;NEGATIVE EXPONENT
	ESIGN=40		;EXPONENT SIGN
	OFLO=100		;OVERFLOW INTO CHARACTERISTIC
	DECF=1000		;DECIMAL POINT FLAG
PDSV=PPPDP+1

FLIRT:	MOVEM 16,PDSV+16
	MOVEI 16,PDSV
	BLT 16,PDSV+15
	CLEARB	ACNO,FL
	CLEARB H,ACT
IB:
CL:	JUMPE W,ENDF1	;END OF FIELD
	ILDB ACO,A12
	SOS W		;DECREMENT FILED WIDTH
	CAIG ACO,71	;TEST FOR DIGIT
	CAIGE ACO,60
	JRST NODIG	;NOT A DIGIT
	TLO FL,FIRDIG	;SET FIRST-DIGIT FLAG
	SUBI ACO,60	;REMOVE ASCII CODE
IM:	TLNN FL,OFLO	;OVERFLOW FLAG SET?
	JRST IM1		;NO, FORM AN INTEGER
	TLNN FL,FRAC	;IS THIS THE FRACTION?
	ADD ACT,L1	;NO, INCREMENT OVERFLOW COUNTER
	JRST IB		;GET NEXT CHARACTER
IM1:	IMULI ACNO,12	;FORM AND SAVE INTEGER
	ADD ACNO,ACO
	TLNE	FL,FRAC		;FRACTION?
	AOS	ACT		;YES
	TLNN ACNO,377000	;OVERFLOW IN CHARACTERISTIC?
	JRST IB		;NO, GET NEXT CHAR.
	PUSH PDP,ACNO+1	;SAVE ACNO+1
	IDIVI ACNO,12	;OTHERWISE, COMPENSATE:
	CAIL ACNO+1,5	;IF DROPPED DIGIT >,= 5,
	AOS ACNO		;ADD ONE TO LAST CHAR
	ADD ACT,L1	;INCREMENT OVERFLOW CNTR
	TLO FL,OFLO	;SET OVERFLOW FLAG
	POP PDP,ACNO+1	;RESTORE ACNO+1
	JRST IB		;GET NEXT CHARACTER
ENDF1:	EXCH H,ACNO
	JUMPE H,RETURN
	TLNE FL,NEGEXP	;IS EXP NEGATIVE?
	MOVNS ACNO	;YES, COMPLEMENT IT
	HLRZ ACO,ACT	;SET UP REDUCTION CNTR
	TLNN FL,DECF	;DECIMAL POINT FLAG SET?
	JRST ERRORS
	ADD ACNO,ACO
	SUBI ACNO,(ACT)	;SET MULTIPLICATION FACTOR
	JOV .+1		;CLEAR OV
	CAIG ACNO,46	;IS EXPONENT WITHIN RANGE?
	CAMGE ACNO,M46
	JRST BADEXP	;NO, OUT OF RANGE
	TLC H,233000
	FAD H,ZE		;RANGE OK, NORMALIZE FRACTION
	JUMPGE ACNO,FMR	;IS EXPONENT .GE. 0?
	MOVMS ACNO	;NO, THEN COMPLEMENT IT
	MOVEI ACT,-6	;AND SET CNTR = -6
	JRST .+2
FMR:	MOVEI ACT,1	;OTHERWISE, SET CNTR = 1
TR:	TRNE ACNO,1	;IF LOW ORDER BIT OF EXPONENT
	FMPR H,TBLP.(ACT)	;IS ONE,MULTIPLY BY POWER OF TEN
	ASH ACNO,-1
	AOS ACT
	JUMPN ACNO,TR	;ANY MORE CHARS?
	JOV BADEXP	;NO, CHECK OV
TLF:	TRNE FL,NEGFRA	;IF NEGATIVE FRACTION,
	MOVNS H		;COMPLEMENT IT
	JRST RETURN	;NORMAL RETURN
NODIG:NOTE:	CAIN	ACO,40	;BLANK?
	JRST	BLK	;YES
NBL:	CAIN ACO,56	;NOT BLANK, .
	JRST DECPT
	CAIN ACO,55	;-
	JRST MINUS
	CAIN ACO,53	;+
	JRST PLUS
BADEXP:
ERRORS:	POPJ P,
RETURN:	MOVEM H,(A0)	;STORE RESULT
	MOVEI H,R	;REAL DATA TYPE
	MOVEM H,1(A0)
	MOVSI 16,PDSV
	BLT 16,16
	JRST CPOPJ1
BLK:	TLNN FL,4	;BLANK,FIRST DIGIT IN?
	JRST IB		;NO,GET NEXT CHAR.
	JRST ERRORS	;BLANKS NOT ALLOWED IN MIDDLE

ADDCNT:	AOS	2(7)		;ADD ONE TO THE ITEM COUNT
	JRST	ENDF1		;PROCESS NUMBER
DECPT:	TLON FL,FRAC+DECF	;SET FRACTION AND DEC. PT. FLAGS
	JRST IB		;NO, GET NEXT CHAR
	JRST ERRORS	;NO, ILLEGAL
MINUS:	TROA FL,NEGFRA	;-, SET RT. HALF TO 10
PLUS:	HRRI FL,0		;+, SET RT. HALF TO 0
	TLNE FL,FIRDIG	;FIRST DIGIT IN?
	JRST ERRORS
	TLO FL,(FL)	;NO - SET RESULT SIGN
	JRST IB		;GET NEXT CHAR
L1:	XWD 1,0
PTR1:	POINT 7,FMT,17
PTR2:	POINT 7,FMT,10
ZE:	Z
M46:	DEC -38

SPREAX:	MOVE W,SPECL(A1)
	MOVE A12,SPECO(A1)
	JRST FLIRT



PAGE
REPEAT 0,<
; THIS CODE REPLACED BY SOMETHING MORE CLEAVER AND SHORTER
REALSX:	MOVE A2,(A1)
	MOVEM A2,SVFN
	MOVEI A4,BUFSPX
	MOVEM A4,(A0)
	SETZM 1(A0)	;CLEAR FLAG AND VALUE FIELDS
	SETZM SPECL(A0)	;INITIALIZE LENGTH
	HRLI A4,440700
	MOVEM A4,SPECO(A0)
	MOVEM A4,ARRAY0
	MOVEI A2,6	;NUMBER OF DIGITS PAST DECIMAL PT.
	MOVEM A2,SVNN
REALS1:	MOVEM 17,SV17N
	MOVEI 17,SVON
	BLT 17,SVON+2	;SAVE ACS 0,1,2
	MOVE P,PNPDP
	MOVEI 1,"-"
	SKIPGE SVFN
	IDPB 1,ARRAY0
	MOVMS SVFN 	;GET MAGNITUDE
	SKIPGE 1,SVNN	;FRACTIONAL PRINT?
	MOVEI 1,0	;NO, INDICATE NO ZEROES
	MOVNS 1
	MOVSI 0,(10.0)
	PUSHJ P,EXP2.0
	MOVEM 0,T2
	FSC 0,-1
	FADRB 0,SVFN	;ROUND IN FIRST INSIGN. DIGIT
	FDVR 0,T2	;SCALE TO AN INTEGER
	MOVEM 0,TEMP
	JSA Q,IFIX
	JUMP 0,TEMP	;AN INTEGER INTEGER
	MOVEM 0,UNITS
	PUSHJ P,DECPLT
	MOVEI 1,"."
	SKIPN SVNN	;NEED A DEC. PT.?
	IDPB 1,ARRAY0
ENDNUM:	MOVSI 17,SVON
	BLT 17,2	;RESTORE ACS
	MOVE 17,SV17N
	MOVE A1,[POINT 7,BUFSPX,]
END12:	CAMN A1,ARRAY0	;CALCULATE LENGTH OF STRING
	POPJ P,
	AOS SPECL(A0)
	IBP A1
	JRST END12

DECPLT:	MOVM 1,UNITS
	SETZM DIGITS	;NO OF DIGITS BEING PRINTED
DECP3:	IDIVI 1,12
	HRLM 2,(P)	;SAVE REMAINDER
	AOS DIGITS
	SKIPE 1;DECOMPOSE UNTIL GONE TO ZERO
	PUSHJ P,DECP3
	MOVE 0,DIGITS
	CAMLE 0,SVNN
	JRST DECP4
	MOVEI 1,"."
	IDPB 1,ARRAY0
	CAML 0,SVNN
	JRST DECP4A
DECP5:	MOVEI 1,"0"
	IDPB 1,ARRAY0
	AOS 1,DIGITS
	CAMGE 1,SVNN
	JRST DECP5
DECP4A:	SETOM SVNN	;FAKE OUT NEXT TIME AROUND
DECP4:	SOS DIGITS
	HLRZ 1,(P)
	TRO 1,60	;CONVERT TO ASCII
	IDPB 1,ARRAY0
	POPJ P,

>






PAGE
	EXTERN STROUT,SAVDP.,LNGTH


	EXTERN DEPOT.,FLOUT.
	EXTERN NCTRLC,CUTFLG

; CALLING SEQUENCE
; A0=ADDRESS OF OUTPUT SPECIFIER
; A1=ADDRESS OF INPUT DESCRIPTOR

REALSX:	SETOM NCTRLC	;INDICATE ^C NOT POSSIBLE HERE
	MOVE A2,[JRST TRAPCH]
	EXCH A2,DEPOT.	;INTERCEPT THE CONVERTED CHARACTERS
	MOVEM A2,SAVDP.
	MOVEI 11,0	;FLAG WORD FOR FLOUT.-FREE FORMAT
	PUSH PDP,11	;THIS IS WHERE FLOUT. EXPECTS IT
	MOVE 0,(A1)	;GET THE REAL NUMBER
	MOVEI A2,BUFSPX
	MOVEM A2,(A0)
	HRLI A2,440700
	MOVEM A2,STROUT
	MOVEM A2,SPECO(A0)
	SETZM 1(A0)
	MOVEI A2,SPECL(A0)
	MOVEM A2,LNGTH	;REMEMBER THE LENGTH
	SETZM SPECL(A0)
	PUSHJ PDP,FLOUT.
	MOVE A0,SAVDP.
	MOVEM A0,DEPOT.
	POP PDP,(PDP)	;GET RID OF 'F' ENTRY
	SETZM NCTRLC
	SKIPE CUTFLG	;HAS 'REENTER' BEEN TYPED IN A SENSITIVE SPOT?
	JRST @CUTFLG
	POPJ PDP,	;RETURN NORMALLY

TRAPCH:	CAIN 0," "	;IGNORE BLANKS
	POPJ PDP,
	AOS @LNGTH
	IDPB 0,STROUT
	POPJ PDP,

PAGE
	EXTERN IFIX,FLOAT,EXP2.0

	EXTERN PPPDP
PNPDP:	XWD -25,PPPDP
	EXTERN UNITS,DIGITS,NARGS,SVFN,SVNN,ARRAY0,TEMP,T2
	EXTERN SVON,SV17N


	INTERN SPCINX

;	STRING TO INTEGER CONVERSION ROUTINE
;	A0=SPECIFIER ADDRESS
;	A1=DESCRIPTOR ADDRESS

SPCINX:	MOVE A2,SPECO(A0)	;GET BYTE POINTER
	MOVE A3,SPECL(A0)	;GET NO. OF CHARACTERS
	MOVEI A5,0
	JUMPE A3,SPC2	;NULL STRING TEST
SPC1:	ILDB A4,A2
	CAIN A4,"-"	;STRING NEGATIVE?
	JRST SPC4
SPC3:
	CAIL A4,"0"
	CAILE A4,"9"
	POPJ P,		;ERROR RETURN
	SUBI A4,"0"
	IMULI A5,^D10
	ADDI A5,(A4)
	SOJG A3,SPC1
	MOVE A2,SPECO(A0)
	ILDB A4,A2
	CAIN A4,"-"	;NEGATIVE CHECK AGAIN
	MOVN A5,A5
SPC2:	MOVEM A5,(A1)	;SAVE RESULT
	MOVEI A4,I	;MAKE IT INTEGER DATA TYPE
	MOVEM A4,1(A1)
	JRST CPOPJ1	;SUCCESS RETURN

SPC4:	ILDB A4,A2	;BYPASS THE MINUS SIGN
	SUBI A3,1
	JRST SPC3

PAGE
	INTERN OUTPTS

	EXTERN INTO.,INTI.

;	A1=FORMAT STATEMENT REFERENCE
;	A0=UNIT FOR OUTPUT
;	A2=ADDRESS OF OUTPUT STRING
	

	EXTERN ETMCL	;FLAG TO INDICATE WHETHER WE ARE
			;IN THE SNOBOL COMPILER OR INTERPRETER

OUTPTS:
;	SINCE THE OUTPUT STRING MAY NOT BE LEFT
;	JUSTIFIED, WE ALWAYS MOVE IT INTO ANOTHER BUFFER
;	SO IT WILL BE JUSTIFIED. THIS BUFFER IS ZERO FILLED
;	SO TRAILING BLANKS ARE NOT PRESENT
;	UNLESS GIVEN BY SNOBOL

	SETZM TXBUF
	MOVE A0,[XWD TXBUF,TXBUF+1]
	BLT A0,TXBUF+^D26	;ZERO IT FIRST
	MOVE A0,SPECO(A2)
	MOVE A4,TXPNT
	MOVE A2,SPECL(A2)
	JUMPE A2,PTS1	;NULL STRING CASE
	MOVEM A2,PTINSZ
	MOVEM A0,PTINBY
	HRRZM A0,PTIN
	MOVEI A5,PTIN
	MOVEI A6,PTSOUT
	SKIPN ETMCL	;FORCE A TRIM IF WE ARE OUTPUTTING SOURCE
	PUSHJ PDP,TRIMIT
	MOVE A10,PTSIZE
	MOVE A0,PTSOUT+SPECO
	MOVE A2,PTSIZE
	CAILE A2,^D132
	PUSHJ P,PTS3	;GET STRING TO LESS THAN 132 CHARACTERS
	ILDB A3,A0
	IDPB A3,A4
	SOJG A2,.-2
	EXTERN OUTIT,PTS2

PTS1:	PUSHJ PDP,OUTPT.
	FIN.
	POPJ PDP,


OUTPT.:	MOVE A10,PTSIZE
	IDIVI A10,5
	SKIPE A11
	ADDI A10,1
OUTALL:	MOVNS A10
	HRLZ A10,A10
	DATA. TXBUF(A10)
	AOBJN A10,.-1
	POPJ PDP,

	EXTERN PTSOUT,PTSIZE,PTIN,PTINBY,PTINSZ

PTS3:	;THE STRING IS LONGER THAN 132 CHARACTERS
	; SO SPLIT IT AMONG SEVERAL BUFFERS
	SETZM TXBUF
	MOVE A1,[XWD TXBUF,TXBUF+1]
	BLT A1,TXBUF+^D26
	CAIG A2,^D132
	POPJ P,		;FINISHED
	MOVEI A16,^D132
	ILDB A3,A0
	IDPB A3,A4
	SOJG A16,.-2
	MOVEI A10,^D27	;OUTPUT THE ENTIRE BUFFER
	PUSHJ PDP,OUTALL
	SUBI A2,^D132
	MOVE A4,TXPNT	;RESTORE POINTER TO BUFFER AREA
	MOVEM A2,PTSIZE	;UPDATE LENGTH LEFT
	JRST PTS3

	DEFINE LDBD (AC,PTR,%A,%B)<
	;IT ALWAYS ASSUMES 0 IS FREE
	LDB AC,PTR
	LDB A0,[POINT 6,PTR,5]
	CAIN A0,^O35	;IS THIS THE LAST BYTE IN THE WORD?
	JRST %A
	ADDI A0,7
	JRST %B
%A:	MOVEI A0,1
	SOS PTR
%B:	DPB A0,[POINT 6,PTR,5]
>

	INTERN TRIMIT

;	CALL A5=ADDRESS OF INPUT SPECIFIER
;	     A6=ADDRESS OF OUTPUT SPECIFIER

TRIMIT:	HRRZ A1,SPECL(A5)	;NO. OF CHARACTERS
	MOVE A2,SPECO(A5)
	JUMPE A1,TRIM2
	IBP A2
	SOJG A1,.-1
;	MOVE TO END OF STRING SINCE LDBD WILL DO A LDB
	MOVE A1,SPECL(A5)
TRIM1:	LDBD A3,A2
	JUMPE A3,TRIM3
	CAIE A3," "
	CAIN A3,"	"
TRIM3:	SOJG A1,TRIM1	;DELETE TABS AND BLANKS
TRIM2:	MOVEM A1,SPECL(A6)
	MOVE A1,A6
	HRL A1,A5
	BLT A1,SPECO(A6)
	POPJ PDP,


PAGE
	EXTERNAL OBSIZ,OBSTRT
	INTERNAL ORDVSX

ORDVSX:	POPJ P,	;DO NOT ORDER VARIABLE STORAGE NOW


	INTERN LOAFNC,UNLFNC,LINKFC
	EXTERN UNDF,INTR10

LOAFNC:	POP PDP,(PDP)	;LOAD FUNCTION ENTRY POINT
	JRST UNDF

UNLFNC:	POPJ PDP,	;UNLOAD FUNCTION

LINKFC:	POP PDP,(PDP)
	JRST INTR10	;LINK MACRO ENTRY POINT

	INTERN INCIOB

INCIOB:	JFCL	;THIS TAGE PUT HERE SO MORE INTELLIGENT ERROR RECOVERY
		;CAN BE DONE LATER
	POPJ PDP,
PAGE

	EXTERN ERR.,END.
	INTERN STREAX

INCHLN=^D80
INBFLN=^D16
;NO. OF CHARACTERS READ EACH TIME ON INPUT = INCHLN
;NO. OF WORDS ALLOCATED FOR READING THESE = INBFLN

STREAX:	MOVEM A1,ERR..	;FIX UP ERROR RETURN
	MOVEM A2,END..	;FIX UP END OF FILE RETURN

	RELOC	;DEFINE DUMMY CELLS
ERR..:	EXP 0
END..:	EXP 0
	RELOC

	MOVEI A1,STRER
	MOVEM A1,ERR.
	MOVEI A1,STREND
	MOVEM A1,END.

; WE HAVE TO PUT IN A DUMMY ROUTINE ON ERR= AND END= TYPE TRAPS
; OTHERWISE THE STACK WILL NOT BE CLEANED UP PROPERLY
REPEAT 0,<
	MOVE A1,SPECL(A4)	;GET STRING LENGTH
	IDIVI A1,5
	SKIPE A2
	ADDI A1,1	;MAX. NO. OF WORDS TO READ
	HRRM A1,STRLTH	;FIX UP SLIST. LENGTH
	MOVE A5,[POINT 7,STRFMT,6] ;BY-PASS "("
	JUMPE A1,CPOPJ
	PUSHJ PDP,FIXFMT
	MOVE A1,[ASCIZ /A5)/]
	MOVE A6,[POINT 7,A1,]
STRX2:	ILDB A7,A6
	JUMPE A7,STRX1	;DYNAMICALLY CREATE A FORMAT STATEMENT
	IDPB A7,A5
	JRST STRX2
STRX1:
	IN. 01,(A3)
	HRRZ A1,SPECO(A4)
	HRRM A1,STRSLI	;FIX UP THE SLIST ADDRESS
; ZERO OUT THE RECEVING BUFFER
	SETZM (A1)
	HRLS A1
	ADDI A1,1
	HLRZ A2,A1
	ADD A2,STRLTH
	SUBI A2,1
	BLT A1,(A2)

	PUSHJ PDP,STRSLI	;DO TH INPUT NOW
	MOVE A2,SPECL(A4)	;GET ORIGINAL LENGTH
	SETZM SPECL(A4)
; BY-PASS LINE SEQUENCE NUMBERS

STRX4:
	MOVE A5,@A0
	TRNN A5,1	;SEE IF 1B35 IS ON
	JRST STRX3	;NOT ON, SO DONE
	AOS SPECO(A4)	;SKIP OVER THE WORD
	SUBI A2,5	;AND DECREMENT STRING LENGTH
	JRST STRX4
STRX3:
	MOVE A0,SPECO(A4)
	MOVE A1,A0	;GET BYTE POINTERS
; COMPRESS OUT NULL CHARACTERS
STRX5:
	ILDB A3,A0
	SKIPN A3
	JRST STRX6
	IDPB A3,A1
	AOS SPECL(A4)
STRX6:
	SOJG A2,STRX5
	POPJ PDP,
>
; THE ABOVE CODE LEFT AROUND SINCE IT ALMOST WORKED AND WOULD HAVE
; ALLOWED INPUT OF ARBITRARILY LONG STRINGS. THE ONE BIG PROBELM
; WAS CAUSED BY THE FACT THAT THE STRING TO BE INPUT IS 
; SOMETIMES NOT LEFT JUSTIFIED IN A WORD AND FORSE IS INCAPABLE OF
; DOING ANYTHING ABOUT. CONSEQUENTLY WE MUST READ THE STRING INTO
; AN INTERMEDITATE BUFFER AND TRANSFER IT

	MOVEI A1,INFMT
	IN. 01,(A3)
	PUSHJ PDP,BUFCLR
	MOVEI A0,INBFLN	;READ ONLY INBFLN WORDS
	HRRM A0,STRLTH
	MOVEI A0,BUFIN
	HRRM A0,STRSLI
	PUSHJ PDP,STRSLI
	RELOC	;SWITCH TO LOW SEGMENT

STRSLI:	SLIST. 0,.	;FIXED UP AT RUN TIME
STRLTH:	JUMP 0,.	;FIXED UP AT RUN TIME
	FIN.
	POPJ PDP,

	RELOC	;SWITCH BACK TO HIGH SEGMENT

STRX3:
	MOVE A2,SPECL(A4)
	CAIL A2,INCHLN	;TAKE THE LEAST VALUE
	MOVEI A2,INCHLN	;ALLOW ONLY INCHLN CHARACTERS
	MOVE A0,BUFPNT
	MOVE A1,SPECO(A4)
	MOVEI A5,0
STRX5:
	ILDB A3,A0
	JUMPE A3,STRX6
	AOS A5		;KEEP TRACK OF THE LENGTH WE SEE
	IDPB A3,A1
STRX6:
	SOJG A2,STRX5

; NOW MAKE SURE WE BLANK FILL TO RETURN TNE EXACT NO. OF CHARACTERS
; THE MACRO CALLED FOR
	CAML A5,SPECL(A4)
	POPJ PDP,
	MOVE A2,SPECL(A4)
	SUB A2,A5
	MOVEI A3,40	;ASCII BLANK
	IDPB A3,A1
	SOJG A2,.-1
	POPJ PDP,
	POPJ PDP,


REPEAT 0,<
FIXFMT:	IDIVI A1,12
	HRLM A2,(PDP)	;SAVE REMAINDER
	SKIPE A1	;ANY REMAINDER IN ORIGINAL VALUE?
	PUSHJ PDP,FIXFMT	;RECURSIVE CALL
	HLRZ A1,(PDP)
	TRO 1,60	;CONVERT TO ASCII
	IDPB A1,A5
	POPJ PDP,	;BACK TO ORIGINAL WHEN DONE

>

STREND:	POP PDP,(PDP)	;CLEAN UP THE STACK
	POP PDP,(PDP)
	JRST @END..
STRER:	POP PDP,(PDP)
	POP PDP,(PDP)
	JRST @ERR..

PAGE
	INTERN IFILEX,OFILEX,BUFCLR

; CALL
;	A1 = ADDRESS OF DESCRIPTOR CONTAINING UNIT NO.
;	A2 = ADDRESS OF SPECIFIER CONTAINING THE FILENAME
;	PUSHJ PDP,IFILEX/OFILEX
;	ALWAYS RETURN HERE

; FOLLOWING TRANSFER OF STRINGS IS NECESSARY BECAUSE SNOBOL
; DOESN'T ALWAYS CLEAR OUT STRING STORAGE BEFORE
; APPENDING CHARACTER STRINGS

BUFCLR:	SETZM BUFIN
	MOVE A7,[XWD BUFIN,BUFIN+1]
	BLT A7,BUFIN+^D26
	POPJ PDP,

BUFTRN:	PUSHJ PDP,BUFCLR
	MOVE A7,SPECL(A2)	;GET STRING LENGTH
	JUMPE A7,CPOPJ
	MOVE A10,SPECO(A2)	;GET BYTE POINTER
	MOVE A11,BUFPNT
	ILDB A0,A10
	IDPB A0,A11
	SOJG A7,.-2
	POPJ P,

IFILEX:	PUSHJ P,BUFTRN
	JSA ^O16,IFILE
	ARG (A1)
	ARG 5,BUFIN
	POPJ P,

OFILEX:	PUSHJ P,BUFTRN
	JSA ^O16,OFILE
	ARG (A1)
	ARG 5,BUFIN
	POPJ P,




PAGE
	INTERN LOCATX,LOCAVX

LOCATX:	MOVE A0,(A11)
	JUMPE A0,CPOPJ	;ERROR RETURN
	HRRZ A1,1(A0)	;GET MAX. NUMBER TO TEST FOR
	ADD A1,A0
	MOVEI A2,(A0)	;SETUP FOR I=0
LOC1:	MOVE A3,D(A2)
	CAMN A3,(A10)	;CHECK ADDRESS FIELD
	JRST LOC2
LOC3:	ADDI A2,2*D
	CAIGE A2,(A1)	;CHECK FOR DONE
	JRST LOC1	;CONTINUE
	POPJ P,		;NOT FOUND,ERROR RETURN
LOC2:	MOVE A7,D+1(A2)	;CHECK FLAG + VALUE FIELD
	CAME A7,1(A10)
	JRST LOC3	;CONTINUE
	MOVE A5,1(A11)	;TRANSFER GOOD STUFF
	MOVEM A5,1(A6)
	MOVEM A2,(A6)
	JRST CPOPJ1	;SUCCESS RETURN

LOCAVX:	MOVE A0,(A11)
	JUMPE A0,CPOPJ	;ERROR RETURN
	HRRZ A1,1(A0)	;GET MAX. NUMBER TO TEST FOR
	ADD A1,A0
	MOVEI A2,(A0)	;SET FOR I=0
LOCV1:	MOVE A3,2*D(A2)
	CAMN A3,(A10)	;CHECK ADDRESS FIELD
	JRST LOCV2	;FOUND TO BE EQUAL SO FAR
LOCV3:	ADDI A2,2*D
	CAIGE A2,(A1)	;CHECK FOR DONE
	JRST LOCV1	;CONTINUE
	POPJ P,		;ERROR RETURN-NONE FOUND
LOCV2:	MOVE A7,2*D+1(A2)
	CAME A7,1(A10)	;CHECK FLAG + VALUE FIELD
	JRST LOCV3	;NOT EQUAL,SO CONTINUE
	MOVE A5,1(A11)
	MOVEM A5,1(A6)
	MOVEM A2,(A6)
	JRST CPOPJ1	;SUCCESS RETURN



PAGE
; THIS CODE WAS PLACED HER IN ORDER TO MINIMIZE THE AMOUNT OF
; CODE USED BY THE RCALL RRTURN PAIR. BY NOT EXPANDING
; THOSE MACROS ALL IN-LINE, I WAS ABLE TO SAVE ABOUT 2600
; (DECIMAL) WORDS WHICH IS VERY SIGNIFICANT. I FIGURE THAT
; THIS TECHNIQUE ADDS A FEW EXTRA CYCLES, PROBABLY 4,
; FOR EACH OCCURRENCE AND MAKES THE EXECUTION LONGER BY A FEW
; PERCENT.

	INTERN RCALX0,RCALX1,RCALX2,RCALX3,RCALX4,RCALX5
	INTERN RCALX6,RCALX7
	INTERN RCALD0,RCALD1,RCALD2,RCALD3,RCALD4,RCALD5
	INTERN RCALD6,RCALD7

ZERO:	Z	;A WORD OF ALL ZEROES

RCALX0:	MOVE A0,CSTACK	;SAVE CURRENT STACK POSITION
	MOVEI A3,0		;INDICATE NO ARGUMENT ON RETURN
	JRST RX1
RCALD0:	MOVE A0,CSTACK
	HLRZ A3,(A2)	;SAVE ADDRESS OF RESULT DESCRIPTOR
RX1:	PUSH CSTACK,OSTACK
	PUSH CSTACK,A3
	PUSH CSTACK,A2	;SAVE RETURN ADDRESS
	PUSH CSTACK,ZERO
	MOVE OSTACK,A0	;FIX UP OLD STACK POINTER
	HRRZ A2,(A2)	;GET PROCEDURE ADDRESS
	JRST (A2)

RCALX1:	MOVE A0,CSTACK
	MOVEI A3,0
	JRST RX2
RCALD1:	MOVE A0,CSTACK
	HLRZ A3,(A2)
RX2:	PUSH CSTACK,OSTACK
	PUSH CSTACK,A3
	PUSH CSTACK,A2	;SAVE RETURN ADDRESS
	PUSH CSTACK,ZERO
	MOVE OSTACK,A0
	PUSH CSTACK,(A4)
	PUSH CSTACK,1(A4)
	HRRZ A2,(A2)
	JRST (A2)

RCALX:	MOVE A0,CSTACK
	MOVEI A3,0
	JRST RX3
RCALD:	MOVE A0,CSTACK
	HLRZ A3,(A2)
RX3:	PUSH CSTACK,OSTACK
	PUSH CSTACK,A3
	PUSH CSTACK,A2	;SAVE RETURN ADDRESS
	PUSH CSTACK,ZERO
	HRRZ A2,(A2)	;GET PROCEDURE ADDRESS
	MOVE OSTACK,A0
	PUSH CSTACK,(A4)
	PUSH CSTACK,1(A4)	;SAVE ARGUMENTS
	PUSH CSTACK,(A5)
	PUSH CSTACK,1(A5)
	SOJE A16,(A2)
	PUSH CSTACK,(A6)
	PUSH CSTACK,1(A6)
	SOJE A16,(A2)
	PUSH CSTACK,(A7)
	PUSH CSTACK,1(A7)
	SOJE A16,(A2)
	PUSH CSTACK,(A10)
	PUSH CSTACK,1(A10)
	SOJE A16,(A2)
	PUSH CSTACK,(A11)
	PUSH CSTACK,1(A11)
	SOJE A16,(A2)
	PUSH CSTACK,(A12)
	PUSH CSTACK,1(A12)
	SOJE A16,(A2)
	HALT .	;ASSUME NO MORE ARGUMENNTS THAN THIS

RCALX2:	MOVEI A16,1
	JRST RCALX
RCALX3:	MOVEI A16,2
	JRST RCALX
RCALX4:	MOVEI A16,3
	JRST RCALX
RCALX5:	MOVEI A16,4
	JRST RCALX
RCALX6:	MOVEI A16,5
	JRST RCALX
RCALX7:	MOVEI A16,6
	JRST RCALX

RCALD2:	MOVEI A16,1
	JRST RCALD
RCALD3:	MOVEI A16,2
	JRST RCALD
RCALD4:	MOVEI A16,3
	JRST RCALD
RCALD5:	MOVEI A16,4
	JRST RCALD
RCALD6:	MOVEI A16,5
	JRST RCALD
RCALD7:	MOVEI A16,6
	JRST RCALD

PAGE
	INTERN RRTND,RRTNX

; THIS CODE PLACED HERE TO REDUCE THE AMOUNT OF CODE 
; EXPANDED IN-LINE.
;
; THE FORMAT IS SLIGHTLY CHANGED FROM THE STANDARD IN THAT
; THE POSSIBLE ADDRESS OF THE DESCRIPTOR RECEIVING THE VALUE
; IS STORED ON THE STACK AND NOT IN-LINE

; RRTND RETURNS A VALUE, RRTNX DOES NOT
; A1 CONTAINS THE EXIT RETURN NUMBER , TO N

RRTND:	SKIPN A3,2(OSTACK)
	JRST RRFIN	;NO ADDRESS
	MOVE A0,(A2)	;GE T THE DESCRIPTOR
	MOVEM A0,(A3)
	MOVE A0,1(A2)
	MOVEM A0,1(A3)
RRTNX:
RRFIN:	MOVE CSTACK,OSTACK
	ADD A1,D+1(OSTACK) ;FORM RETURN ADDRESS
	MOVE OSTACK,1(OSTACK)
	JRST 1(A1)	;RETURN
	END