************************************************************************* * * * 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: 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 ; 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