X86 Macro compiler/LLVM error

OpenVMS x86 native compilers, cross compilers news and questions.
User avatar

Topic author
cct
Master
Posts: 128
Joined: Sat Aug 15, 2020 9:00 am
Reputation: 0
Location: Cambridge, UK
Status: Offline

X86 Macro compiler/LLVM error

Post by cct » Mon Apr 01, 2024 2:20 pm

Trying to compile some macro code that was ported from VAX to Alpha, and worked on I64, and 3 files are coming up with:

LLVM ERROR: invalid symbol redefinition

Not that I know diddly about macro, but what does this mean?
I have been looking at the latest Vax Macro reference manual and it doesn't reference LLVM at all. Are there any suitable references available?

Also is there any rule fo thumb for what command line to compile old macro on X86?
Last edited by cct on Mon Apr 01, 2024 3:34 pm, edited 2 times in total.
--
Chris


simon
Visitor
Posts: 1
Joined: Wed Apr 17, 2024 9:27 pm
Reputation: 0
Location: Melbourne, Australia
Status: Offline
Contact:

Re: X86 Macro compiler/LLVM error

Post by simon » Wed Apr 17, 2024 9:34 pm

One issue is that sometimes the PSECT name is fixed by another party. An example of this is RDB$MESSAGE_VECTOR. We cant change the names. But we have a Macro32 module which provides mapping onto this for us. In this case we cannot change the names.


roberbrooks
VSI Expert
Contributor
Posts: 22
Joined: Thu Jun 20, 2019 11:48 am
Reputation: 0
Status: Offline

Re: X86 Macro compiler/LLVM error

Post by roberbrooks » Wed Apr 17, 2024 11:29 pm

> Also is there any rule fo thumb for what command line to compile old macro on X86

Yeah, use the same command line options that were used on Alpha/IA64.

Seriously; you should not need to alter the command at all.

Post a listing file and we'll take a look.
--
-- Rob

User avatar

Topic author
cct
Master
Posts: 128
Joined: Sat Aug 15, 2020 9:00 am
Reputation: 0
Location: Cambridge, UK
Status: Offline

Re: X86 Macro compiler/LLVM error

Post by cct » Thu Apr 18, 2024 7:31 am

roberbrooks wrote:
Wed Apr 17, 2024 11:29 pm
> Also is there any rule fo thumb for what command line to compile old macro on X86

Yeah, use the same command line options that were used on Alpha/IA64.

Seriously; you should not need to alter the command at all.

Post a listing file and we'll take a look.
I have fixed one file by looking at the BAISC file where it is called, and it only calls the macro without mentioning the psect, so I renamed that.

The big one is quite a few small routines, used for screen handling:

Code: Select all

	.TITLE KBIO
	.IDENT /DTW.04F/

	$IODEF					; DEFINE IO FUNCTION CODES


	.PSECT CORCOM,LONG,NOPIC,OVR,REL,GBL,NOSHR,NOEXE,WRT,NOVEC
						; Standard PSECT
						; for CORCOM is repeated in
						; MESSAGES, TTIO, VDIOS and KBIO
						; so watch the offsets if CORCOM
						; changes
CORCOM_DETAIL:
	.BLKB	8 				; NOT INTERESTED
CC_CHECK:
	.BLKW	1 				
	.BLKB	40				; NOT INTERESTED
CC_MODE:                                                                                                                 
	.BLKB	1
CC_KBSTAT1:
	.BLKB	1				; CC.KBSTAT1 - ERROR DISPLAYED FLAG


	.PSECT	KBIOWK,LONG,NOPIC,OVR,REL,GBL,NOSHR,NOEXE,WRT,NOVEC
DELIM:	.BLKL	1
LINIT:	.BLKW	1
LANG:	.BLKW	1

	.PSECT	LANG_TRN,LONG,NOPIC,OVR,REL,GBL,NOSHR,NOEXE,WRT,NOVEC
ENGLISH:
ENGLEN:	.BLKL	1
ENGADD:	.BLKL	1

LA_DES:
LA_LEN:	.BLKL		1
LA_ADD:	.ADDRESS	LA_STR
LA_STR:	.BLKB	256

	; PSECT AREA TO HOLD ALL BUFFERS AND VARIABLES
	; --------------------------------------------

	.PSECT	KBIOMP,LONG,NOPIC,OVR,REL,GBL,NOSHR,NOEXE,WRT,NOVEC

TT_TYPE:					; STORE TERM TYPE HERE -
	.BLKW	1				; 64 = VT52, VT100
TT_CHAN:					; KEYBOARD CHANNEL NUMBER
	.BLKW	1

TT_DESC:					; DESCRIPTOR FOR LOGICAL NAME
	.ASCID	/SYS$OUTPUT/			; OF KEYBOARD
DEV_DESC:					; DESCRIPTOR FOR PHYSICAL NAME
PHYS_NAME_LEN:					; OF KEYBOARD
	.LONG	63
PHYS_NAME_ADR:
	.ADDRESS	PHYS_NAME
PHYS_NAME:
	.BLKB	63
	.BYTE	0	; WORD ALIGN

TT_FLAGS:
	.BLKL	1				; JUST NEED THIS FOR INFO CALL

IN_LEN:						; WORD FOR LENGTH OF
	.BLKW	1				; STRING RETURNED BY KB_ECHO

IN_BUF:						; PRINCIPAL INPUT BUFFER
	.BLKB	132

ODES::
OLEN:	.WORD	0
	.WORD	^X020E			; hexadecimal string identifier
	.ADDRESS	OUTPUT_STR
BUFF_LEN = 512
OUTPUT_STR:					; LOCATION OF PROMPT STRING
	.BLKB	BUFF_LEN
BUFF_END = OUTPUT_STR+BUFF_LEN-9		; FLUSH THE BUFFER IF THE
						; POINTER PASSES THIS POINT
BUFF_PTR:
	.BLKL	1				; NEXT CHARACTER POSITION
						; FOR WRITING IN OUTPUT_STR
CSIDES:
	.LONG	1
	.ADDRESS	CSICHR
CSICHR:	.BYTE	-101				; equiv to chr$(155%)

FKEYS_8BIT:					   ; to define function keys
	.ASCII	<144>=1;0|23/1B;24/08;25/0A=<156>   ;	F11, F12 + F13
FKEYS_8LEN = .-FKEYS_8BIT			   ; as ESC, BS  + LF

EDGE_OF_SCREEN:
	.BLKW	1				; EITHER 80 OR 132, DEPENDING ON WHERE EDGE OF SCREEN IS

FLUSH_STATUS:
	.BLKL	1				; 1 - FLUSH BUFFER ON EVERY IO
						; 0 - ONLY FLUSH WHEN:
						;     KB_ECHO CALLED
						;     BUFF_PTR EXCEDES BUFF_END
						;     KBFLSH IS CALLED WITH A 
						;     FLUSH-NOW CODE


	.PSECT	KBIOMP2,LONG,PIC,OVR,GBL,SHR,NOEXE

PAINT_CHARS:
	.BYTE	95[132]				; 132 UNDERSCORES
NO_ECHO:
	.BLKL	1
DELIM_MASK:
	.BLKL	1
ARG_CT:	.BLKL	1
OUT_DEL:					; STRING TO DO A DELETE
	.BYTE	8
OUT_SPACE:					; THIS IS A SPACE
	.ASCII	/ /
	.BYTE	8
OUT_DEL_LEN=.-OUT_DEL

OUT_BEL:					; STRING TO DO A BELL
	.BYTE	7
OUT_BEL_LEN=.-OUT_BEL

KBFUNN:	.ASCII	<155>/[0m/		; Normalise screen attributes
	.ASCII	<155>/[1v/		;		and cursor off
KBFD1:	.BYTE		8		; Descriptor of KBFUNN
	.ADDRESS	KBFUNN

KBFUN0:	.ASCII	<155>/[0v/		; Set	Cursor on
KBFUN1:	.ASCII	<155>/[1m/		; Set	Bold
KBFUN2:	.ASCII	<155>/[4m/		; Set	Underline
KBFUN3:	.ASCII	<155>/[5m/		; Set	Blink
KBFUN4:	.ASCII	<155>/[7m/		; Set	Inverse
KBFD2:	.BYTE		4		; Descriptor of KBFUN0
KBFD2A:	.ADDRESS	KBFUN0

IN_CHAR_BUFF:					; SINGLE CHARACTER BUFFER
	.BLKB	1
IN_CHAR_BUFLEN=.-IN_CHAR_BUFF

IO_IOSB:					; IO STATUS BLOCK
IO_IOSB_STAT:					; STATUS
	.BLKW	1
IO_IOSB_OFF:					; OFFSET
	.BLKW	1
IO_IOSB_TERM:					; TERMINATOR
	.BLKW	1
IO_IOSB_TSIZE:					; TERMINATOR SIZE
	.BLKW	1

IN_TERM_DESC_DEL:				; INPUT TERMINATOR DESCRIPTOR
	.LONG	16				; USED WHEN PAINT CHARACTERS
	.ADDRESS TERM_ADD			; ARE REQUIRED
TERM_ADD:
	.LONG	^XFFFFFFFF
	.LONG	0
	.LONG	0
	.LONG	^X80000000

IN_TERM_DESC:					; INPUT TERMINATOR DESCRIPTOR
	.LONG	0				; BLOCK
	.LONG	^XFFFFFFFF

	.PSECT	KBIOREAD,LONG,PIC,OVR,GBL,SHR

READ_AREA:					; PRINCIPAL INPUT QIO VECTOR
	$QIO	FUNC=IO$_READLBLK!IO$M_TRMNOECHO,-
		IOSB=IO_IOSB,-
		P1=IN_BUF,-
		P4=IN_TERM_DESC

READ_PASS_AREA:					; AREA FOR 1 CHAR PASSALL MODE
	$QIO	FUNC=IO$_TTYREADALL!IO$M_NOECHO,-
		IOSB=IO_IOSB,-
		P1=IN_CHAR_BUFF,-
		P2=IN_CHAR_BUFLEN

READ_ESC_AREA:					; AREA FOR REST OF A PART ESC.
	$QIO	FUNC=IO$_TTYREADALL!IO$M_NOECHO,-
		IOSB=IO_IOSB



	.PSECT	KBIOMP3,LONG,PIC,OVR,GBL,SHR,NOEXE

WRITE_AREA:					; STRING OUTPUT AREA
	$QIO	FUNC=IO$_WRITEVBLK!IO$M_NOFORMAT,-
		IOSB=IO_IOSB

	;
	; K B _ O P E N
	; -------------
	.PSECT	$CODE,NOWRT,PIC,SHR,LONG

	.ENTRY	KB_OPEN,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

	TSTW	TT_CHAN
	BEQL	TRNLOG
	BRW	KB_OPEN_EXIT

TRNLOG:
	$TRNLOG_S -	
		LOGNAM=TT_DESC, -
		RSLLEN=PHYS_NAME_LEN, -
		RSLBUF=DEV_DESC
	CMPB	PHYS_NAME,#^X1B
	BNEQ	10$
	SUBL	#4,PHYS_NAME_LEN
	ADDL	#4,PHYS_NAME_ADR

10$:
	$ASSIGN_S -
		DEVNAM=DEV_DESC, -
		CHAN=TT_CHAN
	BLBS	R0,20$
	$EXIT_S	R0
	RET

20$:
	PUSHL	#0					; FIND OUT TERMINAL TYPE
	PUSHL	#0
	PUSHAW	TT_TYPE
	PUSHAL	TT_FLAGS
	CALLS	#4,G^LIB$SCREEN_INFO
	BLBS	R0,30$
	$EXIT_S	R0
	RET

30$:
	MOVZWL	TT_CHAN,READ_AREA+QIO$_CHAN		; INIT. QIO CTRL AREAS
	MOVZWL	TT_CHAN,WRITE_AREA+QIO$_CHAN
	MOVZWL	TT_CHAN,READ_PASS_AREA+QIO$_CHAN
	MOVZWL	TT_CHAN,READ_ESC_AREA+QIO$_CHAN

	MOVAL	OUTPUT_STR,BUFF_PTR

	CMPW	TT_TYPE,#TT$_VT200_SERIES
	BEQL	40$
	CMPW	TT_TYPE,#TT$_VT300_SERIES
	BEQL	40$
	CMPW	TT_TYPE,#TT$_VT400_SERIES
	BNEQ	KB_OPEN_EXIT

40$:
	MOVL	#FKEYS_8LEN,R6		; on a VT200, VT300, or VT400 we need
	MOVAL	FKEYS_8BIT,R8		; to define keys F11, F12 + F13
	MOVL	BUFF_PTR,R3		;	as       ESC, BS  + LF
	JSB	OUTPUT_STRING
	MOVL	R3,BUFF_PTR

KB_OPEN_EXIT:
	CLRL	R0
	RET


	; K B _ E C H O
	; -------------
        .PSECT	$CODE,NOWRT,PIC,SHR,LONG

	.CALL_ENTRY LABEL=KB_ECHO,PRESERVE=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>,MAX_ARGS=64,HOME_ARGS=TRUE

	;
	; FORMAL PARAMETERS AND THEIR OFFSET FROM THE ARGUMENT POINTER
	;
	KB_ECHO_RETURN = 4				; STRING FUNCTION RETURNED VALUE
	KB_ECHO_ROW = 8					; ROW POSITION FOR INPUT
	KB_ECHO_COL = 12					; COLUMN POSITION FOR INPUT
	KB_ECHO_LEN = 16				; LENGTH OF INPUT
							;  THE FOLLOWING ARE OPTIONAL
	KB_ECHO_TIME = 20				; TIME OUT PERIOD (SECS)
	KB_ECHO_PAINT = 24				; PAINT CHARACTER IF OTHER THAN SPACE
	KB_ECHO_NOECHO = 28				; SET NON ZERO IF INPUT IS NOT TO BE ECHOED
	KB_ECHO_DELIM = 32				; ASCII OF DELIMITER TO USE OTHER THAN <CR>

	KB_ECHO_ESCAPE = 36

	; MACRO TO DISPLAY A STRING ON THE SCREEN
	; ---------------------------------------

	.MACRO	DISPL STR_ADR,-			; ADDRESS OF STRING TO DISPLAY
			STR_LEN		   	; LENGTH OF STRING

	MOVL	#STR_LEN,WRITE_AREA+QIO$_P2	; SET UP WRITE AREA
	MOVAL	STR_ADR,WRITE_AREA+QIO$_P1
	TSTL	NO_ECHO
	BEQL	1$
	CLRL	WRITE_AREA+QIO$_P2
1$:	
	$QIOW_G	WRITE_AREA			; OUTPUT STRING
.ENDM

                   
	MOVW	#80,EDGE_OF_SCREEN			; ASSUME SCREEN EDGE IS AT COL 80
	MOVZWL	@KB_ECHO_LEN(AP),R0			; ADD TOGETHER THE COL AND THE LEN
	MOVZBL	@KB_ECHO_COL(AP),R1
	ADDL2	R1,R0					; INTO R0

	CMPW	R0, #81					; COMPARE WITH 81
	BLEQ	10$					; IF LESS OR EQUAL, THEN EDGE IS AT 80
	MOVW	#132, EDGE_OF_SCREEN			; OTHERWISE ASSUME ITS AT 132

10$:	
	MOVL	#IO$_READLBLK!IO$M_TRMNOECHO!IO$M_ESCAPE,READ_AREA+QIO$_FUNC
	CLRL	READ_AREA+QIO$_P3
	MOVAL	IN_TERM_DESC,READ_AREA+QIO$_P4

	MOVL	#IO$_TTYREADALL!IO$M_NOECHO,READ_PASS_AREA+QIO$_FUNC
	CLRL	READ_PASS_AREA+QIO$_P3

	MOVB	#32,OUT_SPACE

	CLRL	DELIM_MASK					; IF SET INDICATES PRIVATE DELIMITER MASK
	CLRL	NO_ECHO					; IF SET INDICATES NO ECHO

	; CHECK OUT WHATS REQUIRED FROM THE OPTIONAL PARAMETER LIST
	; ---------------------------------------------------------

	CMPL	(AP),#5
	BLSS	START_ECHO				; JUST 3 PARAMS - NO OPTIONS TO CHECK
	TSTL	KB_ECHO_TIME(AP)			; HAS TIME PARAMETER BEEN PASSED
	BEQL	20$					; NO  - CHECK NEXT PARAMETER

	TSTW	@KB_ECHO_TIME(AP)
	BEQL	20$
        
	; YES - GET THINGS TICKING
	BISL2	#IO$M_TIMED, READ_AREA+QIO$_FUNC	; SET THE TIMED BIT
	BISL2	#IO$M_TIMED, READ_PASS_AREA+QIO$_FUNC

	MOVZWL  @KB_ECHO_TIME(AP), READ_AREA+QIO$_P3	; FILL IN HOW LONG FOR
	MOVZWL  @KB_ECHO_TIME(AP), READ_PASS_AREA+QIO$_P3	

20$:
	CMPL	(AP),#7
	BLSS	START_ECHO				; JUST 5 PARAMETERS - SO START NOW
	TSTL	KB_ECHO_NOECHO(AP)			; IS INPUT NOT TO BE ECHOED
	BEQL	30$					; NO  - CHECK NEXT ONE

	MOVZBL	@KB_ECHO_NOECHO(AP),NO_ECHO
	BEQL	30$
	BISL2	#IO$M_NOECHO, READ_AREA+QIO$_FUNC

30$:
	CMPL	(AP),#8
	BLSS	START_ECHO				; JUST 6 PARAMETERS - SO START NOW
	TSTL	KB_ECHO_DELIM(AP)			; IS PRIVATE DELIMITER REQUIRED
	BEQL	START_ECHO				; NO  - CHECK NEXT ONE
	MOVL 	@KB_ECHO_DELIM(AP),DELIM_MASK           ; YES - DELIMITER

START_ECHO:
	; LOAD UP PROMPT STRING FOR SPECIFIED ROW AND COLUMN
	; --------------------------------------------------

	MOVL	BUFF_PTR,R3

	JSB	DISPLAY_PAINT				; INITIAL DISPLAY

	BISB2	#1,FLUSH_STATUS+1		; FORCE HIGH BYTE NON ZERO
	JSB	FLUSH_BUFFER_JSB		; FLUSH ANYWAY
	CLRB	FLUSH_STATUS+1			; "UNFORCE" FLUSHING


	MOVZWL	@KB_ECHO_LEN(AP),READ_AREA+QIO$_P2	; MOVE LENGTH OF INPUT TO READ AREA
READIT:
	$QIOW_G	READ_AREA				; DO READ FOR 'LEN' CHARS.
	BLBS	R0,50$					; WATCH OUT FOR ERRORS
	$EXIT_S	R0
	RET

50$:
	CMPW	IO_IOSB_STAT,#SS$_TIMEOUT
	BNEQ	51$
	BRW	TIMED_OUT
51$:
	MOVZWL	IO_IOSB_OFF,R8				; R8 CONTAINS THE NUMBER OF CHARACTERS SO FAR

	CMPW	IO_IOSB_STAT,#SS$_PARTESCAPE
	BNEQ	52$
	BRW	BUZZ_EM
52$:
	CMPW	IO_IOSB_STAT,#SS$_BADESCAPE
	BNEQ	53$
	BRW	BUZZ_EM
53$:
	TSTW	IO_IOSB_TERM				; WAS TERMINATOR IN BUFFER
	BEQL	READ_FOR_TERM				; NO  - DO READ FOR 1 CHAR
	CMPW	IO_IOSB_TERM,#127			; WAS TERMINATOR A DELETE
	BEQL	CHECK_DELETE				; YES - CHECK IT OUT
	BRW	TERM_IN_BUFF				; NO  - FAIRLY EASY

READ_FOR_TERM:
	$QIOW_G	READ_PASS_AREA				; 1 CHAR PASSALL READ
	BLBS	R0,60$
	$EXIT_S	R0
	RET

60$:	
	CMPW	IO_IOSB_STAT,#SS$_TIMEOUT
	BNEQ	61$
	BRW	TIMED_OUT

61$:	
	CMPB	IN_CHAR_BUFF,#13			; WAS CHAR A <CR>
	BNEQ	NOT_CR					; NO  - KEEP TESTING

	BRW	NORMAL_EXIT				; AND EXIT

NOT_CR:	
	CMPB	IN_CHAR_BUFF,#127			; DID WE GET A <DEL>
	BNEQ	NOT_DEL					; NO  - KEEP TESTING

CHECK_DELETE:
	TSTL	R8					; DELETE PRESSED WHITH NOTHING INPUT
	BNEQ	75$
	BRW	READIT					; BACK TO SQUARE ONE

75$:	
	MOVZBL	@KB_ECHO_COL(AP), R0			; START COLUMN IN R0
	ADDW2	R8,R0					; SO, R0 = CURRENT CURSOR POSN
	CMPW	R0,EDGE_OF_SCREEN			; ARE WE PAST EDGE OF SCREEN
	BLEQ	NORM_DEL				; NO  - DELETE AS USUAL
	DISPL	OUT_SPACE,1				; YES - JUST DISPLAY A SPACE
	BRB	END_DEL

NORM_DEL:
	DISPL	OUT_DEL, OUT_DEL_LEN			; DISPLAY <BS><SP><BS>
END_DEL:
	DECL	R8					; ONE LESS CHARACTER
	BNEQ	67$					; READ 1 MORE CHARACTER
	BRW	READIT					; IF COUNT IS 0 - BACK TO SQUARE 1
67$:	
	BRW	READ_FOR_TERM

NOT_DEL:
	MOVB	IN_CHAR_BUFF,IN_BUF[R8]			; STORE CHAR IN BUFFER
	MOVZBW	IN_CHAR_BUFF,IO_IOSB_TERM		; AND IN TERMINATOR FIELD OF IOSB
	CMPB	IN_CHAR_BUFF,#32			; IS CHAR PRINTABLE
	BLSS	CHECK_DELIMITER				; NO  - CHECK FOR PRIVATE DELIMITER
	CMPW	R8,@KB_ECHO_LEN(AP)			; YES - IS BUFFER ALREADY FULL
	BGEQ	BUZZ_EM					;       YES - <BUZZ>

	DISPL	IN_CHAR_BUFF, IN_CHAR_BUFLEN		; DISPLAY CHARACTER
10$:	
	INCL	R8					; INC CHARACTER COUNT
	BRW	READ_FOR_TERM				; READ 1 NORE CHAR

BUZZ_EM:
	MOVL	#OUT_BEL_LEN,WRITE_AREA+QIO$_P2		; SET UP WRITE AREA
	MOVAL	OUT_BEL,WRITE_AREA+QIO$_P1
	$QIOW_G	WRITE_AREA				; OUTPUT STRING
	BRW	READ_FOR_TERM				; AND READ 1 MORE CHAR

	; NORMAL STRING RETURN - HOPEFULLY
	; --------------------------------
	;	NB: For RDC purposes, escape sequences are NOT REQUIRED and
	;	    should be ignored/treated as if an invalid character had
	;	    been input. ie Bell them and CONTINUE with input of field.

TERM_IN_BUFF:
	CMPW	IO_IOSB_TERM,#13
	BEQL	NORMAL_EXIT
	TSTW	IO_IOSB_OFF				; DOES ANYTHING PRECEDE TERMINATOR
	BGTR	CHECK_DELIMITER				; YES - POSS NORMAL STRING RETURN
	CMPW	IO_IOSB_TERM,#27			; NO  - WAS TERM AN ESCAPE ?
	BEQL	ESCAPE					;	YES - SEE WHAT WE HAVE TO DO WITH ESCAPES

CHECK_DELIMITER:
	CMPW	IO_IOSB_TERM,#27			; IF TERM WAS AN <ESC>, THEN JUST IGNORE IT
	BEQL	10$					;	AND READ REMAINDER OF FIELD AGAIN
	MOVL	#1,R0					; JUST ONE BIT 
	ROTL	IO_IOSB_TERM,R0,R1			; MOVE THE BIT TO THE RIGHT
							; A NUMBER OF POSITIONS ACCORDING TO THE TERMINATOR
	BITL	R1,DELIM_MASK				; SEE IF THE RESULTANT BIT IS SET IN THE USER'S TERMINATOR MASK
	BNEQ	30$					; IF IT IS BRANCH AND COPY IT

							; DECIDE WHETHER TO READ WHOLE FIELD OR JUST TO LOOK FOR A TERMINATLR
10$:	TSTL	R8
	BEQL	20$					; BACK TO SQUARE ONE
	BRW	READ_FOR_TERM				; LOOK FOR A TERMINATOR
20$:	BRW	READIT

30$:	INCL	R8					; RETURN THE SPECIAL DELIMITER AS THE LAST CHARACTER IN THE RETURNED STRING

NORMAL_EXIT:
	PUSHAB	IN_BUF					; COPY RIGHT PART OF BUFFER 
	MOVW	R8,IN_LEN
	PUSHAW	IN_LEN					; TO RETURN STRING
	PUSHAQ	@KB_ECHO_RETURN(AP)
	CALLS	#3,G^STR$COPY_R
	BLBC	R0,70$
	BRW	KB_ECHO_EXIT				; AND EXIT
70$:	
	$EXIT_S	R0
	RET

	;----------------------------------------------------------------------
	;	Got a good escape sequence
ESCAPE:
	CMPL	(AP),#9					; THEY DONT WANT ESC. SEQ.
	BLSS	11$					; IF PARAMETER 9 NOT THERE

	TSTL	KB_ECHO_ESCAPE(AP)			; ALSO, IT HAS TO BE NON ZERO
	BEQL	11$

	MOVZWL	IO_IOSB_TSIZE, R8			; RETURN THE WHOLE SEQUENCE
	BRW	NORMAL_EXIT

11$:	BRW	BUZZ_EM

	;----------------------------------------------------------------------
	;	Got a timeout, so just return a nul  -  chr$(0)
TIMED_OUT:
	MOVW	#1,IN_LEN
	CLRB	IN_BUF
	PUSHAB	IN_BUF
	PUSHAW	IN_LEN
	PUSHAQ	@KB_ECHO_RETURN(AP)
	CALLS	#3,G^STR$COPY_R
	BRW	KB_ECHO_EXIT

KB_ECHO_EXIT:
	MOVL	R3,BUFF_PTR
	CLRL	R0
	RET

	;	p o s n _ c u r s
	;	-----------------
	;
	; JSB ENTRY POINT TYPE SUBROUTINE TO LOAD INTO THE STRING POINTED
	; TO BY R3 THE CORRECT ESCAPE SEQUENCE TO POSITION CURSOR AT 
	; '@COL(AP)', '@ROW(AP)'
	;
	; R1 = COL
	; R0 = ROW
	;
	; ON EXIT R3 - POINTS TO 1 BYTE BEYOND LAST CHARACTER WRITTEN
	; USES R0 AS A TEMPORARY
	;
	; -----------------------------------------------------------
        .PSECT	$CODE,NOWRT,PIC,SHR,LONG

TT$_VT200_SERIES = 110		; THESE VALUES ARE NOT DEFINED IN 
TT$_VT300_SERIES = 112		; THE SUPPLIED DEFINITION MACRO
TT$_VT400_SERIES = 113		; 


POSN_CURS::
	.JSB_ENTRY,INPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>,OUTPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

	CMPW	TT_TYPE,#DT$_VT52			; VT52 SEQUENCE ?
	BEQL	5$
	CMPW	TT_TYPE,#DT$_VT100			; use ansii style sequences for VT100/200/300
	BEQL	3$
	CMPW	TT_TYPE,#TT$_VT200_SERIES
	BEQL	3$
	CMPW	TT_TYPE,#TT$_VT300_SERIES
	BEQL	3$
	CMPW	TT_TYPE,#TT$_VT400_SERIES
	BNEQ	6$					; NO - DONT DO ANY POSITIONING

3$:	
	MOVB	#155,(R3)+				; MOVE <ESC> THEN INC POINTER3
	MOVB	#^A/[/,(R3)+				; MOVE '[' THEN INC POINTER3
							; VALUE OF ROW ALREADY IN R0
	BSBW	NUM_CONVERT				; CONVERTED STRING WILL BE PLACED AT (R3)
							; AND POINTER WILL BE INC. TO NEXT CHAR
	MOVB	#^A/;/,(R3)+				; MOVE ';'
	MOVL	R1,R0					; VALUE OF COL IN R0
	BSBW	NUM_CONVERT
	MOVB	#^A/H/,(R3)+
	RSB

5$:	
	MOVB	#155,(R3)+				; MOVE <ESC> THEN INC POINTER3
	MOVB	#89,(R3)+
	ADDB3	#31,R0,(R3)+				; ROW
	ADDB3	#31,R1,(R3)+				; COLUMN

6$:
	RSB

	; 	N U M _ C O N V E R T
	;	---------------------
	;
	; ROUTINE TO CONVERT A NUMBER IN THE RANGE 0 - 80 TO AN ASCII STRING
	;	R3 - DESTINATION ADDRESS OF STRING (INC. TO NEXT BYTE AFTER STRING WRITTEN)
	;	R0 - VALUE TO CONVERT
	;-------------------------------------------------------------------

NUM_CONVERT::
	.JSB_ENTRY,INPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>,OUTPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

	TSTL	R0			; watch out for -ve row/col
	BGEQ	10$
	MNEGL	R0,R0
10$:	
	CMPL	R0,#10					; LESS THAN 10 IS ONLY 1 CHAR
	BLSS	$210
	MOVW	NUM_TABLE[R0],(R3)+			; GET TWO BYTES FROM TABLE
	RSB

$210:	
	MOVB	NUM_TABLE[R0],(R3)+			; GET 1 BYTE FROM TABLE
	RSB


        .PSECT NUM_TABLE,LONG,SHR,GBL,PIC,NOEXE

NUM_TABLE:						; NOTE - FIRST 10 BYTES ARE FOR
	.ASCII	/0123456789          /			;	 SINGLE CHARACTER RETURN
	.ASCII	/10111213141516171819/			;	 NEXT 10 ARE JUST PADDING
	.ASCII	/20212223242526272829/			;	 SO THAT BYTES /10...../
	.ASCII	/30313233343536373839/			;	 START AT OFFSET = 20
	.ASCII	/40414243444546474849/
	.ASCII	/50515253545556575859/
	.ASCII	/60616263646566676869/
	.ASCII	/70717273747576777879/
	.ASCII	/80818283848586788889/
	.ASCII	/90919293949596979899/

	;	S E T _ T I M E R
	;	-----------------
	;
	;	JSB SUBROUTINE TO MODIFY THE QIO ARGUMENT LISTS TO ACCEPT 
	;	TIMED INPUT
	;	---------------------------------------------------------

        .PSECT $CODE,NOWRT,PIC,SHR,LONG

SET_TIMER:	
	.JSB_ENTRY,INPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>,OUTPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

	RSB

	;	S E T _ D E L I M
	;	-----------------
	;
	;	SET UP THE DELIMITER MASK IN DELIM_MASK
	;	--------------------------------

SET_DELIM:
	.JSB_ENTRY,INPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>,OUTPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
	RSB

	;	D I S P L A Y _ P A I N T
	;	-------------------------
	;
	;	R3 IS ASSUMED TO POINT TO THE NEXT LOCATION IN THE OUTPUT
	;	BUFFER (MUST HAVE CALLED POSN_CURS FIRST)
	;	R3 IS SAVED
	;	A STRING OF LEN PAINT CHARACTERS IS MOVED TO THE OUTPUT BUFFER
	;	--------------------------------------------------------------

DISPLAY_PAINT:
	.JSB_ENTRY,INPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>,OUTPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

	CVTBL	@KB_ECHO_ROW(AP),R0
	CVTBL	@KB_ECHO_COL(AP),R1
	JSB	POSN_CURS

	CMPL	(AP),#6
	BLSS	999$					; JUST 5 PARAMETERS - SPACE PAINT
	TSTL	KB_ECHO_PAINT(AP)			; IS PAINT CHARACTER REQUIRED
	BEQL	999$					; NO  - CHECK NEXT ONE

	CMPB	@KB_ECHO_PAINT(AP),#32			; SPACE PAINT CHARACTER IS CATERED FOR ANYWAY
	BEQL	999$

	MOVB	PAINT_CHARS,OUT_SPACE			; THIS IS WHAT TO DO IF  THEY PRESS DELETE
	BISL2	#IO$M_NOFILTR, READ_AREA+QIO$_FUNC	; SYSTEM WILL NOT PROCESS DELETE AUTOMATICALLY
	MOVAL	IN_TERM_DESC_DEL,READ_AREA+QIO$_P4	; DELETE WILL BE TREATED AS A TERMINATOR
	JSB	DP_TERMS

999$:
	RSB

	;	DP_TERMS
	;	--------
	;
	; JSB ENTRY POINT TYPE SUBROUTINE EXTRACTED FROM PAINT
	; TO AVOID BRANCHES OUT OF RANGE (quick fix DTW)
	;
	; -----------------------------------------------------------


DP_TERMS::
	.JSB_ENTRY,INPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>,OUTPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

	CMPW	TT_TYPE,#DT$_VT52			; only paint on VTxxx
	BEQL	15$
	CMPW	TT_TYPE,#DT$_VT100
	BEQL	15$
	CMPW	TT_TYPE,#TT$_VT200_SERIES
	BEQL	15$
	CMPW	TT_TYPE,#TT$_VT300_SERIES
	BEQL	15$
	CMPW	TT_TYPE,#TT$_VT400_SERIES
	BNEQ	20$ 					; NO PAINT CHARACTERS IF HARDCOPY

15$:	
	TSTL 	NO_ECHO					; ARE WE NOECHOING
	BNEQ	20$

	MOVAL	PAINT_CHARS,R8				; SET POINTER TO PAINTS
	MOVZWL	@KB_ECHO_LEN(AP),R6			; COUNT OF PAINT CHARACTERS TO DISPLAY

	JSB	OUTPUT_STRING				; OUTPUT IT

	CVTBL	@KB_ECHO_ROW(AP),R0
	CVTBL	@KB_ECHO_COL(AP),R1			; GET CURSOR BACK TO BEGINING
	JSB	POSN_CURS

20$:
	RSB
			

	;	O U T P U T _ S T R I N G
	;	-------------------------
	;
	; LOAD STRING INTO THE OUTPUT BUFFER, FLUSHING THE BUFFER IF NECESSARY.
	;
	; PARAMETERS:
	;   R6: LENGTH OF STRING TO BE OUTPUT. REDUCED ON EACH MOVE TO THE
	;	OUTPUT BUFFER TO REFLECT THE NUMBER OF CHARS YET TO BE OUTPUT
	;   R8: ADDRESS OF STRING TO BE OUTPUT. ADJUSTED IF THE STRING HAS TO
	;	BE MOVED IN MORE THAN ONE GO.
	;   R3: ADDRESS OF NEXT BYTE TO USE IN OUTPUT BUFFER. ADJUSTED AS
	;	CHARACTERS ARE MOVED TO THE BUFFER.
	;
	; REGISTER USAGE:
	;	R7 - COUNT OF CHARACTERS TO BE MOVED TO OUTPUT BUFFER
	;	R2 - COUNT OF CHARACTERS AVAILABLE IN OUTPUT BUFFER

OUTPUT_STRING::
	.JSB_ENTRY,INPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>,OUTPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

	MOVZBL	(R8),R7
	CMPB	#126,R7			; if first char of string is not a tilde
	BNEQ	10$			; then string doesn't need translating

	TSTW	LANG
	BEQL	5$
	MOVL	R3,BUFF_PTR
	JSB	LANG_CONV		; destroy's R3 using MOVC3
	MOVL	BUFF_PTR,R3
	BRW	10$

5$:	
	DECL	R6			; we're outputting english, so drop
	INCL	R8			; the tilde

10$:	
	MOVL	R6,R7			; DEFAULT TO LENGTH REQUIRED
	SUBL3	R3,#BUFF_END,R2		; BUT, DETERMINE SPACE AVAILABLE
	BLEQ	25$			; NEGATIVE RESULT
	CMPL	R7,R2			;      AND CHECK
	BLEQ	20$			; BRANCH IF SUFFICIENT SPACE

15$:	
	MOVL	R2,R7			; NOT ENOUGH, SO FIRST BITE
					;  IS LENGTH AVAILABLE

20$:	
	MOVC3	R7,(R8),(R3)		; MOVE R7 CHARS, FROM STRING TO O/P BUFF
	MOVL	R1,R8
					; ON COMPLETION, R8 = R8+R7, R3=R3+R7

	SUBL2	R7,R6			; R6 = NUMBER LEFT TO O/P	
	BEQL	999$			; IF NONE THEN PISS OFF

	JSB	FLUSH_BUFFER_JSB	; FLUSH BUFFER AS REQUIRED
	BRB	10$			; LOOP ROUND TO OUTPUT THE REST 

25$:	
	CLRL	R2			; NO SPACE IN BUFFER
	BRB	15$

999$:
	RSB

	; F L U S H _ B U F F E R _ J S B
	; -------------------------------
	;
	; IF THE BUFFER IS FULL OR FLUSHING IS REQUIRED EVERY TIME THIS
	; ROUTINE WRITES THE CONTENTS OF THE BUFFER TO THE SCREEN

FLUSH_BUFFER_JSB::
	.JSB_ENTRY,INPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>,OUTPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

	CMPL	#OUTPUT_STR,R3				; ANYTHING TO OUTPUT?
	BEQL	5$					; NO  - EXIT

	CMPL	R3,#BUFF_END
	BGEQ	FLUSH_IT

	TSTW	FLUSH_STATUS				; IS FLUSHING REQUIRED EVERY TIME
	BNEQ	FLUSH_IT				; YES
5$:	JMP	FLUSH_EXIT

FLUSH_IT:
	SUBL2	#OUTPUT_STR,R3		;  WORK OUT LENGTH OF STRING
	MOVW	R3,OLEN

	CMPW	TT_TYPE,#TT$_VT200_SERIES
	BEQL	10$
	CMPW	TT_TYPE,#TT$_VT300_SERIES
	BEQL	10$
	CMPW	TT_TYPE,#TT$_VT400_SERIES
	BNEQ	20$
10$:	PUSHAL	CSIDES			; on a VT200, VT300, or VT400, so replace
	PUSHAL	ODES			; CHR$(155%) with CHR$(27%)
	CALLS	#2,G^STR$POSITION	; and loop round to check for another.
	TSTL	R0
	BEQL	30$
	DECL	R0
	MOVB	#27,OUTPUT_STR[R0]
	BRW	10$
20$:	CMPB	CC_MODE,#4
	BNEQ	30$
	PUSHAL	ODES			; if this is a batch job, we need to
	CALLS	#1,TTOUT		;	PRINT #1%, ""
	BRW	40$

30$:	MOVAL	OUTPUT_STR,WRITE_AREA+QIO$_P1	; SET UP ADDRESS OF PROMPT FOR WRITE
	MOVZWL	OLEN,WRITE_AREA+QIO$_P2		; LENGTH OF STRING
	$QIOW_G	WRITE_AREA		

40$:	MOVAL	OUTPUT_STR,R3

FLUSH_EXIT:
	RSB





LANG_CONV: 
	.JSB_ENTRY,INPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>,OUTPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
	; DUMMY ONLY

	MOVZWL	(R1),ENGLEN
	DECL	ENGLEN	; note: English is one char too long (~)
	ADDL3	#1,4(R1),ENGADD

	MOVL	#-1,LA_LEN	; Let trnstr know to use our descriptor/string
	PUSHAL	ENGLISH
	PUSHAL	LA_DES
	CALLS	#2,G^TRNSTR

	MOVAL	LA_DES,R1		; point R1 to the new descriptor
	BRW	LANG_CONV_EXIT

LANG_CONV_EXIT:
	MOVL	LA_LEN,R6
	MOVAL	LA_STR,R8
	RSB

	; K B B E L L
	; -----------
	;
	;	SOUND THE BELL AT TERMINAL
	;
        .PSECT KBBELL,LONG,SHR,GBL,PIC,NOEXE

BELL:
	.BYTE	7

        .PSECT	$CODE,NOWRT,PIC,SHR,LONG

	.ENTRY KBBELL,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

	;
	; FORMAL PARAMETERS AND THEIR OFFSET FROM THE ARGUMENT POINTER
	;
	;	NONE

	MOVL	BUFF_PTR,R3			; GET POINTER FROM MAPPED AREA
		
	MOVL	#1,R6				; LENGTH OF STRING
	MOVAL	BELL,R8				; AND THEN POINTER TO STRING

	JSB	OUTPUT_STRING			; OUTPUT IT
	JSB	FLUSH_BUFFER_JSB		; FLUSH IF NECESSARY

	MOVL	R3,BUFF_PTR			; REMEMBER TO TO PUT BUFFER
						; POINTER BACK IN MAPPED AREA
	RET

	;	K B C A N C
	;	-----------
	;
	;	CANCEL TYPE AHEAD - FLUSH BUFFER FIRST
	;
        .PSECT	$CODE,NOWRT,PIC,SHR,LONG

	.ENTRY KBCANC,^M<R3>

	MOVL	BUFF_PTR, R3			; PASS OUTPUT BUFFER POINTER

	BISB2	#1,FLUSH_STATUS+1		; FORCE HIGH BYTE NON ZERO
	JSB FLUSH_BUFFER_JSB			; FLUSH ANYWAY
	CLRB	FLUSH_STATUS+1			; "UNFORCE" FLUSHING

	$QIOW_S	CHAN=TT_CHAN,-
		FUNC=#IO$_READVBLK!IO$M_PURGE!IO$M_NOECHO

	MOVAL	OUTPUT_STR, BUFF_PTR

	RET

	; KB Clear screen and portion of screen routines.
	; -----------------------------------------------

        .PSECT	$CODE,NOWRT,PIC,SHR,LONG

	.ENTRY KBCBOS,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
	;	CLEAR SCREEN FROM GIVEN COORDINATES TO BEGINING OF SCREEN

	MOVL	#4,R6
	MOVAL	VT100_BOS,R8
	CVTBL	@4(AP),R0	; row
	CVTBL	@8(AP),R1	; col
	JSB 	KBC_POSN
	RET

        .PSECT	$CODE,NOWRT,PIC,SHR,LONG

	.ENTRY KBCEOL,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
	;	CLEAR TO END OF LINE

	MOVL	#3,R6
	MOVAL	VT100_EOL,R8
	CVTBL	@4(AP),R0	; row
	CVTBL	@8(AP),R1	; col
	JSB 	KBC_POSN
	RET


        .PSECT	$CODE,NOWRT,PIC,SHR,LONG

	.ENTRY KBCEOS,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
	;	CLEAR TO END OF SCREEN

	MOVL	#3,R6
	MOVAL	VT100_EOS,R8
	CVTBL	@4(AP),R0	; row
	CVTBL	@8(AP),R1	; col
	JSB 	KBC_POSN
        RET


KBC_POSN::
	.JSB_ENTRY,INPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>,OUTPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

	MOVL	BUFF_PTR,R3			; GET POINTER FROM MAPPED AREA
	JSB	POSN_CURS
	JSB	KBC_CLEAR
	RSB


        .PSECT KBSCR,LONG,SHR,GBL,PIC,NOEXE

VT100_BOS:	.ASCII	<155>/[1J/
VT100_EOL:	.ASCII	<155>/[K/
VT100_EOS:	.ASCII	<155>/[J/
VT100_SCR:	.ASCII	<155>/[H/<155>/[J/

        .PSECT	$CODE,NOWRT,PIC,SHR,LONG

	.ENTRY KBCSCR,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
	;	CLEAR ENTIRE SCREEN AND LEAVE CURSOR AT 1,1

	MOVL	BUFF_PTR,R3			; GET POINTER FROM MAPPED AREA
	MOVL	#6,R6				; LENGTH OF STRING
	MOVAL	VT100_SCR,R8			; AND THEN POINTER TO STRING
	JSB 	KBC_CLEAR
	RET


KBC_CLEAR::					; O/P THE ACTUAL SCRN CLEAR
	.JSB_ENTRY,INPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>,OUTPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

	JSB	OUTPUT_STRING			;		ESC SEQ.
	JSB	FLUSH_BUFFER_JSB		; FLUSH IF NECESSARY

	MOVL	R3,BUFF_PTR			; REMEMBER TO TO PUT BUFFER
						; POINTER BACK IN MAPPED AREA
	RSB


	; K B E R R
	; ---------
        .PSECT	$CODE,NOWRT,PIC,SHR,LONG

	.CALL_ENTRY LABEL=KBERR,PRESERVE=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>,MAX_ARGS=64,HOME_ARGS=TRUE

	MOVL	#VT100_ERR_FIRST_LEN,R6		; LENGTH OF STRING
	JSB 	KBERRMESS	
	RET


	; K B M E S S
	; -----------
        .PSECT KBMESS,LONG,SHR,GBL,PIC,NOEXE

VT100_ERR_FIRST:
	.ASCII	<155>/7/<155>/[24;1H/<155>/[K/<155>/[1m/<7>
	;       store  ^  row 24    ^  clear ^  o/p    ^ BELL
	;       cursor ^     col 1  ^  line  ^ in bold ^
	;	pos+atts
VT100_ERR_FIRST_LEN=.-VT100_ERR_FIRST

VT100_ERR_LAST:
	.ASCII	<155>/8/		; restore cursor posn+attributes
VT100_ERR_LAST_LEN=.-VT100_ERR_LAST

        .PSECT	$CODE,NOWRT,PIC,SHR,LONG

	.CALL_ENTRY LABEL=KBMESS,PRESERVE=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>,MAX_ARGS=64,HOME_ARGS=TRUE

	MOVL	#VT100_ERR_FIRST_LEN-1,R6	; length of string (no BELL)
	JSB 	KBERRMESS	
	RET

KBERRMESS::
	.JSB_ENTRY,INPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>,OUTPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

	MOVAL	VT100_ERR_FIRST,R8		; POINTER TO STRING
	MOVL	BUFF_PTR,R3			; GET POINTER FROM MAPPED AREA

	JSB	OUTPUT_STRING			; OUTPUT IT

	MOVL	#1,R10
	JSB	KBSEND_LOOP

	MOVL	#VT100_ERR_LAST_LEN,R6		; LENGTH OF STRING
	MOVAL	VT100_ERR_LAST,R8		; AND THEN POINTER TO STRING

	JSB	OUTPUT_STRING			; OUTPUT IT
	JSB	FLUSH_BUFFER_JSB		; FLUSH IF NECESSARY

	MOVB	#-1,CC_KBSTAT1
	MOVL	R3,BUFF_PTR			; REMEMBER TO TO PUT BUFFER
						; POINTER BACK IN MAPPED AREA
	RSB

	; 	K B F L S H 
	; 	-----------
	;
	;
        .PSECT	$CODE,NOWRT,PIC,SHR,LONG

	.ENTRY KBFLSH,^M<R3,R6>

	;
	; FORMAL PARAMETERS AND THEIR OFFSET FROM THE ARGUMENT POINTER
	;
	KBFLSH_FLAG = 4				; STATUS FLAG

	MOVZWL	FLUSH_STATUS, R6

	MOVW	@KBFLSH_FLAG(AP),FLUSH_STATUS	; REMEMBER NEW STATUS
	BEQL	2$				; 0 - SET STATUS, BUT DONT FLUSH
	BGEQ	1$				; 1 - SET STATUS, AND FLUSH
						; -1 - DON'T CHANGE STATUS

	MOVW	R6,FLUSH_STATUS			; PUT IT BACK IF ITS FLUSH-NOW
	BISB2	#1,FLUSH_STATUS+1		; FORCE HIGH BYTE NON ZERO

1$:	MOVL	BUFF_PTR, R3			; PASS OUTPUT BUFFER POINTER

	JSB 	FLUSH_BUFFER_JSB		; FLUSH ANYWAY
	CLRB	FLUSH_STATUS+1			; "UNFORCE" FLUSHING

	MOVL 	R3, BUFF_PTR			; RETURN BUFFER POINTER TO MAP
2$:	MOVL	R6,R0				; RETURN OLD FLUSH STATUS

KBFLSH_EXIT:
	RET


	; K B L I N E
	; -----------
        .PSECT KBLINE,LONG,SHR,GBL,PIC,NOEXE

HORIZONTAL_LINE:
	.ASCII	<155>\(0\		; switch into graphics
	.BYTE	113[132]		; 132 * horizontal line

VERTICAL_LINE:
	.ASCII	<155>\(0\		; switch into graphics
			; now: vert line, BS, LF  (repeated 24 times)
	.BYTE	120,8,10,	120,8,10,	120,8,10
	.BYTE	120,8,10,	120,8,10,	120,8,10
	.BYTE	120,8,10,	120,8,10,	120,8,10
	.BYTE	120,8,10,	120,8,10,	120,8,10
	.BYTE	120,8,10,	120,8,10,	120,8,10
	.BYTE	120,8,10,	120,8,10,	120,8,10
	.BYTE	120,8,10,	120,8,10,	120,8,10
	.BYTE	120,8,10,	120,8,10,	120,8,10


NORMAL_ASCII:	
	.ASCII	<155>\(B\		; note: this for normal ASCII keyboard
					;   use ESC(A for ENGLISH kb (to output
					;   pound sign rather than hash)
					; taken from VT320 manual page 89.
        .PSECT	$CODE,NOWRT,PIC,SHR,LONG

	.ENTRY KBLINE,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

	;
	; FORMAL PARAMETERS AND THEIR OFFSET FROM THE ARGUMENT POINTER
	;
	KBLINE_ROW = 4				; ROW POSITION FOR INPUT
	KBLINE_COL = 8				; COLUMN POSITION FOR INPUT
	KBLINE_LEN = 12				; LINE OF LENGTH 'LENG'
						;  LINE HORIZONTAL IF > 0
						;  LINE VERTICAL IF < 0

	MOVL	BUFF_PTR,R3			; GET POINTER FROM MAPPED AREA
		
	CVTBL	@KBLINE_ROW(AP),R0		; PARAMETERS FOR POSN_CURS
	CVTBL	@KBLINE_COL(AP),R1		;      "      "      "
	JSB	POSN_CURS

	MOVZBL	@KBLINE_LEN(AP),R6		; LENGTH OF STRING
	TSTB	R6
	BLEQ	DO_VERTICAL

	ADDL2	#3,R6				; PLUS 3 CHARACTER 'GO GRAPHIC'
	MOVAL	HORIZONTAL_LINE,R8		; AND THEN POINTER TO STRING

	JSB	OUTPUT_STRING			; OUTPUT IT
	BRB	BACK_TO_NORMAL

DO_VERTICAL:
	MNEGB	R6,R6				; MAKE COUNT POSITIVE
	MULL2	#3,R6				; 3 CHARACTERS REQUIRED PER EACH
	INCL	R6				; PLUS 1 TO CATER FOR 'GO GRAPHIC'
	MOVAL	VERTICAL_LINE,R8		; AND THEN POINTER TO STRING
	JSB	OUTPUT_STRING

BACK_TO_NORMAL:				; NOW RESET KB TO ALPHA/NUM O/P
	MOVL	#3,R6				; LENGTH OF STRING

	MOVAL	NORMAL_ASCII,R8		; reset to ASCII l/case chars

	JSB	OUTPUT_STRING			; OUTPUT IT
	JSB	FLUSH_BUFFER_JSB		; FLUSH IF NECESSARY

	MOVL	R3,BUFF_PTR			; REMEMBER TO PUT BUFFER
						; POINTER BACK IN MAPPED AREA
	RET

	; K B P O S N
	; -----------
        .PSECT	$CODE,NOWRT,PIC,SHR,LONG

	.ENTRY KBPOSN,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

	;
	; FORMAL PARAMETERS AND THEIR OFFSET FROM THE ARGUMENT POINTER
	;
	KBPOSN_ROW = 4					; ROW POSITION FOR INPUT
	KBPOSN_COL = 8					; COLUMN POSITION FOR INPUT

	MOVL	BUFF_PTR,R3			; GET POINTER FROM MAPPED AREA
		
	CVTBL	@KBPOSN_ROW(AP),R0		; PARAMETERS FOR POSN_CURS
	CVTBL	@KBPOSN_COL(AP),R1		;      "      "      "
	JSB	POSN_CURS

	JSB	FLUSH_BUFFER_JSB		; FLUSH IF NECESSARY

	MOVL	R3,BUFF_PTR			; REMEMBER TO TO PUT BUFFER
						; POINTER BACK IN MAPPED AREA
	RET

	;	K B P R I N
	;	-----------
	;
        .PSECT	$CODE,NOWRT,PIC,SHR,LONG

	.CALL_ENTRY LABEL=KBPRIN,PRESERVE=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>,MAX_ARGS=64,HOME_ARGS=TRUE

	MOVL	BUFF_PTR,R3			; POINTER TO NEXT BYTE IN BUFFER
	MOVL	#1,R10				; OFFSET OF FIRST STRING FROM AP

10$:
	CMPL	R10,(AP)			; ANY STRINGS LEFT?
	BGTR	999$				; NO - EXIT
	MOVL	(AP)[R10],R1			; GET ADDRESS OF CURRENT STRING INR1
	INCL	R10				; NEXT STRING POINTER
	MOVZWL	(R1),R6				; STRING LENGTH
	BEQL	10$				; ignore null strings
	MOVL	4(R1),R8			; STRING POINTER
	JSB	OUTPUT_STRING			; OUTPUT IT
	BRB	10$				; TRY NEXT ONE

999$:
	JSB	FLUSH_BUFFER_JSB		; FLUSH IF NECESSARY
	MOVL	R3,BUFF_PTR			; PUT POINTER BACK
	RET

	; K B S C R O
	; -----------
        .PSECT KBSCRO,LONG,SHR,GBL,PIC,NOEXE
	
VT100_SCRO:
	.ASCII	/r/
        
	.PSECT	$CODE,NOWRT,PIC,SHR,LONG

	.ENTRY KBSCRO,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

	;
	; FORMAL PARAMETERS AND THEIR OFFSET FROM THE ARGUMENT POINTER
	;
	KBSCRO_TOP = 4					; ROW POSITION FOR INPUT
	KBSCRO_BOT = 8					; COLUMN POSITION FOR INPUT

	TSTB	CC_MODE
	BNEQ	KBSCRO_EXIT			;   teletype and detached jobs.

	MOVL	BUFF_PTR,R3			; GET POINTER FROM MAPPED AREA
		
	CVTBL	@KBSCRO_TOP(AP),R0		; PARAMETERS FOR POSN_CURS
	CVTBL	@KBSCRO_BOT(AP),R1		;      "      "      "
	JSB	POSN_CURS

	SUBL2	#1,R3

	MOVL	#1,R6				; LENGTH OF STRING
	MOVAL	VT100_SCRO,R8			; AND THEN POINTER TO STRING

	JSB	OUTPUT_STRING			; OUTPUT IT
	JSB	FLUSH_BUFFER_JSB		; FLUSH IF NECESSARY

	MOVL	R3,BUFF_PTR			; REMEMBER TO TO PUT BUFFER

						; POINTER BACK IN MAPPED AREA
KBSCRO_EXIT:
	CLRL	R0
	RET


	; K B S E N D
	; -----------
        .PSECT	$CODE,NOWRT,PIC,SHR,LONG

	.CALL_ENTRY LABEL=KBSEND,PRESERVE=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>,MAX_ARGS=64,HOME_ARGS=TRUE

	MOVL	BUFF_PTR,R3		; GET POINTER FROM MAPPED AREA
		
	CVTBL	@4(AP),R0		; PARAMETERS FOR POSN_CURS
	CVTBL	@8(AP),R1		;      "      "      "
	JSB	POSN_CURS
	MOVL	R3,BUFF_PTR		; PUT BUFFER POINTER BACK IN MAPPED AREA

	MOVL	#3,R10			; look at 3rd argument (and 4th?)
	JSB	KBSEND_LOOP
	RET


KBSEND_LOOP::
	.JSB_ENTRY,INPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>,OUTPUT=<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>

5$:
	MOVL	(AP)[R10],R1			; GET ADDR OF CURR STRING DESC IN R1
	INCL	R10

	MOVZWL	(R1),R6			; LENGTH OF STRING
	BEQL	10$			;    ignore null strings
	MOVL	4(R1),R8		; ADDRESS OF STRING

	JSB	OUTPUT_STRING		; OUTPUT IT
10$:	
	CMPL	R10,(AP)
	BLEQ	5$
	JSB	FLUSH_BUFFER_JSB	; FLUSH IF NECESSARY
	MOVL	R3,BUFF_PTR		; PUT BUFFER POINTER BACK IN MAPPED AREA
	RSB


	.END
; DEC/CMS REPLACEMENT HISTORY, Element KBIO.MAR
; *1    20-OCT-1992 15:15:04 ANSELLG "Macro Source"
; DEC/CMS REPLACEMENT HISTORY, Element KBIO.MAR
; CMS REPLACEMENT HISTORY, Element KBIO.MAR
; *1    10-MAR-2009 19:15:47 TOWNLEYC "Initial IA64 insertion"
; CMS REPLACEMENT HISTORY, Element KBIO.MAR
This one doesn't look as easy!

Code is currently compiled with:
MACRO/LIST='LOCATION'/OBJ='START_DIRECTORY'
--
Chris


hb
Valued Contributor
Posts: 79
Joined: Mon May 01, 2023 12:11 pm
Reputation: 0
Status: Offline

Re: X86 Macro compiler/LLVM error

Post by hb » Thu Apr 18, 2024 9:18 am

You have to look for identical names for PSECTs and label/entries. A quick

Code: Select all

$ grep -i '\.psect' big.mar |awk '{print $2}' |awk -F, '{print $1}' |sort -u
$CODE
CORCOM
KBBELL
KBIOMP
KBIOMP2
KBIOMP3
KBIOREAD
KBIOWK
KBLINE
KBMESS
KBSCR
KBSCRO
LANG_TRN
NUM_TABLE
$
$ grep '\$CODE:\|CORCOM:\|KBBELL:\|KBIOMP:\|KBIOMP2:\|KBIOMP3:\|KBIOREAD:\|KBIOWK:\|KBLINE:\|KBMESS:\|KBSCR:\|KBSCRO:\|LANG_TRN:\|NUM_TABLE:' big.mar 
NUM_TABLE:                                              ; NOTE - FIRST 10 BYTES ARE FOR
$
indicates that you only have to change NUM_TABLE.


hb
Valued Contributor
Posts: 79
Joined: Mon May 01, 2023 12:11 pm
Reputation: 0
Status: Offline

Re: X86 Macro compiler/LLVM error

Post by hb » Thu Apr 18, 2024 9:28 am

simon wrote:
Wed Apr 17, 2024 9:34 pm
One issue is that sometimes the PSECT name is fixed by another party. An example of this is RDB$MESSAGE_VECTOR. We cant change the names. But we have a Macro32 module which provides mapping onto this for us. In this case we cannot change the names.
So you have a MACRO32 source with a PSECT named RDB$MESSAGE_VECTOR to match a given PSECT and you have a symbol RDB$MESSAGE_VECTOR - otherwise you would not see the reported llvm error. Can you change the symbol in your source? Or is this also something you have to match? In MACRO32 that is a label or code entry. (This looks like Oracle rdb. I would expect that they experience the same problem on x86 if they require an identical name for a PSECT and a symbol.)

If you are desperate and really need both, the symbol name and the PSECT name to be identical, you can change one of them in your source module, compile it and patch the object file to make them identical again. I do not suggest to do this. Patching an object file has its own challenges. But this should work, because same names work on IA64, which uses ELF, and ELF allows identical names for sections and symbols.

User avatar

Topic author
cct
Master
Posts: 128
Joined: Sat Aug 15, 2020 9:00 am
Reputation: 0
Location: Cambridge, UK
Status: Offline

Re: X86 Macro compiler/LLVM error

Post by cct » Thu Apr 18, 2024 2:33 pm

hb wrote:
Thu Apr 18, 2024 9:18 am
You have to look for identical names for PSECTs and label/entries. A quick

Code: Select all

$ grep -i '\.psect' big.mar |awk '{print $2}' |awk -F, '{print $1}' |sort -u
$CODE
CORCOM
KBBELL
KBIOMP
KBIOMP2
KBIOMP3
KBIOREAD
KBIOWK
KBLINE
KBMESS
KBSCR
KBSCRO
LANG_TRN
NUM_TABLE
$
$ grep '\$CODE:\|CORCOM:\|KBBELL:\|KBIOMP:\|KBIOMP2:\|KBIOMP3:\|KBIOREAD:\|KBIOWK:\|KBLINE:\|KBMESS:\|KBSCR:\|KBSCRO:\|LANG_TRN:\|NUM_TABLE:' big.mar 
NUM_TABLE:                                              ; NOTE - FIRST 10 BYTES ARE FOR
$
indicates that you only have to change NUM_TABLE.
Oops - I posted the version where I had (I thought) removed all duplicates, but I missed NUM_TABLE

Is the 2nd NUM_TABLE just a label, or does it link the table to the psect? Do I actually need the label?

BTW do you have a working grep on X86? I so far only found Hunters one from 1992
--
Chris


hb
Valued Contributor
Posts: 79
Joined: Mon May 01, 2023 12:11 pm
Reputation: 0
Status: Offline

Re: X86 Macro compiler/LLVM error

Post by hb » Thu Apr 18, 2024 6:04 pm

cct wrote:
Thu Apr 18, 2024 2:33 pm
Is the 2nd NUM_TABLE just a label, or does it link the table to the psect? Do I actually need the label?
I don't know anything about the code. If you search for NUM_TABLE in this source, you will find that it is used. It is a local label/symbol. It can't be found from other modules. The PSECT is not OVR, so changing the PSECT name should not affect anything else - except someone thought of using linker options for this PSECT.
BTW do you have a working grep on X86? I so far only found Hunters one from 1992
No.

User avatar

arne_v
Master
Posts: 348
Joined: Fri Apr 17, 2020 7:31 pm
Reputation: 0
Location: Rhode Island, USA
Status: Offline
Contact:

Re: X86 Macro compiler/LLVM error

Post by arne_v » Thu Apr 18, 2024 6:52 pm

GNV seems to have a grep last modified in 2016.

https://sourceforge.net/projects/gnv/files/grep/

Alpha and Itanium - not x86-64.

But as usual it could be worth trying to build it - it may work!

Added in 3 minutes 24 seconds:
But even better Jouk has a grep that has been build on on VMS x86-64.

http://galop.nano.tudelft.nl/openvms/software1.html

go down to grep and download.
Arne
arne@vajhoej.dk
VMS user since 1986

User avatar

Topic author
cct
Master
Posts: 128
Joined: Sat Aug 15, 2020 9:00 am
Reputation: 0
Location: Cambridge, UK
Status: Offline

Re: X86 Macro compiler/LLVM error

Post by cct » Thu Apr 18, 2024 7:30 pm

I am sure that jouk does a great job, but you go to grep, download the main release, then hid patch. There are dependencies, so you click on that, which as 4 more...

I gave up at that point.

This is surely not the way to encourage using opensource software
--
Chris

User avatar

arne_v
Master
Posts: 348
Joined: Fri Apr 17, 2020 7:31 pm
Reputation: 0
Location: Rhode Island, USA
Status: Offline
Contact:

Re: X86 Macro compiler/LLVM error

Post by arne_v » Thu Apr 18, 2024 8:03 pm

It is open source.

Anybody that prefer a different packaging are free to create their own packaging.
Arne
arne@vajhoej.dk
VMS user since 1986

Post Reply