;MASTER CATALOG UPDATE - UCAT.ASM
;01/07/78 BY WARD CHRISTENSEN
;01/10/78 ADD:
; 01/12/81 W. EARNEST MOD FOR CPM 2.X,
; ADD USER NR FIELD SUPPORT.
;		(RUN UCAT)
;		ERA MAST.BAK
;		REN MAST.BAK=MAST.CAT
;		REN MAST.CAT=NEW.CAT
;		ERA NAMES.SUB
	ORG	100H
BSIZE	EQU	4096	;DK BUF SIZE (TIMES 3)
IGNSIZE	EQU	1024	;BUFF FOR IGNORED NAMES
DFCB	EQU	5CH	;CMD FILE NAME
TEST	EQU	0	;TESTING?
	MACLIB	SEQIO
FILERR	SET	EXIT	;EXIT IF ERRORS
MOVE	MACRO	?F,?T,?L
	MVI	B,?L
	LXI	D,?F
	LXI	H,?T
	CALL	MOVER
	ENDM
COMPARE	MACRO	?F1,?F2,?L
	MVI	B,?L
	LXI	D,?F1
	LXI	H,?F2
	CALL	COMPR
	ENDM
;
;SAVE CP/M'S STACK
;
	POP	H	;GET CP/M RET ADDR
	SHLD	EXIT+1	;SAVE IN EXIT JMP
	LXI	SP,STACK
	FILE	INFILE,MASTIN,,MAST,CAT,BSIZE
	FILE	INFILE,NAMES,,NAMES,SUB,BSIZE
	IF	NOT TEST
	FILE	OUTFILE,MASTOUT,,NEW,CAT,BSIZE
	ENDIF
	FILE	SETFILE,BAK,,MAST,BAK
;
;SETUP THE FILES
;
INITRD	CALL	READNA	;READ NAMES FILE
;
;IF NAME IS $$$.SUB THEN SKIP IT
;
	COMPARE	NADAT,SUBNAME,12
	JZ	INITRD
;
;CHECK FOR '-DISKNAME' HAVING BEEN READ
;
	LDA	NADAT
	CPI	'-'
	JZ	NAMEOK
	LDA	DFCB+2
	CPI	'-'
	JNZ	NODASH
	LDA	DFCB+10
	CPI	' '
	JNZ	CMDNAM
	CALL	MSGXIT
	DB	'++SERIAL MUST BE 3 DIGITS$'
CMDNAM	MOVE	DFCB+2,DKNAME,7
	MOVE	DFCB+8,DKNAME+9,3
	JMP	GETIGN
;
NODASH	CALL	MSGXIT
	DB	'++NO ''-NAME.NNN'' IN NAMES.SUB'
	DB	0DH,0AH
	DB	'++REISSUE: UCAT -NAME.NNN$'
;
NAMEOK	MOVE	NADAT+1,DKNAME,7
	MOVE	NADAT+9,DKNAME+9,3
;
;READ IN THE NAMES TO BE IGNORED (I.E. NOT
;CATALOGED).  THEY ARE AT THE FRONT OF MAST CAT.
;THEY ARE SIMPLY A LIST OF FILENAME.FILETYPE (CR/LF)
;WITH THE FIRST HAVING A ( BEFORE IT, AND THE
;LAST HAVING A ) AFTER IT.
;
GETIGN	GET	MASTIN	;GET THE LEADING '('
	JZ	NOIGN	;IF EOF
	CPI	'('
	JNZ	NOIGN
	PUT	MASTOUT
	LXI	H,IGNORE ;POINT TO BUFFER
	LXI	B,IGNSIZE ;FOR BUFFER OVERFLOW TEST
IGNRD	PUSH	B
	PUSH	H
	GET	MASTIN
	JZ	IGNEOF	;UNEXPECTED EOF
	PUSH	PSW	;SAVE CHAR
	PUT	MASTOUT
	POP	PSW
	POP	H
	POP	B
	MOV	M,A
	INX	H
	CPI	')'
	JZ	IGNEND	;TABLE IS LOADED
	DCX	B	;MORE ROOM IN TABLE?
	MOV	A,B
	ORA	C
	JNZ	IGNRD
;TABLE OVERFLOW
	CALL	MSGXIT
	DB	'++TOO MANY IGNORE NAMES FOR TABLE$'
NOIGN	CALL	MSGXIT
	DB	'++NO IGNORE NAMES IN MAST.CAT$'
IGNEOF	CALL	MSGXIT
	DB	'++EOF READING FOR IGNORE NAMES.'
	DB	0DH,0AH,'MAY BE MISSING ) AFTER LAST NAME.$'
IGNEND	GET	MASTIN
	JZ	IGNEOF
	PUSH	PSW
	PUT	MASTOUT
	POP	PSW
	CPI	0AH
	JNZ	IGNEND	;DELETE CR/LF
	JMP	MASTLP	;LEAVE DISK NR IN PLACE
;PRIME THE BUFFERS
;
NAMELP	CALL	READNA	;READ NAME INTO NADAT
MASTLP	CALL	READMI	;READ MASTER INTO MIDAT
;IF EOF ON BOTH FILES, WE ARE ALL DONE
COMPLP	LDA	NAEOFLG	;NAME FILE EOF?
	ORA	A
	JZ	NOTEOF	;..NO
	LDA	MIEOFLG	;MASTER IN EOF?
	ORA	A
	JNZ	ALLDONE	;YES, THAT'S IT.
NOTEOF	LDA	NADAT
	MOV	B,A
	LDA	MIDAT
	CMP	B
	JNZ	NOTE2	;CAN'T BE REPLACE
	CPI	'['
	JNZ	NOTE2	;NOT SPACE LEFT NAME
	COMPARE NADAT+9,MIDAT+9,18 ;JUST CK TYPE
	JMP	NOTE3	;GO WITH THE FLAGS
;
NOTE2	COMPARE	NADAT,MIDAT,27
NOTE3	JZ	EQUAL
	JC	WRITEN
;
;MASTER IS LOWER - WRITE IT IF FOR ANOTHER DISK
;
	COMPARE	MIDSK,DKNAME,12 ;SAME DISK?
	JZ	DELMI	;DELETING MIDAT
	MOVE	MIDAT,MODAT,27
	CALL	WRITEMO
	JMP	MASTLP
;
;DELETE MASTER IN
;
DELMI	LXI	D,DELMSG
	LXI	H,MIDAT
	CALL	MESG
	JMP	MASTLP
DELMSG	DB	'DEL: $'
;
;NAME IS LOWER - WRITE IT
;
WRITEN	MOVE	NADAT,MODAT,27
	CALL	WRITEMO
;
;PRINT THAT NAME WAS ADDED
;
	LXI	D,ADDMSG
	LXI	H,NADAT
	CALL	MESG
	CALL	READNA	;READ NEXT NAME
	JMP	COMPLP
ADDMSG	DB	'ADD: $'
;
;BOTH FILES EQUAL
;
EQUAL	MOVE	NADAT,MODAT,27
	CALL	WRITEMO	;WRITE OUT MASTER
	JMP	NAMELP	;READ BOTH
;
;READ NAME FILE
;
READNA	LXI	H,NADAT
	MVI	B,8
	CALL	READNAC	;READ CHARACTERS
	MVI	M,'.'
	INX	H
	MVI	B,3	;TYPE LENGTH
	CALL	READNAC
	MVI	M,','
	LXI	H,DKNAME+12
	MVI	M,';'
	INX	H
	MVI	B,1
	CALL	READNAC
;
;IF THIS IS A NAME NOT TO BE CATALOGED,
;READ THE NEXT
;
	LXI	D,IGNORE	;GET IGNORE TABLE
IGNLP	LXI	H,NADAT
	MVI	B,12	;# OF CHARS TO MATCH
IGNCLP	LDAX	D
	CMP	M
	JZ	IGNMAT	;MATCHED
	MOV	A,M	;GET CHAR
	CPI	' '	;SPACE?
	JZ	IGNMAT1
;
;GET NEXT ENTRY
;
IGNEXTE	LDAX	D
	INX	D
	CPI	')'	;END OF TABLE?
	RZ		;..YES, RETURN
	CPI	0AH	;NEXT LINE?
	JNZ	IGNEXTE
	JMP	IGNLP
;
;CHAR MATCHED
;
IGNMAT	INX	D	;SKIP MATCH CHAR
IGNMAT1	INX	H
	DCR	B
	JNZ	IGNCLP	;LOOP UNTIL DONE
;
;NAME IS TO BE DELETED
;
	JMP	READNA	;READ NEXT NAME
;
;READ CHARACTERS INTO NAME BUFFER
;
READNAC	LDA	NAEOFLG	;EOF ON NAMES?
	ORA	A
	JNZ	NAEOF	;YES, PAD W/0FFH
	PUSH	H
	PUSH	B
GETNA	GET	NAMES
	CPI	0AH
	JZ	GETNA	;IGNORE LF
	POP	B
	POP	H
	CPI	'.'	;END?
	JZ	NAEND
	CPI	';'
	JZ	NAEND
	CPI	0DH	;END?
	JZ	NAEND
	CPI	'Z'-40H	;EOF?
	JZ	NAEOF
NAMOR	MOV	M,A
	INX	H
	DCR	B
	JNZ	READNAC
	PUSH	B
	PUSH	H
	GET	NAMES	;KILL DELIMITER CHAR
	POP	H
	POP	B
	CPI	'Z'-40H	;EOF?
	RNZ
	STA	NAEOFLG
	RET
NAEND	MVI	M,' '
	INX	H
	DCR	B
	JNZ	NAEND
	RET
NAEOF	MVI	M,0FFH
	INX	H
	DCR	B
	JNZ	NAEOF
	MVI	A,1
	STA	NAEOFLG
	RET
;
;READ MASTER IN NAME
;
READMI	LXI	H,MIDAT
	CALL	MINAME	;GET FILE NAME
	MVI	M,','	;SEPARATOR
	INX	H
	CALL	MINAME	;GET DISK NAME
	LDA	MASDEL	;DELIMITER FOUND
	CPI	';'
	RNZ		;NO USER NR
	GET	MASTIN
	STA	MIDSK+13
	GET	MASTIN	;EAT DELIMITER
	RET
;
;READ MASTER IN, 1 FIELD
;
MINAME	MVI	B,8
	CALL	READMIC	;GET CHARS
	MVI	M,'.'
	INX	H
	MVI	B,3
	CALL	READMIC	;GET TYPE
	RET
;
;READ CHARS INTO MASTER NAME
;
READMIC	LDA	MIEOFLG
	ORA	A
	JNZ	MIEOF
	PUSH	H
	PUSH	B
GETMI	GET	MASTIN
	CPI	0AH	;IGNORE LF
	JZ	GETMI	;L/F'S
	POP	B
	POP	H
	CPI	','
	JZ	MIEND
	CPI	'.'
	JZ	MIEND
	CPI	';'
	JZ	MIEND
	CPI	0DH
	JZ	MIEND
	CPI	'Z'-40H	;EOF?
	JZ	MIEOF
	MOV	M,A
	INX	H
	DCR	B
	JNZ	READMIC
	PUSH	B
	PUSH	H
	GET	MASTIN	;GET DELIMITER
	STA	MASDEL	;SAVE IT
	POP	H
	POP	B
	CPI	'Z'-40H	;EOF?
	RNZ
	STA	MIEOFLG
	RET
MIEND	MVI	M,' '
	INX	H
	DCR	B
	JNZ	MIEND
	STA	MASDEL	;SAVE DELIMITER
	RET
MIEOF	MVI	M,0FFH
	INX	H
	DCR	B
	JNZ	MIEOF
	STA	MIEOFLG	;SHOW EOF
	RET
;
;WRITE AN ENTRY TO MASTER OUT
;ALSO BUMP COUNT OF ENTRIES WRITTEN
;
WRITEMO	LXI	H,COUNT+3
BUMP	MOV	A,M	;GET COUNT DIGIT
	CPI	' '
	JNZ	BUMPNB
	MVI	A,'0'
BUMPNB	INR	A
	MOV	M,A
	CPI	'9'+1	;TIME TO CARRY?
	JNZ	BUMPD	;..NO, DONE
	MVI	M,'0'
	DCX	H
	JMP	BUMP
BUMPD	LXI	H,MODAT
	MVI	B,27
WRMOL	MOV	A,M
	CPI	' '	;NULL CHAR?
	JZ	WRSKIP
	PUSH	B
	PUSH	H
	IF	NOT TEST
	PUT	MASTOUT
	ELSE
	PUT	CON
	ENDIF
	POP	H
	POP	B
WRSKIP	INX	H	;POINT TO NEXT CHAR
	DCR	B
	JNZ	WRMOL	;LOOP UNTIL DONE
	MVI	A,0DH
	IF	NOT TEST
	PUT	MASTOUT
	ELSE
	PUT	CON
	ENDIF
	MVI	A,0AH
	IF	NOT TEST
	PUT	MASTOUT
	ELSE
	PUT	CON
	ENDIF
	RET
;
;PRINT MESSAGE IN DE, THEN NAME IN HL
;
MESG	PUSH	H
	MVI	C,@MSG
	CALL	@BDOS
	POP	H
	MVI	B,12	;NAME + '.' + TYPE
MESGL	PUSH	H
	PUSH	B
	MOV	A,M	;GET CHAR
	CPI	' '
	JZ	MESGS	;SKIP IF ' '
	PUT	CON
MESGS	POP	B
	POP	H
	INX	H
	DCR	B
	JNZ	MESGL
	MVI	A,0DH
	PUT	CON
	MVI	A,0AH
	PUT	CON
	RET
;
;MOVE SUBROUTINE (DE)=>(HL), LEN IN (B)
;
MOVER	LDAX	D
	MOV	M,A
	INX	D
	INX	H
	DCR	B
	JNZ	MOVER
	RET
;
;COMPARE ROUTINE (DE)<=>(HL), LENGTH IN B
;
COMPR	LDAX	D
	CMP	M
	RNZ		;RET W/NON ZERO SET
	INX	D
	INX	H
	DCR	B
	JNZ	COMPR
	RET		;ZERO SET, SHOWS =
;
;ALL DONE - WRITE EOF TO OUTPUT, RETURN
;
ALLDONE	EQU	$
	MVI	A,'Z'-40H ;EOF CHAR
	IF	NOT TEST
	PUT	MASTOUT
	FINIS	MASTOUT
	ENDIF
;
;RUN WAS SUCCESSFUL - SET FINAL FILE DISPOSITIONS
;
	ERASE	BAK		;ERA CAT.BAK
	ERASE	NAMES		;ERA NAMES.SUB
	RENAME	BAK,MASTIN	;REN MAST.BAK=MAST.CAT
	RENAME	MASTIN,MASTOUT	;REN MAST.CAT=MAST.NEW
	CALL	MSGXIT
	DB	'MAST.CAT HAS '
COUNT	DB	'     ENTRIES.$'
;
MSGXIT	POP	D	;GET MSG
	MVI	C,@MSG
	CALL	@BDOS
EXIT	JMP	$-$	;TO CP/M RETURN ADDR
	DS	50	;STACK SPACE
STACK	EQU	$
NAEOFLG	DB	0	;NAME FILE EOF FLAG
MIEOFLG	DB	0	;MASTER IN EOF FLAG
NADAT	DB	'XXXXXXXX.YYY,'
DKNAME	DB	'        .     '
MIDAT	DB	'XXXXXXXX.YYY,'
MIDSK	DB	'XXXXXXXX.YYY;Z'
MODAT	DB	'XXXXXXXX.YYY,XXXXXXXX.YYY;Z'
SUBNAME	DB	'$$$     .SUB'
MASDEL	DB	0
;NAMES TO BE IGNORED READ IN HERE:
IGNORE	DB	')'	;DUMMY END OF TABLE
	DS	IGNSIZE
BUFFERS	EQU	$
MEMSIZE	EQU	BUFFERS+@NXTB
;
	END
