Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_SRC_3_19910112 - utilities/formac.mac
There is 1 other file named formac.mac in the archive. Click here to see a list.
;+.FT.rm 72.TITLE FORMAC - A MACRO library for FORTRAN programs
;.C ;Description of programs in the library FORMAC
;.c ;July 8, 1981
;.c ;Norm Samuelson, 2644
;.b1.nj;All of the routines described in this document are
;available in the relocatable library FORMAC.
;(The source is in MAC:FORMAC.MAC).
;To access any or all of these subroutines, simply add
;",REL:FORMAC.REL/LIB" to your LOAD or EXECUTE command.
;.b1;All of these routines are designed to be called from
;FORTRAN programs.  Some can be called from COBOL also.
;Some are FUNCTIONS, others are SUBROUTINES
;(see comments with each one).

;.b1;The source file contains RUNOFF input to produce this
;documentation.  To get a copy type the command:
;.i8;RUNOFF TTY:=MAC:FORMAC.MAC
;.I5;or RUNOFF LPT:=MAC:FORMAC.MAC
;-

UNIVERSAL	SLAUNV - DEFINE SANDIA DEFAULTS
SUBTTL	NH SAMUELSON, 2641, 4/76

COMMENT	
This file defines common symbols used in many Sandia programs
It is accessable to anyone by simply adding the statement
	SEARCH	SLAUNV
To your MACRO source.

This has been included in FORMAC to put all the required sources
into a single file to make distribution easier.




DEFINE ND (NAME,VALUE),<IFNDEF NAME,<NAME==VALUE>>
ND FTF40,0	;DONT SUPPORT F40 ANY MORE
ND FTKA10,0	;WE GOT RID OF IT IN FEB-79
ND ftjsys,-1
ife ftjsys,<PRINTX BUILDING UNIVERSALS FOR TOPS10>
IFN ftjsys,<PRINTX BUILDING UNIVERSALS FOR TOPS20>
IFN FTKA10,<
	PRINTX %BUILDING KA10 COMPATIBLE CODE
	pagsiz==2000
>
IFE FTKA10,<PAGSIZ==1000>
IFN FTF40,<PRINTX %BUILDING F40 COMPATIBLE CODE>

;IO CHANNELS
ife ftjsys,<
DSK==1
LPT==2
MTA==3
SYS==4
MFD==5
UFD==6
PTY==7
LOG==10
LST==11
CMD==12
TTY==13
>;END ife ftjsys

;ACCUMULATORS
F=0
syn	f,t0		;t0 is a synonym for f
T1=1
T2=t1+1
T3=t2+1
T4=t3+1
t5=t4+1
P1=t5+1
P2=p1+1
P3=p2+1
P4=p3+1
ap=16
P=17
STKSIZ==20

;special ppn's
ife ftjsys,<
SYSPPN==1,,4
OPRPPN==1,,2
QUEPPN==3,,3
NIKPPN==2,,20
>;END ife ftjsys

.TTHP==4			;HP2624
.TTADM==5			;ADM3a
.TTTEK==6			;TEKTRONIX
.TTTK5==7			;TEKTRONIX 4015

subttl	MACRO DEFINITIONS
DEFINE	MAKSTK,<MOVE	P,[IOWD STKSIZ,STAK]>

DEFINE	FXCASE (AC),<
	CAIL	AC,"a"
	SUBI	AC,"a"-"A"
>

DEFINE	HELLO	(EP),<
	SIXBIT/EP/
EP:	ENTRY	EP
IFN FTF40,<
	JRST	EP+3
	CALL	EP+3
	JRST	16,@(16)
>>;END HELLO MACRO

DEFINE	SLAPLG(%ID),<	;STANDARD PROLOGUE
	SALL
	.DIRECT	SFCOND
	.DIRECT	FLBLST
IFN FTJSYS,<SEARCH	MONSYM, MACSYM>
IFE FTJSYS,<
	SEARCH	UUOSYM, MACTEN
	DEFINE	TMSG(%TEXT),<OUTSTR	[ASCIZ/%TEXT/]>
>
	IFNB	<%ID>,<
ND %ID'VER,1	;DEFAULT VERSION NUMBER
ND %ID'MVR,0	;MINOR VERSION
ND %ID'EDT,0	;EDIT NUMBER
ND %ID'WHO,1	;WHO (NON-DEC)
	VERNUM==BYTE(3)%ID'WHO(9)%ID'VER(6)%ID'MVR(18)%ID'EDT
>>;END PROLOGUE

DEFINE	MOV2	(AC,MEM),<
IFN FTKA10,<
	.DIRECTIVE KA10
	MOVE	AC,MEM
	MOVE	AC+1,1+MEM
>
IFE FTKA10,<
	.DIRECTIVE KI10,KL10
	DMOVE	AC,MEM
>>;END MOV2

DEFINE	MOV2M	(AC,MEM),<
IFN FTKA10,<
	.DIRECTIVE KA10
	MOVEM	AC,MEM
	MOVEM	AC+1,1+MEM
>
IFE FTKA10,<
	.DIRECTIVE KI10,KL10
	DMOVEM	AC,MEM
>>;END MOV2M

;the following are special cases for indirect moves on the ka10

define	imov2	(ac,mem),<
ife ftka10,<
	.DIRECTIVE KI10,KL10
	DMOVE	AC,MEM>
IFN FTKA10,<
	.DIRECTIVE KA10
	MOVEI	AC+1,MEM
	MOV2	AC,(AC+1)
>>;END IMOV2 MACRO

DEFINE	IMOV2M	(AC,MEM,AUX<15>),<
IFE FTKA10,<
	.DIRECTIVE KI10,KL10
	DMOVEM	AC,MEM>
IFN FTKA10,<
	.DIRECTIVE KA10
	MOVEI	AUX,MEM
	MOV2M	AC,(AUX)
>>;END IMOV2M MACRO

;USEFUL OPDEFs

OPDEF	CALL	[PUSHJ	P,]
OPDEF	RETURN	[POPJ	P,]

;STATES WORD - SCHED BITS
ife ftjsys,<
	ST%SPO==1B18	;SYSTEM PROGRAMMERS ONLY
	ST%MSG==1B19	;SPECIAL MESSAGE IN "SYS:MESSAG.TXT"
			;(USED BY LOGIN, REPORTED BY OTHERS)

;BITS IN RIBPCA - PRIV CUST ARG IN RIB OF EACH FILE
	RB%PRG==1B18	;THIS FILE IS TO BE PURGED
>;END ife ftjsys

;MISC DEFINITIONS
MAXINT==377777,,777777

;NBS DATE TIME UNITS
	NBSDAY==1B17
	NBSHR==NBSDAY/^D24
	NBSMIN==NBSHR/^D60
	NBSSEC==NBSMIN/^D60

subttl	macros for COMND JSYS calls
ifn ftjsys,<

;Key - define an entry in a keyword table.  It takes one to three arguemnts.
;The first argument is the keyword.
;The second argument is the value to be associated with the keyword.
;If omitted it defaults to a value of "." concatenated with the keyword,
;ie:  key foo####would have a value of ".FOO"
;The third argument is a combination of flag bits.
;[if more than one flag bit is specified they should be separated by
;exclamation points (!).]
;

define	key(nam,val,bits),<
  ifnb <val>,<
	ifb <bits>,<[asciz/nam/],,val>		;;normal case
	ifnb <bits>,<[cm%fw!bits		;;bits are messy but useful
			[asciz/nam/]],,val>
   >
  ifb <val>,<
		ifb <bits>,<[asciz/nam/],,.'nam> ;;normal case
	ifnb <bits>,<[cm%fw!bits		;;bits are messy but useful
			[asciz/nam/]],,.'nam>
   >
>;end key macro

;.b1;IKEY - KEY with invisible bit set

define	IKEY(nam,val,bits<0>),<
	KEY(nam,val,cm%inv!bits)
>;end IKEY macro

;.b1;TV - even easier than KEY, value is just index into keyword table.

define	TV(nam),<
	zzzz==zzzz+1				;;increment value
	key(nam,zzzz)
>;end TV macro

;.b1;ITV - same as TV but invisible.

define	ITV(nam),<
	zzzz==zzzz+1
	ikey(nam,zzzz)
>;end ITV macro
>;end ifn ftjsys
	PRGEND

Title	SHIFT - single word shift and rotate routines
subttl	NH Samuelson, 2641, 8/2/78

	SEARCH	SLAUNV
	SLAPLG	;STANDARD PROLOGUE

;+.HL1 SHIFT routines
;.nj;The following group of FUNCTIONS are special case routines
;to produce results equivalent to the strange SHIFT FUNCTION found
;on CDC 6600 and 7600 computers.

;.b1.nf;Calling sequence:
;	SHIFT(W,N)	   left=circular	right=sign extended
;  or	ASH(W,N)	   left=zero fill	right=sign extended
;  or	LSH(W,N)	   left=zero fill	right=zero fill
;  or	ROT(W,N)	   left=curcular	right=circular
; where	W is a SINGLE WORD quantity to be shifted
;  and	N is the SHIFT COUNT (+=LEFT, -=RIGHT)
;.b1.f.nj;The FUNCTION to be used should be declared LOGICAL in the
;-calling program.

WORD==0
COUNT==1

HELLO	SHIFT
	SKIPL	T1,@COUNT(AP)	;IS COUNT NEGATIVE?
	 JRST	ROT..		;NO - POSITIVE = ROTATE LEFT
	JRST	ASH..		;YES - RIGHT WITH SIGN EXTENSION

HELLO	ASH
	MOVE	T1,@COUNT(AP)
ASH..:	MOVE	T0,@WORD(AP)
	ASH	T0,(T1)
	RETURN

HELLO	ROT
	MOVE	T1,@COUNT(AP)
ROT..:	MOVE	T0,@WORD(AP)
	ROT	T0,(T1)
	RETURN

HELLO	LSH
	MOVE	T1,@COUNT(AP)
	MOVE	T0,@WORD(AP)
	LSH	T0,(T1)
	RETURN

	PRGEND

Title	DSHIFT - DOUBLE PRECISION shift and rotate routines
subttl	NH Samuelson, 2641, 8/2/78

	SEARCH	SLAUNV
	SLAPLG	;STANDARD PROLOGUE

;+.HL1 DSHIFT routines
;.F.nj;The following group of DOUBLE PRECISION FUNCTIONS are
;special case routines to produce results equivalent to the strange
;SHIFT FUNCTION found on CDC 6600 and 7600 computers.

;.b1.nf;Calling sequence:
;	DSHIFT(DD,N)  left=circular	right=sign extended
;	DASH(DD,N)    left=zero fill	right=sign extended
;	DLSH(DD,N)    left=zero fill	right=zero fill
;	DROT(DD,N)    left=curcular	right=circular
; where	DD is a DOUBLE WORD quantity to be shifted
; and	N is the SHIFT COUNT (+=LEFT, -=RIGHT)
;.b1.f.nj;The FUNCTION to be used should be delcared DOUBLE PRECISION
;-in the calling program.

WORDS==0
COUNT==1

HELLO	DSHIFT
	PUSH	P,T2
	SKIPL	T2,@COUNT(AP)
	 JRST	DROT..		;NO - POSITIVE = ROTATE LEFT
	JRST	DASH..		;YES - RIGHT WITH SIGN EXTENSION

HELLO	DASH
	PUSH	P,T2
	MOVE	T2,@COUNT(AP)
DASH..:	IMOV2	T0,@WORDS(AP)
	ASHC	T0,(T2)
	JRST	T2POPJ

HELLO	DROT
	PUSH	P,T2
	MOVE	T2,@COUNT(AP)
DROT..:	IMOV2	T0,@WORDS(AP)
	ROTC	T0,(T2)
	JRST	T2POPJ

HELLO	DLSH
	PUSH	P,T2
	MOVE	T2,@COUNT(AP)
	IMOV2	T0,@WORDS(AP)
	LSHC	T0,(T2)
T2POPJ:	POP	P,T2
	RETURN

	PRGEND

Title	MASK - generate an N-bit mask (single or double precision)
Subttl	NH Samuelson, 2641, 10/79

	SEARCH	SLAUNV
	SLAPLG	;STANDARD PROLOGUE

;+.HL1 MASK function
;.f.nj;The MASK function generates a mask of up to 72 bits, similar to
;the MASK function on CDC computers.

;.b1.nf;Calling sequence:
;	BITS = MASK(NBITS)
; where	NBITS is integer number of bits in the mask
;  and	BITS and MASK are of the same type (both LOGICAL, both REAL,
;	or both DOUBLE PRECISION)
;.F.NJ;Note: If NBITS is negative the mask generated is the complement
;-of that generated by MASK(ABS(NBITS))

NBITS==0

	HELLO	MASK
	CLEARB	T0,T1
	PUSH	P,T2
	PUSH	P,T3
	SKIPN	T2,@NBITS(AP)
	 JRST	MASKOK			;IF NBITS IS ZERO
	MOVM	T2,T2
	IDIVI	T2,^D36
	SOJG	T2,ALLSET		;IS COUNT .GE. 72?
	JUMPE	T3,NOSHFT		;EVEN # WORDS?
	MOVX	T0,<1B0>		;SET THE FIRST BIT
	MOVNI	T3,(T3)			;NEGATE SHIFT COUNT FOR RIGHT SHIFT
	ASH	T0,1(T3)		;BUILD THE PARTIAL WORD
NOSHFT:	JUMPL	T2,ONEWRD		;SINGLE WORD?
	CAIA
ALLSET:	SETO	T0,
	MOVE	T1,T0
	SETO	T0,			;AND SET ALL BITS IN THE FIRST
ONEWRD:	SKIPL	@NBITS(AP)		;WAS SHIFT COUNT NEGATIVE?
	 JRST	MASKOK			;NO - DONT COMPLEMENT
	SETCM	T0,T0
	SETCM	T1,T1
MASKOK:	POP	P,T3			;RESTORE WORK ACs
	POP	P,T2
	RETURN

	PRGEND

title	CSHIFT - character circular shift SUBROUTINE or FUNCTION
subttl	nh samuelson, 2641, 4/14/78

	SEARCH	SLAUNV
	SLAPLG	;STANDARD PROLOGUE

;+.TP15.HL1 CSHIFT
;.NJ;CSHIFT is either a SUBROUTINE, or a FUNCTION.
;It does character shifting in DOUBLE PRECISION (ie: A10 FORMAT)
;such that the characters come out in normal character positions, in
;spite of the extra bit in each word.
;.B1.nf;Calling sequence:
;	CALL CSHIFT(DPVAR,NUMCH,DPRES)
;or	DPRES = CSHIFT(DPVAR,NUMCH)
; where	DPVAR is a DOUBLE PRECISION variable in A10 format
;	DPRES is the DOUBLE PRECISION result (in A10 format)
;	NUMCH is the number of character positions to shift
;		if NUMCH is positive, the characters are shifted
;		#LEFT, END AROUND (ie: rotated).
;		If NUMCH is negative, the characters are shifted
;		#RIGHT, END OFF with blank fill
; on return the contents of DPVAR and NUMCH are un-changed.
;.F.NJ.b1;NOTE - If called as a FUNCTION, CSHIFT must be declared 
;-DOUBLE PRECISION in the calling program.

;register assignments:
;	t0&t1 = output string
;	t2 = temp
;	t3 = count
;	t4 = current pointer to input
;	p1 = initial pointer to input
;	p2 = negative shift count
;	p3 = byte pointer to string in t0+t1

DPVAR==0
NUMCH==1
DPRES==2

HELLO	CSHIFT
	move	t1,[t2,,savrgs]
	blt	t1,savrgs+p3-t2
	move	p3,[point 7,t0]	;starting byte pointer
	movei	p1,@DPVAR(AP)	;get address of chars
	hrli	p1,(point 7,)	;make a byte pointer
	move	t4,p1		;get copy of byte pointer
	skipge	t2,@NUMCH(AP)	;get number of characters to shift
	 jrst	right		;negative count = shift right
	idivi	t2,^d10		;get remainder ie: n mod 10.
	jumpe	t3,noshft	;zero count?
left:
	movn	p2,t3		;save negative shift count
	clearb	t0,t1		;new words built here
ifn ftka10,<
	ibp	t4		;skip over first n characters
	sojg	t3,.-1
>;end ifn ftka10
ife ftka10,<
	adjbp	t3,t4		;skip over first n characters
	move	t4,t3
>;end ife ftka10
	movei	t3,^d10(p2)	;get # chars remaining
	call	copy
	move	t4,p1		;get byte pointer for first chars
	movm	t3,p2		;and count
	call	copy
	jrst	store

right:
	move	t0,[ascii/     /]	;blanks
	move	t1,t0		;in both words
	movm	t3,t2		;get (+) shift count
	cail	t3,^d10		;loose everything?
	 jrst	store		;yes - all blanks
	move	p2,t2		;save neg shift count
ifn ftka10,<
	ibp	p3		;skip the blanks
	sojg	t3,.-1		;loop till enuf
>;end ifn ftka10
ife ftka10,<
	adjbp	t3,p3		;skip the blanks
	move	p3,t3
>;end ife ftka10
	movei	t3,^d10(p2)	;# chars remaining
	call	copy
	jrst	store

copy:
	ildb	t2,t4		;get a byte
	idpb	t2,p3		;store it
	sojg	t3,copy		;loop till done
	return

noshft:
	mov2	t0,(p1)		;copy the input
store:
	hlrz	t2,-1(AP)	;arg count
	caie	t2,-3		;3 args?
	 jrst	gobak		;we were called as a FUNCTION
	movei	t2,@DPRES(AP)	;result address
	MOV2M	T0,(T2)		;STORE THE RESULT
gobak:
	move	p3,[savrgs,,t2]
	blt	p3,p3
	return

savrgs:	block	p3-t2+1

	PRGEND

TITLE	ECHO - TURN ECHO ON OR OFF
SUBTTL	NHS, 2641, 7/26/78

	SEARCH	SLAUNV
	SLAPLG	;STANDARD PROLOGUE

;+.TP15.HL1 Terminal control routines
;.f.nj;These FORTRAN SUBROUTINES take no arguments.
;A call to ECHO will turn on echo, a call to NOECHO will turn it off.
;A call to CTRLO will restart typeout in case the user stopped it
;-with _^O.  (This is a good idea before typeing error messages).

HELLO	ECHO
ife ftjsys,<
	SETO	T1,
	GETLCH	T1		;GET CHARACTERISTICS OF MY TTY
	TXZ	T1,GL.LCP	;TURN ON ECHO
	SETLCH	T1
>;end ife ftjsys
ifn ftjsys,<
	movei	t1,.priin
	rfmod
	txo	t2,tt%eco	;set the echo bit
	sfmod
>;end ifn ftjsys
	RETURN

HELLO	NOECHO
ife ftjsys,<
	SETO	T1,
	GETLCH	T1
	TXO	T1,GL.LCP
	SETLCH	T1
>;end ife ftjsys
ifn ftjsys,<
	movei	t1,.priin
	rfmod
	txz	t2,tt%eco	;clear the echo bit
	sfmod
>;end ifn ftjsys
	RETURN

HELLO	CTRLO
ife ftjsys,<
	SKPINL			;CHECK FOR TTY INPUT, WAKE THE TTY
	 RETURN
>;end ife ftjsys
ifn ftjsys,<
	movei	t1,.priou
	rfmod
	txz	t2,tt%osp	;clear the suppress output bit
	sfmod
>;end ifn ftjsys
	RETURN

	PRGEND

TITLE	IBYTE - TO GET AN ARBITRARY BYTE FROM ANY WORD
SUBTTL	NH SAMUELSON - 9/75

	SEARCH	SLAUNV
	SLAPLG	;STANDARD PROLOGUE

;+.TP15.HL1 IBYTE
;.NJ;IBYTE is a FUNCTION which returns an arbitrary sized byte
;from any word.
;.b1.nf;Calling sequence:
;	IBYTE(WORD,SIZE,LOC)
; where	WORD is the word containing the desired byte
;	SIZE is the (INTEGER) length of the byte
;  and	LOC  is the (INTEGER) location of the rightmost bit
;	  (bits are numbered from 0 on the left to 35 on the right)
;-.b1.f.nj;IBYTE should be declared LOGICAL in the calling program.

WORD==0
SIZE==1
LOC==2

HELLO	IBYTE
	MOVEI	T1,^D35		;COMPUTE "P"
	SUB	T1,@LOC(AP)	;..
	LSH	T1,6		;POSITION IT
	ADD	T1,@SIZE(AP)	;GET BYTE SIZE ("S")
	LSH	T1,^D24		;BUILD BYTE POINTER
	HRRI	t1,@WORD(AP)	;GET THE ADDRESS
	LDB	t0,t1		;GET THE BYTE INTO AC0 FOR RETURN
	RETURN

	PRGEND

title	PUTBYT - Put any byte anywhere in any word
subttl	NH Samuelson, 2644, 2/80

	search	slaunv
	slaplg

;+.tp15.hl1 PUTBYT
;.nj;PUTBYT is a SUBROUTINE which puts an arbitrary sized byte
;into any word.
;.b1.nf;Calling sequence:
;	CALL PUTBYT(WORD,SIZE,LOC,VAL)
; where	WORD is the word to be modified
;	SIZE is the (INTEGER) length of the byte
;	LOC  is the (INTEGER) location of the rightmost bit
;  and	VAL  is the value to be stored
;-	  (bits are numbered from 0 on the left to 35 on the right)

WORD==0
SIZE==1
LOC==2
VAL==3

	hello	putbyt
	MOVEI	T1,^D35		;COMPUTE "P"
	SUB	T1,@LOC(AP)	;..
	LSH	T1,6		;POSITION IT
	ADD	T1,@SIZE(AP)	;GET BYTE SIZE ("S")
	LSH	T1,^D24		;BUILD BYTE POINTER
	HRRI	t1,@WORD(AP)	;GET THE ADDRESS
	MOVE	T0,@VAL(AP)	;get the value to store
	DPB	T0,T1		;store the byte
	RETURN

	PRGEND

TITLE	ICHAR - TO GET A ARBITRARY CHARACTER FROM A STRING
SUBTTL	NH SAMUELSON, 2641, 8/78

	SEARCH	SLAUNV
	SLAPLG	;STANDARD PROLOGUE

;+.TP15.HL1 ICHAR
;.F.NJ;ICHAR is a FUNCTION which returns the Nth character of
;an ASCII character string.
;.b1.nf;Calling sequence:
;	ICHAR(STRING,NPOS)
; where	STRING is a variable (or array) containing an ASCII string
;  and	NPOS is the position of the character desired
;	(starting with position 1 at the left)
;.b1.f.nj;ICHAR should be decalred INTEGER or LOGICAL in 
;-the calling program.

STRING==0
NPOS==1
CHAR==2

HELLO	ICHAR
	CALL	BLDPTR			;BUILD BYTE POINTER
	LDB	T0,T0			;GET THE CHARACTER
	RETURN

;+.TP15.HL1 PUTCHR
;.F.NJ;PUTCHR is a SUBROUTINE which replaces a character in
;an ASCII string.
;.b1.nf;Calling sequence:
;	CALL PUTCHR(STRING,NPOS,CHAR)
; where STRING is a variable (or array) containing an ASCII STRING
;	NPOS is the position of the character to be replaced
;	  (starting with position 1 at the left)
;  and	CHAR is the character to insert into the string right justified
;	  (as is the character returned by ICHAR)
;note: to take a character from one string and put it into another
;you can call PUTCHR and ICHAR as follows:
;-	CALL PUTCHR(STR1,NPOS1,ICHAR(STR2,NPOS2))

HELLO	PUTCHR
	CALL	BLDPTR			;BUILD BYTE POINTER
	MOVE	T1,@CHAR(AP)		;GET THE CHARACTER
	DPB	T1,T0			;STORE IT
	RETURN

BLDPTR:	MOVE	T0,@NPOS(AP)		;GET POSITION
	SOJL	T0,BADCNT		;BAD COUNT
	IDIVI	T0,5			;CONVERT TO WORDS
	ADDI	T0,@STRING(AP)		;GET ADDRESS OF DESIRED WORD
	HLL	T0,[POINT 7,0,6
		    POINT 7,0,13
		    POINT 7,0,20
		    POINT 7,0,27
		    POINT 7,0,34](T1)	;MAKE BYTE POINTER
	RETURN

BADCNT:	tmsg	<
?Character position not positive in call to PUTCHR or ICHAR
>
ife ftjsys,<MONRT.>
ifn ftjsys,<haltf>
	clear	t0,			;IN CASE OF CONTINUE
	jrst	bldptr+2

	PRGEND

title	MEMORY - dynamic memory allocation for FORTRAN
subttl	N Samuelson, 2641, 4/78

	SEARCH	SLAUNV
	SLAPLG	;STANDARD PROLOGUE

;+.TP15.HL1 DYNAMIC MEMORY MANAGEMENT
;.NJ;Two routines are provided to interface with the memory allocation
;routines in FOROTS (the fortran run-time library).  One to allocate
;core (MORCOR) and the other to return it (RELCOR).
;.hl2 MORCOR
;MORCOR is a FORTRAN FUNCTION which requests core from FOROTS
;and returns the OFFSET to be used to make future references to
;the allocated memory.
;.B1.nf;Calling sequence:
;	OFFSET = MORCOR(ARAY,LENGTH)
;.B1.F.NJ;MORCOR should be declared LOGICAL or INTEGER in the calling
;program.  The newly allocated memory will be zeroed by FOROTS.
;.b1;To access the allocated memory use the following:
;-.I6;ARAY(OFFSET+I)

ARAY==0
LENGTH==1
OFFSET==1

HELLO	MORCOR
	skipg	@LENGTH(AP)	;is request .gt. 0?
	 jrst	badreq		;bad request
	movei	t1,@ARAY(AP)	;get address of array
	movem	t1,reladr	;save address
	move	t1,1(AP)	;get length pointer from arg list
	movei	AP,getarg	;setup new pointer
	movem	t1,0(AP)	;store the length pointer
	CALL	alcor.##	;get some core
	jumpl	t0,nocore	;cant get it?
	sub	t0,reladr	;compute offset
	return

badreq:	tmsg	<
?less than one word of core requested in MORCOR>
	jrst	.exit
nocore:	tmsg	<
?CORE request failed in MORCOR>
.exit:
ife ftjsys,<monrt.>		;die
ifn ftjsys,<haltf>
	clear	t0,		;in case of continue
	return

;+.HL2 RELCOR
;RELCOR is a FORTRAN SUBROUTINE to release core allocated by MORCOR.
;.b1.nf;Calling sequence:
;	CALL RELCOR(ARAY,OFFSET)
;where OFFSET is the value returned by MORCOR
;NOTE: RELCOR returns the memory to FOROTS, but FOROTS does not,
;at present, release the core to the system.
;-It does, however, re-use it if possible on future calls to MORCOR.

HELLO	RELCOR
	movei	t1,@ARAY(AP)	;get array address
	add	t1,@OFFSET(AP)	;ADDRESS OF CORE TO GIVE BACK
	movem	t1,reladr	;save the address
	movei	AP,relarg	;new arg pointer
	jrst	decor.##	;give core back to FOROTS

	-1,,0			;arg list for alcor.
getarg:	block	1

	-1,,0			;arg list for decor.
relarg:	2b12!reladr
reladr:	block	1		;address of block to be returned

	PRGEND

TITLE	ZERO - zero a block of memory quickly
SUBTTL	NH SAMUELSON, 2641, 10/78

	SEARCH	SLAUNV
	SLAPLG	;STANDARD PROLOGUE

;+.TP15.HL1 ZERO
;.F.NJ;ZERO is a group of FORTRAN SUBROUTINEs which clear memory.
;The entry point names were chosen for an existing application (SPICE2)
;They are related to IBM terminology (ie: REAL*4, REAL*8, etc).
;.B1.nf;Calling sequence:
;	CALL ZERO4(A,N)
;  or	CALL ZERO8(A,N)
;  or	CALL ZERO16(A,N)
; where	A is the start of the block to zero
; and	N is the number of elements to zero.
;	(ie: elements are words(ZERO4), double-words(ZERO8),
;	  or quad-words(ZERO16))
;.b1.f.nj;The memory is cleared with Block Transfer instruction,
;-which is very efficient.

A==0
N==1

HELLO	ZERO16
	MOVEI	T1,2			;QUADRUPLE WORDS
	JRST	ZERO

HELLO	ZERO8
	MOVEI	T1,1			;DOUBLE WORDS
	JRST	ZERO

HELLO	ZERO4
	CLEAR	T1,			;NO SHIFT
ZERO:	SKIPG	T2,@N(AP)		;GET # WORDS TO CLEAR
	 RETURN
	LSH	T2,(T1)			;ADJUST FOR ELEMENT SIZE
	MOVEI	T1,@A(AP)		;GET START ADDRESS
	SETZM	(T1)			;ZERO THE FIRST WORD
	SOJLE	T2,RTN			;# WORDS LEFT TO CLEAR
	ADDI	T2,(T1)			; LAST ADDRESS TO CLEAR
	HRLI	T1,(T1)			; FWA,,FWA
	AOS	T1			; FWA,,FWA+1
	BLT	T1,(T2) 		;CLEAR THE REST
RTN:	RETURN

	PRGEND

TITLE	COPY - COPY A BLOCK OF MEMORY
SUBTTL	NH SAMUELSON, 2641, 10/78

	SEARCH	SLAUNV
	SLAPLG	;STANDARD PROLOGUE

;+.TP15.HL1 COPY
;.F.NJ;COPY is a group of FORTRAN SUBROUTINEs which copy blocks of memory.
;The entry point names were chosen for an existing application (SPICE2).
;They are related to IBM terminology (ie: REAL*4, REAL*8, etc).
;.b1.nf;Calling sequence:
;	CALL COPY4(A,B,N)
;  or	CALL COPY8(A,B,N)
;  or	CALL COPY16(A,B,N)
; where	A is the start of the FROM block
;	B is the start of the TO block
; and	N is the number of elements to copy.
;	(ie: elements are words(ZERO4), double-words(ZERO8),
;	  or quad-words(ZERO16))
;.f.nj.b1;The Block Transfer instruction is used for fast block
;copying when possible.  That is not possible if the block is
;being moved up in memory and the blocks overlap, in that case
;it is necessary to use a loop to transfer one word at a time.
;-The loop used is as fast as possible under the circumstances.

A==0
B==1
N==2

HELLO	COPY16
	MOVEI	T2,2
	JRST	COPY

HELLO	COPY8
	MOVEI	T2,1
	JRST	COPY

HELLO	COPY4
	CLEAR	T2,
COPY:	SKIPG	T3,@N(AP)
	 RETURN				;dont copy anything
	LSH	T3,(T2)			;ADJUST FOR ELEMENT LENGTH
	SOJLE	T3,CPY1WD		;WORD COUNT MINUS ONE
	MOVEI	T1,@A(AP)		;FROM ADDRESS
	MOVEI	T2,@B(AP)		;TO ADDRESS
	CAILE	T1,(T2) 		;MOVING DOWN?
	 JRST	MOVEOK			;YES - ALWAYS SAFE
	MOVEI	T0,(T2)
	SUBI	T0,(T1)
	CAIG	T0,(T3)			;OR UP FAR ENOUGH
	 JRST	MOVEUP			;NO - TOO BAD
MOVEOK:	HRLI	T2,(T1)			;PREPARE FOR BLT
	ADDI	T3,(T2)			;END ADDRESS
	BLT	T2,(T3)
RTN:	RETURN

CPY1WD:	MOVE	T1,@A(AP)		;GET THE ONE WORD
	MOVEM	T1,@B(AP)		;STORE IT
	RETURN

;THE FOLLOWING IS SOME OF THE MOST OBSCURE CODE I EVER HOPE TO WRITE
;IT IS TAKEN FROM THE HARDWARE REFERENCE MANUAL, IN A MARGINAL NOTE
;RELATED TO THE POP INSTRUCTION.

;A TWO INSTRUCTION LOOP, FOLLOWED BY A RETURN, IS LOADED INTO AC'S
;P1 THRU P3, THEN WE JUMP INTO THE AC'S TO PERFORM THIS MAGIC.

MOVEUP:	MOVSI	P1,(POP T1,0(T1))	;BUILD A POP INSTR. IN P1
	ADD	P1,T0			;IE:  POP T1,B-A(T1)
	HRLI	T1,400000(T3)		;SETUP T1 AS THE STACK POINTER
	ADDI	T1,(T3)			;IE: 400000+N-1,,B+N-1
	MOVE	P2,[JUMPL T1,P1]	;PUT JUMPL INSTR. IN P2
	MOVE	P3,RTN			;AND RETURN INSTR. IN P3
	JRST	P1			;GOOD LUCK!

	PRGEND

TITLE	TTSYNC	GET IN SYNC WITH TTY OUTPUT
SUBTTL	NH SAMUELSON, 2641, 5/16/79

	SEARCH	SLAUNV
	SLAPLG	;STANDARD PROLOGUE
ITIM==0		;ONLY ARG - SLEEP TIME AFTER OUTPUT DONE
;+.TP15.HL1 TTSYNC
;TTSYNC is a FORTRAN SUBROUTINE which allows a program to get back
;into sync with terminal output.  It waits for the output buffer to
;become empty, then turns off the effect of any control-O which might
;have been typed by the user.
;It can also wait a specified period after output has stopped,
;to allow the terminal to settle down (eg: for TEKTRONIX graphics
;terminals to clear the screen).
;.b1;Calling sequence:
;.i8;CALL TTSYNC(ITIME)
;-.i2;where ITIME is the number of milliseconds to wait after output stops.

SLPTIM==^D100	;100 MILLISECONDS PER HIBER WAITING FOR OUTPUT DONE

	HELLO	TTSYNC
ife ftjsys,<
	SETO	T3,
	TRMNO.	T3,			;GET OUR TTY #
	 RETURN				;NO TTY - DONT WAIT
	MOVEI	T2,.TOSOP		;FUNCTION=SKIP IF DOING OUTPUT
CHKBFR:	MOVE	T1,[2,,T2]
	TRMOP.	T1,
	 JRST	NOTBSY			;BUFFER EMPTY NOW
	MOVEI	T1,SLPTIM		;SET SLEEP TIME
	HIBER	T1,			;SLEEP
	 SLEEP	T1,			;REALLY SLEEP
	JRST	CHKBFR			;THEN TRY AGAIN

NOTBSY:	SKPINL				;CHECK FOR INPUT TO WAKE TTY
	 JFCL
	SKIPLE	T1,@ITIM(AP)		;EXTRA SLEEP TIME
	HIBER	T1,
	 JFCL
>;end ife ftjsys
ifn ftjsys,<
	movei	t1,.priou
	dobe				;dismiss until output buffer empty
	skiple	t1,@itim(ap)		;time to sleep
	disms
>;end ifn ftjsys
	RETURN

	PRGEND

TITLE	FORKS - SUBROUTINES TO CONTROL FORKS
SUBTTL	NH Samuelson, 2641, 10/79

	SEARCH	SLAUNV
	SLAPLG		;PROLOGUE
ife ftjsys,<
	printx	?You cant have forks on a DEC-10
	END
>
	.request	rel:macrel

;+.HL1 FORK HANDLING ROUTINES
;.F.NJ;FORKS is a collection of FORTRAN (or PASCAL) callable routines
;to manipulate forks.  Facilities are provided to create forks, destroy forks,
;load programs into forks, start forks, freeze forks, resume forks, and
;wait on forks.
;.b1;All fork handling routines require a 'fork handle' to distinguish
;between possible multiple forks.  When a fork is created
;a handle is returned, that same handle must be used in all future
;references to that fork

;.hl2 FRKCRE - Create a fork
;.nf.b1;Calling sequence:
;	CALL FRKCRE(BITS,HANDLE)
; where BITS is a logical mask to control the forks address space and capabilities (Normally ZERO)
;- and	HANDLE (on return) is the new fork handle (INTEGER)

	HELLO	FRKCRE
	SKIPE	T1,@0(AP)		;GET THE BITS
	TXO	T1,CR%CAP	;GIVE HIM OUR CAPABILITIES
	CFORK
	 JSERR
	MOVEM	T1,@1(AP)		;RETURN THE FORK HANDLE
	RETURN

;+.HL2 FRKKIL - Kill a fork
;.b1.nf;Calling sequence:
;-	CALL FRKKIL(HANDLE)

	HELLO	FRKKIL
	MOVE	T1,@0(AP)		;GET HANDLE
	KFORK				;KILL IT
	 ERJMP	JSERR0
	RETURN

;+.HL2 FRKHLT - Halt a fork
;.b1.nf;Calling sequence:
;-	CALL FRKHLT(HANDLE)

	HELLO	FRKHLT
	MOVE	T1,@0(AP)
	HFORK
	 ERJMP	JSERR0
	RETURN

;+.HL2 FRKWAI - Wait for a fork to exit
;.b1.nf;Calling sequence:
;-	CALL FRKWAI(HANDLE)

	HELLO	FRKWAI
	MOVE	T1,@0(AP)
	WFORK%
	 ERJMP	JSERR0
	MOVE	T1,@0(AP)
	RFSTS%
	 ERJMP	JSERR0
	LDB	T1,[POINT 17,T1,17] ;GET RF%STS
	CAIN	T1,.RFHLT	;DID IT HALT VOLUNTARILY?
	 RET			;YES
	TMSG	<?
?Error in fork termination - >
	MOVEI	T1,.PRIOU
	HRLO	T2,@0(AP)	;GET HANDLE AGAIN
	CLEAR	T3,
	ERSTR%
	 ERJMP	JSERR0
	 ERJMP	JSERR0
	RETURN

;+.HL2 FRKFRZ - Freeze (suspend) a fork
;.b1.nf;Calling sequence:
;-	CALL FRKFRZ(HANDLE)

	HELLO	FRKFRZ
	MOVE	T1,@0(AP)
	FFORK
	 ERJMP	JSERR0
	RETURN

;+.HL2 FRKRES - Resume a (suspended) fork
;.b1.nf;Calling sequence:
;-	CALL FRKRES(HANDLE)

	HELLO	FRKRES
	MOVE	T1,@0(AP)
	RFORK
	 ERJMP	JSERR0
	RETURN

;+.HL2 FRKSTA - Start a fork
;.b1.nf;Calling sequence:
;	CALL FRKSTA(HANDLE)
;Optional calling sequence:
;	CALL FRKSTA(HANDLE,OFFSET)
;-where OFFSET is the offset into the entry vector to the desired starting address.

	HELLO	FRKSTA
	MOVE	T1,@0(AP)
	hlre	t2,-1(ap)	;get arg count
	movm	t2,t2		;make it positive
	cail	t2,2		;are there 2 args?
	 skipa	t2,@1(ap)	;yes, get the second arg
	 clear	t2,		;no, normal starting address
	sfrkv
	 ERJMP	JSERR0
	RETURN

;+.HL2 FRKGET - Get (load) an .EXE file into a fork
;.b1.nf;Calling sequence:
;	CALL FRKGET(HANDLE,JFN)
;- where	JFN is a 'Job File Number' for the file to be loaded (obtained from GETJFN)
; THE FOLLOWING OPDEF IS TO AVOID CONFLICT WITH "GET" IN PASLIB
	OPDEF	GET.	[JSYS	200]

	HELLO	FRKGET
	MOVS	T1,@0(AP)
	HRR	T1,@1(AP)
	CLEAR	T2,
	GET.
	 ERJMP	JSERR0
	RETURN

;+.hl2 FRKSAC - Set fork ACs.  This should rarely be used, but
;is necessary when running programs which expect parameters to be
;set in the accumulators (ACs).  (EDIT is such a program).
;.b1.nf;Calling sequence:
;	CALL FRKSAC(HANDLE,ACBLOK)
;- where	ACBLOK is an array of 16 words (INTEGER)

	HELLO	FRKSAC
	MOVE	T1,@0(AP)	; GET FORK HANDLE
	MOVEI	T2,@1(AP)	; AND ADDRESS OF ACBLOK
	SFACS
	RET

;+.HL2 GETJFN
;The GETJFN routine returns a number (called a JFN) which is used by
;the operating system for all calls related to files.  It is included in
;the FORKS package because a JFN is required in the FRKGET routine to
;specify the file to be loaded.
;.nf.b1;Calling sequence:
;	CALL GETJFN(FILNAM,JFN)
; where	FILNAM is an array or literal containing the name of the file desired
;-  and	JFN is (on return) the JFN for the desired file

	HELLO	GETJFN
	MOVX	T1,<GJ%OLD!GJ%SHT>	;SHORT FORM, OLD FILE ONLY
	HRROI	T2,@0(AP)		;POINTER TO STRING
	GTJFN
	 ERCAL	JSERR0
	MOVEM	T1,@1(AP)	;RETURN THE JFN
	RETURN

	PRGEND
TITLE	EXIT0 - SETUP FOR QUIET EXIT FROM FORTRAN

	SEARCH	SLAUNV
	SLAPLG

;+.HL1 EXIT0 routine
;.f.nj;The routine EXIT0 can be called from FORTRAN ONLY!
;Its purpose is to signal FOROTS that, on exit, the CPU time and ELAPSED
;time message are NOT to be typed out.  It does NOT exit, it merely sets
;that flag.

;.b1.nf;Calling sequence: fortran:
;-	CALL EXIT0

	HELLO	EXIT0
	MOVEI	T0,12		;ARGUMENT TO FOROP.
	CALLRET	FOROP.##	;IN FOROTS

	PRGEND

TITLE	DOJSYS - PASCAL, FORTRAN, AND COBOL CALLABLE JSYS DOER
SUBTTL	NH SAMUELSON, 2641, 10/3/79

	SEARCH	SLAUNV
	SLAPLG	;STANDARD PROLOGUE
	.request rel:macrel


;+.HL1 DOJSYS routine
;.f.nj;The routine DOJSYS can be called from either FORTRAN or COBOL
;to perform any JSYS monitor call in TOPS-20.

;.b1.nf;Calling sequence: fortran:
;	CALL DOJSYS(NUMBER,ARG1,ARG2,...,ARGN [,$LABEL])
;PASCAL:
;Define DOJSYS as:
;	PROCEDURE DOJSYS(JSYS_NUM: INTEGER; VAR AC1,AC2,AC3,AC4: INTEGER); FORTRAN;
;Call it with:
;	DOJSYS(NUMBER, ARG1, ARG2, ARG3, ARG4)
;COBOL:
;	ENTER MACRO DOJSYS USING NUMBER, ARG1, ARG2,...,ARGN [,PROC-NAME].
; where	NUMBER is the JSYS number to be performed
;	ARG1 thru ARGN are the arguments for the JSYS
;	$LABEL or PROC-NAME is the return address in case of error
;-.f.nj;Note: In PASCAL the error-return address cannot be used.

	hello	DOJSYS
	hll	ap,-1(ap)	;form aobjn word for rest of arglist
	move	15,@0(ap)	;get JSYS number
	hrli	15,(JSYS)	;make a JSYS
	movei	14,0		;point at first AC
	aobjp	ap,doj2		;step to next arg
doj1:	move	13,@0(ap)	;get next arg
	aoj	14,		;point to next AC
	movem	13,(14)		;store in the AC
	aobjn	ap,doj1		;do all the args
doj2:	ldb	13,[point 4,-1(ap),12]	;get type of last arg
	cain	13,7		;label?
	skipa	13,(14)		;yes - save it
	 movei	13,0		;no - clear it
	xct	15		;do the jsys
	 erjmp	doj4		;error return 1
	 erjmp	doj4		;error return 2
doj3:	move	13,(14)		;get an arg back
	movem	13,@-1(ap)	;store for user
	sub	ap,[1,,1]	;point to previous
	sojg	14,doj3		;store all args away
	RETURN

doj4:	jumpe	13,doj5		;did user give error label?
	movem	13,-1(p)	;yes - fixup stack
	jrst	doj3		;and continue

doj5:	jshlt		;type error message and die

	prgend

Title	FLT11 - convert pdp10 real to pdp11 real
subttl	NH Samuelson, 2641, 1/80

	search	slaunv

;+.tp15.hl1 DATA conversion routines
;.f.nj;This is a collection of SUBROUTINEs to convert PDP-10 floating
;point numbers to PDP-11 floating point and vice-versa.
;.hl2 F3632 - convert 36bit floating poing to 32-bit
;.nf.b1;Calling sequence:
;	CALL F3632(FIN,FOUT,NUM)
; where	FIN is the input array of PDP-10 36bit real numbers
;	FOUT is the output array of PDP-11 32 bit numbers
;-  and	NUM is the length of each array

FIN==0
FOUT==1
NUM==2

byte1:	point	8,t1,16
byte2:	point	8,t1,7
byte3:	point	8,t1,32
byte4:	point	8,t1,24
expofs==0	;difference in exponents between -10 and -11

	hello	f3632
	movei	p1,@fin(ap)	;address of input array
	movei	p2,@fout(ap)	;address of output array
	hrli	p2,(point 8,0)	;make a byte pointer
	skipa	p3,@num(ap)	;number of elements
go.1:	 aos	p1		;advance input pointer
	skipl	t1,(p1)		;get next number
	 jrst	pos.1		;jump if positive
	movn	t1,t1		;convert to sign/magnitude
	tlo	t1,(t1)		; ...
pos.1:
	 fsc	t1,expofs	;normalize and correct exp.
	ldb	t2,byte1	;get the first byte
	tlnn	t1,(1b8)	;even exponent?
	 trz	t2,200		;yes - clear the low bit of the exp.
	idpb	t2,p2		;store it
	ldb	t2,byte2
	idpb	t2,p2
	ldb	t2,byte3
	idpb	t2,p2
	ldb	t2,byte4	;get the last byte
	idpb	t2,p2
	sojg	p3,go.1		;loop till done
	return

;+.hl2 F3236 - convert 32bit to 36bit
;.nf.b1;Calling sequence:
;	CALL F3236(FIN,FOUT,NUM)
; where	FIN is the input array of PDP-11 32bit real numbers
;	FOUT is the output array of PDP-10 36 bit numbers
;-  and	NUM is the length of each array

	hello	f3236
	movei	p1,@fin(ap)	;address of input array
	hrli	p1,(point 8,0)	;make a byte pointer
	movei	p2,@fout(ap)	;address of output array
	skipa	p3,@num(ap)	;number of elements
go.2:	 aos	p2		;advance output pointer
	clear	t1,
	ildb	t2,p1		;get first byte
	troe	t2,200		;check for odd exponent
	 tlo	t1,(1b8)	; ...
	dpb	t2,byte1
	ildb	t2,p1		;get next byte
	dpb	t2,byte2
	ildb	t2,p1
	dpb	t2,byte3
	ildb	t2,p1		;get the last byte
	dpb	t2,byte4
	tlze	t1,(1b0)	;convert sign/mag to twos comp.
	 movn	t1,t1
	fsc	t1,-expofs	;correct the exponent
	movem	t1,(p2)		;store the result
	sojg	p3,go.2
	return

	prgend

title	RUNTIM - return PROCESS runtime.
subttl	NH Samuelson, 2644, 2/4/80

search	slaunv
	slaplg

;+.tp15.hl1 RUNTIME - return PROCESS runtime
;.f.nj;The SUBROUTINE RUNTIME returns the runtime used by this process
;(not by the JOB) in milliseconds.
;.nf.b1;Calling sequence:
;	CALL RUNTIM(ITIME)
;- where	ITIME is an INTEGER

ITIM==0

	hello	runtim
	movei	t1,.fhslf
	runtm
	movem	t1,@itim(ap)
	return

	prgend

Title	LOCF - return the address of an argument
Subttl	NH Samuelson, 2644, 2/80

	SEARCH	SLAUNV
	SLAPLG

;+.TP15.HL1 LOCF
;.F.NJ;LOCF is a FUNCTION which returns the address of the argument
;.b1.nf;Calling sequence:
;	LOCF(ARG)
;- where	ARG is ANY argument of ANY type, including a literal

ARG==0

	HELLO	LOCF
	XMOVEI	T0,@ARG(AP)	;GET THE ADDRESS
	RETURN			;RETURN IT TO THE USER

	prgend

TITLE NXTJOB FORTRAN CALLABLE ROUTINE TO START ANOTHER JOB
SUBTTL	NH Samuelson, 2644, 2/13/80

	SEARCH	SLAUNV
	SLAPLG	;STANDARD PROLOGUE

;+.TP15.HL1 NXTJOB
;.f.nj;NXTJOB is a FORTRAN SUBROUTINE which will never return.
;It is equivalent to giving a RUN command at monitor level.
;It will cause the monitor to replace the current program with
;a program which is in an executable core image file (.EXE).
;.b1.nf;Calling sequence:
;	CALL NXTJOB(JFN)
; where	JFN is a TOPS-20 JFN for the file (see GETJFN routine)
;Alternate calling sequence (macro)
;	MOVE	T1,JFN
;	JRST	NXTJB1
;.NOTE WARNING
;Any files which are open for output should be closed before NXTJOB
;is called, or they will never be closed.
;-.end note

JFN==0
	entry	nxtjb1

	HELLO	NXTJOB
	MOVE	T1,@JFN(AP)	; GET THE JFN
NXTJB1:	HRRM	T1,ACCODE
	MOVSI	17,ACCODE
	BLT	17,ACEND
	JRST	ACGO

ACCODE:
	PHASE	0		; BUILD CODE FOR THE AC'S
	.FHSLF,,0		; JFN WILL GO IN RIGHT HALF
	-1
	.FHSLF,,0
	1B0!1000
ACGO:	PMAP			; DELETE ALL CORE
	MOVE	1,0		; GET .FHSLF,,JFN
	CLEAR	2,
	GET			; GET THE .EXE FILE
	RESET			; reset I/O
	MOVEI	1,.FHSLF
ACEND:	SFRKV
	prgend
title	DDT - enter DDT - load DDT if necessary...
subttl	NH Samuelson, 2644, 7/8/81

	search	slaunv
	slaplg

;+.hl1 DDT
;Load DDT if it is not already loaded, then transfer control to it.
;-This routine takes no arguments and is callable from any language.

;Note - this was stolen from LIBMAC, which stole it from FOROTS...

	hello	ddt
	MOVE	1,[.FHSLF,,770]	;[114] LOOK AT PAGE 770
	RPACS%			;[114] GET PAGE ACCESS BITS
	TXNN	2,PA%PEX	;[114] DOES PAGE 770 EXIST?
	  JRST	MAPDDT		;[114] NO, GO MAP IN UDDT.EXE
	MOVE	1,770000	;[114] GET DDT ENTRY VECTOR
	CAMN	1,[JRST 770002]	;[114] IS IT REALLY DDT?
	  JRST	GODDT		;[114] YES, JUMP TO IT

MAPDDT:	MOVEI	1,.FHSLF	;[114] GET ENTRY VECTOR LOC
	GEVEC%
	PUSH	P,2		;[114] SAVE SINCE GET WRECKS IT
	MOVX	1,GJ%SHT+GJ%OLD	;[114] SHORT FORM, FILE MUST EXIST
	HRROI	2,[ASCIZ /SYS:UDDT.EXE/] ;[114] DDT
	GTJFN%			;[114] FIND IT
	  ERJMP ERR11		;[114] NOT THERE, CAN'T HELP
	HRLI	1,.FHSLF	;[114] MAP INTO THIS FORK
	GET			;[114] READ IN DDT
	  ERJMP	ERR11		;[114] CAN'T
	DMOVE	1,116		;[114] GET SYMBOL TABLE POINTERS
	MOVEM	1,@770001	;[114] STORE FOR DDT
	MOVEM	2,@770002
	POP	P,2		;[114] GET ENTRY VECTOR BACK
	MOVEI	1,.FHSLF	;[114] THIS FORK
	SEVEC%			;[114] RESTORE ENTRY VECTOR

GODDT:	TMSG	<Type PDDT$G to continue
>
	JRST	770000		;jump into DDT
err11:	TMSG	<
%Sorry, I cant seem to get DDT for you
>
PDDT::	RET
	prgend

title	clear - screen clear routine for all supported terminals
subttl	NH Samuelson, 2644, 8/8/80

	search	slaunv
	slaplg

;+.hl1 CLEAR
;Clear the screen of any supported terminal capable of it.
;-This routine takes no arguments and is callable from any language.

	hello	clear
	push	p,p1		;save some acs
	push	p,t3
	push	p,t2
	movx	t1,.cttrm	;jobs controlling terminal
	gttyp%			;get its terminal type
	move	p1,t2		;save it
	rfmod%			;get the mode word
	push	p,t2		;save it
	txz	t2,tt%dam	;no translation
	sfmod%			;change output mode temporarily
	movx	t2,.morxo	;get current "pause on end-of-page" setting
	mtopr%
	push	p,t3		;save it
	movx	t2,.moxof	;set no pause on end-of-page
	movx	t3,.mooff
	mtopr%
	caig	p1,max.ty	;known legal type number?
	skipn	t1,blnktb(p1)	;get the clear sequence, if any
	 jrst blank2		; none - do nothing
	tlnn	t1,-1		; string or pntr?
	 tloa	t1,-1		; pntr to text
	  hrroi	t1,blnktb(p1)	; string - point to it instead
	psout%			; dump it

	movei	t1,^d1500	;for tektronix terminals sleep 1.5 seconds
	cain	p1,6		;is this tektronix?
	 disms%			;yes

blank2:	movx	t1,.cttrm	;jobs controlling terminal
	pop	p,t3		;get original "pause on end-of-page" bit
	movx	t2,.moxof
	mtopr%
	pop	p,t2		;get original mode word
	sfmod%			;restore it
	pop	p,t2		;restore the acs
	pop	p,t3
	pop	p,p1
	ret

BLNKTB:	0			; (0) TTY 33
	0			; (1) TTY 35
	0			; (2) TTY 37
	0			; (3) TI / EXECUPORT
	BYTE (7)33,"H",33,"J",0	;4 - HP2624
	byte(7).chcnz		;5 - ADM3A.
	byte(7).chesc,.chffd	;6 - Tektronix
	byte(7).chesc,.chffd	;7 - TK4015
	0			; (8) SYSTEM DEFAULT
	0			; (9) IDEAL (NO FILL)
	[BYTE (7)35,177,177,177,177,177,177,37,0] ; (10) VT05
	BYTE (7)33,"H",33,"J",0	; (11) VT50
	0			; (12) LA30
	BYTE (7)35,37		; (13) GT40 - NO FILL REQUIRED
	0			; (14) LA36
	BYTE (7)33,"H",33,"J",0	; (15) VT52
	[BYTE (7)33,"[","H",33,"[","J",0] ; (16) VT100
	0			; (17) LA38
	0			; (18) LA120
max.ty==.-blnktb

	END