mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2907 lines
65 KiB
2907 lines
65 KiB
|
|
*************************************************************************
|
|
* *
|
|
* Z C P R 3 -- Z80-Based Command Processor Replacement, Version 3.0 *
|
|
* *
|
|
* Copyright (c) 1984 by Richard Conn *
|
|
* Copyright US Government *
|
|
* All Rights Reserved *
|
|
* *
|
|
* ZCPR3 was written by Richard Conn, who assumes no responsibility *
|
|
* or liability for its use. ZCPR3 is released to the CP/M user *
|
|
* community for non-commercial use only. *
|
|
* *
|
|
* All registered users of CP/M are encouraged to freely copy and use *
|
|
* ZCPR3 and its associated utilities on their registered systems for *
|
|
* non-commercial purposes. *
|
|
* *
|
|
* Any commercial use of ZCPR3 is prohibited unless approved by the *
|
|
* author, Richard Conn, or his authorized agent, Echelon, Inc, in *
|
|
* writing. *
|
|
* *
|
|
* This is the RELEASE VERSION of ZCPR3. Dated: 21 Apr 84 *
|
|
* *
|
|
*************************************************************************
|
|
|
|
;
|
|
; ZCPR3 -- CP/M Z80 Command Processor Replacement (ZCPR) Version 3.0
|
|
;
|
|
; ZCPR3 is based upon ZCPR2
|
|
;
|
|
;******** Structure Notes ********
|
|
;
|
|
; ZCPR3 is divided into a number of major sections. The following
|
|
; is an outline of these sections and the names of the major routines
|
|
; located therein.
|
|
;
|
|
; Section Function/Routines
|
|
; ------- -----------------
|
|
;
|
|
; -- Opening Comments, Equates, and Macro Definitions
|
|
;
|
|
; 0 JMP Table into ZCPR3
|
|
; ENTRY
|
|
;
|
|
; 1 Buffers
|
|
; 1. Input Command Line and Default Command
|
|
; 2. File Type of COM File
|
|
; 3. SUBMIT File Control Block
|
|
; 4. Command File Control Block
|
|
; 5. Line Count Buffer
|
|
; 6. Resident Command Table
|
|
;
|
|
; 2 CPR Starting Modules
|
|
; CPR1 CPR RESTRT RS0 RS1
|
|
; RS2 PARSER SCANNER DUSCAN DIRSCAN
|
|
; PASSCK SKSP TSTEOL INITFCB IFCB
|
|
; FILL PRNNF
|
|
;
|
|
; 3 Utilities
|
|
; CONIN CRLF CONOUT LCOUT LSTOUT
|
|
; PAGER READF READ BDOSB NOTE
|
|
; PRINTC PRINT PRIN1 GETDRV DEFDMA
|
|
; DMASET RESET BDOSJP LOGIN OPENF
|
|
; OPEN GRBDOS CLOSE SEARF SEAR1
|
|
; SEARN SUBKIL DELETE GETUSR SETUSR
|
|
;
|
|
; 4 CPR Utilities
|
|
; SETUD UCASE PROMPT READBUF BREAK
|
|
; SDELM ADDAH LDIR NUMBER NUMERR
|
|
; HEXNUM FCBLOG SLOGIN WHLCHK CMDSER
|
|
;
|
|
; 5 CPR-Resident Commands and Functions
|
|
; 5A DIR DIRPR PRFN DIRPTR GETSBIT
|
|
; 5B ERA
|
|
; 5C LIST
|
|
; 5D TYPE
|
|
; 5E SAVE AMBCHK EXTEST
|
|
; 5F REN
|
|
; 5G JUMP
|
|
; 5H GO
|
|
; 5I COMDIR COM CALLPROG
|
|
; 5J GET MLOAD DLOGIN PRNLE PATH
|
|
; MPATH STACK PWLIN
|
|
;
|
|
|
|
;
|
|
; The following MACLIB statements load all the user-selected equates
|
|
; which are used to customize ZCPR3 for the user's working environment.
|
|
;
|
|
MACLIB Z3BASE
|
|
MACLIB Z3HDR
|
|
;
|
|
CTRLC EQU 03H
|
|
TAB EQU 09H
|
|
LF EQU 0AH
|
|
CR EQU 0DH
|
|
;
|
|
WBOOT EQU BASE+0000H ;CP/M WARM BOOT ADDRESS
|
|
UDFLAG EQU BASE+0004H ;USER NUM IN HIGH NYBBLE, DISK IN LOW
|
|
BDOS EQU BASE+0005H ;BDOS FUNCTION CALL ENTRY PT
|
|
TFCB EQU BASE+005CH ;DEFAULT FCB BUFFER
|
|
TFCB2 EQU TFCB+16 ;2ND FCB
|
|
TBUFF EQU BASE+0080H ;DEFAULT DISK I/O BUFFER
|
|
TPA EQU BASE+0100H ;BASE OF TPA
|
|
BIOS EQU CCP+0800H+0E00H ;BIOS Location
|
|
;
|
|
$-MACRO ;FIRST TURN OFF THE EXPANSIONS
|
|
;
|
|
; MACROS TO PROVIDE Z80 EXTENSIONS
|
|
; MACROS INCLUDE:
|
|
;
|
|
; JR - JUMP RELATIVE
|
|
; JRC - JUMP RELATIVE IF CARRY
|
|
; JRNC - JUMP RELATIVE IF NO CARRY
|
|
; JRZ - JUMP RELATIVE IF ZERO
|
|
; JRNZ - JUMP RELATIVE IF NO ZERO
|
|
; DJNZ - DECREMENT B AND JUMP RELATIVE IF NO ZERO
|
|
; PUTRG - SAVE REGISTERS
|
|
; GETRG - RESTORE REGISTERS
|
|
;
|
|
; @GENDD MACRO USED FOR CHECKING AND GENERATING
|
|
; 8-BIT JUMP RELATIVE DISPLACEMENTS
|
|
;
|
|
@GENDD MACRO ?DD ;;USED FOR CHECKING RANGE OF 8-BIT DISPLACEMENTS
|
|
IF (?DD GT 7FH) AND (?DD LT 0FF80H)
|
|
DB 100H,?DD ;Displacement Range Error
|
|
ELSE
|
|
DB ?DD
|
|
ENDIF ;;RANGE ERROR
|
|
ENDM
|
|
;
|
|
;
|
|
; Z80 MACRO EXTENSIONS
|
|
;
|
|
JR MACRO ?N ;;JUMP RELATIVE
|
|
IF I8080 ;;8080/8085
|
|
JMP ?N
|
|
ELSE ;;Z80
|
|
DB 18H
|
|
@GENDD ?N-$-1
|
|
ENDIF ;;I8080
|
|
ENDM
|
|
;
|
|
JRC MACRO ?N ;;JUMP RELATIVE ON CARRY
|
|
IF I8080 ;;8080/8085
|
|
JC ?N
|
|
ELSE ;;Z80
|
|
DB 38H
|
|
@GENDD ?N-$-1
|
|
ENDIF ;;I8080
|
|
ENDM
|
|
;
|
|
JRNC MACRO ?N ;;JUMP RELATIVE ON NO CARRY
|
|
IF I8080 ;;8080/8085
|
|
JNC ?N
|
|
ELSE ;;Z80
|
|
DB 30H
|
|
@GENDD ?N-$-1
|
|
ENDIF ;;I8080
|
|
ENDM
|
|
;
|
|
JRZ MACRO ?N ;;JUMP RELATIVE ON ZERO
|
|
IF I8080 ;;8080/8085
|
|
JZ ?N
|
|
ELSE ;;Z80
|
|
DB 28H
|
|
@GENDD ?N-$-1
|
|
ENDIF ;;I8080
|
|
ENDM
|
|
;
|
|
JRNZ MACRO ?N ;;JUMP RELATIVE ON NO ZERO
|
|
IF I8080 ;;8080/8085
|
|
JNZ ?N
|
|
ELSE ;;Z80
|
|
DB 20H
|
|
@GENDD ?N-$-1
|
|
ENDIF ;;I8080
|
|
ENDM
|
|
;
|
|
DJNZ MACRO ?N ;;DECREMENT B AND JUMP RELATIVE ON NO ZERO
|
|
IF I8080 ;;8080/8085
|
|
DCR B
|
|
JNZ ?N
|
|
ELSE ;;Z80
|
|
DB 10H
|
|
@GENDD ?N-$-1
|
|
ENDIF ;;I8080
|
|
ENDM
|
|
;
|
|
PUTRG MACRO
|
|
PUSH H ;;SAVE REGISTERS IN ORDER
|
|
PUSH D
|
|
PUSH B
|
|
ENDM
|
|
;
|
|
GETRG MACRO
|
|
POP B ;;RESTORE REGISTERS IN ORDER
|
|
POP D
|
|
POP H
|
|
ENDM
|
|
;
|
|
; END OF Z80 MACRO EXTENSIONS
|
|
;
|
|
;
|
|
;**** Section 0 ****
|
|
;
|
|
ORG CPRLOC
|
|
;
|
|
; ENTRY POINTS INTO ZCPR3
|
|
;
|
|
; IF MULTCMD (MULTIPLE COMMANDS ON ONE LINE) is FALSE:
|
|
; If ZCPR3 is entered at location CPRLOC (at the JMP to CPR), then
|
|
; the default command in CMDLIN will be processed. If ZCPR3 is entered
|
|
; at location CPRLOC+3 (at the JMP to CPR1), then the default command in
|
|
; CMDLIN will NOT be processed.
|
|
; NOTE: Entry into ZCPR3 at CPRLOC is permitted, but in order for this
|
|
; to work, CMDLIN MUST be initialized to contain the command line (ending in 0)
|
|
; and the C register MUST contain a valid User/Disk Flag
|
|
; (the most significant nybble contains the User Number and the least
|
|
; significant nybble contains the Disk Number).
|
|
;
|
|
; IF MULTCMD is TRUE:
|
|
; Entry at CPR or CPR1 has the same effect. Multiple command processing
|
|
; will still continue.
|
|
;
|
|
; If MULTCMD is FALSE, a user program need only load the buffer
|
|
; CMDLIN with the desired command line, terminated by a zero, in order to
|
|
; have this command line executed. If MULTCMD is TRUE, a user program must
|
|
; load this buffer as before, but he must also set the NXTCHR pointer to
|
|
; point to the first character of the command line.
|
|
;
|
|
; NOTE: ***** (BIG STAR) ***** Programs such as SYNONYM3 will fail if
|
|
; multiple commands are enabled, but this feature is so very useful that I
|
|
; feel it is worth the sacrifice. Some ZCPR3 utilities, like ALIAS and MENU,
|
|
; require multiple commands, and this feature also permits simple chaining
|
|
; of programs to be possible under the ZCPR3 environment.
|
|
;
|
|
; Enjoy using ZCPR3!
|
|
; Richard Conn
|
|
;
|
|
ENTRY:
|
|
JMP CPR ; Process potential default command
|
|
JMP CPR1 ; Do NOT process potential default command
|
|
;
|
|
;**** Section 1 ****
|
|
; BUFFERS ET AL
|
|
;
|
|
; **** 1. INPUT COMMAND LINE AND DEFAULT COMMAND
|
|
;
|
|
IF MULTCMD ;MULTIPLE COMMANDS ALLOWED?
|
|
;
|
|
; For Multiple Commands, the command line buffer (CMDLIN) is located external
|
|
; to ZCPR3 so that it is not overlayed during Warm Boots; the same is true
|
|
; for NXTCHR, the 2nd key buffer. BUFSIZ and CHRCNT are not important and
|
|
; are provided so the BDOS READLN function can load CMDLIN directly and
|
|
; a user program can see how much space is available in CMDLIN for its text.
|
|
;
|
|
NXTCHR EQU Z3CL ;NXTCHR STORED EXTERNALLY (2 bytes)
|
|
BUFSIZ EQU NXTCHR+2 ;BUFSIZ STORED EXTERNALLY (1 byte)
|
|
CHRCNT EQU BUFSIZ+1 ;CHRCNT STORED EXTERNALLY (1 byte)
|
|
CMDLIN EQU CHRCNT+1 ;CMDLIN STORED EXTERNALLY (long)
|
|
BUFLEN EQU Z3CLS ;LENGTH OF BUFFER
|
|
;
|
|
ELSE
|
|
;
|
|
; If no multiple commands are permitted, these buffers are left internal
|
|
; to ZCPR3 so that the original CCP command line facility (as used by
|
|
; programs like SYNONYM3) can be left intact.
|
|
;
|
|
BUFLEN EQU 80 ;MAXIMUM BUFFER LENGTH
|
|
BUFSIZ:
|
|
DB BUFLEN ;MAXIMUM BUFFER LENGTH
|
|
CHRCNT:
|
|
DB 0 ;NUMBER OF VALID CHARS IN COMMAND LINE
|
|
CMDLIN:
|
|
DB ' ' ;DEFAULT (COLD BOOT) COMMAND
|
|
DB 0 ;COMMAND STRING TERMINATOR
|
|
DS BUFLEN-($-CMDLIN)+1 ;TOTAL IS 'BUFLEN' BYTES
|
|
;
|
|
NXTCHR:
|
|
DW CMDLIN ;POINTER TO COMMAND INPUT BUFFER
|
|
;
|
|
ENDIF ;MULTCMD
|
|
;
|
|
|
|
;
|
|
; **** 2. FILE TYPE FOR COMMAND
|
|
;
|
|
COMMSG:
|
|
COMTYP ;USE MACRO FROM Z3HDR.LIB
|
|
;
|
|
IF SUBON ;IF SUBMIT FACILITY ENABLED ...
|
|
;
|
|
; **** 3. SUBMIT FILE CONTROL BLOCK
|
|
;
|
|
SUBFCB:
|
|
DB 1 ;DISK NAME SET TO DEFAULT TO DRIVE A:
|
|
DB '$$$' ;FILE NAME
|
|
DB ' '
|
|
SUBTYP ;USE MACRO FROM Z3HDR.LIB
|
|
DB 0 ;EXTENT NUMBER
|
|
DB 0 ;S1
|
|
SUBFS2:
|
|
DS 1 ;S2
|
|
SUBFRC:
|
|
DS 1 ;RECORD COUNT
|
|
DS 16 ;DISK GROUP MAP
|
|
SUBFCR:
|
|
DS 1 ;CURRENT RECORD NUMBER
|
|
;
|
|
ENDIF ;SUBON
|
|
;
|
|
; **** 4. COMMAND FILE CONTROL BLOCK
|
|
;
|
|
IF EXTFCB NE 0 ;MAY BE PLACED EXTERNAL TO ZCPR3
|
|
;
|
|
FCBDN EQU EXTFCB ;DISK NAME
|
|
FCBFN EQU FCBDN+1 ;FILE NAME
|
|
FCBFT EQU FCBFN+8 ;FILE TYPE
|
|
FCBDM EQU FCBFT+7 ;DISK GROUP MAP
|
|
FCBCR EQU FCBDM+16 ;CURRENT RECORD NUMBER
|
|
;
|
|
ELSE ;OR INTERNAL TO ZCPR3
|
|
;
|
|
FCBDN:
|
|
DS 1 ;DISK NAME
|
|
FCBFN:
|
|
DS 8 ;FILE NAME
|
|
FCBFT:
|
|
DS 3 ;FILE TYPE
|
|
DS 1 ;EXTENT NUMBER
|
|
DS 2 ;S1 AND S2
|
|
DS 1 ;RECORD COUNT
|
|
FCBDM:
|
|
DS 16 ;DISK GROUP MAP
|
|
FCBCR:
|
|
DS 1 ;CURRENT RECORD NUMBER
|
|
;
|
|
ENDIF ;EXTFCB
|
|
;
|
|
|
|
;
|
|
; **** 5. LINE COUNT BUFFER
|
|
;
|
|
IF LTON
|
|
PAGCNT:
|
|
DB NLINES-2 ;LINES LEFT ON PAGE
|
|
ENDIF ;LTON
|
|
;
|
|
; **** 6. RESIDENT COMMAND TABLE
|
|
; EACH TABLE ENTRY IS STRUCTURED AS FOLLOWS:
|
|
; DB 'NAME' ;NCHARS LONG
|
|
; DW ADDRESS ;ADDRESS OF COMMAND
|
|
;
|
|
CMDTBL:
|
|
DB NCHARS ;SIZE OF TEXT IN COMMAND TABLE
|
|
CTABLE ;DEFINE COMMAND TABLE VIA MACRO IN Z3HDR FILE
|
|
DB 0 ;END OF TABLE
|
|
;
|
|
|
|
;
|
|
;**** Section 2 ****
|
|
; ZCPR3 STARTING POINTS
|
|
;
|
|
; START ZCPR3 AND DON'T PROCESS DEFAULT COMMAND STORED IF MULTIPLE COMMANDS
|
|
; ARE NOT ALLOWED
|
|
;
|
|
CPR1:
|
|
;
|
|
IF NOT MULTCMD ;IF MULTIPLE COMMANDS NOT ALLOWED
|
|
;
|
|
XRA A ;SET END OF COMMAND LINE SO NO DEFAULT COMMAND
|
|
STA CMDLIN ;FIRST CHAR OF BUFFER
|
|
;
|
|
ENDIF ;NOT MULTCMD
|
|
;
|
|
; START ZCPR3 AND POSSIBLY PROCESS DEFAULT COMMAND
|
|
;
|
|
; NOTE ON MODIFICATION BY Ron Fowler: BDOS RETURNS 0FFH IN
|
|
; ACCUMULATOR WHENEVER IT LOGS IN A DIRECTORY, IF ANY
|
|
; FILE NAME CONTAINS A '$' IN IT. THIS IS NOW USED AS
|
|
; A CLUE TO DETERMINE WHETHER OR NOT TO DO A SEARCH
|
|
; FOR SUBMIT FILE, IN ORDER TO ELIMINATE WASTEFUL SEARCHES.
|
|
;
|
|
CPR:
|
|
LXI SP,STACK ;RESET STACK
|
|
;
|
|
IF NOT MULTCMD ;ONLY ONE COMMAND PERMITTED
|
|
LXI H,CMDLIN ;SET PTR TO BEGINNING OF COMMAND LINE
|
|
SHLD NXTCHR
|
|
ENDIF ;NOT MULTCMD
|
|
;
|
|
PUSH B
|
|
MOV A,C ;C=USER/DISK NUMBER (SEE LOC 4)
|
|
RAR ;EXTRACT USER NUMBER
|
|
RAR
|
|
RAR
|
|
RAR
|
|
ANI 0FH
|
|
STA CURUSR ;SET USER
|
|
CALL SETUSR ;SET USER NUMBER
|
|
CALL RESET ;RESET DISK SYSTEM
|
|
;
|
|
IF SUBON ;IF SUBMIT FACILITY ENABLED
|
|
;
|
|
STA RNGSUB ;SAVE SUBMIT CLUE FROM DRIVE A:
|
|
;
|
|
ENDIF ;SUBON
|
|
;
|
|
POP B
|
|
MOV A,C ;C=USER/DISK NUMBER (SEE LOC 4)
|
|
ANI 0FH ;EXTRACT CURRENT DISK DRIVE
|
|
STA CURDR ;SET IT
|
|
CNZ LOGIN ;LOG IN DEFAULT DISK IF NOT ALREADY LOGGED IN
|
|
CALL SETUD ;SET USER/DISK FLAG
|
|
CALL DEFDMA ;SET DEFAULT DMA ADDRESS
|
|
;
|
|
IF SUBON ;CHECK FOR $$$.SUB IF SUBMIT FACILITY IS ON
|
|
;
|
|
LXI D,SUBFCB ;CHECK FOR $$$.SUB ON CURRENT DISK
|
|
RNGSUB EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;2ND BYTE (IMMEDIATE ARG) IS THE RNGSUB FLAG
|
|
ORA A ;SET FLAGS ON CLUE
|
|
CNZ SEAR1
|
|
STA RNGSUB ;SET FLAG (0=NO $$$.SUB)
|
|
;
|
|
ENDIF ;SUBON
|
|
;
|
|
JR RS1 ;CHECK COMMAND LINE FOR CONTENT
|
|
;
|
|
; PROMPT USER AND INPUT COMMAND LINE FROM HIM
|
|
;
|
|
RESTRT:
|
|
LXI SP,STACK ;RESET STACK
|
|
;
|
|
; READ INPUT LINE FROM USER OR $$$.SUB
|
|
;
|
|
RS0:
|
|
;
|
|
IF Z3MSG NE 0
|
|
XRA A ;SET NO OUTPUT MESSAGE
|
|
STA Z3MSG+3 ;ZCPR3 COMMAND STATUS
|
|
INR A ;SET ZCPR3 INPUT PROMPT
|
|
STA Z3MSG+7 ;ZEX MESSAGE BYTE
|
|
ENDIF ;Z3MSG NE 0
|
|
;
|
|
LXI H,CMDLIN ;SET POINTER TO FIRST CHAR IN COMMAND LINE
|
|
SHLD NXTCHR ;POINTER TO NEXT CHARACTER TO PROCESS
|
|
MVI M,0 ;ZERO OUT COMMAND LINE IN CASE OF WARM BOOT
|
|
PUSH H ;SAVE PTR
|
|
CALL READBUF ;INPUT COMMAND LINE FROM USER (OR $$$.SUB)
|
|
;
|
|
IF Z3MSG NE 0
|
|
XRA A ;NORMAL PROCESSING RESUMED
|
|
STA Z3MSG+7 ;ZEX MESSAGE BYTE
|
|
ENDIF
|
|
;
|
|
POP H ;GET PTR
|
|
MOV A,M ;CHECK FOR COMMENT LINE
|
|
CPI COMMENT ;BEGINS WITH COMMENT CHAR?
|
|
JRZ RS0 ;INPUT ANOTHER LINE IF SO
|
|
;
|
|
; PROCESS INPUT LINE; NXTCHR PTS TO FIRST LETTER OF COMMAND
|
|
;
|
|
RS1:
|
|
LXI SP,STACK ;RESET STACK
|
|
;
|
|
; RETURN TO CURRENT DIRECTORY AND POINT TO NEXT CHAR IN COMMAND LINE
|
|
;
|
|
CALL DLOGIN ;RETURN TO CURRENT DIRECTORY
|
|
LHLD NXTCHR ;PT TO FIRST CHAR OF NEXT COMMAND
|
|
PUSH H ;SAVE PTR
|
|
;
|
|
; CAPITALIZE COMMAND LINE
|
|
;
|
|
CAPBUF:
|
|
MOV A,M ;CAPITALIZE COMMAND CHAR
|
|
CALL UCASE
|
|
MOV M,A
|
|
INX H ;PT TO NEXT CHAR
|
|
ORA A ;EOL?
|
|
JRNZ CAPBUF
|
|
POP H ;GET PTR TO FIRST CHAR IN LINE
|
|
;
|
|
; SET POINTER FOR MULTIPLE COMMAND LINE PROCESSING TO FIRST CHAR OF NEW CMND
|
|
;
|
|
RS2:
|
|
CALL SKSP ;SKIP OVER SPACES
|
|
ORA A ;END OF LINE?
|
|
JRZ RESTRT
|
|
CPI CTRLC ;ABORT CHAR?
|
|
JRZ RESTRT
|
|
;
|
|
IF MULTCMD ;MULTIPLE COMMANDS ALLOWED?
|
|
MOV A,M ;GET FIRST CHAR OF COMMAND
|
|
CPI CMDSEP ;IS IT A COMMAND SEPARATOR?
|
|
JRNZ RS3
|
|
INX H ;SKIP IT IF IT IS
|
|
JR RS2
|
|
ENDIF ;MULTCMD
|
|
;
|
|
RS3:
|
|
SHLD NXTCHR ;SET PTR TO FIRST CHAR OF NEW COMMAND LINE
|
|
SHLD CURCMD ;SAVE PTR TO COMMAND LINE FOR ERROR RETURN
|
|
;
|
|
; PARSE COMMAND LINE PTED TO BY HL
|
|
;
|
|
CALL PARSER ;PARSE ENTIRE COMMAND LINE
|
|
;
|
|
; CHECK FOR SHELL INVOCATION AND RUN IT IF SO
|
|
;
|
|
IF Z3MSG NE 0
|
|
LDA Z3MSG+3 ;GET COMMAND STATUS
|
|
CPI 1 ;SHELL?
|
|
JZ RS4
|
|
ENDIF ;Z3MSG NE 0
|
|
;
|
|
; IF IFON AND FCP AVAILABLE, TRY TO RUN FROM FCP
|
|
;
|
|
IF IFON AND (FCP NE 0)
|
|
LXI H,FCP+5 ;PT TO COMMAND TABLE
|
|
CALL CMDSCAN ;SCAN TABLE
|
|
JZ CALLP ;RUN IF FOUND (NO LEADING CRLF)
|
|
ENDIF ;IFON AND (FCP NE 0)
|
|
;
|
|
; IF IFON, THEN CHECK FOR RUNNING IF AND FLUSH COMMAND LINE IF ENABLED
|
|
;
|
|
IF IFON
|
|
LXI H,Z3MSG+1 ;PT TO IF BYTE
|
|
MOV A,M ;GET IT
|
|
ORA A ;SEE IF ANY IF
|
|
JRZ RS4 ;CONTINUE IF NOT
|
|
INX H ;PT TO IF ACTIVE BYTE
|
|
ANA M ;SEE IF CURRENT IF IS ACTIVE
|
|
JRZ RS1 ;SKIP IF NOT
|
|
ENDIF ;IFON
|
|
RS4:
|
|
;
|
|
; IF DIR: PREFIX, HANDLE AS COM FILE
|
|
;
|
|
COLON EQU $+1 ;FLAG FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;COMMAND OF THE FORM 'DIR:COMMAND'?
|
|
ORA A ;0=NO
|
|
JNZ COMDIR ;PROCESS AS COM FILE IF DIR: FORM
|
|
;
|
|
; CHECK FOR RESIDENT COMMAND
|
|
;
|
|
CALL CMDSER ;SCAN FOR CPR-RESIDENT COMMAND
|
|
JZ CALLP ;RUN CPR-RESIDENT COMMAND WITH NO LEADING CRLF
|
|
;
|
|
; CHECK FOR RESIDENT COMMAND PACKAGE
|
|
;
|
|
IF RCP NE 0
|
|
LXI H,RCP+5 ;PT TO RCP COMMAND TABLE
|
|
CALL CMDSCAN ;CHECK FOR RCP
|
|
JZ CALLPROG
|
|
ENDIF
|
|
;
|
|
; PROCESS AS COM FILE
|
|
;
|
|
JMP COM ;PROCESS COM FILE
|
|
|
|
;
|
|
; ERROR PROCESSOR
|
|
;
|
|
ERROR:
|
|
;
|
|
IF SUBON ;IF SUBMIT FACILITY IS ON
|
|
;
|
|
CALL SUBKIL ;TERMINATE ACTIVE $$$.SUB IF ANY
|
|
;
|
|
ENDIF ;SUBON
|
|
;
|
|
CALL CRLF ;NEW LINE
|
|
;
|
|
IF Z3MSG NE 0 ;MESSAGES ENABLED?
|
|
;
|
|
LDA Z3MSG+3 ;WAS ERROR CAUSED BY NO SHELL?
|
|
ANI 1 ;BIT 0 SAYS ZCPR3 TRIED TO RUN A SHELL
|
|
JRNZ ERRSH ;ABORT SHELL
|
|
LDA Z3MSG ;GET ERROR HANDLER MESSAGE
|
|
MOV B,A ;... IN B
|
|
ORA A ;FLUSH AND RESUME?
|
|
JRZ ERR0
|
|
MVI A,2 ;SET ERROR FLAG
|
|
STA Z3MSG+3 ;IN SHELL STATUS BUFFER
|
|
LHLD CURCMD ;PT TO BEGINNING OF ERROR
|
|
SHLD Z3MSG+4 ;SAVE IN MESSAGE
|
|
LXI H,Z3MSG+10H ;PT TO COMMAND LINE
|
|
SHLD NXTCHR ;NEXT CHARACTER TO EXECUTE
|
|
JMP RS1 ;RUN CONTENTS OF BUFFER
|
|
;
|
|
; CLEAR SHELL STACK AND RESTART COMMAND PROCESSING
|
|
;
|
|
ERRSH:
|
|
;
|
|
IF SHSTK NE 0 ;IF SHELL STACK AVAILABLE
|
|
XRA A ;CLEAR SHELL STACK
|
|
STA SHSTK
|
|
ENDIF
|
|
;
|
|
JMP RESTRT ;RESTART PROCESSING
|
|
ERR0:
|
|
;
|
|
ENDIF ;Z3MSG NE 0
|
|
;
|
|
CURCMD EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
LXI H,0 ;PT TO BEGINNING OF COMMAND LINE
|
|
ERR1:
|
|
MOV A,M ;GET CHAR
|
|
ORA A ;END OF LINE?
|
|
JRZ ERR2
|
|
CALL CONOUT ;PRINT COMMAND CHAR
|
|
INX H ;PT TO NEXT CHAR
|
|
JR ERR1 ;CONTINUE
|
|
ERR2:
|
|
CALL PRINT ;PRINT '?'
|
|
DB '?'+80H
|
|
ERR3:
|
|
JMP RESTRT ;RESTART CPR
|
|
|
|
;
|
|
; PARSE COMMAND LINE PTED TO BY HL
|
|
; RETURN WITH NZ IF ERROR IN COMMAND NAME
|
|
;
|
|
PARSER:
|
|
;
|
|
; INITIALIZE THE COMMAND AND TOKEN FCBS
|
|
;
|
|
LXI D,FCBDN ;PT TO COMMAND FCB
|
|
CALL INITFCB ;INIT IT
|
|
LXI D,TFCB ;PT TO TOKEN FCB
|
|
CALL INITFCB ;INIT IT
|
|
;
|
|
; EXTRACT COMMAND NAME
|
|
;
|
|
LXI D,FCBDN ;PLACE COMMAND NAME INTO COMMAND FCB
|
|
CALL SCANNER ;EXTRACT COMMAND NAME
|
|
JRNZ ERROR ;ERROR RETURN
|
|
;
|
|
; CHECK FOR ERROR IN COMMAND NAME (FILE TYPE GIVEN)
|
|
;
|
|
LXI D,FCBFT ;PT TO FILE TYPE
|
|
LDAX D ;GET FIRST CHAR OF FILE TYPE
|
|
CPI ' ' ;MUST BE BLANK, OR ERROR
|
|
JRNZ ERROR ;ERROR RETURN
|
|
;
|
|
; SET TYPE OF COMMAND
|
|
;
|
|
PUSH H ;SAVE PTR TO NEXT BYTE
|
|
LXI H,COMMSG ;PLACE DEFAULT FILE TYPE (COM) INTO FCB
|
|
MVI B,3 ;3 BYTES
|
|
CALL LDIR
|
|
POP H ;GET PTR TO NEXT BYTE
|
|
;
|
|
; SET DIR: PREFIX FLAG
|
|
;
|
|
MYCOLON EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;PREVIOUS TOKEN CONTAINED A COLON?
|
|
STA COLON
|
|
;
|
|
; SAVE POINTER TO COMMAND TAIL FOR LATER COPY INTO TBUFF AND FIND END OF
|
|
; COMMAND LINE; THIS IS ALSO THE ENTRY POINT FOR CMDRUN FACILITY TO
|
|
; PARSE THE ENTIRE COMMAND LINE AS A TAIL
|
|
;
|
|
PARSET:
|
|
SHLD TAILSV ;SAVE PTR TO COMMAND TAIL
|
|
PUSH H ;SAVE PTR
|
|
CTAIL:
|
|
MOV A,M ;GET CHAR
|
|
CALL TSTEOL ;AT EOL?
|
|
JRZ CTAIL1
|
|
INX H ;PT TO NEXT
|
|
JR CTAIL
|
|
CTAIL1:
|
|
SHLD NXTCHR ;SAVE PTR TO NEXT LINE
|
|
POP H ;GET PTR TO COMMAND TAIL
|
|
;
|
|
; EXTRACT FIRST TOKEN
|
|
;
|
|
CALL SKSP ;SKIP OVER SPACES
|
|
RZ ;DONE IF EOL OR END OF COMMAND
|
|
LXI D,TFCB ;STORE FIRST TOKEN IN TFCB
|
|
CALL SCANNER ;EXTRACT TOKEN
|
|
;
|
|
; EXTRACT SECOND TOKEN
|
|
;
|
|
CALL SKSP ;SKIP OVER SPACES
|
|
RZ ;DONE IF EOL OR END OF COMMAND
|
|
LXI D,TFCB+16 ;PT TO 2ND FCB AND FALL THRU TO SCANNER
|
|
;
|
|
; EXTRACT TOKEN FROM COMMAND LINE AND PLACE IT INTO FCB PTED TO BY DE
|
|
; FORMAT FCBDN FCB IF TOKEN RESEMBLES FILE NAME AND TYPE (FILENAME.TYP)
|
|
; ON INPUT, HL PTS TO NEXT CHAR AND DE PTS TO FCB
|
|
; ON OUTPUT, HL PTS TO DELIMITER AFTER TOKEN AND ZERO FLAG IS RESET
|
|
; IF '?' IS IN TOKEN
|
|
;
|
|
; ENTRY POINTS:
|
|
; SCANNER - LOAD TOKEN INTO FCB PTED TO BY DE
|
|
;
|
|
SCANNER:
|
|
XRA A ;A=0
|
|
STAX D ;SET DEFAULT DRIVE
|
|
STA MYCOLON ;SET NO COLON
|
|
STA TEMPDR ;SET TEMPORARY DRIVE NUMBER TO DEFAULT
|
|
STA QMCNT ;ZERO QUESTION MARK COUNTER
|
|
LDA CURUSR ;GET CURRENT USER
|
|
STA TEMPUSR ;SET TEMPUSR
|
|
PUSH D ;SAVE PTR TO FIRST BYTE OF FCB
|
|
MVI B,8 ;8 CHARS MAX
|
|
CALL SCANF ;PLACE FIRST TOKEN INTO FILE NAME FIELD
|
|
POP D ;GET PTR TO FIRST BYTE OF FCB
|
|
MOV A,M ;GET TERMINATING CHAR
|
|
STA ENDCHAR ;SET ENDING CHAR
|
|
CPI ':' ;COLON?
|
|
JRNZ SCAN1 ;NO, WE HAVE A FILE NAME
|
|
STA MYCOLON ;SET COLON
|
|
INX H ;PT TO CHAR AFTER COLON
|
|
;
|
|
; SCAN TOKEN FOR DIR: FORM, WHICH MEANS WE HAVE A USER/DISK SPECIFICATION
|
|
; HL PTS TO CHAR AFTER COLON
|
|
;
|
|
IF (Z3NDIR NE 0) AND NDINCP ;NAMED DIRS AVAILABLE
|
|
;
|
|
IF DUFIRST ;DU: BEFORE DIR:
|
|
;
|
|
; CHECK FOR DU: FORM
|
|
;
|
|
IF ACCPTDU ;PERMIT DU: FORM
|
|
PUSH D ;SAVE PTR TO FCB DN
|
|
PUSH H ;SAVE PTR TO NEXT CHAR IN LINE
|
|
CALL DUSCAN ;CHECK FOR DU: FORM
|
|
POP H ;GET PTR TO NEXT CHAR
|
|
POP D ;GET PTR TO FCB
|
|
JRZ SUD1 ;GOT IT
|
|
ENDIF ;ACCPTDU
|
|
;
|
|
; CHECK FOR DIR: FORM
|
|
;
|
|
IF ACCPTND ;PERMIT DIR: FORM
|
|
PUSH D ;SAVE PTR TO FCB
|
|
PUSH H ;SAVE PTR TO NEXT CHAR
|
|
CALL DIRSCAN ;CHECK FOR DIR: FORM
|
|
POP H ;GET PTR TO NEXT CHAR
|
|
POP D ;GET PTR TO FCB
|
|
JRNZ SCAN1 ;ERROR IN PREFIX
|
|
ENDIF ;ACCPTND
|
|
SUD1:
|
|
;
|
|
ELSE ;DIR: BEFORE DU:
|
|
;
|
|
; CHECK FOR DIR: FORM
|
|
;
|
|
IF ACCPTND ;PERMIT DIR: FORM
|
|
PUSH D ;SAVE PTR TO FCB
|
|
PUSH H ;SAVE PTR TO NEXT CHAR
|
|
CALL DIRSCAN ;CHECK FOR DIR: FORM
|
|
POP H ;GET PTR TO NEXT CHAR
|
|
POP D ;GET PTR TO FCB
|
|
JRZ SUD1 ;GOT IT
|
|
ENDIF ;ACCPTND
|
|
;
|
|
; CHECK FOR DU: FORM
|
|
;
|
|
IF ACCPTDU ;PERMIT DU: FORM
|
|
PUSH D ;SAVE PTR TO FCB DN
|
|
PUSH H ;SAVE PTR TO NEXT CHAR IN LINE
|
|
CALL DUSCAN ;CHECK FOR DU: FORM
|
|
POP H ;GET PTR TO NEXT CHAR
|
|
POP D ;GET PTR TO FCB
|
|
JRNZ SCAN1 ;ERROR IN PREFIX
|
|
ENDIF ;ACCPTDU
|
|
SUD1:
|
|
;
|
|
ENDIF ;DUFIRST
|
|
;
|
|
ELSE ;DU ONLY
|
|
;
|
|
; CHECK FOR DU: FORM
|
|
;
|
|
IF ACCPTDU ;ALLOW DU: FORM
|
|
PUSH D ;SAVE PTR TO FCB DN
|
|
PUSH H ;SAVE PTR TO NEXT CHAR IN LINE
|
|
CALL DUSCAN ;CHECK FOR DU: FORM
|
|
POP H ;GET PTR TO NEXT CHAR
|
|
POP D ;GET PTR TO FCB
|
|
JRNZ SCAN1 ;ERROR IN PREFIX
|
|
ENDIF ;ACCPTDU
|
|
;
|
|
ENDIF ;(Z3NDIR NE 0) AND NDINCP
|
|
;
|
|
; SET DRIVE REFERENCED
|
|
;
|
|
LDA TEMPDR ;SET DRIVE
|
|
STAX D ;... IN FCB
|
|
;
|
|
; REINIT FCB PTED TO BY DE
|
|
;
|
|
PUSH D ;SAVE PTR
|
|
INX D ;PT TO FN FIELD
|
|
CALL IFCB ;ONLY PARTIAL INIT (17 BYTES TOTAL)
|
|
POP D
|
|
;
|
|
; EXTRACT FILENAME FIELD
|
|
;
|
|
XRA A
|
|
STA QMCNT ;ZERO QUESTION MARK COUNTER
|
|
PUSH D ;SAVE PTR TO FIRST BYTE OF FCB
|
|
MVI B,8 ;8 CHARS MAX
|
|
CALL SCANF ;STORE FILE NAME
|
|
POP D ;GET PTR TO FIRST BYTE OF FCB
|
|
MOV A,M ;GET OFFENDING CHAR
|
|
STA ENDCHAR ;SET ENDING CHAR
|
|
;
|
|
; SKIP TO FILE TYPE FIELD
|
|
; HL PTS TO NEXT CHAR, DE PTS TO DN FIELD OF FCB
|
|
;
|
|
SCAN1:
|
|
ENDCHAR EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;GET ENDING CHAR
|
|
XCHG
|
|
LXI B,8 ;PT TO BEFORE FILE TYPE FIELD OF FCB
|
|
DAD B
|
|
XCHG
|
|
;
|
|
; EXTRACT FILETYPE FIELD
|
|
;
|
|
MVI B,3 ;PREPARE TO EXTRACT FILE TYPE
|
|
CPI '.' ;IF '.', WE HAVE A TYPE
|
|
JRNZ SCAN2
|
|
INX H ;PT TO CHAR AFTER '.'
|
|
PUSH D
|
|
CALL SCANF ;GET FCB FILE TYPE
|
|
POP D
|
|
SCAN2:
|
|
;
|
|
; SET USER NUMBER REFERENCED
|
|
; HL PTS TO NEXT CHAR, DE PTS TO BEFORE FCB FT
|
|
;
|
|
XCHG
|
|
LXI B,5 ;PT TO S1 FIELD
|
|
DAD B
|
|
XCHG
|
|
LDA TEMPUSR ;STORE USER NUMBER HERE
|
|
STAX D
|
|
;
|
|
; SKIP TO SPACE, CHAR AFTER =, OR EOL
|
|
; HL PTS TO NEXT CHAR IN LINE
|
|
;
|
|
SCAN3:
|
|
MOV A,M ;GET NEXT CHAR
|
|
CPI ' '+1 ;DONE IF LESS THAN SPACE
|
|
JRC SCAN4
|
|
CALL TSTEOL ;EOL?
|
|
JRZ SCAN4
|
|
INX H ;PT TO NEXT
|
|
CPI '=' ;EQUATE?
|
|
JRNZ SCAN3
|
|
SCAN4:
|
|
;
|
|
; SET ZERO FLAG TO INDICATE PRESENCE OF '?' IN DIR:FILENAME.TYP
|
|
;
|
|
QMCNT EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;NUMBER OF QUESTION MARKS
|
|
ORA A ;SET ZERO FLAG
|
|
RET
|
|
;
|
|
; SCANF -- SCAN TOKEN PTED TO BY HL FOR A MAX OF B BYTES; PLACE IT INTO
|
|
; FILE NAME FIELD PTED TO BY DE; EXPAND AND INTERPRET WILD CARDS OF
|
|
; '*' AND '?'; ON EXIT, DE PTS TO TERMINATING DELIMITER
|
|
;
|
|
SCANF:
|
|
CALL SDELM ;DONE IF DELIMITER ENCOUNTERED
|
|
RZ
|
|
INX D ;PT TO NEXT BYTE IN FCB
|
|
CPI '*' ;IS (DE) A WILD CARD?
|
|
JRNZ SCANF1 ;CONTINUE IF NOT
|
|
MVI A,'?' ;PLACE '?' IN FCB AND DON'T ADVANCE HL IF SO
|
|
STAX D
|
|
CALL SCQ ;SCANNER COUNT QUESTION MARKS
|
|
JR SCANF2
|
|
SCANF1:
|
|
STAX D ;STORE FILENAME CHAR IN FCB
|
|
INX H ;PT TO NEXT CHAR IN COMMAND LINE
|
|
CPI '?' ;CHECK FOR QUESTION MARK (WILD)
|
|
CZ SCQ ;SCANNER COUNT QUESTION MARKS
|
|
SCANF2:
|
|
DJNZ SCANF ;DECREMENT CHAR COUNT UNTIL 8 ELAPSED
|
|
SCANF3:
|
|
CALL SDELM ;8 CHARS OR MORE - SKIP UNTIL DELIMITER
|
|
RZ ;ZERO FLAG SET IF DELIMITER FOUND
|
|
INX H ;PT TO NEXT CHAR IN COMMAND LINE
|
|
JR SCANF3
|
|
;
|
|
; INCREMENT QUESTION MARK COUNT FOR SCANNER
|
|
; THIS ROUTINE INCREMENTS THE COUNT OF THE NUMBER OF QUESTION MARKS IN
|
|
; THE CURRENT FCB ENTRY
|
|
;
|
|
SCQ:
|
|
PUSH H ;SAVE HL
|
|
LXI H,QMCNT ;GET COUNT
|
|
INR M ;INCREMENT
|
|
POP H ;GET HL
|
|
RET
|
|
;
|
|
; SCAN FOR AND EXTRACT DISK/USER INFO ASSUMING DU: FORM
|
|
; ON ENTRY, DE PTS TO FIRST BYTE OF FCB CONTAINING POSSIBLE DU FORM
|
|
; ON EXIT, ZERO FLAG SET MEAN OK AND TEMPDR AND TEMPUSR SET
|
|
;
|
|
IF ACCPTDU ;ALLOW DU: FORM
|
|
DUSCAN:
|
|
XCHG ;PTR IN HL
|
|
INX H ;PT TO FIRST BYTE OF FN
|
|
MOV A,M ;GET FIRST CHAR
|
|
CPI 'A' ;CONVERT POSSIBLE DRIVE SPEC TO NUMBER
|
|
JRC DUS1 ;IF LESS THAN 'A', MUST BE DIGIT
|
|
;
|
|
; SET DISK NUMBER (A=1)
|
|
;
|
|
SUI 'A'-1 ;CONVERT DRIVE NUMBER TO 1-16
|
|
CPI MAXDISK+1 ;WITHIN RANGE?
|
|
JRNC DUSE1 ;INVALID DISK NUMBER
|
|
STA TEMPDR ;SET TEMPORARY DRIVE NUMBER
|
|
INX H ;PT TO NEXT CHAR
|
|
MOV A,M ;SEE IF IT IS A SPACE
|
|
CPI ' '
|
|
RZ
|
|
CALL DIGCK ;CHECK FOR DIGIT
|
|
RC
|
|
;
|
|
; SET USER NUMBER
|
|
;
|
|
DUS1:
|
|
PUSH H ;SAVE PTR TO DIGITS
|
|
MVI B,2 ;UP TO 2 DIGITS
|
|
DUS1A:
|
|
MOV A,M ;CHECK FOR DIGIT OR SPACE
|
|
CPI ' ' ;IF SPACE, THEN NO DIGIT
|
|
JRZ DUS2
|
|
CALL DIGCK ;CHECK FOR DIGIT
|
|
JRC DUSE
|
|
INX H
|
|
DJNZ DUS1A ;COUNT DOWN
|
|
MOV A,M ;3RD CHAR
|
|
CPI ' ' ;MUST BE SPACE
|
|
JRNZ DUSE
|
|
DUS2:
|
|
POP H
|
|
CALL NUM0A ;GET NUMBER
|
|
CPI MAXUSR+1 ;WITHIN LIMIT?
|
|
JRNC DUSE1
|
|
STA TEMPUSR ;SAVE USER NUMBER
|
|
XRA A ;SET OK
|
|
RET
|
|
DUSE:
|
|
POP H ;CLEAR STACK
|
|
DUSE1:
|
|
XRA A
|
|
DCR A
|
|
RET
|
|
;
|
|
ENDIF ;ACCPTDU
|
|
;
|
|
IF (Z3NDIR NE 0) AND NDINCP AND ACCPTND
|
|
;
|
|
; SCAN FOR DIR FORM
|
|
; ON ENTRY, DE PTS TO FCB CONTAINING NAME TO CHECK FOR
|
|
; ON EXIT, IF FOUND, Z AND TEMPUSR AND TEMPDR SET
|
|
;
|
|
DIRSCAN:
|
|
XCHG ;PTR IN HL
|
|
INX H ;PT TO FN
|
|
LXI D,Z3NDIR ;PT TO FIRST ENTRY IN MEMORY-BASED DIR
|
|
DIRS1:
|
|
LDAX D ;GET NEXT CHAR
|
|
ORA A ;ZERO IF END OF DIR
|
|
JRZ DIRSERR
|
|
INX D ;PT TO DIR NAME
|
|
INX D
|
|
PUSH H ;SAVE PTR TO FILE NAME
|
|
PUSH D ;SAVE PTR TO DIR ENTRY
|
|
MVI B,8 ;MATCH?
|
|
DIRS2:
|
|
LDAX D ;GET BYTE
|
|
CMP M ;COMPARE
|
|
JRNZ DIRS3
|
|
INX H ;PT TO NEXT
|
|
INX D
|
|
DJNZ DIRS2 ;COUNT DOWN
|
|
DIRS3:
|
|
POP D ;RESTORE REGS
|
|
POP H
|
|
JRZ DIRS4
|
|
XCHG ;ADVANCE TO NEXT ENTRY
|
|
LXI B,16 ;8 BYTES FOR NAME + 8 BYTES FOR PASSWORD
|
|
DAD B
|
|
XCHG
|
|
JR DIRS1
|
|
;
|
|
; NO DIR match
|
|
;
|
|
DIRSERR:
|
|
XRA A ;RETURN NZ
|
|
DCR A
|
|
RET
|
|
;
|
|
; DIR match
|
|
;
|
|
DIRS4:
|
|
;
|
|
IF PWCHECK
|
|
PUSH D ;SAVE PTR TO DE
|
|
LXI B,8 ;PT TO PW
|
|
XCHG ;HL PTS TO ENTRY
|
|
DAD B
|
|
CALL PASSCK ;CHECK FOR PW
|
|
POP D ;GET PTR
|
|
JNZ DIRSERR
|
|
ENDIF ;PWCHECK
|
|
;
|
|
DCX D ;PT TO USER
|
|
LDAX D ;GET USER
|
|
STA TEMPUSR
|
|
DCX D ;PT TO DISK
|
|
LDAX D ;GET IT
|
|
STA TEMPDR ;A=1
|
|
XRA A ;SET Z
|
|
RET
|
|
;
|
|
ENDIF ;(Z3NDIR NE 0) AND NDINCP AND ACCPTND
|
|
;
|
|
IF PWCHECK
|
|
;
|
|
; CHECK FOR PASSWORD PTED TO BY HL
|
|
; RETURN WITH ZERO FLAG SET IF MATCH
|
|
;
|
|
PASSCK:
|
|
MOV A,M ;CHECK FOR NO PW
|
|
CPI ' '
|
|
RZ
|
|
PUSH H ;SAVE PTR
|
|
CALL PRINT
|
|
DB CR,LF,'PW?',' '+80H
|
|
LXI D,PWLIN
|
|
MVI A,9 ;SET CHAR COUNT
|
|
STAX D
|
|
MVI C,10 ;BDOS READLN
|
|
PUSH D
|
|
CALL BDOS
|
|
POP H ;GET PTR TO BUFFER
|
|
INX H ;PT TO CHAR COUNT
|
|
MOV A,M ;GET CHAR COUNT
|
|
INX H ;PT TO FIRST CHAR
|
|
PUSH H ;SAVE PTR
|
|
CALL ADDAH ;HL PTS TO AFTER LAST CHAR
|
|
MVI M,' ' ;PLACE SPACE
|
|
POP D ;PT TO USER INPUT
|
|
POP H ;PT TO PASSWORD
|
|
MVI B,8 ;8 CHARS MAX
|
|
PWCK:
|
|
LDAX D ;GET NEXT CHAR
|
|
CALL UCASE ;CAPITALIZE USER INPUT
|
|
CMP M ;COMPARE FOR MATCH
|
|
RNZ ;NO MATCH
|
|
CPI ' ' ;DONE?
|
|
RZ
|
|
INX H ;PT TO NEXT
|
|
INX D
|
|
DJNZ PWCK
|
|
XRA A ;SET ZERO FLAG
|
|
RET
|
|
;
|
|
ENDIF ;PWCHECK
|
|
|
|
;
|
|
; SKIP OVER SPACES PTED TO BY HL
|
|
; ON RETURN, ZERO FLAG SET MEANS WE HIT EOL OR CMDSEP
|
|
;
|
|
SKSP:
|
|
MOV A,M ;GET NEXT CHAR
|
|
INX H ;PT TO NEXT
|
|
CPI ' ' ;SPACE?
|
|
JRZ SKSP
|
|
DCX H ;PT TO NON-SPACE
|
|
;
|
|
; CHECK TO SEE IF CHAR IN A IS EOL OR CMDSEP
|
|
;
|
|
TSTEOL:
|
|
ORA A ;EOL?
|
|
;
|
|
IF MULTCMD ;MULTIPLE COMMANDS SUPPORTED?
|
|
RZ ;RETURN WITH FLAG
|
|
CPI CMDSEP ;COMMAND SEPARATOR?
|
|
ENDIF ;MULTCMD
|
|
;
|
|
RET
|
|
|
|
;
|
|
; INIT FCB PTED TO BY DE
|
|
;
|
|
INITFCB:
|
|
XRA A
|
|
STAX D ;SET DEFAULT DISK (DN BYTE IS 0)
|
|
INX D ;PT TO FILE NAME FIELD
|
|
CALL IFCB ;FILL 1ST PART OF FCB; FALL THRU TO IFCB TO RUN AGAIN
|
|
;
|
|
; FILL FN, FT, EX, S1, S2, RC, AND FOLLOWING CR (OR DN) FIELDS
|
|
;
|
|
IFCB:
|
|
MVI B,11 ;STORE 11 SPACES
|
|
MVI A,' '
|
|
CALL FILL
|
|
XRA A
|
|
STAX D ;SET EX TO ZERO
|
|
INX D
|
|
LDA CURUSR
|
|
STAX D ;SET S1 TO CURRENT USER
|
|
INX D
|
|
MVI B,3 ;STORE 3 ZEROES
|
|
XRA A ;FALL THRU TO FILL
|
|
;
|
|
; FILL MEMORY POINTED TO BY DE WITH CHAR IN A FOR B BYTES
|
|
;
|
|
FILL:
|
|
STAX D ;FILL WITH BYTE IN A
|
|
INX D ;PT TO NEXT
|
|
DJNZ FILL
|
|
RET
|
|
;
|
|
; No File Error Message
|
|
;
|
|
PRNNF:
|
|
CALL PRINTC ;NO FILE MESSAGE
|
|
DB 'No Fil','e'+80H
|
|
RET
|
|
;
|
|
;**** Section 3 ****
|
|
; I/O UTILITIES
|
|
;
|
|
; OUTPUT CHAR IN REG A TO CONSOLE AND DON'T CHANGE BC
|
|
;
|
|
CONIN:
|
|
MVI C,1 ;INPUT CHAR
|
|
CALL BDOS ;GET INPUT CHAR WITH ^S PROCESSING AND ECHO
|
|
JMP UCASE ;CAPITALIZE
|
|
;
|
|
; OUTPUT <CRLF>
|
|
;
|
|
CRLF:
|
|
MVI A,CR
|
|
CALL CONOUT
|
|
MVI A,LF ;FALL THRU TO CONOUT
|
|
;
|
|
CONOUT:
|
|
PUTRG ;SAVE REGS
|
|
MVI C,2
|
|
OUTPUT:
|
|
MOV E,A
|
|
CALL BDOS
|
|
GETRG ;GET REGS
|
|
RET
|
|
;
|
|
LCOUT:
|
|
PUSH PSW ;OUTPUT CHAR TO CON: OR LST: DEP ON PRFLG
|
|
PRFLG EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;2ND BYTE (IMMEDIATE ARG) IS THE PRINT FLAG
|
|
ORA A ;0=TYPE
|
|
JRZ LC1
|
|
POP PSW ;GET CHAR
|
|
;
|
|
; OUTPUT CHAR IN REG A TO LIST DEVICE
|
|
;
|
|
LSTOUT:
|
|
PUTRG ;SAVE REGISTERS
|
|
MVI C,5
|
|
JR OUTPUT
|
|
LC1:
|
|
POP PSW ;GET CHAR
|
|
PUSH PSW
|
|
CALL CONOUT ;OUTPUT TO CON:
|
|
POP PSW
|
|
;
|
|
IF LTON
|
|
CPI LF ;CHECK FOR PAGING
|
|
RNZ
|
|
;
|
|
; PAGING ROUTINES
|
|
; PAGER COUNTS DOWN LINES AND PAUSES FOR INPUT (DIRECT) IF COUNT EXPIRES
|
|
; PAGSET SETS LINES/PAGE COUNT
|
|
;
|
|
PAGER:
|
|
PUSH H
|
|
LXI H,PAGCNT ;COUNT DOWN
|
|
DCR M
|
|
JRNZ PAGER1 ;JUMP IF NOT END OF PAGE
|
|
MVI M,NLINES-2 ;REFILL COUNTER
|
|
;
|
|
PGFLG EQU $+1 ;POINTER TO IN-THE-CODE BUFFER PGFLG
|
|
MVI A,0 ;0 MAY BE CHANGED BY PGFLG EQUATE
|
|
CPI PGDFLG ;PAGE DEFAULT OVERRIDE OPTION WANTED?
|
|
;
|
|
IF PGDFLT ;IF PAGING IS DEFAULT
|
|
JRZ PAGER1 ; PGDFLG MEANS NO PAGING
|
|
ELSE ;IF PAGING NOT DEFAULT
|
|
JRNZ PAGER1 ; PGDFLG MEANS PLEASE PAGINATE
|
|
;
|
|
ENDIF ;PGDFLG
|
|
;
|
|
PUSH B ;SAVE REG
|
|
CALL BIOS+9 ;BIOS CONSOLE INPUT ROUTINE
|
|
POP B ;GET REG
|
|
CPI 'C'-'@' ;^C
|
|
JZ RS1 ;RESTART CPR
|
|
PAGER1:
|
|
POP H ;RESTORE HL
|
|
|
|
ENDIF ;LTON
|
|
;
|
|
RET ;RETURN FOR LC1 IF NOT LTON
|
|
;
|
|
; READ FILE BLOCK FUNCTION
|
|
;
|
|
READF:
|
|
LXI D,TFCB ;FALL THRU TO READ
|
|
READ:
|
|
MVI C,14H ;FALL THRU TO BDOSB
|
|
;
|
|
; CALL BDOS AND SAVE BC
|
|
;
|
|
BDOSB:
|
|
PUSH B
|
|
CALL BDOS
|
|
POP B
|
|
ORA A
|
|
;
|
|
; THIS RETURN IS FOR BDOSB AND FOR THE NULL FUNCTION CALLED NOTE
|
|
;
|
|
NOTE:
|
|
RET
|
|
;
|
|
; PRINT STRING (ENDING IN CHAR WITH MSB SET) PTED TO BY RET ADR
|
|
; START WITH <CRLF>
|
|
;
|
|
PRINTC:
|
|
CALL CRLF ;NEW LINE
|
|
;
|
|
PRINT:
|
|
XTHL ;GET PTR TO STRING
|
|
CALL PRIN1 ;PRINT STRING
|
|
XTHL ;RESTORE HL AND RET ADR
|
|
RET
|
|
;
|
|
; PRINT STRING (ENDING IN 0 OR BYTE WITH MSB SET) PTED TO BY HL
|
|
;
|
|
PRIN1:
|
|
MOV A,M ;GET NEXT BYTE
|
|
INX H ;PT TO NEXT BYTE
|
|
ORA A ;END OF STRING?
|
|
RZ ;STRING TERMINATED BY BINARY 0
|
|
PUSH PSW ;SAVE FLAGS
|
|
ANI 7FH ;MASK OUT MSB
|
|
CALL CONOUT ;PRINT CHAR
|
|
POP PSW ;GET FLAGS
|
|
RM ;STRING TERMINATED BY MSB SET
|
|
JR PRIN1
|
|
;
|
|
; BDOS FUNCTION ROUTINES
|
|
;
|
|
;
|
|
; RETURN NUMBER OF CURRENT DISK IN A
|
|
;
|
|
GETDRV:
|
|
MVI C,19H
|
|
JR BDOSJP
|
|
;
|
|
; SET 80H AS DMA ADDRESS
|
|
;
|
|
DEFDMA:
|
|
LXI D,TBUFF ;80H=TBUFF
|
|
DMASET:
|
|
MVI C,1AH
|
|
JR BDOSJP
|
|
;
|
|
RESET:
|
|
MVI C,0DH
|
|
BDOSJP:
|
|
JMP BDOS
|
|
;
|
|
LOGIN:
|
|
MOV E,A
|
|
MVI C,0EH
|
|
JR BDOSJP ;SAVE SOME CODE SPACE
|
|
;
|
|
OPENF:
|
|
XRA A
|
|
STA FCBCR
|
|
LXI D,FCBDN ;FALL THRU TO OPEN
|
|
;
|
|
OPEN:
|
|
MVI C,0FH ;FALL THRU TO GRBDOS
|
|
;
|
|
GRBDOS:
|
|
CALL BDOS
|
|
INR A ;SET ZERO FLAG FOR ERROR RETURN
|
|
RET
|
|
;
|
|
CLOSE:
|
|
MVI C,10H
|
|
JR GRBDOS
|
|
;
|
|
SEARF:
|
|
LXI D,TFCB ;SPECIFY FCB
|
|
SEAR1:
|
|
MVI C,11H
|
|
JR GRBDOS
|
|
;
|
|
SEARN:
|
|
MVI C,12H
|
|
JR GRBDOS
|
|
;
|
|
; CHECK FOR SUBMIT FILE IN EXECUTION AND ABORT IT IF SO
|
|
;
|
|
IF SUBON ;ENABLE ONLY IF SUBMIT FACILITY IS ENABLED
|
|
;
|
|
SUBKIL:
|
|
LXI H,RNGSUB ;CHECK FOR SUBMIT FILE IN EXECUTION
|
|
MOV A,M
|
|
ORA A ;0=NO
|
|
RZ
|
|
MVI M,0 ;ABORT SUBMIT FILE
|
|
LXI D,SUBFCB ;DELETE $$$.SUB
|
|
;
|
|
ENDIF ;SUBON
|
|
;
|
|
DELETE:
|
|
MVI C,13H
|
|
JR BDOSJP ;SAVE MORE SPACE
|
|
;
|
|
; GET/SET USER NUMBER
|
|
;
|
|
GETUSR:
|
|
MVI A,0FFH ;GET CURRENT USER NUMBER
|
|
SETUSR:
|
|
MOV E,A ;USER NUMBER IN E
|
|
MVI C,20H ;SET USER NUMBER TO VALUE IN E (GET IF E=FFH)
|
|
JR BDOSJP ;MORE SPACE SAVING
|
|
;
|
|
; END OF BDOS FUNCTIONS
|
|
;
|
|
;
|
|
;**** Section 4 ****
|
|
; ZCPR3 UTILITIES
|
|
;
|
|
; SET USER/DISK FLAG TO CURRENT USER AND DEFAULT DISK
|
|
;
|
|
SETUD:
|
|
CALL GETUSR ;GET NUMBER OF CURRENT USER
|
|
ANI 0FH ;MASK SURE 4 BITS
|
|
ADD A ;PLACE IT IN HIGH NYBBLE
|
|
ADD A
|
|
ADD A
|
|
ADD A
|
|
LXI H,CURDR ;MASK IN CURRENT DRIVE NUMBER (LOW NYBBLE)
|
|
ORA M ;MASK IN
|
|
STA UDFLAG ;SET USER/DISK NUMBER
|
|
RET
|
|
;
|
|
; CONVERT CHAR IN A TO UPPER CASE
|
|
;
|
|
UCASE:
|
|
ANI 7FH ;MASK OUT MSB
|
|
CPI 61H ;LOWER-CASE A
|
|
RC
|
|
CPI 7BH ;GREATER THAN LOWER-CASE Z?
|
|
RNC
|
|
ANI 5FH ;CAPITALIZE
|
|
RET
|
|
;
|
|
; PRINT DU (DIR) PROMPT
|
|
;
|
|
PROMPT:
|
|
;
|
|
; PRINT PROMPT (DU>)
|
|
;
|
|
CALL CRLF ;PRINT PROMPT
|
|
;
|
|
IF INCLDU ;IF DRIVE IN PROMPT
|
|
LDA CURDR ;CURRENT DRIVE IS PART OF PROMPT
|
|
ADI 'A' ;CONVERT TO ASCII A-P
|
|
CALL CONOUT
|
|
LDA CURUSR ;GET USER NUMBER
|
|
;
|
|
IF SUPRES ;IF SUPPRESSING USR # REPORT FOR USR 0
|
|
ORA A
|
|
JRZ PRMPT2
|
|
ENDIF ;SUPRES
|
|
;
|
|
CPI 10 ;USER < 10?
|
|
JRC PRMPT1
|
|
SUI 10 ;SUBTRACT 10 FROM IT
|
|
PUSH PSW ;SAVE IT
|
|
MVI A,'1' ;OUTPUT 10'S DIGIT
|
|
CALL CONOUT
|
|
POP PSW
|
|
PRMPT1:
|
|
ADI '0' ;OUTPUT 1'S DIGIT (CONVERT TO ASCII)
|
|
CALL CONOUT
|
|
PRMPT2:
|
|
ENDIF ;INCLDU
|
|
;
|
|
; PRINT NDIR ENTRY IF ANY
|
|
;
|
|
IF INCLNDR AND (Z3NDIR NE 0)
|
|
;
|
|
LDA CURDR ;GET CURRENT DU IN BC
|
|
INR A
|
|
MOV B,A
|
|
LDA CURUSR
|
|
MOV C,A
|
|
LXI H,Z3NDIR ;SCAN DIRECTORY FOR MATCH
|
|
;
|
|
; MAIN LOOP FOR SCANNING NDR FOR DU IN BC
|
|
;
|
|
PRMPT3:
|
|
MOV A,M ;END OF NDR?
|
|
ORA A
|
|
RZ
|
|
INX H ;PT TO USER
|
|
CMP B ;COMPARE DISK
|
|
JRNZ PRMPT5
|
|
MOV A,M ;COMPARE USER
|
|
CMP C
|
|
JRNZ PRMPT5
|
|
;
|
|
; MATCH OF DU
|
|
;
|
|
IF INCLDU ;SEPARATE DU AND NDR WITH COLON
|
|
MVI A,':' ;PRINT SEPARATOR
|
|
CALL CONOUT
|
|
ENDIF ;INCLDU
|
|
;
|
|
MVI B,8 ;8 CHARS MAX
|
|
PRMPT4:
|
|
INX H ;PT TO NEXT CHAR
|
|
MOV A,M ;GET NEXT CHAR
|
|
CPI ' ' ;DONE IF SPACE
|
|
RZ
|
|
CALL CONOUT ;PRINT CHAR
|
|
DJNZ PRMPT4 ;COUNT DOWN
|
|
RET
|
|
;
|
|
; ADVANCE TO NEXT DU
|
|
;
|
|
PRMPT5:
|
|
LXI D,16+1 ;SKIP USER (1 BYTE) AND NAME/PW (16 BYTES)
|
|
DAD D
|
|
JR PRMPT3 ;CONTINUE SCAN
|
|
;
|
|
ENDIF ;INCLNDR AND (Z3NDIR NE 0)
|
|
;
|
|
RET
|
|
;
|
|
; INPUT NEXT COMMAND TO CPR
|
|
; This routine determines if a SUBMIT file is being processed
|
|
; and extracts the command line from it if so or from the user's console
|
|
;
|
|
READBUF:
|
|
;
|
|
IF SUBON ;IF SUBMIT FACILITY IS ENABLED, CHECK FOR IT
|
|
;
|
|
LDA RNGSUB ;SUBMIT FILE CURRENTLY IN EXECUTION?
|
|
ORA A ;0=NO
|
|
JRZ RB1 ;GET LINE FROM CONSOLE IF NOT
|
|
LXI D,SUBFCB ;OPEN $$$.SUB
|
|
PUSH D ;SAVE DE
|
|
CALL OPEN
|
|
POP D ;RESTORE DE
|
|
JRZ RB1 ;ERASE $$$.SUB IF END OF FILE AND GET CMND
|
|
LDA SUBFRC ;GET VALUE OF LAST RECORD IN FILE
|
|
DCR A ;PT TO NEXT TO LAST RECORD
|
|
STA SUBFCR ;SAVE NEW VALUE OF LAST RECORD IN $$$.SUB
|
|
CALL READ ;DE=SUBFCB
|
|
JRNZ RB1 ;ABORT $$$.SUB IF ERROR IN READING LAST REC
|
|
LXI D,CHRCNT ;COPY LAST RECORD (NEXT SUBMIT CMND) TO CHRCNT
|
|
LXI H,TBUFF ; FROM TBUFF
|
|
MVI B,BUFLEN ;NUMBER OF BYTES
|
|
CALL LDIR
|
|
LXI H,SUBFS2 ;PT TO S2 OF $$$.SUB FCB
|
|
MVI M,0 ;SET S2 TO ZERO
|
|
INX H ;PT TO RECORD COUNT
|
|
DCR M ;DECREMENT RECORD COUNT OF $$$.SUB
|
|
LXI D,SUBFCB ;CLOSE $$$.SUB
|
|
CALL CLOSE
|
|
JRZ RB1 ;ABORT $$$.SUB IF ERROR
|
|
CALL PROMPT ;PRINT PROMPT
|
|
MVI A,SPRMPT ;PRINT SUBMIT PROMPT TRAILER
|
|
CALL CONOUT
|
|
LXI H,CMDLIN ;PRINT COMMAND LINE FROM $$$.SUB
|
|
CALL PRIN1
|
|
CALL BREAK ;CHECK FOR ABORT (ANY CHAR)
|
|
RNZ ;IF NO ^C, RETURN TO CALLER AND RUN
|
|
CALL SUBKIL ;KILL $$$.SUB IF ABORT
|
|
JMP RESTRT ;RESTART CPR
|
|
;
|
|
; INPUT COMMAND LINE FROM USER CONSOLE
|
|
;
|
|
RB1:
|
|
CALL SUBKIL ;ERASE $$$.SUB IF PRESENT
|
|
;
|
|
ENDIF ;SUBON
|
|
;
|
|
; IF SHELL STACKS ARE IMPLEMENTED, CHECK FOR CONTENT AT THIS TIME
|
|
;
|
|
IF SHSTK NE 0
|
|
;
|
|
LXI H,SHSTK ;PT TO STACK
|
|
MOV A,M ;CHECK FIRST BYTE
|
|
CPI ' '+1 ;SEE IF ANY ENTRY
|
|
JRC RB2 ;GET USER INPUT IF NONE
|
|
;
|
|
ENDIF ;SHSTK NE 0
|
|
;
|
|
IF (SHSTK NE 0) OR (Z3MSG NE 0)
|
|
;
|
|
RUNBUF:
|
|
LXI D,CMDLIN ;PT TO FIRST CHAR OF COMMAND LINE
|
|
MVI B,SHSIZE ;COPY SHELL LINE INTO COMMAND LINE BUFFER
|
|
CALL LDIR ;DO COPY
|
|
XCHG ;HL PTS TO END OF LINE
|
|
MVI A,1 ;SAY SHELL WAS INVOKED
|
|
STA Z3MSG+3 ;Z3 OUTPUT MESSAGE
|
|
JR RB3 ;STORE ENDING ZERO AND EXIT
|
|
RB2:
|
|
;
|
|
ENDIF ;(SHSTK NE 0) OR (Z3MSG NE 0)
|
|
;
|
|
CALL PROMPT ;PRINT PROMPT
|
|
MVI A,CPRMPT ;PRINT PROMPT TRAILER
|
|
CALL CONOUT
|
|
MVI C,0AH ;READ COMMAND LINE FROM USER
|
|
LXI D,BUFSIZ ;PT TO BUFFER SIZE BYTE OF COMMAND LINE
|
|
CALL BDOS
|
|
;
|
|
; STORE ZERO AT END OF COMMAND LINE
|
|
;
|
|
LXI H,CHRCNT ;PT TO CHAR COUNT
|
|
MOV A,M ;GET CHAR COUNT
|
|
INX H ;PT TO FIRST CHAR OF COMMAND LINE
|
|
CALL ADDAH ;PT TO AFTER LAST CHAR OF COMMAND LINE
|
|
RB3:
|
|
MVI M,0 ;STORE ENDING ZERO
|
|
RET
|
|
;
|
|
; CHECK FOR ANY CHAR FROM USER CONSOLE; RET W/ZERO SET IF NONE
|
|
;
|
|
BREAK:
|
|
PUTRG ;SAVE REGISTERS
|
|
CALL BIOS+6 ;CONSOLE STATUS CHECK
|
|
ORA A ;SET FLAGS
|
|
CNZ BIOS+9 ;GET INPUT CHAR WITH ^S PROCESSING
|
|
CPI 'S'-'@' ;PAUSE IF ^S
|
|
CZ BIOS+9 ;GET NEXT CHAR
|
|
GETRG ;RESTORE REGISTERS
|
|
CPI 'C'-'@' ;CHECK FOR ABORT
|
|
RET
|
|
|
|
;
|
|
; CHECK TO SEE IF HL PTS TO DELIMITER; IF SO, RET W/ZERO FLAG SET
|
|
;
|
|
SDELM:
|
|
MOV A,M ;GET NEXT CHAR FROM LINE
|
|
CPI ' '+1 ;DELIM IF <= <SP>
|
|
JRC ZERO
|
|
CPI '=' ;'='=DELIMITER
|
|
RZ
|
|
CPI 5FH ;UNDERSCORE=DELIMITER
|
|
RZ
|
|
CPI '.' ;'.'=DELIMITER
|
|
RZ
|
|
CPI ':' ;':'=DELIMITER
|
|
RZ
|
|
CPI ',' ;','=DELIMITER
|
|
RZ
|
|
;
|
|
IF CMDSEP NE ';'
|
|
CPI ';' ;';'=DELIMITER
|
|
RZ
|
|
ENDIF
|
|
;
|
|
CPI '<' ;'<'=DELIMITER
|
|
RZ
|
|
CPI '>' ;'>'=DELIMITER
|
|
RZ
|
|
JMP TSTEOL ;CHECK FOR EOL
|
|
ZERO:
|
|
XRA A ;SET ZERO FLAG
|
|
RET
|
|
;
|
|
; ADD A TO HL (HL=HL+A)
|
|
;
|
|
ADDAH:
|
|
ADD L
|
|
MOV L,A
|
|
RNC
|
|
INR H
|
|
RET
|
|
;
|
|
; COPY FROM HL TO DE FOR B BYTES
|
|
;
|
|
LDIR:
|
|
MOV A,M ;GET BYTE
|
|
STAX D ;PUT BYTE
|
|
INX H ;PT TO NEXT
|
|
INX D
|
|
DJNZ LDIR
|
|
RET
|
|
;
|
|
; EXTRACT DECIMAL NUMBER FROM COMMAND LINE
|
|
; RETURN WITH VALUE IN REG A; ALL REGISTERS MAY BE AFFECTED
|
|
;
|
|
NUMBER:
|
|
LXI H,TFCB+8 ;PT TO END OF TOKEN FOR CONVERSION
|
|
MVI B,8 ;8 CHARS MAX
|
|
;
|
|
; CHECK FOR SUFFIX FOR HEXADECIMAL NUMBER
|
|
;
|
|
NUMS:
|
|
MOV A,M ;GET CHARS FROM END, SEARCHING FOR SUFFIX
|
|
DCX H ;BACK UP
|
|
CPI ' ' ;SPACE?
|
|
JRNZ NUMS1 ;CHECK FOR SUFFIX
|
|
DJNZ NUMS ;COUNT DOWN
|
|
JR NUM0 ;BY DEFAULT, PROCESS
|
|
NUMS1:
|
|
CPI NUMBASE ;CHECK AGAINST BASE SWITCH FLAG
|
|
JRZ HEXNUM
|
|
;
|
|
; PROCESS DECIMAL NUMBER
|
|
;
|
|
NUM0:
|
|
LXI H,TFCB+1 ;PT TO BEGINNING OF TOKEN
|
|
NUM0A:
|
|
LXI B,1100H ;C=ACCUMULATED VALUE, B=CHAR COUNT
|
|
; (C=0, B=11)
|
|
NUM1:
|
|
MOV A,M ;GET CHAR
|
|
CALL SDELM ;DONE IF DELIMITER
|
|
JRZ NUM2
|
|
INX H ;PT TO NEXT CHAR
|
|
CALL DIGCK ;CHECK FOR DIGIT IN A
|
|
JRC NUMERR
|
|
MOV D,A ;DIGIT IN D
|
|
MOV A,C ;NEW VALUE = OLD VALUE * 10
|
|
RLC ;*2
|
|
JRC NUMERR
|
|
RLC ;*4
|
|
JRC NUMERR
|
|
ADD C ;*5
|
|
JRC NUMERR
|
|
RLC ;*10
|
|
JRC NUMERR
|
|
ADD D ;NEW VALUE = OLD VALUE * 10 + DIGIT
|
|
JRC NUMERR ;CHECK FOR RANGE ERROR
|
|
MOV C,A ;SET NEW VALUE
|
|
DJNZ NUM1 ;COUNT DOWN
|
|
;
|
|
; RETURN FROM NUMBER
|
|
;
|
|
NUM2:
|
|
MOV A,C ;GET ACCUMULATED VALUE
|
|
RET
|
|
;
|
|
; NUMBER ERROR ROUTINE FOR SPACE CONSERVATION
|
|
;
|
|
NUMERR:
|
|
JMP ERROR ;USE ERROR ROUTINE - THIS IS RELATIVE PT
|
|
;
|
|
; CHECK TO SEE IF A IS A DIGIT
|
|
; IF SO, RETURN ITS VALUE
|
|
; IF NOT, RETURN WITH CARRY SET
|
|
;
|
|
DIGCK:
|
|
SUI '0' ;DIGIT?
|
|
RC ;ERROR
|
|
CPI 10 ;RANGE?
|
|
JRNC DIGCK1
|
|
CMC ;FLIP CARRY
|
|
RET
|
|
DIGCK1:
|
|
STC ;SET CARRY
|
|
RET
|
|
;
|
|
; EXTRACT HEXADECIMAL NUMBER FROM COMMAND LINE
|
|
; RETURN WITH VALUE IN REG A; ALL REGISTERS MAY BE AFFECTED
|
|
;
|
|
HEXNUM:
|
|
LXI H,TFCB+1 ;PT TO TOKEN FOR CONVERSION
|
|
LXI D,0 ;DE=ACCUMULATED VALUE
|
|
MVI B,11 ;B=CHAR COUNT
|
|
HNUM1:
|
|
MOV A,M ;GET CHAR
|
|
CPI ' ' ;DONE?
|
|
JRZ HNUM3 ;RETURN IF SO
|
|
CPI NUMBASE ;DONE IF NUMBASE SUFFIX
|
|
JRZ HNUM3
|
|
SUI '0' ;CONVERT TO BINARY
|
|
JRC NUMERR ;RETURN AND DONE IF ERROR
|
|
CPI 10 ;0-9?
|
|
JRC HNUM2
|
|
SUI 7 ;A-F?
|
|
CPI 10H ;ERROR?
|
|
JRNC NUMERR
|
|
HNUM2:
|
|
INX H ;PT TO NEXT CHAR
|
|
MOV C,A ;DIGIT IN C
|
|
MOV A,D ;GET ACCUMULATED VALUE
|
|
RLC ;EXCHANGE NYBBLES
|
|
RLC
|
|
RLC
|
|
RLC
|
|
ANI 0F0H ;MASK OUT LOW NYBBLE
|
|
MOV D,A
|
|
MOV A,E ;SWITCH LOW-ORDER NYBBLES
|
|
RLC
|
|
RLC
|
|
RLC
|
|
RLC
|
|
MOV E,A ;HIGH NYBBLE OF E=NEW HIGH OF E,
|
|
; LOW NYBBLE OF E=NEW LOW OF D
|
|
ANI 0FH ;GET NEW LOW OF D
|
|
ORA D ;MASK IN HIGH OF D
|
|
MOV D,A ;NEW HIGH BYTE IN D
|
|
MOV A,E
|
|
ANI 0F0H ;MASK OUT LOW OF E
|
|
ORA C ;MASK IN NEW LOW
|
|
MOV E,A ;NEW LOW BYTE IN E
|
|
DJNZ HNUM1 ;COUNT DOWN
|
|
;
|
|
; RETURN FROM HEXNUM
|
|
;
|
|
HNUM3:
|
|
XCHG ;RETURNED VALUE IN HL
|
|
MOV A,L ;LOW-ORDER BYTE IN A
|
|
RET
|
|
;
|
|
; LOG INTO DU CONTAINED IN FCB PTED TO BY DE
|
|
;
|
|
FCBLOG:
|
|
PUSH D ;SAVE PTR TO FCB
|
|
XCHG
|
|
MOV A,M ;GET DRIVE
|
|
STA TEMPDR ;SET TEMP DRIVE
|
|
LXI B,13 ;PT TO S1 FIELD
|
|
DAD B
|
|
MOV A,M ;GET USER
|
|
STA TEMPUSR ;SET TEMP USER
|
|
CALL SLOGIN ;LOG IN
|
|
POP D ;GET PTR TO FCB
|
|
RET
|
|
;
|
|
; CHECK FOR SPECIFIED DRIVE AND LOG IT IN
|
|
;
|
|
SLOGIN:
|
|
TEMPDR EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;2ND BYTE (IMMEDIATE ARG) IS TEMPDR
|
|
ORA A ;0=CURRENT DRIVE
|
|
JRNZ SLOG1
|
|
LDA CURDR ;LOG IN CURRENT DRIVE
|
|
INR A ;ADD 1 FOR NEXT DCR
|
|
SLOG1:
|
|
DCR A ;ADJUST FOR PROPER DISK NUMBER (A=0)
|
|
CALL LOGIN ;LOG IN NEW DRIVE
|
|
TEMPUSR EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;2ND BYTE IS USER TO BE SELECTED
|
|
JMP SETUSR ;LOG IN NEW USER
|
|
;
|
|
; ROUTINE TO CHECK FOR A WHEEL BYTE AS NON-ZERO
|
|
; IF WHEEL BYTE IS ZERO, THEN ABORT (POP STACK AND RETURN)
|
|
;
|
|
;
|
|
IF WHEEL ;WHEEL FACILITY?
|
|
WHLCHK:
|
|
LDA Z3WHL ;GET WHEEL BYTE
|
|
ORA A ;ZERO?
|
|
RNZ ;OK IF NOT
|
|
JMP ERROR ;PROCESS AS ERROR
|
|
ENDIF ;WHEEL
|
|
;
|
|
|
|
;
|
|
; CMDTBL (COMMAND TABLE) SCANNER
|
|
; ON RETURN, HL CONTAINS ADDRESS OF COMMAND IF CPR-RESIDENT
|
|
; ON RETURN, ZERO FLAG SET MEANS CPR-RESIDENT COMMAND
|
|
;
|
|
CMDSER:
|
|
LXI H,CMDTBL ;PT TO COMMAND TABLE
|
|
;
|
|
; ENTRY POINT TO PERMIT RCP TABLE TO BE SCANNED
|
|
;
|
|
CMDSCAN:
|
|
MOV B,M ;GET SIZE OF COMMAND TEXT
|
|
INX H ;PT TO FIRST COMMAND
|
|
CMS1:
|
|
MOV A,M ;CHECK FOR END OF TABLE
|
|
ORA A
|
|
JRZ CMS5
|
|
LXI D,FCBFN ;PT TO STORED COMMAND NAME
|
|
PUSH B ;SAVE SIZE OF COMMAND TEXT
|
|
CMS2:
|
|
LDAX D ;COMPARE AGAINST TABLE ENTRY
|
|
CMP M
|
|
JRNZ CMS3 ;NO MATCH
|
|
INX D ;PT TO NEXT CHAR
|
|
INX H
|
|
DJNZ CMS2 ;COUNT DOWN
|
|
LDAX D ;NEXT CHAR IN INPUT COMMAND MUST BE <SP>
|
|
CPI ' '
|
|
JRNZ CMS4
|
|
POP B ;CLEAR STACK
|
|
MOV A,M ;GET ADDRESS FROM TABLE INTO HL
|
|
INX H
|
|
MOV H,M
|
|
MOV L,A ;HL CONTAINS ADDRESS
|
|
XRA A ;ZERO FLAG SET FOR COMMAND FOUND
|
|
RET ;COMMAND IS RESIDENT (ZERO FLAG SET)
|
|
CMS3:
|
|
INX H ;SKIP TO NEXT COMMAND TABLE ENTRY
|
|
DJNZ CMS3
|
|
CMS4:
|
|
POP B ;GET SIZE OF COMMAND TEXT
|
|
INX H ;SKIP ADDRESS
|
|
INX H
|
|
JR CMS1
|
|
CMS5:
|
|
XRA A ;SET NZ
|
|
DCR A ;COMMAND NOT FOUND IF NZ
|
|
RET
|
|
|
|
;
|
|
;**** Section 5 ****
|
|
; CPR-Resident Commands
|
|
;
|
|
;
|
|
;Section 5A
|
|
;Command: DIR
|
|
;Function: To display a directory of the files on disk
|
|
;Forms:
|
|
; DIR <afn> Displays the DIR files
|
|
; DIR <afn> S Displays the SYS files
|
|
; DIR <afn> A Display both DIR and SYS files
|
|
;Notes:
|
|
; The flag SYSFLG defines the letter used to display both DIR and
|
|
; SYS files (A in the above Forms section)
|
|
; The flag SOFLG defines the letter used to display only the SYS
|
|
; files (S in the above Forms section)
|
|
; The flag WIDE determines if the file names are spaced further
|
|
; apart (WIDE=TRUE) for 80-col screens
|
|
; The flag FENCE defines the character used to separate the file
|
|
; names
|
|
;
|
|
IF DIRON ;DIR ENABLED
|
|
;
|
|
DIR:
|
|
LXI D,TFCB ;PT TO TARGET FCB
|
|
PUSH D ;SAVE PTR
|
|
INX D ;PT TO FILE NAME
|
|
LDAX D ;GET FIRST CHAR
|
|
CPI ' ' ;IF <SP>, MAKE ALL WILD
|
|
JRNZ DIR1
|
|
MVI B,11 ;11 BYTES
|
|
MVI A,'?' ;WILD
|
|
CALL FILL
|
|
DIR1:
|
|
POP D ;GET PTR TO FCB
|
|
LXI D,TFCB ;PT TO TARGET FCB
|
|
CALL FCBLOG ;LOG IN TEMP DISK/USER
|
|
LDA TFCB2+1 ;LOOK AT NEXT INPUT CHAR
|
|
MVI B,80H ;PREPARE FOR DIR-ONLY SELECTION
|
|
CPI ' '
|
|
JRZ DIRPR ;THERE IS NO FLAG, SO DIR ONLY
|
|
MVI B,1 ;SET FOR BOTH DIR AND SYS FILES
|
|
CPI SYSFLG ;SYSTEM AND DIR FLAG SPECIFIER?
|
|
JRZ DIRPR ;GOT SYSTEM SPECIFIER
|
|
CPI SOFLG ;SYS ONLY?
|
|
JRNZ DIRPR
|
|
DCR B ;B=0 FOR SYS FILES ONLY
|
|
;DROP INTO DIRPR TO PRINT DIRECTORY
|
|
; THEN RESTART CPR
|
|
;
|
|
ENDIF ;DIRON
|
|
;
|
|
; DIRECTORY PRINT ROUTINE; ON ENTRY, B REG IS SET AS FOLLOWS:
|
|
; 0 FOR ONLY SYSTEM FILES, 80H FOR ONLY DIR FILES, 1 FOR BOTH
|
|
;
|
|
IF DIRON OR ERAON
|
|
;
|
|
DIRPR:
|
|
MOV A,B ;GET FLAG
|
|
STA SYSTST ;SET SYSTEM TEST FLAG
|
|
MVI E,0 ;SET COLUMN COUNTER TO ZERO
|
|
PUSH D ;SAVE COLUMN COUNTER (E)
|
|
CALL SEARF ;SEARCH FOR SPECIFIED FILE (FIRST OCCURRENCE)
|
|
JRNZ DIR3
|
|
CALL PRNNF ;PRINT NO FILE MSG; REG A NOT CHANGED
|
|
XRA A ;SET ZERO FLAG IN CASE CALLED BY ERA
|
|
POP D ;RESTORE DE
|
|
RET
|
|
;
|
|
; ENTRY SELECTION LOOP; ON ENTRY, A=OFFSET FROM SEARF OR SEARN
|
|
;
|
|
DIR3:
|
|
CALL GETSBIT ;GET AND TEST FOR TYPE OF FILES
|
|
JRZ DIR6
|
|
POP D ;GET ENTRY COUNT (=<CR> COUNTER)
|
|
MOV A,E ;GET ENTRY COUNTER
|
|
INR E ;INCREMENT ENTRY COUNTER
|
|
PUSH D ;SAVE IT
|
|
ANI 03H ;OUTPUT <CRLF> IF 4 ENTRIES PRINTED IN LINE
|
|
JRNZ DIR4
|
|
CALL CRLF ;NEW LINE
|
|
JR DIR5
|
|
DIR4:
|
|
CALL PRINT
|
|
;
|
|
IF WIDE
|
|
;
|
|
DB ' ' ;2 SPACES
|
|
DB FENCE ;THEN FENCE CHAR
|
|
DB ' ',' '+80H ;THEN 2 MORE SPACES
|
|
;
|
|
ELSE
|
|
;
|
|
DB ' ' ;SPACE
|
|
DB FENCE ;THEN FENCE CHAR
|
|
DB ' '+80H ;THEN SPACE
|
|
;
|
|
ENDIF ;WIDE
|
|
;
|
|
DIR5:
|
|
; MVI B,01H ;PT TO 1ST BYTE OF FILE NAME
|
|
; MOV A,B ;A=OFFSET
|
|
MVI A,1 ;PT TO 1ST BYTE OF FILE NAME
|
|
CALL DIRPTR ;HL NOW PTS TO 1ST BYTE OF FILE NAME
|
|
CALL PRFN ;PRINT FILE NAME
|
|
DIR6:
|
|
CALL BREAK ;CHECK FOR ABORT
|
|
JRZ DIR7
|
|
CALL SEARN ;SEARCH FOR NEXT FILE
|
|
JRNZ DIR3 ;CONTINUE IF FILE FOUND
|
|
DIR7:
|
|
POP D ;RESTORE STACK
|
|
MVI A,0FFH ;SET NZ FLAG
|
|
ORA A
|
|
RET
|
|
;
|
|
ENDIF ;DIRON OR ERAON
|
|
;
|
|
; PRINT FILE NAME PTED TO BY HL
|
|
;
|
|
PRFN:
|
|
MVI B,8 ;8 CHARS
|
|
CALL PRFN1
|
|
MVI A,'.' ;DOT
|
|
CALL CONOUT
|
|
MVI B,3 ;3 CHARS
|
|
PRFN1:
|
|
MOV A,M ; GET CHAR
|
|
INX H ; PT TO NEXT
|
|
CALL CONOUT ; PRINT CHAR
|
|
DCR B ; COUNT DOWN
|
|
JRNZ PRFN1
|
|
RET
|
|
;
|
|
; PT TO DIRECTORY ENTRY IN TBUFF WHOSE OFFSET IS SPECIFIED BY A AND C
|
|
;
|
|
DIRPTR:
|
|
LXI H,TBUFF ;PT TO TEMP BUFFER
|
|
ADD C ;PT TO 1ST BYTE OF DIR ENTRY
|
|
CALL ADDAH ;PT TO DESIRED BYTE IN DIR ENTRY
|
|
MOV A,M ;GET DESIRED BYTE
|
|
RET
|
|
;
|
|
; AFTER A SEARCH, RETURN NZ SET IF DESIRED TYPE OF FILE FOUND, Z IF NOT
|
|
; THIS ALGORITHM LOOKS AT THE SYSTEM BIT OF THE LOCATED FILE; THIS
|
|
; BIT IS SET TO 1 IF THE FILE IS A SYSTEM FILE AND 0 IF NOT A SYSTEM
|
|
; FILE. THE FOLLOWING EXCLUSIVE OR MASKS ARE APPLIED TO RETURN Z OR NZ
|
|
; AS REQUIRED BY THE CALLING PROGRAM:
|
|
;
|
|
; SYSTEM BYTE: X 0 0 0 0 0 0 0 (AFTER 80H MASK, X=1 IF SYS, 0 IF DIR)
|
|
;
|
|
; SYS-ONLY : 0 0 0 0 0 0 0 0 (XOR 0 = 0 if X=0, = 80H if X=1)
|
|
; DIR-ONLY : 1 0 0 0 0 0 0 0 (XOR 80H = 80h if X=0, = 0 if X=1)
|
|
; BOTH : 0 0 0 0 0 0 0 1 (XOR 1 = 81H or 1H, NZ in both cases)
|
|
;
|
|
GETSBIT:
|
|
DCR A ;ADJUST TO RETURNED VALUE
|
|
RRC ;CONVERT NUMBER TO OFFSET INTO TBUFF
|
|
RRC
|
|
RRC
|
|
ANI 60H
|
|
MOV C,A ;OFFSET INTO TBUFF IN C (C=OFFSET TO ENTRY)
|
|
MVI A,10 ;ADD 10 TO PT TO SYSTEM FILE ATTRIBUTE BIT
|
|
CALL DIRPTR ;A=SYSTEM BYTE
|
|
ANI 80H ;LOOK AT ONLY SYSTEM BIT
|
|
SYSTST EQU $+1 ;IN-THE-CODE VARIABLE
|
|
XRI 0 ; IF SYSTST=0, SYS ONLY; IF SYSTST=80H, DIR
|
|
; ONLY; IF SYSTST=1, BOTH SYS AND DIR
|
|
RET ;NZ IF OK, Z IF NOT OK
|
|
;
|
|
;Section 5B
|
|
;Command: ERA
|
|
;Function: Erase files
|
|
;Forms:
|
|
; ERA <afn> Erase Specified files and print their names
|
|
; ERA <afn> V Erase Specified files and print their names, but ask
|
|
; for verification before Erase is done
|
|
;Notes:
|
|
; Several Key Flags affect this command:
|
|
; ERAV - If TRUE, the V option is enabled, and the character
|
|
; which turns it on (the V) is defined by ERDFLG
|
|
; ERAOK - If TRUE, the OK? prompt is enabled
|
|
; If ERAOK is FALSE, the verification feature is disabled regardless
|
|
; of what value ERAV has
|
|
; If ERAOK is TRUE, then:
|
|
; If ERAV is TRUE, verification is requested only if the V
|
|
; flag (actual letter defined by ERDFLG) is in the
|
|
; command line
|
|
; If ERAV is FALSE, verification is always requested, and a
|
|
; V flag in the command line will cause an error
|
|
; message to be printed (V?) after the ERA is completed
|
|
;
|
|
IF ERAON ;ERA ENABLED?
|
|
;
|
|
ERA:
|
|
;
|
|
IF WERA ;WHEEL FACILITY ENABLED?
|
|
CALL WHLCHK ;CHECK FOR IT
|
|
ENDIF ;WERA
|
|
;
|
|
IF ERAV AND ERAOK ;V FLAG AND OK? ENABLED?
|
|
LDA TFCB2+1 ;GET ERAFLG IF IT'S THERE
|
|
STA ERAFLG ;SAVE IT AS A FLAG
|
|
ENDIF ;ERAV
|
|
;
|
|
LXI D,TFCB ;PT TO TARGET FCB
|
|
CALL FCBLOG ;LOG INTO DU IN FCB
|
|
MVI B,1 ;DISPLAY ALL MATCHING FILES
|
|
CALL DIRPR ;PRINT DIRECTORY OF ERASED FILES
|
|
RZ ;ABORT IF NO FILES
|
|
;
|
|
IF ERAOK ;PRINT PROMPT
|
|
;
|
|
IF ERAV ;TEST VERIFY FLAG
|
|
;
|
|
ERAFLG EQU $+1 ;ADDRESS OF FLAG
|
|
MVI A,0 ;2ND BYTE IS FLAG
|
|
CPI ERDFLG ;IS IT A VERIFY OPTION?
|
|
JRNZ ERA2 ;SKIP PROMPT IF IT IS NOT
|
|
;
|
|
ENDIF ;ERAV
|
|
;
|
|
CALL PRINTC
|
|
DB 'OK to Erase','?'+80H
|
|
CALL CONIN ;GET REPLY
|
|
CPI 'Y' ;YES?
|
|
RNZ ;ABORT IF NOT
|
|
;
|
|
ENDIF ;ERAOK
|
|
;
|
|
ERA2:
|
|
LXI D,TFCB ;DELETE FILE SPECIFIED
|
|
JMP DELETE ;DELETE FILE AND REENTER CCP
|
|
;
|
|
ENDIF ;ERAON
|
|
;
|
|
;Section 5C
|
|
;Command: LIST
|
|
;Function: Print out specified file on the LST: Device
|
|
;Forms:
|
|
; LIST <ufn> Print file (NO Paging)
|
|
;Notes:
|
|
; The flags which apply to TYPE do not take effect with LIST
|
|
;
|
|
IF LTON ;LIST AND TYPE ENABLED?
|
|
;
|
|
LIST:
|
|
MVI A,0FFH ;TURN ON PRINTER FLAG
|
|
JR TYPE0
|
|
;
|
|
;Section 5D
|
|
;Command: TYPE
|
|
;Function: Print out specified file on the CON: Device
|
|
;Forms:
|
|
; TYPE <ufn> Print file
|
|
; TYPE <ufn> P Print file with paging flag
|
|
;Notes:
|
|
; The flag PGDFLG defines the letter which toggles the paging
|
|
; facility (P in the forms section above)
|
|
; The flag PGDFLT determines if TYPE is to page by default
|
|
; (PGDFLT=TRUE if TYPE pages by default); combined with
|
|
; PGDFLG, the following events occur --
|
|
; If PGDFLT = TRUE, PGDFLG turns OFF paging
|
|
; If PGDFLT = FALSE, PGDFLG turns ON paging
|
|
;
|
|
TYPE:
|
|
XRA A ;TURN OFF PRINTER FLAG
|
|
;
|
|
; ENTRY POINT FOR CPR LIST FUNCTION (LIST)
|
|
;
|
|
TYPE0:
|
|
STA PRFLG ;SET FLAG
|
|
;
|
|
IF WLT ;WHEEL ON?
|
|
CALL WHLCHK ;CHECK WHEEL BYTE
|
|
ENDIF ;WLT
|
|
;
|
|
LDA TFCB2+1 ;GET PGDFLG IF IT'S THERE
|
|
STA PGFLG ;SAVE IT AS A FLAG
|
|
LXI D,TFCB ;PT TO TARGET FILE FCB
|
|
CALL AMBCHK ;CHECK FOR QUESTION MARKS IN TFCB
|
|
RZ ;ERROR IF ANY QUESTION MARKS
|
|
CALL FCBLOG ;LOG INTO DU IN FCB
|
|
LXI D,TFCB ;PT TO SELECT FILE
|
|
CALL OPEN ;OPEN SELECTED FILE
|
|
JZ PRNNF ;ABORT IF ERROR
|
|
CALL CRLF ;NEW LINE
|
|
MVI A,NLINES-1 ;SET LINE COUNT
|
|
STA PAGCNT
|
|
LXI B,080H ;SET CHAR POSITION AND TAB COUNT
|
|
; (B=0=TAB, C=080H=CHAR POSITION)
|
|
;
|
|
; MAIN LOOP FOR LOADING NEXT BLOCK
|
|
;
|
|
TYPE2:
|
|
MOV A,C ;GET CHAR COUNT
|
|
CPI 80H
|
|
JRC TYPE3
|
|
PUSH H ;READ NEXT BLOCK
|
|
PUSH B
|
|
CALL READF
|
|
POP B
|
|
POP H
|
|
RNZ ;ERROR?
|
|
MVI C,0 ;SET CHAR COUNT
|
|
LXI H,TBUFF ;PT TO FIRST CHAR
|
|
;
|
|
; MAIN LOOP FOR PRINTING CHARS IN TBUFF
|
|
;
|
|
TYPE3:
|
|
MOV A,M ;GET NEXT CHAR
|
|
ANI 7FH ;MASK OUT MSB
|
|
CPI 1AH ;END OF FILE (^Z)?
|
|
RZ ;RESTART CPR IF SO
|
|
;
|
|
; OUTPUT CHAR TO CON: OR LST: DEVICE WITH TABULATION
|
|
;
|
|
CPI CR ;RESET TAB COUNT?
|
|
JRZ TYPE4
|
|
CPI LF ;RESET TAB COUNT?
|
|
JRZ TYPE4
|
|
CPI TAB ;TAB?
|
|
JRZ TYPE5
|
|
;
|
|
; OUTPUT CHAR AND INCREMENT CHAR COUNT
|
|
;
|
|
CALL LCOUT ;OUTPUT CHAR
|
|
INR B ;INCREMENT TAB COUNT
|
|
JR TYPE6
|
|
;
|
|
; OUTPUT <CR> OR <LF> AND RESET TAB COUNT
|
|
;
|
|
TYPE4:
|
|
CALL LCOUT ;OUTPUT <CR> OR <LF>
|
|
MVI B,0 ;RESET TAB COUNTER
|
|
JR TYPE6
|
|
;
|
|
; TABULATE
|
|
;
|
|
TYPE5:
|
|
MVI A,' ' ;<SP>
|
|
CALL LCOUT
|
|
INR B ;INCR POS COUNT
|
|
MOV A,B
|
|
ANI 7
|
|
JRNZ TYPE5
|
|
;
|
|
; CONTINUE PROCESSING
|
|
;
|
|
TYPE6:
|
|
INR C ;INCREMENT CHAR COUNT
|
|
INX H ;PT TO NEXT CHAR
|
|
CALL BREAK ;CHECK FOR ABORT
|
|
RZ ;RESTART IF SO
|
|
JR TYPE2
|
|
;
|
|
ENDIF ;LTON
|
|
;
|
|
;Section 5E
|
|
;Command: SAVE
|
|
;Function: To save the contents of the TPA onto disk as a file
|
|
;Forms:
|
|
; SAVE <Number of Pages> <ufn>
|
|
; Save specified number of pages (start at 100H)
|
|
; from TPA into specified file; <Number of
|
|
; Pages> is in DEC
|
|
; SAVE <Number of Sectors> <ufn> S
|
|
; Like SAVE above, but numeric argument specifies
|
|
; number of sectors rather than pages
|
|
;Notes:
|
|
; The MULTCMD flag (Multiple Commands Allowed) expands the code slightly,
|
|
; but is required to support multiple commands with SAVE
|
|
; The SECTFLG defines the letter which indicates a sector count
|
|
; (S in the Forms section above)
|
|
;
|
|
IF SAVEON ;SAVE ENABLED?
|
|
;
|
|
SAVE:
|
|
;
|
|
IF WSAVE ;WHEEL FACILITY?
|
|
CALL WHLCHK ;CHECK FOR WHEEL BYTE
|
|
ENDIF ;WSAVE
|
|
;
|
|
CALL NUMBER ;EXTRACT NUMBER FROM COMMAND LINE
|
|
MOV L,A ;HL=PAGE COUNT
|
|
MVI H,0
|
|
PUSH H ;SAVE PAGE COUNT
|
|
LXI H,TFCB2 ;COPY 2ND FCB INTO POSITION OF FIRST
|
|
LXI D,TFCB
|
|
PUSH D ;SAVE PTR TO FCB
|
|
MVI B,14 ;14 BYTES
|
|
CALL LDIR
|
|
POP D ;GET PTR TO FCB
|
|
CALL AMBCHK ;CHECK FOR AMBIGUOUS
|
|
POP H
|
|
RZ ;ABORT IF SO
|
|
PUSH H
|
|
CALL EXTEST ;TEST FOR EXISTENCE OF FILE AND ABORT IF SO
|
|
MVI C,16H ;BDOS MAKE FILE
|
|
CALL GRBDOS
|
|
POP H ;GET PAGE COUNT
|
|
JRZ SAVE3 ;ERROR?
|
|
LXI D,TPA-128 ;PT TO START OF SAVE AREA (TPA)
|
|
DAD H ;DOUBLE 256-BYTE BLOCK COUNT FOR SECTOR COUNT
|
|
XCHG ;DE IS COUNT, HL IS NEXT BLOCK - 128 BYTES
|
|
SAVE1:
|
|
MOV A,D ;DONE WITH SAVE?
|
|
ORA E ;DE=0 IF SO
|
|
JRZ SAVE2
|
|
DCX D ;COUNT DOWN ON SECTORS
|
|
PUSH D ;SAVE PTR TO BLOCK TO SAVE
|
|
LXI D,128 ;128 BYTES PER SECTOR
|
|
DAD D ;PT TO NEXT SECTOR
|
|
PUSH H ;SAVE ON STACK
|
|
XCHG ;DE IS ADDRESS
|
|
CALL DMASET ;SET DMA ADDRESS FOR WRITE (ADDRESS IN DE)
|
|
LXI D,TFCB ;WRITE SECTOR
|
|
MVI C,15H ;BDOS WRITE SECTOR
|
|
CALL BDOSB ;SAVE BC
|
|
POP H ;GET PTR TO NEXT SECTOR IN HL
|
|
POP D ;GET SECTOR COUNT IN DE
|
|
JRNZ SAVE3 ;WRITE ERROR?
|
|
JR SAVE1 ;CONTINUE
|
|
SAVE2:
|
|
LXI D,TFCB ;CLOSE SAVED FILE
|
|
CALL CLOSE
|
|
INR A ;ERROR?
|
|
JRNZ SAVE4
|
|
SAVE3:
|
|
CALL PRNLE ;PRINT 'NO SPACE' ERROR
|
|
SAVE4:
|
|
JMP DEFDMA ;SET DMA TO 0080 AND RESTART CPR
|
|
;
|
|
ENDIF ;SAVEON
|
|
;
|
|
IF LTON OR SAVEON OR RENON ;FOR LIST/TYPE, SAVE, AND REN FCTS
|
|
;
|
|
; TEST FCB PTED TO BY DE TO SEE IF ANY ? CHARS IN IT
|
|
; RETURN WITH Z IF SO, NZ IF NOT; DON'T AFFECT DE
|
|
;
|
|
AMBCHK:
|
|
PUSH D
|
|
INX D ;PT TO FIRST CHAR
|
|
MVI B,11 ;11 CHARS
|
|
AMB1:
|
|
LDAX D ;GET CHAR
|
|
CPI '?' ;ERROR?
|
|
JRZ AMB2
|
|
INX D ;PT TO NEXT
|
|
DJNZ AMB1
|
|
DCR B ;SET NZ
|
|
POP D ;RESTORE PTR
|
|
RET
|
|
AMB2:
|
|
CALL PRINT
|
|
DB CR,LF,'AFN Erro','r'+80H
|
|
XRA A ;SET ZERO FLAG
|
|
POP D ;RESTORE PTR
|
|
RET
|
|
;
|
|
ENDIF ;LTON OR SAVEON
|
|
;
|
|
; Test File in FCB for existence, ask user to delete if so, and abort if he
|
|
; choses not to
|
|
;
|
|
IF SAVEON OR RENON ;FOR SAVE AND REN FUNCTIONS
|
|
;
|
|
EXTEST:
|
|
LXI D,TFCB ;PT TO FCB
|
|
PUSH D ;SAVE PTR
|
|
CALL FCBLOG ;LOG INTO DU
|
|
CALL SEARF ;LOOK FOR SPECIFIED FILE
|
|
POP D ;GET PTR TO FCB
|
|
RZ ;OK IF NOT FOUND
|
|
PUSH D ;SAVE PTR TO FCB
|
|
CALL PRINTC
|
|
DB 'Erase',' '+80H
|
|
LXI H,TFCB+1 ;PT TO FILE NAME FIELD
|
|
CALL PRFN ;PRINT IT
|
|
MVI A,'?' ;PRINT QUESTION
|
|
CALL CONOUT
|
|
CALL CONIN ;GET RESPONSE
|
|
POP D ;GET PTR TO FCB
|
|
CPI 'Y' ;KEY ON YES
|
|
JNZ ERR3 ;RESTART AS ERROR IF NO
|
|
PUSH D ;SAVE PTR TO FCB
|
|
CALL DELETE ;DELETE FILE
|
|
POP D ;GET PTR TO FCB
|
|
RET
|
|
;
|
|
ENDIF ;SAVEON OR RENON
|
|
;
|
|
;Section 5F
|
|
;Command: REN
|
|
;Function: To change the name of an existing file
|
|
;Forms:
|
|
; REN <New ufn>=<Old ufn> Perform function
|
|
;
|
|
IF RENON ;REN ENABLED?
|
|
;
|
|
REN:
|
|
;
|
|
IF WREN ;WHEEL FACILITY?
|
|
CALL WHLCHK ;CHECK FOR WHEEL BYTE
|
|
ENDIF ;WREN
|
|
;
|
|
LXI D,TFCB ;CHECK FOR AMBIGUITY IN FIRST FILE NAME
|
|
CALL AMBCHK
|
|
RZ
|
|
LXI D,TFCB2 ;CHECK FOR AMBIGUITY IN SECOND FILE NAME
|
|
CALL AMBCHK
|
|
RZ
|
|
CALL EXTEST ;TEST FOR FILE EXISTENCE AND RETURN
|
|
; IF FILE DOESN'T EXIST; ABORT IF IT DOES
|
|
MVI B,16 ;EXCHANGE NEW AND OLD FILE NAMES
|
|
LXI H,TFCB ;PT TO NEW
|
|
LXI D,TFCB2 ;PT TO OLD
|
|
REN0:
|
|
LDAX D ;GET OLD
|
|
MOV C,A
|
|
MOV A,M ;GET NEW
|
|
STAX D ;PUT NEW
|
|
MOV M,C ;PUT OLD
|
|
INX H ;ADVANCE
|
|
INX D
|
|
DJNZ REN0
|
|
;
|
|
; PERFORM RENAME FUNCTION
|
|
;
|
|
LXI D,TFCB ;RENAME FILE
|
|
XRA A
|
|
STAX D ;SET CURRENT DISK
|
|
MVI C,17H ;BDOS RENAME FCT
|
|
CALL GRBDOS
|
|
RNZ
|
|
JMP PRNNF ;PRINT NO FILE MSG
|
|
;
|
|
ENDIF ;RENON
|
|
;
|
|
;Section 5G
|
|
;Command: JUMP
|
|
;Function: To Call the program (subroutine) at the specified address
|
|
; without loading from disk
|
|
;Forms:
|
|
; JUMP <adr> Call at <adr>;<adr> is in HEX
|
|
;
|
|
IF JUMPON ;JUMP ENABLED?
|
|
;
|
|
JUMP:
|
|
|
|
;
|
|
IF WJUMP ;WHEEL FACILITY?
|
|
CALL WHLCHK ;CHECK FOR WHEEL BYTE
|
|
ENDIF ;WJUMP
|
|
;
|
|
CALL HEXNUM ;GET LOAD ADDRESS IN HL
|
|
JR CALLPROG ;PERFORM CALL
|
|
;
|
|
ENDIF ;JUMPON
|
|
;
|
|
;Section 5H
|
|
;Command: GO
|
|
;Function: To Call the program in the TPA without loading
|
|
; loading from disk. Same as JUMP 100H, but much
|
|
; more convenient, especially when used with
|
|
; parameters for programs like STAT. Also can be
|
|
; allowed on remote-access systems with no problems.
|
|
;
|
|
;Form:
|
|
; GO <parameters like for COMMAND>
|
|
;
|
|
IF GOON ;GO ENABLED?
|
|
;
|
|
GO:
|
|
|
|
;
|
|
IF WGO ;WHEEL FACILITY?
|
|
CALL WHLCHK ;CHECK FOR WHEEL BYTE
|
|
ENDIF ;WGO
|
|
;
|
|
LXI H,TPA ;Always to TPA
|
|
JR CALLPROG ;Perform call
|
|
;
|
|
ENDIF ;GOON
|
|
;
|
|
;Section 5I
|
|
;Command: COM file processing
|
|
;Function: To load the specified COM file from disk and execute it
|
|
;Forms: <command line>
|
|
;Notes:
|
|
; COM files are processed as follows --
|
|
; 1. File name buffers are initialized and a preliminary
|
|
; error check is done
|
|
; 2. MLOAD is used to search for the file along the Path
|
|
; and load it into the TPA
|
|
; 3. CALLPROG is used to set up the buffers to be used by
|
|
; the transient (FCB at 5CH, FCB at 6CH, BUFF at 80H)
|
|
; and run the program
|
|
; The flag MULTCMD comes into play frequently here; it mainly serves
|
|
; to save space if MULTCMD is FALSE and enables Multiple
|
|
; Commands on the same line if MULTCMD is TRUE
|
|
;
|
|
COMDIR:
|
|
IF DRVPREFIX
|
|
;
|
|
LDA FCBFN ;ANY COMMAND?
|
|
CPI ' ' ;' ' MEANS COMMAND WAS 'DIR:' TO SWITCH
|
|
JRNZ COM ;NOT <SP>, SO MUST BE TRANSIENT OR ERROR
|
|
;
|
|
; ENTRY POINT TO SELECT USER/DISK VIA DIR: PREFIX
|
|
;
|
|
IF WDU ;WHEEL FACILITY?
|
|
CALL WHLCHK ;CHECK FOR WHEEL BYTE
|
|
ENDIF ;WDU
|
|
;
|
|
LDA FCBDN+13 ;GET SELECTED USER
|
|
CPI 16 ;OUT OF RANGE?
|
|
JNC ERROR
|
|
LXI D,FCBDN ;PT TO FCB
|
|
CALL FCBLOG ;LOG INTO DU
|
|
LDA TEMPUSR ;GET TEMPORARY USER
|
|
STA CURUSR ;SET CURRENT USER (MAKE PERMANENT)
|
|
LDA TEMPDR ;GET SELECTED DISK
|
|
ORA A ;IF 0 (DEFAULT), NO CHANGE
|
|
JRZ COMDR
|
|
DCR A ;ADJUST FOR LOGIN
|
|
STA CURDR ;SET CURRENT DRIVE
|
|
COMDR:
|
|
CALL SETUD ;SET UD BYTE
|
|
JMP RS1 ;RESUME COMMAND LINE PROCESSING
|
|
;
|
|
ENDIF ;DRVPREFIX
|
|
;
|
|
; PROCESS COMMAND
|
|
;
|
|
COM:
|
|
;
|
|
IF CMDRUN ;COMMAND RUN FACILITY AVAILABLE?
|
|
MVI A,0FFH ;USE IT IF AVAILABLE (MLOAD INPUT)
|
|
ENDIF ;CMDRUN
|
|
;
|
|
|
|
;
|
|
; SET EXECUTION AND LOAD ADDRESS
|
|
;
|
|
LXI H,TPA ;TRANSIENT PROGRAM AREA
|
|
PUSH H ;SAVE TPA ADDRESS FOR EXECUTION
|
|
CALL MLOAD ;LOAD MEMORY WITH FILE SPECIFIED IN CMD LINE
|
|
POP H ;GET EXECUTION ADDRESS; FALL THRU TO CALLPROG
|
|
;
|
|
; CALLPROG IS THE ENTRY POINT FOR THE EXECUTION OF THE LOADED
|
|
; PROGRAM; ON ENTRY TO THIS ROUTINE, HL MUST CONTAIN THE EXECUTION
|
|
; ADDRESS OF THE PROGRAM (SUBROUTINE) TO EXECUTE
|
|
;
|
|
CALLPROG:
|
|
CALL CRLF ;LEADING NEW LINE
|
|
CALLP:
|
|
SHLD EXECADR ;PERFORM IN-LINE CODE MODIFICATION
|
|
;
|
|
; COPY COMMAND TAIL INTO TBUFF
|
|
;
|
|
TAILSV EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
LXI H,0 ;ADDRESS OF FIRST CHAR OF COMMAND TAIL
|
|
LXI D,TBUFF ;PT TO TBUFF
|
|
PUSH D ;SAVE PTR
|
|
MVI B,0 ;SET COUNTER
|
|
INX D ;PT TO FIRST CHAR
|
|
TAIL:
|
|
MOV A,M ;GET CHAR
|
|
CALL TSTEOL ;CHECK FOR EOL
|
|
JRZ TAIL1
|
|
STAX D ;PUT CHAR
|
|
INX H ;PT TO NEXT
|
|
INX D
|
|
INR B ;INCREMENT COUNT
|
|
JR TAIL
|
|
TAIL1:
|
|
XRA A ;STORE ENDING ZERO
|
|
STAX D
|
|
POP H ;GET PTR
|
|
MOV M,B ;SAVE COUNT
|
|
;
|
|
; RUN LOADED TRANSIENT PROGRAM
|
|
;
|
|
CALL DEFDMA ;SET DMA TO 0080
|
|
;
|
|
; EXECUTION (CALL) OF PROGRAM (SUBROUTINE) OCCURS HERE
|
|
;
|
|
EXECADR EQU $+1 ;CHANGE ADDRESS FOR IN-LINE CODE MODIFICATION
|
|
CALL TPA ;CALL TRANSIENT
|
|
;
|
|
; RETURN FROM EXECUTION
|
|
;
|
|
CALL DEFDMA ;SET DMA TO 0080, IN CASE PROG CHANGED IT
|
|
JMP RS1 ;RESTART CPR AND CONTINUE COMMAND PROCESSING
|
|
;
|
|
;Section 5J
|
|
;Command: GET
|
|
;Function: To load the specified file from disk to the specified address
|
|
;Forms:
|
|
; GET <adr> <ufn> Load the specified file at the specified page;
|
|
; <adr> is in HEX
|
|
;
|
|
IF GETON ;GET ENABLED?
|
|
;
|
|
GET:
|
|
;
|
|
IF WGET ;WHEEL ON?
|
|
CALL WHLCHK ;CHECK WHEEL BYTE
|
|
ENDIF ;WGET
|
|
;
|
|
LXI H,TFCB2 ;COPY TFCB2 TO FCBDN FOR LOAD
|
|
LXI D,FCBDN
|
|
MVI B,14 ;14 BYTES (INCLUDES DU)
|
|
CALL LDIR
|
|
CALL HEXNUM ;GET LOAD ADDRESS IN HL
|
|
;
|
|
; FALL THRU TO MLOAD
|
|
;
|
|
IF CMDRUN ;COMMAND RUN FACILITY AVAILABLE?
|
|
XRA A ;NO CMDRUN IF FACILITY IS THERE (MLOAD INPUT)
|
|
ENDIF ;CMDRUN
|
|
;
|
|
ENDIF ;GETON
|
|
|
|
;
|
|
; MEMORY LOAD SUBROUTINE
|
|
;
|
|
; LOAD MEMORY WITH THE FILE WHOSE NAME IS SPECIFIED IN THE COMMAND LINE
|
|
; ON INPUT, HL CONTAINS STARTING ADDRESS TO LOAD
|
|
;
|
|
; EXIT POINTS ARE A RETURN AND LOG IN CURRENT USER/DISK IF NO ERROR,
|
|
; A JMP TO ERROR IF COM FILE NOT FOUND OR A MESSAGE AND ABORT IF MEMORY FULL
|
|
;
|
|
MLOAD:
|
|
;
|
|
IF CMDRUN ;CMDRUN FACILITY?
|
|
STA CRFLAG ;SAVE FLAG
|
|
ENDIF ;CMDRUN
|
|
;
|
|
SHLD LOADADR ;SET LOAD ADDRESS
|
|
XCHG ;LOAD ADDRESS IN DE
|
|
CALL DMASET ;SET DMA ADDRESS
|
|
;
|
|
; MLA is a reentry point for a non-standard CP/M Modification
|
|
; The PATH command-search is implemented by this routine
|
|
;
|
|
MLA:
|
|
;
|
|
; Set attributes of COM files which match search
|
|
;
|
|
MVI A,COMATT ;CUSTOMIZER-SPECIFIED ATTRIBUTES
|
|
STA SYSTST ;SET FLAG
|
|
|
|
;
|
|
; Analyze current path, generating a minimal, optimal absolute
|
|
; path equivalent in the buffer MPATH
|
|
;
|
|
IF MINPATH ;IF MINIMUM PATH SEARCH EMPLOYED
|
|
XRA A
|
|
STA MPATH ;SET EMPTY PATH
|
|
;
|
|
IF DRVPREFIX ;PAY ATTENTION TO DU:COM PREFIX?
|
|
;
|
|
; Convert DU in FCBDN into absolute expression in MPATH
|
|
;
|
|
LXI D,MPATH ;BUILD MPATH BUFFER
|
|
LXI H,FCBDN ;HL PTS TO FCB, DE PTS TO MPATH
|
|
MOV A,M ;GET DRIVE
|
|
ORA A ;SELECT CURRENT
|
|
JRNZ MLAMPD
|
|
LDA CURDR ;SET CURRENT DRIVE
|
|
INR A ;ADJUST FOR PATH
|
|
MLAMPD:
|
|
STAX D ;SET DRIVE
|
|
INX D ;PT TO USER
|
|
LXI B,13 ;PT TO USER
|
|
DAD B
|
|
MOV A,M ;GET USER
|
|
STAX D ;SAVE USER
|
|
INX D ;PT TO NEXT
|
|
XRA A ;A=0
|
|
STAX D ;STORE ENDING 0 IN MPATH
|
|
ENDIF ;DRVPREFIX
|
|
;
|
|
IF SCANCUR ;SCAN CURRENT DU AT ALL TIMES?
|
|
LDA CURDR ;GET CURRENT DRIVE
|
|
INR A ;ADD 1 FOR A=1
|
|
MOV B,A
|
|
LDA CURUSR ;GET CURRENT USER
|
|
MOV C,A ;BC=DU
|
|
LXI H,PATH ;PT TO FIRST PATH ELEMENT
|
|
JR MPATHBC ;PLACE ENTRY INTO MPATH
|
|
ENDIF ;SCANCUR
|
|
;
|
|
; Convert symbolic path at PATH into absolute path at MPATH
|
|
;
|
|
LXI H,PATH ;PT TO SYMBOLIC PATH
|
|
MPATH1:
|
|
MOV A,M ;CHECK FOR END OF SYMBOLIC PATH
|
|
ORA A ;0=END OF PATH
|
|
JRZ MPATH7
|
|
;
|
|
; Place absolute form for current path element in BC
|
|
;
|
|
ANI 7FH ;MASK OUT SYSTEM BIT
|
|
CPI CURIND ;CHECK FOR CURRENT DRIVE
|
|
JRNZ MPATH2
|
|
LDA CURDR ;GET CURRENT DRIVE
|
|
INR A ;ADJUST FOR A=1
|
|
MPATH2:
|
|
MOV B,A ;DRIVE IN B (1=A)
|
|
INX H ;PT TO USER
|
|
MOV A,M ;GET USER
|
|
INX H ;PT TO NEXT ELEMENT
|
|
ANI 7FH ;MASK OUT SYSTEM BIT
|
|
CPI CURIND ;CHECK FOR CURRENT USER
|
|
JRNZ MPATH3
|
|
LDA CURUSR ;GET CURRENT USER
|
|
MPATH3:
|
|
MOV C,A ;SET USER IN C
|
|
;
|
|
; Scan MPATH for DU element in BC
|
|
;
|
|
MPATHBC:
|
|
PUSH H ;SAVE PTR TO NEXT PATH ELEMENT
|
|
LXI H,MPATH ;PT TO MINIMUM PATH
|
|
MPATH4:
|
|
MOV A,M ;CHECK FOR END OF PATH
|
|
ORA A
|
|
JRZ MPATH6
|
|
INX H ;PT TO USER
|
|
CMP B ;CHECK FOR DISK MATCH
|
|
JRNZ MPATH5
|
|
MOV A,M ;GET USER
|
|
CMP C ;CHECK FOR USER MATCH
|
|
JRNZ MPATH5
|
|
POP H ;MATCH, SO BC IS DUPLICATE
|
|
JR MPATH1 ;CONTINUE
|
|
MPATH5:
|
|
INX H ;PT TO NEXT ELEMENT
|
|
JR MPATH4
|
|
;
|
|
; No match, so BC is a unique DU and store it in path
|
|
;
|
|
MPATH6:
|
|
MOV M,B ;STORE DRIVE
|
|
INX H
|
|
MOV M,C ;STORE USER
|
|
INX H
|
|
MVI M,0 ;STORE ENDING 0
|
|
POP H ;PT TO NEXT ENTRY
|
|
JR MPATH1 ;CONTINUE
|
|
;
|
|
; MPATH now contains the minimal path
|
|
;
|
|
MPATH7:
|
|
;
|
|
ENDIF ;MINPATH
|
|
;
|
|
; Non-MINPATH Processing:
|
|
; If DRVPREFIX or SCANCUR are TRUE, look in DU in FCBDN
|
|
;
|
|
IF (NOT MINPATH) AND (DRVPREFIX OR SCANCUR)
|
|
LXI D,FCBDN ;LOOK FOR FILE
|
|
CALL FCBLOG ;LOG INTO FCB
|
|
CALL SEAR1
|
|
JNZ MLA4
|
|
ENDIF ;(NOT MINPATH) AND (DRVPREFIX OR SCANCUR)
|
|
;
|
|
; Select current disk at all times
|
|
;
|
|
XRA A
|
|
STA FCBDN ;SET CURRENT DISK
|
|
MLARUN:
|
|
;
|
|
; The following selects the path to be followed; if the Minimal Path is
|
|
; available, it is followed; else, the Symbolic Path is followed
|
|
;
|
|
IF MINPATH ;IF MINIMAL PATH USED
|
|
LXI H,MPATH ;PT TO MINIMAL PATH
|
|
|
|
ELSE ;NOT MINPATH
|
|
LXI H,PATH ;PT TO SYMBOLIC PATH
|
|
|
|
ENDIF ;MINPATH
|
|
;
|
|
; This is the main path search loop; HL pts to the next path element
|
|
;
|
|
MLA0:
|
|
MOV A,M ;GET DRIVE
|
|
ORA A ;0=DONE=COMMAND NOT FOUND
|
|
;
|
|
IF NOT CMDRUN ;ERROR ABORT IF NO COMMAND RUN FACILITY
|
|
JZ ERROR ;PATH EXHAUSTED
|
|
;
|
|
ELSE ;CONTINUE PROCESSING FOR COMMAND RUN
|
|
;
|
|
; CMDRUN Facility
|
|
;
|
|
JRNZ NOCRUN ;NOT READY FOR CMD RUN YET
|
|
CRFLAG EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;CHECK CRFLAG
|
|
ORA A ;0=NO
|
|
JZ ERROR ;PROCESS AS ERROR IF CMD RUN EXHAUSTED
|
|
;
|
|
IF ROOTONLY ;ONLY LOOK FOR EXT COMMAND PROCESSOR AT ROOT
|
|
PUSH H ;SAVE PTR TO PATH END
|
|
ENDIF ;ROOTONLY
|
|
;
|
|
XRA A ;DO NOT REENTER THIS CODE
|
|
STA CRFLAG ;SET ZERO FOR NO ENTRY
|
|
LXI H,CFCB ;SET CFCB AS COMMAND
|
|
LXI D,FCBDN ;... BY COPYING IT INTO FCBDN
|
|
MVI B,12 ;ONLY 12 BYTES REQUIRED
|
|
CALL LDIR
|
|
LHLD CURCMD ;GET PTR TO CURRENT COMMAND LINE
|
|
CALL PARSET ;PARSE AS COMMAND TAIL
|
|
;
|
|
IF ROOTONLY ;LOOK FOR EXT COMMAND PROCESSOR AT ROOT ONLY?
|
|
JR MLA3RT ;PROCESS FROM PATH END
|
|
ELSE ;FOLLOW PATH LOOKING FOR EXT COMMAND PROCESSOR
|
|
;
|
|
JR MLARUN ;NOW TRY THE RUN FROM THE PATH
|
|
;
|
|
ENDIF ;ROOTONLY
|
|
;
|
|
CFCB:
|
|
CMDFCB ;FCB DEFINING INITIAL COMMAND
|
|
NOCRUN:
|
|
ENDIF ;CMDRUN
|
|
;
|
|
; LOOK FOR COMMAND IN DIRECTORY PTED TO BY HL; DRIVE IN A
|
|
;
|
|
IF NOT MINPATH
|
|
CPI CURIND ;CURRENT DRIVE SPECIFIED?
|
|
JRNZ MLA1 ;SKIP DEFAULT DRIVE SELECTION IF SO
|
|
LDA CURDR ;GET CURRENT DRIVE
|
|
INR A ;SET A=1
|
|
ENDIF ;NOT MINPATH
|
|
;
|
|
MLA1:
|
|
STA TEMPDR ;SELECT DIFFERENT DRIVE IF NOT CURRENT
|
|
INX H ;PT TO USER NUMBER
|
|
MOV A,M ;GET USER NUMBER
|
|
INX H ;PT TO NEXT ENTRY IN PATH
|
|
PUSH H ;SAVE PTR
|
|
;
|
|
IF NOT MINPATH
|
|
ANI 7FH ;MASK OUT SYSTEM BIT
|
|
CPI CURIND ;CURRENT USER SPECIFIED?
|
|
JRNZ MLA2 ;DO NOT SELECT CURRENT USER IF SO
|
|
LDA CURUSR ;GET CURRENT USER NUMBER
|
|
MLA2:
|
|
ENDIF ;NOT MINPATH
|
|
;
|
|
STA TEMPUSR ;SET TEMPORARY USER NUMBER
|
|
CMA ;FLIP BITS SO SYSTEM BIT IS 0 IF SYS-ONLY
|
|
ANI 80H ;MASK FOR ONLY NOT OF SYSTEM BIT TO SHOW
|
|
JRNZ MLA3 ;DON'T SET FLAG IF ORIGINALLY SYSTEM BIT=0
|
|
STA SYSTST ;TEST FLAG IS 0 FOR SYS-ONLY, 1 FOR BOTH
|
|
MLA3:
|
|
CALL SLOGIN ;LOG IN PATH-SPECIFIED USER/DISK
|
|
MLA3RT:
|
|
LXI D,FCBDN ;PT TO FCB
|
|
CALL SEAR1 ;LOOK FOR FILE
|
|
POP H ;GET PTR TO NEXT PATH ENTRY
|
|
JRZ MLA0 ;CONTINUE PATH SEARCH IF SEARCH FAILED
|
|
;LOAD IF SEARCH SUCCEEDED
|
|
;
|
|
; FILE FOUND -- PERFORM SYSTEM TEST AND PROCEED IF APPROVED
|
|
;
|
|
MLA4:
|
|
PUSH H ;SAVE PTR
|
|
CALL GETSBIT ;CHECK SYSTEM BIT
|
|
POP H ;GET PTR
|
|
JRZ MLA0 ;CONTINUE IF NO MATCH
|
|
CALL OPENF ;OPEN FILE FOR INPUT
|
|
LOADADR EQU $+1 ;MEMORY LOAD ADDRESS (IN-LINE CODE MOD)
|
|
LXI H,TPA ;SET START ADDRESS OF MEMORY LOAD
|
|
MLA5:
|
|
MVI A,ENTRY/256-1 ;GET HIGH-ORDER ADR OF JUST BELOW CPR
|
|
CMP H ;ARE WE GOING TO OVERWRITE THE CPR?
|
|
JRC PRNLE ;ERROR IF SO
|
|
PUSH H ;SAVE ADDRESS OF NEXT SECTOR
|
|
XCHG ;... IN DE
|
|
CALL DMASET ;SET DMA ADDRESS FOR LOAD
|
|
LXI D,FCBDN ;READ NEXT SECTOR
|
|
CALL READ
|
|
POP H ;GET ADDRESS OF NEXT SECTOR
|
|
JRNZ MLA6 ;READ ERROR OR EOF?
|
|
LXI D,128 ;MOVE 128 BYTES PER SECTOR
|
|
DAD D ;PT TO NEXT SECTOR IN HL
|
|
JR MLA5
|
|
;
|
|
MLA6:
|
|
DCR A ;LOAD COMPLETE
|
|
JRNZ PRNLE ;MEMORY FULL IF NZ
|
|
;
|
|
; RETURN TO CURRENT DIRECTORY
|
|
;
|
|
DLOGIN:
|
|
CURDR EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;PREP TO LOG IN CURRENT DRIVE
|
|
CALL LOGIN ;LOGIN CURRENT DRIVE
|
|
CURUSR EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;PREP TO LOG IN CURRENT USER NUMBER
|
|
JMP SETUSR ;LOG IN NEW USER
|
|
|
|
;
|
|
; LOAD ERROR
|
|
;
|
|
PRNLE:
|
|
CALL PRINTC
|
|
DB 'Ful','l'+80H
|
|
JMP RESTRT ;RESTART ZCPR
|
|
|
|
;*****
|
|
|
|
;
|
|
; DEFAULT PATH USED FOR PATH COMMAND-SEARCH
|
|
;
|
|
IF EXPATH EQ 0 ;USE THIS PATH?
|
|
;
|
|
PATH:
|
|
IPATH ;PATH DEFINED IN Z3HDR.LIB
|
|
;
|
|
ENDIF ;INTPATH
|
|
;
|
|
|
|
;*****
|
|
|
|
;
|
|
; INTERNAL MINIMUM PATH
|
|
;
|
|
IF MINPATH
|
|
MPATH:
|
|
DS EXPATHS+3 ;SIZE OF PATH, MAX
|
|
; (+2 FOR DU:COM PREFIX, +1 FOR ENDING 0)
|
|
ENDIF ;MINPATH
|
|
|
|
;*****
|
|
IF EXTSTK NE 0 ;EXTERNAL STACK
|
|
|
|
STACK EQU EXTSTK+48 ;SET TOP-OF-STACK ADDRESS
|
|
|
|
ELSE
|
|
;
|
|
; STACK AREA
|
|
;
|
|
DS 48 ;STACK AREA
|
|
STACK EQU $ ;TOP OF STACK
|
|
;
|
|
ENDIF ;INTSTACK
|
|
;
|
|
IF PWCHECK
|
|
PWLIN EQU STACK-48 ;PLACE LINE AT BOTTOM OF STACK
|
|
ENDIF ;PWCHECK
|
|
;
|
|
; The following will cause an error message to appear if
|
|
; the size of ZCPR3 is over 2K bytes.
|
|
;
|
|
IF ($ GT CPRLOC+800H)
|
|
ZCPR3ER EQU NOVALUE ;ZCPR3 IS LARGER THAN 2K BYTES
|
|
ENDIF
|
|
|
|
END
|
|
|