;
;  PROGRAM NAME:  HELPCK
;  AUTHOR:  RICHARD CONN
;  DATE:  18 MAY 84
;  VERSION:  1.0
;  PREVIOUS VERSIONS:  None
;  DERIVATION:  HELP.MAC 5.0 (18 MAY 84)
;  NOTE:  FOR USE WITH ZCPR3 ONLY
;
VERS    EQU     10
Z3ENV   SET     0F400H

;
;       HELPCK performs a syntax check on HLP files.  Refer
; to the file HELP.HLP for more details.
;

FALSE           EQU     0
TRUE            EQU     NOT FALSE

;
; USER EQUATES:
;  Set this to TRUE if all files must be of type HLP
;
FORCEHLP                EQU     TRUE    ; TRUE IF FILES MUST BE OF TYPE HLP

;
;  Address of Help File Buffer (Make Same as HELP.COM Buffer)
;    Used to Test for Memory Overflow
;
HLPBUF                  EQU     0F00H   ; I GOT THIS BY PEEKING AT MEM
                                       ;   AFTER RUNNING HELP ON A FILE

;
;  SYSLIB ROUTINES
;
       EXT     Z3INIT,Z3LOG,GETPRT
       EXT     PUTUD,GETUD
       EXT     SCTLFL,SPRINT,SOUT,CAPS,SADC,SHLDC,LOUT,SFN2
       EXT     INITFCB,F$EXIST,F$OPEN,F$READ,F$CLOSE

;
;  CP/M Constants
;
UDFLAG          EQU     4       ; ADDRESS OF USER/DISK FLAG
BDOS            EQU     5       ; ADDRESS OF BDOS ENTRY POINT
FCB             EQU     5CH     ; ADDRESS OF FILE CONTROL BLOCK
FCB2            EQU     6CH     ; 2ND FCB
BUFF            EQU     80H     ; ADDRESS OF DMA BUFFER

CR              EQU     0DH     ; <CR>
LF              EQU     0AH     ; <LF>
BEL             EQU     'G'-'@' ; ^G
FF              EQU     'L'-'@' ; ^L = FORM FEED
CTRLZ           EQU     'Z'-'@' ; ^Z
CTRLC           EQU     'C'-'@' ; ^C

;
;  HELP Control Characters
;
IHCHAR          EQU     ';'     ; FLAG INDICATING INDEXED BY USER
SECTCHAR        EQU     ':'     ; DEFINED TO BE COLON
PRCHAR          EQU     'P'     ; PRINTER OUTPUT

;
; Environment Definition
;
       if      z3env ne 0
;
; External ZCPR3 Environment Descriptor
;
       jmp     start
       db      'Z3ENV' ;This is a ZCPR3 Utility
       db      1       ;External Environment Descriptor
z3eadr:
       dw      z3env
start:
       lhld    z3eadr  ;pt to ZCPR3 environment
;
       else
;
; Internal ZCPR3 Environment Descriptor
;
       MACLIB  Z3BASE.LIB
       MACLIB  SYSENV.LIB
z3eadr:
       jmp     start
       SYSENV
start:
       lxi     h,z3eadr        ;pt to ZCPR3 environment
       endif

;
; Start of Program -- Initialize ZCPR3 Environment
;
       call    z3init  ;initialize the ZCPR3 Env and the VLIB Env

       MVI     A,1     ; SELECT CONSOLE ONLY
       STA     SCTLFL  ; SET SWITCHED OUTPUT FLAG
       LDA     FCB2+1  ; LOOK FOR PRINT OPTION
       CPI     'P'
       JNZ     START1
       MVI     A,81H   ; SELECT CONSOLE AND PRINTER
       STA     SCTLFL

START1:
       LDA     BDOS+2  ; BASE PAGE OF BDOS
       SUI     10      ; 2K + 2 PAGES
       STA     TPAEND

       XRA     A       ; A=0
       STA     ITYPE   ; SET NON-INDEXED FOR TYPE OF FILE

       CALL    PUTUD   ; SAVE HOME

       CALL    SPRINT
       DB      'HELPCK  Version '
       db      (vers/10)+'0','.',(vers mod 10)+'0',0

       LXI     H,FCB+1 ; CHECK FOR FILE NAME
       MOV     A,M
       CPI     '/'     ; OPTION CAUGHT?
       JZ      STRT0
       CPI     ' '     ; NONE?
       JNZ     STRT1
;
;  PRINT HELP MESSAGE
;
STRT0:
       CALL    SPRINT
       DB      CR,LF,'Syntax:'
       DB      CR,LF,'  HELPCK dir:filename.typ o  <-- Check File'
       DB      CR,LF,'  HELPCK dir:filename     o  <-- Check filename.HLP'
       DB      CR,LF,'Options:'
       DB      CR,LF,'  P = Output to Printer'
       DB      0
       RET

;
;  BEGIN HELP CHECK PROGRAM
;
STRT1:
;
;  CHECK FOR WILD CARDS IN FILE NAME -- ERROR IF SO
;
       LXI     H,FCB+1 ; PT TO FIRST BYTE OF FILE NAME
       MVI     B,11    ; 11 BYTES
FCBWCK:
       MOV     A,M     ; GET BYTE
       ANI     7FH     ; MASK
       CPI     '?'     ; WILD?
       JZ      FCBWERR
       INX     H       ; PT TO NEXT
       DCR     B
       JNZ     FCBWCK
;
;  CHECK FOR FILE TYPE
;
       LXI     H,FCB+9 ; CHECK FOR FILE TYPE

       IF      NOT FORCEHLP
       MOV     A,M     ; CHECK FOR FILE TYPE SPECIFIED
       CPI     ' '     ; NONE?
       JNZ     STRT2
       ENDIF
;
;  PLACE DEFAULT FILE TYPE OF '.HLP' IN FCB
;
       LXI     D,DEFTYP        ; DEFAULT FILE TYPE
       MVI     B,3
       XCHG
       CALL    MOVE    ; MOVE (HL) TO (DE) FOR (B) BYTES

;
;  READ IN FILE
;
STRT2:
       CALL    SPRINT
       DB      '     Help File: ',0
       LXI     D,FCB+1         ; PT TO NAME
       CALL    SFN2
       LXI     D,FCB           ; PT TO FCB
       CALL    Z3LOG           ; LOG INTO DIRECTORY
       CALL    INITFCB         ; RESET FCB
       CALL    F$EXIST         ; IS FILE THERE?
       JNZ     STRT3
;
;  FILE NOT FOUND
;
       CALL    SPRINT
       DB      CR,LF,' File Not Found',0
       RET

;
;  FILE CONTAINS WILD CARDS
;
FCBWERR:
       CALL    SPRINT
       DB      CR,LF,' AFN Not Allowed',0
       RET

;
;  LOAD HELP FILE INFORMATION
;
STRT3:
       LXI     D,FCB   ; OPEN FILE
       CALL    F$OPEN
       LXI     H,HLPBUF        ; PT TO BUFFER
       SHLD    NEXTADR ; SET PTR
;
;  READ RECORDS UNTIL EOF
;
STRT4:
       CALL    READ    ; READ INFO
       JZ      STRT4   ; NOT DONE IF ZERO RETURN
       LXI     D,FCB   ; CLOSE FILE
       CALL    F$CLOSE
       CALL    GETUD   ; RESTORE CURRENT DISK AND USER IF CHANGED

;
;  START OF HELP PROGRAM
;
HELP:
       MVI     A,1     ; SET NUMBER OF INFO SECTION
       STA     INFONUM
       LXI     H,HLPBUF        ; PT TO FIRST CHAR
       MOV     A,M     ; NO HEADER SECTION?
       ANI     7FH     ; MASK OUT MSB
       CPI     SECTCHAR
       JNZ     HELP1   ; HEADER SECTION EXISTS
;
;  CHECK NON-INDEXED HELP FILE
;
       CALL    SPRINT
       DB      CR,LF,' Help File is Not Indexed',0
       CALL    CKINFO  ; CHECK HELP INFO PTED TO BY HL
       RET
;
;  CHECK INDEXED HELP FILE
;
HELP1:
       STA     ITYPE   ; SET INDEX TYPE
       CPI     IHCHAR  ; INDEXED BY USER?
       JNZ     HELP1A
       CALL    SPRINT
       DB      CR,LF,' Help File is User-Indexed',0
       JMP     HELP1B
HELP1A:
       CALL    SPRINT
       DB      CR,LF,' Help File is Indexed by HELP',0
HELP1B:
       CALL    CKHEADER        ; CHECK HEADER
;
;  CHECK INFORMATION SECTIONS OF INDEXED HELP FILE
;
HELP2:
       CALL    CKINFO  ; CHECK INFO SECTION
       PUSH    PSW     ; SAVE FLAG
       LDA     INFONUM ; INCREMENT NUMBER OF INFORMATION SECTION
       INR     A
       STA     INFONUM
       POP     PSW
       CPI     CTRLZ   ; DONE?
       JNZ     HELP2
       LDA     ITYPE   ; USER INDEXED?
       CPI     IHCHAR
       JZ      HELP3
       LDA     INFONUM ; GET COUNT OF INFO SECTIONS
       DCR     A       ; ADJUST TO CORRECT NUMBER
       MOV     B,A     ; SAVE IN B
       CALL    SPRINT
       DB      CR,LF,CR,LF,' Information Section Count is ',0
       LDA     IDXNUM  ; GET NUMBER OF INDEX ENTRIES
       CMP     B
       JZ      HELP2A
       CALL    SPRINT
       DB      'Incorrect',0
       JMP     HELP3
HELP2A:
       CALL    SPRINT
       DB      'Correct',0
HELP3:
       CALL    SPRINT
       DB      CR,LF,' HELPCK Done',CR,LF,0
       LDA     SCTLFL  ; CHECK FOR PRINTER SELECTED
       ANI     80H
       RZ              ; DONE IF NO PRINTER OUTPUT
       CALL    GETPRT  ; GET PRINTER DATA
       INX     H       ; PT TO FF FLAG
       INX     H
       INX     H
       MOV     A,M     ; GET FLAG
       ORA     A       ; 0=NO FF
       RZ
       MVI     A,FF    ; OUTPUT FF
       JMP     LOUT

;
;  MOVE BYTES PTED TO BY HL TO AREA PTED TO BY DE; B BYTES TO MOVE
;
MOVE:
       MOV     A,M     ; GET BYTE
       ANI     7FH     ; MASK OFF MSB -- IN CASE A WS FILE
       STAX    D       ; PUT BYTE
       INX     H       ; PT TO NEXT
       INX     D
       DCR     B
       JNZ     MOVE
       RET

;
;  READ RECORD FROM DISK; NEXTADR CONTAINS ADDRESS TO READ TO
;       ON RETURN, BDOS ERROR CODE IS IN A (0=NO ERROR)
;
READ:
       LXI     D,FCB   ; PT TO FCB
       CALL    F$READ  ; READ NEXT RECORD
       PUSH    PSW     ; SAVE RETURN CODE
       LHLD    NEXTADR ; PT TO LOAD ADDRESS
       LDA     TPAEND  ; CHECK AGAINST END PAGE OF TPA
       CMP     H       ; IF AT SAME PAGE, YES
       JZ      READERROR
       LXI     D,BUFF  ; PT TO BUFFER TO LOAD FROM
       MVI     B,128   ; NUMBER OF BYTES TO MOVE
       XCHG
       CALL    MOVE
       XCHG
       MVI     M,CTRLZ ; STORE ENDING CTRLZ IN CASE OF EOF
       POP     PSW     ; GET RETURN CODE
       ORA     A       ; DONE?  <>0 IF SO
;
;  READ DONE -- SAVE PTR TO NEXT BLOCK
;
       SHLD    NEXTADR ; SET NEXT ADDRESS
       RET

READERROR:
       POP     PSW     ; CLEAR PSW
       POP     PSW     ; CLEAR RET ADR
       CALL    SPRINT
       DB      CR,LF,' Memory Full',0
       RET

;
;  CHECK HEADER
;
CKHEADER:
       MVI     A,0     ; SET LINE COUNT
       STA     IDXNUM
CKH1:
       MOV     A,M     ; CHECK FOR DONE
       CPI     SECTCHAR        ; DONE?
       JZ      CKH2
       CPI     CTRLZ   ; EOF?
       JZ      CKH3
       CALL    SKPLINE ; SKIP TO NEXT LINE
       LDA     IDXNUM  ; INCREMENT LINE COUNT
       INR     A
       STA     IDXNUM
       JMP     CKH1
CKH2:
       CALL    SPRINT
       DB      CR,LF,' Lines in Header: ',0
       LDA     IDXNUM  ; GET COUNT
       CALL    SADC
       RET
CKH3:
       CALL    SPRINT
       DB      CR,LF,' Premature EOF at Header',0
       RET

;
;  CHECK INFORMATION SECTION PTED TO BY HL
;
CKINFO:
       CALL    SPRINT
       DB      CR,LF,CR,LF,' Information Section ',0
       LDA     INFONUM ; GET NUMBER OF INFO SECTION
       CALL    SADC    ; PRINT IT
       MOV     A,M     ; CHECK FOR VALID SECTION CHAR
       ANI     7FH
       CPI     SECTCHAR
       JZ      CKINFO1
       CALL    SPRINT
       DB      CR,LF,'  Info Section Does Not Begin with :',0
CKINFO1:
       INX     H       ; PT TO FIRST CHAR
       LDA     ITYPE   ; TYPE OF INFO SECTION
       CPI     IHCHAR  ; USER-INDEXED?
       JZ      CKINFO2
       MOV     A,M     ; CHECK FOR EXTERNAL FILE REFERENCE
       CPI     SECTCHAR
       JNZ     CKINFO1C
       INX     H       ; PT TO FIRST CHAR OF FILE NAME
CKIHF:
       CALL    SPRINT
       DB      CR,LF,'  External Help File: ',0
       PUSH    H       ; SAVE HL
CKINFO1A:
       MOV     A,M     ; GET CHAR
       INX     H       ; PT TO NEXT
       ANI     7FH
       CALL    CAPS
       CPI     ' '+1   ; CHECK FOR RANGE
       JC      CKINFO1B
       CALL    SOUT    ; PRINT CHAR
       JMP     CKINFO1A
CKINFO1B:
       POP     H       ; RESTORE HL
       CALL    SKPLINE ; SKIP TO EOL
       JMP     CKINFO3
CKINFO1C:
       CALL    SKPLINE ; SKIP TO EOL
       CALL    EMPCK   ; CHECK FOR EMPTY
       JMP     CKINFO3
CKINFO2:
       CALL    SPRINT
       DB      CR,LF,'  User Indices: ',0
CKI2A:
       MOV     A,M     ; GET CHAR
       ANI     7FH
       INX     H       ; PT TO NEXT
       CPI     SECTCHAR        ; EXTERNAL HELP FILE?
       JZ      CKIHF
       CPI     LF
       JZ      CKI2C
       CPI     ' '
       JZ      CKI2A
       CPI     CR
       JZ      CKI2B
       CALL    CAPS    ; CAPITALIZE
       CALL    SOUT    ; PRINT INDEX
       MVI     A,' '   ; FOLLOWING SPACE
       CALL    SOUT
       JMP     CKI2A
CKI2B:
       MOV     A,M     ; CHECK FOR LF
       ANI     7FH
       CPI     LF
       JZ      CKI2C
       INX     H       ; SKIP LF
CKI2C:
       CALL    EMPCK   ; CHECK FOR EMPTY
CKINFO3:
       PUSH    H
       LXI     H,1     ; SET LINE COUNTER
       SHLD    LCOUNT
       POP     H
CKINFO4:
       MOV     A,M     ; CHECK FOR NEW INFO SECTION
       CPI     SECTCHAR
       JZ      CKISUM
       CPI     CTRLZ   ; EOF?
       JZ      CKISUM
       CALL    SKPLINE ; SKIP TO NEXT LINE
       PUSH    H       ; INCREMENT LINE COUNT
       LHLD    LCOUNT
       INX     H
       SHLD    LCOUNT
       POP     H
       JMP     CKINFO4
CKISUM:
       PUSH    H
       CALL    SPRINT
       DB      CR,LF,'  Number of Lines: ',0
       LHLD    LCOUNT
       CALL    SHLDC
       POP     H
       RET

;
;  CHECK TO SEE IF AT EOF OR INFO SECTION AND PRINT EMPTY MESSAGE IF SO
;
EMPCK:
       MOV     A,M     ; GET CHAR
       ANI     7FH
       CPI     CTRLZ   ; EOF?
       JZ      EMPCK1
       CPI     SECTCHAR
       RNZ
EMPCK1:
       CALL    SPRINT
       DB      CR,LF,'  Information Section is Empty',0
       RET

;
;  SKIP TO END OF CURRENT LINE
;
SKPLINE:
       MOV     A,M     ; GET CHAR
       ANI     7FH     ; MASK
       CPI     CTRLZ   ; EOF?
       RZ
       INX     H       ; PT TO NEXT
       CPI     LF
       RZ
       JMP     SKPLINE

;
;  BUFFER SECTION
;
DEFTYP:
       DB      'HLP'   ; DEFAULT TYPE OF HELP FILE
ITYPE:
       DS      1       ; TYPE OF HELP FILE (IF = IHCHAR, IT IS INDEXED BY USR)
TPAEND:
       DS      1       ; END PAGE ADDRESS OF TPA
LCOUNT:
       DS      2       ; LINE COUNTER
INFONUM:
       DS      1       ; INFORMATION SECTION NUMBER
IDXNUM:
       DS      1       ; INDEX NUMBER
FIRSTENTRY:
       DS      2       ; PTR TO FIRST ENTRY OF INFORMATION SECTION
NEXTADR:
       DS      2       ; NEXT LOAD ADDRESS

       END