home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
ZCPR2
/
PATH.MAC
< prev
next >
Wrap
Text File
|
2000-06-30
|
14KB
|
690 lines
;
; PROGRAM: PATH
; VERSION: 1.0
; AUTHOR: RICHARD CONN
; DATE: 12 JAN 83
; PREVIOUS VERSIONS: NONE
;
VERS EQU 10
;
; PATH allows the user to do two things -- display the current path
; and set a new path. Named directories may be used in the definition of
; the new path.
;
; PATH is invoked by the following forms:
; PATH <-- Display Path
; PATH path-expression <-- Set Path
; PATH // <-- Print Help
;
;
; CP/M Constants
;
cpm equ 0 ;base
bdose equ cpm+5
fcb equ cpm+5ch
tbuff equ cpm+80h
cr equ 0dh
lf equ 0ah
;
; SYSLIB Routines
;
ext cline,zgpins,zdname,print,codend,eval10
ext cout,pstr,padc,retud
;
; This program is Copyright (c) 1982, 1983 by Richard Conn
; All Rights Reserved
;
; ZCPR2 and its utilities, including this one, are released
; to the public domain. Anyone who wishes to USE them may do so with
; no strings attached. The author assumes no responsibility or
; liability for the use of ZCPR2 and its utilities.
;
; The author, Richard Conn, has sole rights to this program.
; ZCPR2 and its utilities may not be sold without the express,
; written permission of the author.
;
;
; Branch to Start of Program
;
jmp start
;
;******************************************************************
;
; SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
;
; This data block precisely defines the data format for
; initial features of a ZCPR2 system which are required for proper
; initialization of the ZCPR2-Specific Routines in SYSLIB.
;
;
; EXTERNAL PATH DATA
;
EPAVAIL:
DB 0FFH ; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
EPADR:
DW 40H ; ADDRESS OF EXTERNAL PATH IF AVAILABLE
;
; INTERNAL PATH DATA
;
INTPATH:
DB 0,0 ; DISK, USER FOR FIRST PATH ELEMENT
; DISK = 1 FOR A, '$' FOR CURRENT
; USER = NUMBER, '$' FOR CURRENT
DB 0,0
DB 0,0
DB 0,0
DB 0,0
DB 0,0
DB 0,0
DB 0,0 ; DISK, USER FOR 8TH PATH ELEMENT
DB 0 ; END OF PATH
;
; MULTIPLE COMMAND LINE BUFFER DATA
;
MCAVAIL:
DB 0FFH ; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
MCADR:
DW 0FF00H ; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE
;
; DISK/USER LIMITS
;
MDISK:
DB 4 ; MAXIMUM NUMBER OF DISKS
MUSER:
DB 31 ; MAXIMUM USER NUMBER
;
; FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
;
DOK:
DB 0FFH ; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
UOK:
DB 0FFH ; ALLOW USER CHANGE? (0=NO, 0FFH=YES)
;
; PRIVILEGED USER DATA
;
PUSER:
DB 10 ; BEGINNING OF PRIVILEGED USER AREAS
PPASS:
DB 'chdir',0 ; PASSWORD FOR MOVING INTO PRIV USER AREAS
DS 41-($-PPASS) ; 40 CHARS MAX IN BUFFER + 1 for ending NULL
;
; CURRENT USER/DISK INDICATOR
;
CINDIC:
DB '$' ; USUAL VALUE (FOR PATH EXPRESSIONS)
;
; DMA ADDRESS FOR DISK TRANSFERS
;
DMADR:
DW 80H ; TBUFF AREA
;
; NAMED DIRECTORY INFORMATION
;
NDRADR:
DW 00000H ; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
NDNAMES:
DB 64 ; MAX NUMBER OF DIRECTORY NAMES
DNFILE:
DB 'NAMES ' ; NAME OF DISK NAME FILE
DB 'DIR' ; TYPE OF DISK NAME FILE
;
; REQUIREMENTS FLAGS
;
EPREQD:
DB 0FFH ; EXTERNAL PATH?
MCREQD:
DB 000H ; MULTIPLE COMMAND LINE?
MXREQD:
DB 0FFH ; MAX USER/DISK?
UDREQD:
DB 000H ; ALLOW USER/DISK CHANGE?
PUREQD:
DB 000H ; PRIVILEGED USER?
CDREQD:
DB 0FFH ; CURRENT INDIC AND DMA?
NDREQD:
DB 0FFH ; NAMED DIRECTORIES?
Z2CLASS:
DB 0 ; CLASS 0
DB 'ZCPR2'
DS 10 ; RESERVED
;
; END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
;
;******************************************************************
;
;
; Start of Program
;
start:
call zgpins ; init ZCPR2 buffers
lxi h,tbuff ; pt to buffer
call cline ; save it as string
shld cmdline ; save ptr to command line
call retud ; get current disk and user
mov a,b
sta cdisk ; set disk
mov a,c
sta cuser ; set user
;
; Print Banner
;
call print
db 'PATH Version '
db vers/10+'0','.',(vers mod 10)+'0',0
;
; Check for Help
;
lda fcb+1 ; get first char
cpi '/' ; help?
jnz start1
call print
db cr,lf,' PATH allows the user to display his current path'
db cr,lf,'and set a new path. It is invoked by one of the forms:'
db cr,lf
db cr,lf,' PATH <-- Display Path'
db cr,lf,' PATH path-expression <-- Set Path'
db cr,lf,' PATH // <-- Print Help'
db cr,lf,0
ret
;
; Check for Error and Continue if not:
; Load NAMES.DIR and check for function
;
start1:
lda epavail ; external path available?
ora a ; 0=no
jnz start2
call print
db cr,lf,'Error -- External Path Not Defined -- Aborting',0
ret
start2:
call codend ; pt to buffer
call zdname ; load NAMES.DIR
jnz start3
mvi c,0 ; if no NAMES.DIR or overflow, set no entries
start3:
shld ddir ; save ptr to disk buffer
mov a,c ; set entry count
sta dentry
lxi h,tempath ; pt to temporary path
shld pathptr ; set path ptr
lhld cmdline ; check command line for text
call sblank ; skip to non-blank
shld cmdline ; set ptr to next element
ora a ; EOL=display function
jz pdisp
;
; **** Set New Path ****
; HL pts to next element
;
pbuild:
lhld cmdline ; pt to next element
call sblank ; skip to non-blank
mov a,m ; get first char of next element
ora a ; EOL?
jz pbdone ; done if so, store path and display
shld token ; save ptr to first byte
lda cindic ; get current disk indicator
cmp m ; is it current?
jz pbdu ; DU: form
mov a,m ; get first char again
sui 'A' ; convert to number
jc pbdir ; DIR: form
mov b,a ; save number
lda mdisk ; compare to max disk number
mov c,a
mov a,b
cmp c ; in range?
jnc pbdir ; DIR: form if not
inx h ; pt to next char -- may be DU or DIR
lda cindic ; get current indicator
mov b,a ; ... in B
mov a,m ; get next part of element
cmp b ; current?
jz pbdu ; is a DU: form
digtst:
cpi ':' ; colon ends it
jz pbdu ; is a DU: form
cpi ' ' ; space ends it
jz pbdu
ora a ; EOL ends it
jz pbdu
cpi '0' ; must be a digit
jc pbdir ; DIR: form if not in range
cpi '9'+1
jnc pbdir
inx h ; pt to next
mov a,m ; get it
jmp digtst
;
; It is a DU: form
;
pbdu:
lhld pathptr ; pt to path entry
xchg ; ... in DE
lhld token ; pt to token
lda cindic ; get current indicator
mov b,a
mov a,m ; current?
cmp b
jz pbdu1
sui 'A'-1 ; convert to number from 1 to n
pbdu1:
stax d ; save disk element
inx h ; pt to next
inx d
mov a,m ; current user?
inx h ; pt to after user in case of match to cindic
cmp b ; match cindic?
jz pbdu2
dcx h ; pt to first digit
push d ; save ptr to path
call eval10 ; convert to number
mov a,d ; range error?
ora a
jnz rangerr
lda muser ; check for max user
inr a
mov b,a
mov a,e
cmp b
jnc rangerr
pop d ; get ptr to path
pbdu2:
stax d ; store user number
inx d
mov a,m ; ending with colon?
cpi ':'
jnz pbdu3
inx h ; skip over colon
pbdu3:
shld cmdline ; save ptr to next command line entry
xchg
shld pathptr ; save ptr to next path entry
jmp pbuild ; continue processing
;
; Build DIR: form
;
pbdir:
lhld ndradr ; memory-based directory available?
mov a,h
ora l
jz ddscan ; scan disk dir if not
inx h ; pt to entry count
mov c,m ; get entry count in C
inx h ; pt to first entry
call dirscan ; scan directory
jnz gotud ; store disk/user
ddscan:
lhld ddir ; pt to disk dir
lda dentry ; get entry count
mov c,a ; ... in C
call dirscan ; scan directory
jnz gotud
;
; Entry not found
;
rangerr:
call print
db cr,lf
db cr,lf,'Invalid Path Expression Element -- Error Flagged at:'
db cr,lf,' -->',0
lhld token ; print string starting at token
call pstr
call print
db cr,lf,'This may be an invalid DU: form (disk or user out of '
db 'range)'
db cr,lf,'or an undefined named directory.'
db cr,lf
db cr,lf,'Aborting to CP/M',0
jmp cpm
;
; Got User and Disk -- Store in Path
;
gotud:
lhld pathptr ; get ptr to path
mov m,b ; store disk
inx h
mov m,c ; store user
inx h ; pt to next
shld pathptr
lhld token ; skip over token
gotud1:
mov a,m ; skip to space or EOL
inx h ; pt to next
ora a ; EOL?
jz gotud2
cpi ' ' ; space?
jnz gotud1
gotud2:
dcx h ; pt to EOL or space
shld cmdline ; set ptr to next element
jmp pbuild ; continue building
;
; Path Building is Done -- TEMPATH contains new path
;
pbdone:
lhld pathptr ; store ending zero in path
mvi m,0
lhld epadr ; pt to external path
xchg ; ... in DE
lxi h,tempath ; copy tempath into external path
pcopy:
mov a,m ; get disk
stax d ; put disk
ora a ; end of path?
jz pdisp ; done if so and display
inx h ; pt to user
inx d
mov a,m ; get user
stax d ; put user
inx h ; pt to next disk
inx d
jmp pcopy
;
; **** Display Path Function ****
;
pdisp:
call print
db cr,lf,'Current Path in Symbolic Form -- ',cr,lf,' ',0
lhld epadr ; pt to external path
lda cindic ; get current indicator
mov d,a ; ... in D
pdisp1:
mov a,m ; get disk
ora a ; done?
jz adisp
cmp d ; current?
jz pdisp2
adi '@' ; convert to letter
pdisp2:
call cout ; print disk letter
inx h ; pt to user
mov a,m ; get user number
cmp d ; current?
jnz pdisp3
call cout ; print cindic
jmp pdisp4
pdisp3:
call padc ; print user number
pdisp4:
mvi a,':' ; print colon
call cout
inx h ; pt to next element
mov a,m ; done?
ora a ; 0=yes
jz adisp
call print
db ' --> ',0
jmp pdisp1
;
; Print Absolute Path
;
adisp:
call print
db cr,lf,'Current Path in Absolute Form --',cr,lf,' ',0
call curud ; get current user/disk
lda cindic ; get current indicator
mov d,a ; ... in D
lhld epadr ; pt to path
adisp1:
mov a,m ; get disk
ora a ; done?
jz ndisp
cmp d ; current?
jnz adisp2
mov a,b ; get current disk
inr a ; adjust to 1 to n
adisp2:
adi '@' ; convert to letter
call cout ; print disk letter
inx h ; pt to user
mov a,m ; get user
cmp d ; current?
jnz adisp3
mov a,c ; get current user
adisp3:
call padc ; print user
mvi a,':'
call cout
inx h ; pt to next
mov a,m ; done?
ora a
jz ndisp
call print
db ' --> ',0
jmp adisp1
;
; Print Named Path
;
ndisp:
call print
db cr,lf,'Current Path in Named Directory Form --',cr,lf,' ',0
lhld epadr ; pt to external path
ndisp1:
lda cindic ; get current indicator
mov d,a ; ... in D
call curud ; get current user and disk in C and B
mov a,m ; get disk
ora a ; done?
rz
cmp d ; current?
jz ndisp2
mov b,a ; disk in B
dcr b ; adjust to 0 to n-1
ndisp2:
inx h ; pt to user
mov a,m ; get it
cmp d ; current?
jz ndisp3
mov c,a ; user in C
ndisp3:
inx h ; pt to next
push h ; save ptr
call udscan ; scan dirs for user/disk and print its name
pop h ; get ptr
mvi a,':'
call cout
mov a,m ; done?
ora a
rz
call print
db ' --> ',0
jmp ndisp1
;
; Utilities
;
;
; Scan Memory-Based Directory for Name Pted to by TOKEN
; On entry, HL pts to first entry and C=number of entries
; On exit, return with NZ and BC=disk/user if found
;
dirscan:
mov a,c ; any entries?
ora a
rz ; error return
dirsl:
push h ; save ptr to entry
push b ; save char count
call tokscan ; check for token match
pop b ; get char count
pop h ; get entry ptr
jz dirsfnd ; found?
lxi d,10 ; skip to next entry
dad d
dcr c ; count down
jnz dirsl
ret ; return with Z if not found
dirsfnd:
mov b,m ; entry found, so get disk number
inr b ; adjust to 1 to n
inx h ; pt to user
mov c,m ; get user
mvi a,0ffh ; OK return
ora a
ret
;
; Scan entry pted to by HL to see if it contains the TOKEN
;
tokscan:
xchg ; save ptr in DE
lhld token ; pt to token
xchg ; HL pts to entry, DE pts to token
inx h ; pt to entry in dir
inx h
mvi b,8 ; up to 8 bytes
toks1:
ldax d ; get token char
cpi ':' ; end of token?
jz toks2
cpi ' ' ; space?
jz toks2
ora a ; EOL?
jz toks2
cmp m ; match?
rnz ; error abort if no match
inx h ; pt to next
inx d
dcr b ; count down
jnz toks1
ldax d ; full 8 chars, so token char must be a delim
cpi ':' ; ok?
rz
cpi ' ' ; ok if space
rz
ora a ; ok if EOL
ret
toks2:
mov a,m ; this must be a space for match
cpi ' '
ret
;
; Skip to non-blank
;
sblank:
mov a,m ; get char
inx h ; pt to next
cpi ' ' ; space?
jz sblank
dcx h ; pt to non-blank
ret
;
; Scan directories for user and disk in C and B
; Print name if found or Noname if not
;
udscan:
lhld ndradr ; check memory-based first
mov a,h
ora l
jz udscan1 ; none
inx h ; get entry count
mov d,m ; ... in D
inx h ; pt to first element
call udndscn ; scan named dir
jz udscan2 ; match
udscan1:
lhld ddir ; pt to disk-based dir
lda dentry ; number of entries
mov d,a ; entry count in D
call udndscn ; scan named dir
jnz udscan3 ; return no name
udscan2:
mvi b,8 ; 8 chars max
udsprn:
mov a,m ; get name char
cpi ' ' ; done?
rz
call cout ; print char
inx h ; pt to next
dcr b ; count down
jnz udsprn
ret
udscan3:
call print
db 'Noname',0
ret
;
; Scan dir pted to by HL for D elements
; BC=Disk/User
; Return with Z set and HL pting to name if found
;
udndscn:
mov a,m ; get disk
inx h ; pt to user
cmp b ; match so far?
jnz udnd1
mov a,m ; get user
cmp c ; match?
jnz udnd1
inx h ; pt to name
xra a ; return with zero for found
ret
udnd1:
push d ; save count
lxi d,9 ; pt to next element
dad d
pop d ; get count
dcr d ; count down
jnz udndscn
mvi a,0ffh ; not found
ora a
ret
;
; Return Current Disk and User (in B and C)
;
curud:
lda cdisk ; get disk
mov b,a ; ... in B
lda cuser ; get user
mov c,a ; ... in C
ret
;
; Buffers
;
cdisk:
ds 1 ; current disk
cuser:
ds 1 ; current user
cmdline:
ds 2 ; ptr to next char in command line
token:
ds 2 ; ptr to current token
pathptr:
ds 2 ; ptr to next path entry
ddir:
ds 2 ; ptr to disk dir in memory
dentry:
ds 1 ; number of entries in disk dir
tempath:
ds 50 ; allow for 25 element path
end