mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-25 09:24:19 +00:00
451 lines
7.8 KiB
NASM
451 lines
7.8 KiB
NASM
$title ('MP/M 1.1 Parse Filename')
|
||
name parse
|
||
cseg
|
||
;parse:
|
||
;do;
|
||
|
||
;$include (copyrt.lit)
|
||
;/*
|
||
; Copyright (C) 1979, 1980
|
||
; Digital Research
|
||
; P.O. Box 579
|
||
; Pacific Grove, CA 93950
|
||
;
|
||
; Revised:
|
||
; 18 Jan 80 by Thomas Rolander
|
||
;*/
|
||
;$include (common.lit)
|
||
;$nolist
|
||
;$include (queue.lit)
|
||
;$nolist
|
||
;$include (xdos.lit)
|
||
;$nolist
|
||
;$include (xdos.ext)
|
||
;$nolist
|
||
|
||
; readq:
|
||
extrn readq
|
||
; procedure (uqcbadr) byte external;
|
||
; declare uqcbadr address;
|
||
; end readq;
|
||
|
||
; writeq:
|
||
extrn writeq
|
||
; procedure (uqcbadr) byte external;
|
||
; declare uqcbadr address;
|
||
; end writeq;
|
||
|
||
; xdos:
|
||
extrn xdos
|
||
; procedure (func,info) address external;
|
||
; declare func byte;
|
||
; declare info address;
|
||
; end xdos;
|
||
|
||
dseg
|
||
;/*
|
||
; Parse Queue Data Segment
|
||
;*/
|
||
; declare parse$cqcb structure (cqueue,pdadr address) public
|
||
; initial (0,'MXParse ',0,1);
|
||
public parsecqcb
|
||
parsecqcb:
|
||
dw $-$ ; ql
|
||
db 'MXParse ' ; name
|
||
dw 0 ; msglen
|
||
dw 1 ; nmbmsgs
|
||
dw $-$ ; dqph
|
||
dw $-$ ; nqph
|
||
dw $-$ ; msgin
|
||
dw $-$ ; msgout
|
||
dw $-$ ; msgcnt
|
||
|
||
dw $-$ ; pdadr
|
||
|
||
; declare parse$mutex address public
|
||
; initial (.parse$cqcb);
|
||
parsemutex:
|
||
public parsemutex
|
||
dw parsecqcb ; pointer
|
||
cseg
|
||
|
||
del:
|
||
db 0dh,' =.:<>_[],'
|
||
|
||
; /*
|
||
; parse:
|
||
; */
|
||
|
||
parse:
|
||
; parse:
|
||
; procedure (pcb$adr) address;
|
||
dseg
|
||
; declare pcb$adr address;
|
||
pcbadr: ds 2
|
||
; declare pcb based pcb$adr structure (
|
||
; filename$adr address,
|
||
; fcb$adr address );
|
||
; declare pcb$filename$adr address;
|
||
pcbfilenameadr:
|
||
ds 2
|
||
; declare pcb$fcb$adr address;
|
||
pcbfcbadr:
|
||
ds 2
|
||
; declare filename based pcb$filename$adr (1) byte;
|
||
filename equ pcbfilenameadr+1
|
||
; declare fcb based pcb$fcb$adr (1) byte;
|
||
fcb equ pcbfcbadr+1
|
||
|
||
; declare
|
||
; /* return conditions */
|
||
; endline literally '00000H',
|
||
; badfile literally '0FFFFH',
|
||
; /* useful literals */
|
||
; disk literally 'fcb(0)',
|
||
; fcbname literally '8', /* end of name */
|
||
; fcbtype literally '11', /* end of type field */
|
||
; fcbsize literally '16'; /* partial size of fcb */
|
||
|
||
; declare char byte; /* global temp for current char */
|
||
char: ds 1
|
||
; declare fnp byte; /* index into file name buffer */
|
||
fnp: ds 1
|
||
; declare fnlen byte;
|
||
fnlen: ds 1
|
||
cseg
|
||
|
||
; /* initialize local bases */
|
||
; pcb$filename$adr = pcb.filename$adr;
|
||
LDAX B
|
||
MOV L,A
|
||
INX B
|
||
LDAX B
|
||
MOV H,A
|
||
SHLD PCBFILENAMEADR
|
||
; pcb$fcb$adr = pcb.fcb$adr;
|
||
; /* initialize file control block to empty */
|
||
INX B
|
||
LDAX B
|
||
MOV L,A
|
||
INX B
|
||
LDAX B
|
||
MOV H,A
|
||
SHLD PCBFCBADR
|
||
; char = ' ';
|
||
LXI H,CHAR
|
||
MVI M,20H
|
||
; fnlen = 0;
|
||
LXI H,FNLEN
|
||
MVI M,0H
|
||
; fnp = -1;
|
||
DCX H
|
||
MVI M,0FFH
|
||
; do while fnlen < fcbsize-1;
|
||
@24:
|
||
LDA FNLEN
|
||
CPI 0FH
|
||
JNC @25
|
||
; if fnlen = fcbtype then char = 0;
|
||
SUI 0BH
|
||
JNZ @4
|
||
LXI H,CHAR
|
||
MOV M,A
|
||
@4:
|
||
; call putchar;
|
||
CALL PUTCHAR
|
||
; end;
|
||
JMP @24
|
||
@25:
|
||
; disk = 0;
|
||
; /* scan next name */
|
||
LHLD PCBFCBADR
|
||
MVI M,0H
|
||
; do forever;
|
||
@26:
|
||
; /* deblank command buffer */
|
||
; call gnc;
|
||
CALL GNC ; char left in A
|
||
; do while char = ' ';
|
||
@28:
|
||
CPI 20H
|
||
JZ @26
|
||
; call gnc;
|
||
; end;
|
||
; if delimiter then return badfile;
|
||
CALL DELIMITER
|
||
RAR
|
||
JC @8A
|
||
; fnlen = 0;
|
||
LXI H,FNLEN
|
||
MVI M,0H
|
||
; do while not delimiter;
|
||
@30:
|
||
CALL DELIMITER
|
||
RAR
|
||
JC @31
|
||
; if fnlen >= fcbname then /* error, file name too long */
|
||
LDA FNLEN
|
||
CPI 8H
|
||
JC @6
|
||
; return badfile;
|
||
@8A:
|
||
LXI H,0FFFFH
|
||
RET
|
||
|
||
@6:
|
||
; if char = '*' then call fillq(fcbname); else call putchar;
|
||
LDA CHAR
|
||
CPI 2AH
|
||
JNZ @7
|
||
MVI C,8H
|
||
CALL FILLQ
|
||
JMP @8
|
||
@7:
|
||
CALL PUTCHAR
|
||
@8:
|
||
; call gnc;
|
||
CALL GNC
|
||
; end;
|
||
JMP @30
|
||
@31:
|
||
|
||
; /* check for disk name */
|
||
; if char = ':' then
|
||
LDA CHAR
|
||
CPI 3AH
|
||
JNZ @9
|
||
; do;
|
||
; if not (disk = 0 and fnlen = 1) then
|
||
LHLD PCBFCBADR
|
||
MOV A,M
|
||
ORA A
|
||
JNZ @8A
|
||
LDA FNLEN
|
||
DCR A
|
||
JNZ @8A
|
||
; return badfile;
|
||
; /* must be a disk name */
|
||
; if (disk := fcb(1) - 'A' + 1) > 26
|
||
; /* invalid disk name */
|
||
LHLD PCBFCBADR
|
||
INX H
|
||
MOV A,M
|
||
SUI 41H
|
||
INR A
|
||
DCX H
|
||
MOV M,A
|
||
CPI 27
|
||
JNC @8A
|
||
; then return badfile;
|
||
; /* valid disk name replace space in name */
|
||
; else fcb(fnlen) = ' ';
|
||
LHLD FNLEN
|
||
MVI H,0
|
||
XCHG
|
||
LHLD PCBFCBADR
|
||
DAD D
|
||
MVI M,20H
|
||
; end;
|
||
JMP @26
|
||
@9:
|
||
; else
|
||
; do;
|
||
; /* char is not ':', so file name is set. scan remainder */
|
||
; /* at least one char scanned */
|
||
; fnlen = fcbname;
|
||
LXI H,FNLEN
|
||
MVI M,8H
|
||
; if char = '.' then /* scan file type */
|
||
CPI 2EH
|
||
JNZ @14
|
||
; do;
|
||
; call gnc;
|
||
CALL GNC
|
||
; do while not delimiter;
|
||
@32:
|
||
CALL DELIMITER
|
||
RAR
|
||
JC @33
|
||
; if fnlen >= fcbtype then
|
||
LDA FNLEN
|
||
CPI 0BH
|
||
JC @15
|
||
; /* error, type field too long */
|
||
; return badfile;
|
||
LXI H,0FFFFH
|
||
RET
|
||
@15:
|
||
; if char = '*'
|
||
LDA CHAR
|
||
CPI 2AH
|
||
JNZ @16
|
||
; then call fillq(fcbtype);
|
||
MVI C,0BH
|
||
CALL FILLQ
|
||
JMP @17
|
||
@16:
|
||
; else call putchar;
|
||
CALL PUTCHAR
|
||
@17:
|
||
; call gnc;
|
||
CALL GNC
|
||
; end;
|
||
JMP @32
|
||
@33:
|
||
LDA CHAR
|
||
; end;
|
||
@14:
|
||
|
||
; if char = 0dh
|
||
CPI 0DH
|
||
LXI H,0000H
|
||
; then return endline;
|
||
RZ
|
||
; else return .filename(fnp);
|
||
LHLD FNP
|
||
MVI H,0
|
||
XCHG
|
||
LHLD PCBFILENAMEADR
|
||
DAD D
|
||
RET
|
||
; end;
|
||
; end; /* of forever */
|
||
; end parse;
|
||
|
||
; gnctran:
|
||
gnctran:
|
||
; procedure(b) byte;
|
||
; declare b byte;
|
||
|
||
; if b < ' ' then return 0dh; /* all non-graphics */
|
||
MOV A,C
|
||
CPI 20H
|
||
MVI A,0DH
|
||
RC
|
||
; /* translate alpha to upper case */
|
||
; if b >= 'a' and b <= 'z' then
|
||
MOV A,C
|
||
CPI 'a'
|
||
RC
|
||
CPI 'z'+1
|
||
RNC
|
||
ANI 5FH
|
||
RET
|
||
; b = b and 101$1111b; /* upper case */
|
||
; return b;
|
||
; end gnctran;
|
||
|
||
; gnc:
|
||
gnc:
|
||
; procedure;
|
||
|
||
; char = gnctran(filename(fnp := fnp + 1));
|
||
LXI H,FNP
|
||
INR M
|
||
MOV C,M
|
||
MVI B,0
|
||
LHLD PCBFILENAMEADR
|
||
DAD B
|
||
MOV C,M
|
||
CALL GNCTRAN
|
||
STA CHAR
|
||
; end gnc;
|
||
RET
|
||
|
||
; delimiter:
|
||
delimiter:
|
||
; procedure byte;
|
||
; declare i byte;
|
||
; declare del(*) byte data
|
||
; (0dh,' =.:<>_[],');
|
||
|
||
; do i = 0 to last(del);
|
||
MVI C,11
|
||
LXI D,DEL
|
||
LXI H,CHAR
|
||
@20:
|
||
; if char = del(i) then return true;
|
||
LDAX D
|
||
SUB M
|
||
MVI A,0FFH
|
||
RZ
|
||
INX D
|
||
DCR C
|
||
JNZ @20
|
||
; end;
|
||
; return false;
|
||
XRA A
|
||
RET
|
||
; end delimiter;
|
||
|
||
; putchar:
|
||
putchar:
|
||
; procedure;
|
||
|
||
; fcb(fnlen:=fnlen+1) = char;
|
||
; /* can check here for ambig ref's "char = '?'" */
|
||
LXI H,FNLEN
|
||
INR M
|
||
MOV C,M
|
||
MVI B,0
|
||
LHLD PCBFCBADR
|
||
DAD B
|
||
LDA CHAR
|
||
MOV M,A
|
||
; end putchar;
|
||
RET
|
||
|
||
; fillq:
|
||
fillq:
|
||
; procedure(len);
|
||
; /* fill current name or type with question marks */
|
||
|
||
; declare len byte;
|
||
|
||
; char = '?'; /* question mark */
|
||
LXI H,CHAR
|
||
MVI M,3FH
|
||
; do while fnlen < len;
|
||
@22:
|
||
LDA FNLEN
|
||
CMP C
|
||
RNC
|
||
; call putchar;
|
||
PUSH B
|
||
CALL PUTCHAR
|
||
POP B
|
||
; end;
|
||
JMP @22
|
||
; end fillq;
|
||
|
||
;/*
|
||
; parse$filename:
|
||
;*/
|
||
|
||
; parse$filename:
|
||
parsefilename:
|
||
PUSH B
|
||
; procedure (pcb$adr) address reentrant public;
|
||
public parsefilename
|
||
; declare pcb$adr address;
|
||
; declare nxt$chr$adr address;
|
||
; declare ret byte;
|
||
|
||
; ret = xdos (read$queue,.parse$mutex);
|
||
LXI B,PARSEMUTEX
|
||
CALL READQ
|
||
; nxt$chr$adr = parse (pcb$adr);
|
||
POP B
|
||
CALL PARSE
|
||
PUSH H
|
||
; ret = xdos (write$queue,.parse$mutex);
|
||
LXI B,PARSEMUTEX
|
||
CALL WRITEQ
|
||
; return nxt$chr$adr;
|
||
POP H
|
||
RET
|
||
; end parse$filename;
|
||
|
||
;end parse;
|
||
END
|
||
|