.MACRO	DEF_PSECT PSECT_NAME, TYPE=CODE, ALIGNMENT=PAGE

	.IF BLANK PSECT_NAME
	  .ERROR 0;DEF_PSECT -- name is blank;
	  .MEXIT
	.ENDC

	__TYPE_OK=1

	.IF IDENTICAL <TYPE>,<CODE>
	  __TYPE_OK=0
	  .PSECT PSECT_NAME PIC,USR,CON,REL,GBL,SHR,EXE,RD,NOWRT,'ALIGNMENT'
	.ENDC

	.IF IDENTICAL <TYPE>,<DATA>
	  __TYPE_OK=0
	  .PSECT PSECT_NAME PIC,USR,CON,REL,GBL,NOSHR,NOEXE,RD,WRT,'ALIGNMENT'
	.ENDC

	.IF IDENTICAL <TYPE>,<DATA_SHR>
	  __TYPE_OK=0
	  .PSECT PSECT_NAME PIC,USR,CON,REL,GBL,SHR,NOEXE,RD,WRT,'ALIGNMENT'
	.ENDC

	.IF IDENTICAL <TYPE>,<COMMON>
	  __TYPE_OK=0
	  .PSECT PSECT_NAME PIC,USR,OVR,REL,GBL,SHR,NOEXE,RD,WRT,'ALIGNMENT'
	.ENDC

	.IF IDENTICAL <TYPE>,<RO_DATA>
	  __TYPE_OK=0
	  .PSECT PSECT_NAME PIC,USR,CON,REL,GBL,SHR,NOEXE,RD,NOWRT,'ALIGNMENT'
	.ENDC

	.IF NOT_EQUAL __TYPE_OK
	  .ERROR 0;DEF_PSECT -- PSECT must be CODE,DATA,DATA_SHR,COMMON or RO_DATA;
	.ENDC

.ENDM	DEF_PSECT

.MACRO	SET_PSECT PSECT_NAME, SAVE_CONTEXT

	.IF BLANK PSECT_NAME
	  .ERROR 0;SET_PSECT -- name is blank;
	  .MEXIT
	.ENDC

	.IF NOT_DEFINED __PS_LEVEL
	  __PS_LEVEL=0
	.ENDC

	.IF BLANK SAVE_CONTEXT
	  .SAVE_PSECT
	.ENDC
	.IF NOT_BLANK SAVE_CONTEXT
	  .SAVE_PSECT LOCAL_BLOCK
	.ENDC
	.PSECT	PSECT_NAME
	__PS_LEVEL=__PS_LEVEL+1

.ENDM	SET_PSECT

.MACRO	RESET_PSECT

	.IF NOT_DEFINED __PS_LEVEL
	  .ERROR 0;RESET_PSECT -- attempt to RESET psect without a SET;
	  .MEXIT
	.ENDC
	.IF EQUAL __PS_LEVEL
	  .ERROR 0;RESET_PSECT -- too many resets;
	  .MEXIT
	.ENDC

	__PS_LEVEL=__PS_LEVEL-1
	.RESTORE_PSECT

.ENDM	RESET_PSECT

.MACRO	DISPLAY DESCRIPTOR

	.IF BLANK DESCRIPTOR
	  .ERROR 0;DISPLAY -- nothing to display;
	  .MEXIT
	.ENDC

	.EXTERNAL LIB$PUT_OUTPUT

	PUSHAQ	DESCRIPTOR
	CALLS	#1, G^LIB$PUT_OUTPUT

.ENDM	DISPLAY

.MACRO	ASK FROM=INPUT, PROMPT_STRING=, RESULT_STRING=, RESULT_LENGTH=, FLAGS=

	.IF DIFFERENT <FROM>,<INPUT>
	  .IF DIFFERENT <FROM>,<COMMAND>
	    .IF DIFFERENT <FROM>,<FOREIGN>
	      .ERROR 0;ASK -- input source must be INPUT,COMMAND or FOREIGN;
	      .MEXIT
	    .ENDC
	  .ENDC
	.ENDC
	.IF BLANK PROMPT_STRING
	  .ERROR 0;ASK -- input prompt string missing;
	  .MEXIT
	.ENDC
	.IF BLANK RESULT_STRING
	  .ERROR 0;ASK -- input result string missing;
	  .MEXIT
	.ENDC
	.IF BLANK RESULT_LENGTH
	  .ERROR 0;ASK -- input result length missing;
	  .MEXIT
	.ENDC

	.EXTERNAL LIB$GET_'FROM

	__ARG_COUNT=3

	.IF IDENTICAL <FROM>,<FOREIGN>
	  .IF NOT_BLANK FLAGS
	    PUSHAL  FLAGS
	    __ARG_COUNT=4
	  .ENDC
	.ENDC

	PUSHAW	RESULT_LENGTH
	PUSHAL	PROMPT_STRING
	PUSHAL	RESULT_STRING
	CALLS	#__ARG_COUNT, G^LIB$GET_'FROM

.ENDM	ASK

.MACRO	DO COMMAND

	.IF BLANK COMMAND
	  .ERROR 0;DO -- nothing to do...;
	  .MEXIT
	.ENDC

	.EXTERNAL LIB$DO_COMMAND

	PUSHAL  COMMAND
	CALLS   #1, G^LIB$DO_COMMAND

.ENDM	DO

.MACRO	RUN PROGRAM

	.IF BLANK PROGRAM
	  .ERROR 0;RUN -- nothing to run...;
	  .MEXIT
	.ENDC

	.EXTERNAL LIB$RUN_PROGRAM

	PUSHAL  PROGRAM
	CALLS   #1, G^LIB$RUN_PROGRAM

.ENDM	RUN

.MACRO	SPAWN COMMAND

	.EXTERNAL LIB$SPAWN

	.IF BLANK COMMAND
	  CALLS   #0, G^LIB$SPAWN
	.IF_FALSE
	  PUSHAL  COMMAND
	  CALLS   #1, G^LIB$SPAWN
	.ENDC

.ENDM	SPAWN

.MACRO	WAIT SECONDS

	.IF BLANK SECONDS
	  .ERROR 0;WAIT -- no wait time specified;
	  .MEXIT
	.ENDC

	.EXTERNAL LIB$WAIT

	PUSHAF  SECONDS
	CALLS   #1, G^LIB$WAIT

.ENDM	WAIT

.MACRO	ALLOC_STRING STRING=, BYTE_COUNT=, GBL=NOGLOBAL

	.IF BLANK STRING
	  .ERROR 0;ALLOC_STRING -- no name given;
	  .MEXIT
	.ENDC
	.IF BLANK BYTE_COUNT
	  .ERROR 0;ALLOC_STRING -- no byte count given;
	  .MEXIT
	.ENDC

	.IF IDENTICAL <GBL>,<GLOBAL>
	.LIST
STRING'_S==BYTE_COUNT
STRING'_T::	.BLKB	STRING'_S
STRING::	.LONG	STRING'_S
		.ADDRESS STRING'_T
STRING'_DS::	.LONG	STRING'_S
		.ADDRESS STRING'_T
	.NLIST
	.IF_FALSE
	.LIST
STRING'_S=BYTE_COUNT
STRING'_T:	.BLKB	STRING'_S
STRING:		.LONG	STRING'_S
		.ADDRESS STRING'_T
STRING'_DS:	.LONG	STRING'_S
		.ADDRESS STRING'_T
	.NLIST
	.ENDC

.ENDM	ALLOC_STRING

.MACRO	FIND_LENGTH STRING

	.IF BLANK STRING
	  .ERROR 0;FIND_LENGTH -- no name given;
	  .MEXIT
	.ENDC

	.EXTERNAL STR_LEN

	PUSHAQ	STRING'_DS
	CALLS	#1, G^STR_LEN
	MOVL	R0, STRING

.ENDM	FIND_LENGTH

.MACRO	CONCAT DEST=, S1, S2, S3, S4, S5, S6, S7

	.IF BLANK DEST
	  .ERROR 0;CONCAT -- destination required;
	  .MEXIT
	.ENDC
	.IF BLANK S1
	  .ERROR 0;CONCAT -- at least one source string required;
	  .MEXIT
	.ENDC

	.EXTERNAL STR$CONCAT

	__ARG_COUNT=1

	.IRP	S_NAME, <S7,S6,S5,S4,S3,S2,S1>
	  .IF NOT_BLANK S_NAME
	    PUSHAQ  S_NAME
	    __ARG_COUNT=__ARG_COUNT+1
	  .ENDC
	.ENDR

	PUSHAQ	DEST'_DS
	CALLS	#__ARG_COUNT, G^STR$CONCAT
	FIND_LENGTH DEST

.ENDM	CONCAT

.MACRO	COLLAPSE DEST=, SOURCE=

	.IF BLANK DEST
	  .ERROR 0;COLLAPSE -- destination required;
	  .MEXIT
	.ENDC

	.EXTERNAL STR_COLLAPSE

	.IF BLANK SOURCE
	  PUSHAQ  DEST'_DS
	.IF_FALSE
	  PUSHAQ  SOURCE
	.ENDC

	PUSHAQ	DEST'_DS
	CALLS	#2, G^STR_COLLAPSE
	FIND_LENGTH DEST

.ENDM	COLLAPSE

.MACRO	AOBLEQ_W LIMIT, INDEX, DEST, ?INT, ?NEXT
	AOBLEQ	LIMIT, INDEX, INT
	BRB	NEXT
INT:	BRW	DEST
NEXT:
.ENDM	AOBLEQ_W

.MACRO	AOBLSS_W LIMIT, INDEX, DEST, ?INT, ?NEXT
	AOBLSS	LIMIT, INDEX, INT
	BRB	NEXT
INT:	BRW	DEST
NEXT:
.ENDM	AOBLSS_W

.MACRO	BBCCI_W POS, BASE, DEST, ?INT, ?NEXT
	BBCCI	POS, BASE, INT
	BRB	NEXT
INT:	BRW	DEST
NEXT:
.ENDM	BBCCI_W

.MACRO	BBCC_W POS, BASE, DEST, ?NEXT
	BBSC	POS, BASE, NEXT
	BRW	DEST
NEXT:
.ENDM	BBCC_W

.MACRO	BBCS_W POS, BASE, DEST, ?NEXT
	BBSS	POS, BASE, NEXT
	BRW	DEST
NEXT:
.ENDM	BBCS_W

.MACRO	BBC_W POS, BASE, DEST, ?NEXT
	BBS	POS, BASE, NEXT
	BRW	DEST
NEXT:
.ENDM	BBC_W

.MACRO	BBSC_W POS, BASE, DEST, ?NEXT
	BBCC	POS, BASE, NEXT
	BRW	DEST
NEXT:
.ENDM	BBSC_W

.MACRO	BBSSI_W POS, BASE, DEST, ?INT, ?NEXT
	BBSSI	POS, BASE, INT
	BRB	NEXT
INT:	BRW	DEST
NEXT:
.ENDM	BBSSI_W

.MACRO	BBSS_W POS, BASE, DEST, ?NEXT
	BBCS	POS, BASE, NEXT
	BRW	DEST
NEXT:
.ENDM	BBSS_W

.MACRO	BBS_W POS, BASE, DEST, ?NEXT
	BBC	POS, BASE, NEXT
	BRW	DEST
NEXT:
.ENDM	BBS_W

.MACRO	BCC_W DEST, ?NEXT
	BCS	NEXT
	BRW	DEST
NEXT:
.ENDM	BCC_W

.MACRO	BCS_W DEST, ?NEXT
	BCC	NEXT
	BRW	DEST
NEXT:
.ENDM	BCS_W

.MACRO	BEQLU_W DEST, ?NEXT
	BNEQU	NEXT
	BRW	DEST
NEXT:
.ENDM	BEQLU_W

.MACRO	BEQL_W DEST, ?NEXT
	BNEQ	NEXT
	BRW	DEST
NEXT:
.ENDM	BEQL_W

.MACRO	BGEQU_W DEST, ?NEXT
	BLSSU	NEXT
	BRW	DEST
NEXT:
.ENDM	BGEQU_W

.MACRO	BGEQ_W DEST, ?NEXT
	BLSS	NEXT
	BRW	DEST
NEXT:
.ENDM	BGEQ_W

.MACRO	BGTRU_W DEST, ?NEXT
	BLEQU	NEXT
	BRW	DEST
NEXT:
.ENDM	BGTRU_W

.MACRO	BGTR_W DEST, ?NEXT
	BLEQ	NEXT
	BRW	DEST
NEXT:
.ENDM	BGTR_W

.MACRO	BLBC_W SRC, DEST, ?NEXT
	BLBS	SRC, NEXT
	BRW	DEST
NEXT:
.ENDM	BLBC_W

.MACRO	BLBS_W SRC, DEST, ?NEXT
	BLBC	SRC, NEXT
	BRW	DEST
NEXT:
.ENDM	BLBS_W

.MACRO	BLEQU_W DEST, ?NEXT
	BGTRU	NEXT
	BRW	DEST
NEXT:
.ENDM	BLEQU_W

.MACRO	BLEQ_W DEST, ?NEXT
	BGTR	NEXT
	BRW	DEST
NEXT:
.ENDM	BLEQ_W

.MACRO	BLSSU_W DEST, ?NEXT
	BGEQU	NEXT
	BRW	DEST
NEXT:
.ENDM	BLSSU_W

.MACRO	BLSS_W DEST, ?NEXT
	BGEQ	NEXT
	BRW	DEST
NEXT:
.ENDM	BLSS_W

.MACRO	BNEQU_W DEST, ?NEXT
	BEQLU	NEXT
	BRW	DEST
NEXT:
.ENDM	BNEQU_W

.MACRO	BNEQ_W DEST, ?NEXT
	BEQL	NEXT
	BRW	DEST
NEXT:
.ENDM	BNEQ_W

.MACRO	BVC_W DEST, ?NEXT
	BVS	NEXT
	BRW	DEST
NEXT:
.ENDM	BVC_W

.MACRO	BVS_W DEST, ?NEXT
	BVC	NEXT
	BRW	DEST
NEXT:
.ENDM	BVS_W

.MACRO	SOBGEQ_W INDEX, DEST, ?INT, ?NEXT
	SOBGEQ	INDEX, INT
	BRB	NEXT
INT:	BRW	DEST
NEXT:
.ENDM	SOBGEQ_W

.MACRO	SOBGTR_W INDEX, DEST, ?INT, ?NEXT
	SOBGTR	INDEX, INT
	BRB	NEXT
INT:	BRW	DEST
NEXT:
.ENDM	SOBGTR_W
