mirror of
https://github.com/a2stuff/prodos-path.git
synced 2024-12-27 13:29:22 +00:00
237 lines
5.9 KiB
ArmAsm
237 lines
5.9 KiB
ArmAsm
;;; ============================================================
|
|
;;;
|
|
;;; CD - Change Directory (like PREFIX, plus .. support)
|
|
;;;
|
|
;;; Usage: CD path
|
|
;;;
|
|
;;; * path can be absolute, e.g. CD /VOL/DIR
|
|
;;; * path can be relative, e.g. CD SUBDIR/SUBDIR
|
|
;;; * segments can be .. to go up a dir, e.g. CD ../DIR
|
|
;;; * segments can be . to mean same dir, e.g. CD ./SUBDIR
|
|
;;; * with no path, echoes current PREFIX
|
|
;;;
|
|
;;; ============================================================
|
|
|
|
.include "apple2.inc"
|
|
.include "more_apple2.inc"
|
|
.include "prodos.inc"
|
|
|
|
;;; ============================================================
|
|
|
|
.org $4000
|
|
|
|
;; Follow the BI external command protocol. Although
|
|
;; the parser is not used, this allows returning
|
|
;; BI error codes.
|
|
|
|
;; Point BI's parser at the command execution routine.
|
|
lda #<execute
|
|
sta XTRNADDR
|
|
lda #>execute
|
|
sta XTRNADDR+1
|
|
|
|
;; Mark command as external (zero).
|
|
lda #0
|
|
sta XCNUM
|
|
|
|
;; Set accepted parameter flags
|
|
lda #0
|
|
sta PBITS
|
|
lda #0
|
|
sta PBITS+1
|
|
|
|
clc ; Success (so far)
|
|
rts1: rts ; Return to BASIC.SYSTEM
|
|
|
|
;;; ============================================================
|
|
|
|
PFXBUF := $280
|
|
tmp := $06
|
|
|
|
execute:
|
|
;; Skip command and leading spaces
|
|
ldx XLEN
|
|
inx
|
|
jsr SkipSpaces
|
|
|
|
;; Absolute?
|
|
lda INBUF,x
|
|
cmp #'/'|$80
|
|
beq abs
|
|
|
|
;; No, will need current prefix
|
|
stx tmp
|
|
jsr GetPrefix
|
|
bcs rts1
|
|
ldx tmp
|
|
|
|
;; Empty?
|
|
lda INBUF,x
|
|
cmp #$8D ; CR
|
|
bne common ; no, start processing
|
|
|
|
;; Echo the current prefix
|
|
jsr CROUT
|
|
ldx #0
|
|
: inx
|
|
lda PFXBUF,x
|
|
ora #$80
|
|
jsr COUT
|
|
cpx PFXBUF
|
|
bne :-
|
|
jsr CROUT
|
|
jsr CROUT
|
|
clc
|
|
rts
|
|
|
|
;;; --------------------------------------------------
|
|
;;; Absolute path
|
|
|
|
abs: lda #1 ; init prefix to just '/'
|
|
sta PFXBUF
|
|
lda #'/'
|
|
sta PFXBUF+1
|
|
inx ; consume leading '/'
|
|
;; fall through
|
|
|
|
;;; --------------------------------------------------
|
|
;;; Process the relative path
|
|
;;;
|
|
;;; PFXBUF has the prefix; Y holds the length
|
|
;;; X holds position in INBUF
|
|
|
|
common: ldy PFXBUF
|
|
|
|
;; Loop over segments
|
|
loop: jsr GetC
|
|
cmp #$D ; EOL?
|
|
beq done
|
|
|
|
cmp #'.' ; Maybe "." or ".." ?
|
|
beq dot
|
|
|
|
put: jsr PutC
|
|
jsr GetC
|
|
|
|
cmp #$D ; EOL?
|
|
beq done
|
|
cmp #'/' ; end of segment?
|
|
bne put
|
|
jsr PutC
|
|
bne loop ; always
|
|
|
|
dot: jsr GetC
|
|
cmp #'.' ; ".." ?
|
|
bne :+
|
|
jsr Pop ; yes, pop the last segment
|
|
jsr GetC
|
|
: cmp #$D ; EOL?
|
|
beq done ; groovy
|
|
cmp #'/' ; "./" or "../"?
|
|
beq loop ; also groovy
|
|
|
|
lda #BI_ERR_SYNTAX_ERROR
|
|
sec
|
|
rts
|
|
|
|
;;; --------------------------------------------------
|
|
;;; Try setting the new PREFIX
|
|
|
|
done: sty PFXBUF
|
|
MLI_CALL SET_PREFIX, get_set_prefix_params
|
|
bcc :+
|
|
jsr BADCALL ; Convert MLI error to BI error
|
|
: rts
|
|
|
|
|
|
;;; ============================================================
|
|
;;; Pop a segment
|
|
.proc Pop
|
|
cpy #1
|
|
beq done
|
|
: dey
|
|
lda PFXBUF,y
|
|
cmp #'/'
|
|
bne :-
|
|
|
|
done: rts
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
;;; Get next character from INBUF at X.
|
|
.proc GetC
|
|
lda INBUF,x
|
|
inx
|
|
and #$7F
|
|
rts
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
;;; Append to PFXBUF at Y. Returns non-zero.
|
|
.proc PutC
|
|
iny
|
|
sta PFXBUF,y
|
|
rts
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
;;; Skip over spaces in INBUF, advancing X; returns first non-space.
|
|
.proc SkipSpaces
|
|
repeat: lda INBUF,x
|
|
cmp #' '|$80
|
|
beq :+
|
|
rts
|
|
: inx
|
|
jmp repeat
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
;;; Leave PREFIX at PFXBUF; infers it the same way as BI if empty.
|
|
;;; Returns with Carry set on failure.
|
|
.proc GetPrefix
|
|
;; Try fetching prefix
|
|
MLI_CALL GET_PREFIX, get_set_prefix_params
|
|
lda PFXBUF
|
|
bne done
|
|
|
|
;; Use BI's current slot and drive to construct unit number
|
|
lda DEFSLT ; xxxxxSSS
|
|
asl ; xxxxSSS0
|
|
asl ; xxxSSS00
|
|
asl ; xxSSS000
|
|
asl ; xSSS0000
|
|
asl ; SSS00000
|
|
ldx DEFDRV
|
|
cpx #2 ; C=0 if 1, C=1 if 2
|
|
ror ; DSSS0000
|
|
sta unit
|
|
|
|
;; Get volume name and convert to path
|
|
MLI_CALL ON_LINE, on_line_params
|
|
bcc :+
|
|
jsr BADCALL ; sets Carry
|
|
rts
|
|
|
|
: lda PFXBUF+1
|
|
and #$0F ; mask off name_len
|
|
tax
|
|
inx ; leading and trailing '/'
|
|
inx
|
|
stx PFXBUF
|
|
lda #'/'
|
|
sta PFXBUF+1 ; leading '/'
|
|
sta PFXBUF,x ; trailing '/'
|
|
|
|
done: clc
|
|
rts
|
|
|
|
on_line_params:
|
|
.byte 2
|
|
unit: .byte 0
|
|
.addr PFXBUF+1 ; leave room to insert leading '/'
|
|
.endproc
|
|
|
|
get_set_prefix_params:
|
|
.byte 1
|
|
.addr PFXBUF
|