home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
languags
/
prolog
/
epro23.ark
/
CMD.MAC
< prev
next >
Wrap
Text File
|
1986-11-02
|
14KB
|
860 lines
; ===========================================================
; CMD.Z80
; built-in commands for E-Prolog
; June 1, 1985
.Z80
FALSE EQU 0
TRUE EQU 1
EMPTY EQU -1
UNDEF EQU -2
HT EQU 9
LF EQU 10
CR EQU 13
CTLZ EQU 26
CPM EQU 0000H
BDOS EQU CPM+0005H
CDMA EQU CPM+0080H
TPA EQU CPM+0100H
; compare with given value
;
?CPHL MACRO ?VALUE
PUSH DE
LD DE,?VALUE
CALL CPHL##
POP DE
ENDM
; copy string
;
; input:
; HL -> source
; all registers destroyed
?COPY MACRO ?ADDR
LD DE,?ADDR
CALL COPY##
ENDM
; local storage
DSEG
LOCST: DS 8
REST EQU LOCST
LS EQU LOCST+2
X EQU LOCST+4
Y EQU LOCST+6
SV EQU LOCST+4
PTR EQU LOCST
LSS EQU LS
X1 EQU LOCST+4
X2 EQU LOCST+6
CSEG
;noretry(ast)
; ALPHASTATE * ast;
; {
; ast->datb = (PAIR)empty;
; }
NORE::
LD HL,EMPTY
;setretry(ast,addr)
; ALPHASTATE * ast;
; char * addr;
; {
; ast->datb = (PAIR *)addr;
; }
SETRE::
JP XLDATB##
;SYMBOL *
;vnext(pexp,plsub)
; EXPR * pexp;
; LSUBST * plsub;
; {
; SYMBOL * x;
; SEXPR * y;
DSEG
PEXP: DW 0
PLSUB: DW 0
VX: DW 0
VY: DW 0
CSEG
VNEXT::
LD (PEXP),HL
LD (PLSUB),DE
;
; if (varp(pexp->list))
CALL INDIR##
CALL VARP##
JR Z,VN1
; {
; y = value(vf(pexp->list,*plsub));
PUSH HL
LD HL,(PLSUB)
CALL INDIR##
EX DE,HL
POP HL
CALL VF##
CALL VALUE##
LD (VY),HL
; if (substp(y))
CALL SUBSTP##
JR Z,VN2
; return UNDEF;
LD HL,UNDEF
RET
VN2:
; pexp->list = y->sexp.list;
CALL @EXPR##
EX DE,HL
LD HL,(PEXP)
LD (HL),E
INC HL
LD (HL),D
; *plsub = y->slist;
LD HL,(VY)
CALL @SLIST##
EX DE,HL
LD HL,(PLSUB)
LD (HL),E
INC HL
LD (HL),D
; }
VN1:
; if (nelistp(pexp->list))
LD HL,(PEXP)
CALL INDIR##
CALL NELP##
JR Z,VN3
; {
; x = pexp->list->left.symbol;
CALL @LEFT##
LD (VX),HL
; if (varp(x))
CALL VARP##
JR Z,VN4
; {
; y = value(vf(x,*plsub));
PUSH HL
LD HL,(PLSUB)
CALL INDIR##
EX DE,HL
POP HL
CALL VF##
CALL VALUE##
LD (VY),HL
; x = y->sexp.symbol;
CALL @EXPR##
LD (VX),HL
; if (varp(x))
CALL VARP##
JR Z,VN4
; x = y;
LD HL,(VY)
LD (VX),HL
; }
VN4:
; pexp->list = pexp->list->right.list;
LD HL,(PEXP)
PUSH HL
CALL INDIR##
CALL @RIGHT##
EX DE,HL
POP HL
LD (HL),E
INC HL
LD (HL),D
; return x;
LD HL,(VX)
RET
; }
VN3:
; return UNDEF;
LD HL,UNDEF
RET
; }
RETT:: LD HL,TRUE
RETX: LD A,H
OR L
RET
RETF:: LD HL,FALSE
JR RETX
;built-in commands called in this form:
; f(rest,ast,ls,pbst)
; PAIR rest; (in HL) rest of atom
; ALPHASTATE * ast; (in IX) this state
; LSUBST ls; (in DE ) substs for rest
; BETASTATE * bst; (in IY) empty, at first
;
;return TRUE to succeed, return FALSE to fail
;call noretry() to prohibit further retries
;call setretry() to set entry point for next retry
; ==================== / ====================
;_cut(rest,ast,ls,pbst)
; PAIR rest;
; ALPHASTATE * ast;
; LSUBST ls;
; BETASTATE ** pbst;
; {
; setretry(ast,&rcut);
; return TRUE;
; }
_CUT::
LD HL,RCUT
CALL SETRE
JP RETT
;rcut() /* retry of cut */
; {
; return EMPTY;
; }
RCUT::
LD HL,EMPTY
LD A,H
OR L
RET
; ==================== APPEND ====================
; APPEND command
;
; open file for output, position to the end of the file
_APPEN::
PUSH HL
PUSH DE
CALL NORE
CALL CLOSE## ; close existing output file
POP DE
POP HL
CALL DOOUT##
LD A,(OUTF##)
DEC A
JP NZ,RETT ; not disk file
LD DE,OUTFCB##
LD C,15 ; open file
CALL BDOS
INC A
JR NZ,APPEN1
LD (OUTF),A ; not found, revert to console
JP RETF
APPEN1: LD DE,OUTFCB##
LD C,35 ; compute file size
CALL BDOS
LD HL,(OUTFCB##+33) ; random record number
DEC HL
LD (OUTFCB##+33),HL ; last existing record
LD DE,OUTDMA##
LD C,26 ; set DMA
CALL BDOS
LD DE,OUTFCB##
LD C,33 ; read random
CALL BDOS
LD HL,OUTDMA##
APPEN2: LD A,(HL)
CP CTLZ
JR Z,APPEN3
INC HL
?CPHL OUTE##
JR NZ,APPEN2
LD DE,OUTFCB## ; read sequential to prepare
LD C,20 ; next record field
CALL BDOS
LD HL,OUTE##
APPEN3: LD (OUTP),HL
JP RETT
; ==================== CLOSE ====================
;_close(rest,ast)
; PAIR rest;
; ALPHASTATE * ast;
; {
; noretry(ast);
; close();
; }
_CLOSE::
CALL NORE
CLOSEX: CALL CLOSE##
JP RETT
; ==================== CREATE ====================
; CREATE command
;
; opens a new file as output
; deletes any existing file with the same name
; (cf. APPEND command)
_CREA::
PUSH HL
PUSH DE
CALL NORE
CALL CLOSE## ; close existing output file
POP DE
POP HL
CALL DOOUT##
CALL SAVEX
JP RETT
; ==================== FAIL ====================
;_fail()
; {
; return FALSE;
; }
_FAIL::
JP RETF
; ==================== LESS ====================
;_less(rest,ast,ls,pbst)
; PAIR rest;
; ALPHASTATE * ast;
; LSUBST ls;
; BETASTATE ** pbst;
; {
; static EXPR x1;
; static EXPR x2;
; static LSUBST lss;
_LESS::
;
; lss = ls;
LD (REST),HL
LD (LSS),DE
; noretry(ast);
CALL NORE
; x1.list = vnext(&rest,&lss);
LD HL,REST
LD DE,LSS
CALL VNEXT
LD (X1),HL
; if (x1.list == UNDEF)
; return FALSE;
?CPHL UNDEF
JP Z,RETF
; x2.list = vnext(&rest,&lss);
LD HL,REST
LD DE,LSS
CALL VNEXT
LD (X2),HL
; if (x2.list == UNDEF)
; return FALSE;
?CPHL UNDEF
JP Z,RETF
; if (numbp(x1.number) && numbp(x2.number))
; return (x1.number < x2.number);
LD HL,(X1)
CALL NUMBP##
JR Z,LE1
LD HL,(X2)
CALL NUMBP##
JR Z,LE1
LD HL,(X1)
LD DE,(X2)
CALL CPHL##
JP C,RETT
JP RETF
LE1:
; if (symbp(x1.symbol) && symbp(x2.symbol))
; return (strcmp(x1.symbol->string,x2.symbol->string) < 0);
LD HL,(X1)
CALL SYMBP##
JR Z,LE2
LD HL,(X2)
CALL SYMBP##
JR Z,LE2
LD HL,(X2)
CALL @STR##
PUSH HL
LD HL,(X1)
CALL @STR##
POP DE
CALL STRCMP##
JP C,RETT
JP RETF
LE2:
; *pbst = makebeta(ast,empty);
LD HL,EMPTY
CALL MKBETA##
; if (substp(x1.symbol))
LD HL,(X1)
CALL SUBSTP##
JR Z,LE3
; {
; setretry(ast,&rless);
LD HL,RLESS
CALL SETRE
; if (numbp(x2.number))
LD HL,(X2)
CALL NUMBP##
JR Z,LE5
; {
; lessv(x2.number-1,x1.symbol);
LD HL,(X2)
DEC HL
LD DE,(X1)
CALL LESSV
; return TRUE;
JP RETT
; }
LE5:
; if (substp(x2.symbol))
LD HL,(X2)
CALL SUBSTP##
JP Z,LE6
; {
; lessv(0,x1.symbol);
LD HL,0
LD DE,(X1)
CALL LESSV
; lessv(1,x2.symbol);
LD HL,1
LD DE,(X2)
CALL LESSV
; return TRUE;
JP RETT
; }
LE6 EQU RETF
; }
LE3:
; else if (substp(x2.symbol))
LD HL,(X2)
CALL SUBSTP##
JP Z,LE4
; {
; setretry(ast,&rless);
LD HL,RLESS
CALL SETRE
; if (numbp(x1.number))
LD HL,(X1)
CALL NUMBP##
JP Z,LE4
; {
; lessv(x1.number+1,x2.symbol);
LD HL,(X1)
INC HL
LD DE,(X2)
CALL LESSV
; return TRUE;
JP RETT
; }
; }
LE4 EQU RETF
; return FALSE;
; }
;
;rless()
RLESS: ; needs more work to do retries
; {
; fatal("\r\nRetry on LESS.");
LD HL,RLMSG
JP FATAL##
DSEG
RLMSG: DB CR,LF,'Retry on LESS.',0
CSEG
; }
;
;lessv(val,sub)
; NUMBER val;
; SUBST * sub;
; {
; unify(val,empty,sub->vname,sub);
LESSV:
PUSH DE
LD DE,EMPTY
EXX
POP HL
PUSH HL
CALL @VNAME##
POP DE
EXX
JP UNIFY##
; }
; ==================== LIST ====================
;_list(rest,ast)
; PAIR rest;
; ALPHASTATE * ast;
; {
_LIST::
; noretry(ast);
CALL NORE
; listt((SYMBOL *)sbot);
LISTX: LD HL,(SBOT##)
CALL LISTT
; return TRUE;
JP RETT
; }
;
;listt(ptr) /* recursive */
; SYMBOL * ptr;
; {
; PAIR x;
LISTT:
LD (PTR),HL
;
; if (ptr != (SYMBOL *)empty)
?CPHL EMPTY
RET Z
; {
; listt(ptr->lptr);
LD HL,(PTR)
PUSH HL
CALL @LPTR##
CALL LISTT ; recursive
POP HL
LD (PTR),HL
; if (nelistp(x = (PAIR)(ptr->addr)))
CALL @ADDR##
LD (X),HL
CALL NELP##
JR Z,LI1
; {
; do
LI2:
; {
; listpr(x->left.list);
LD HL,(X)
CALL @LEFT##
CALL LISTPR
; }
; while (nelistp(x = x->right.list)) ;
LD HL,(X)
CALL @RIGHT##
LD (X),HL
CALL NELP##
JR NZ,LI2
; chrout('\r');
; chrout('\n');
CALL CRLF##
; }
LI1:
; listt(ptr->rptr);
LD HL,(PTR)
CALL @RPTR##
JR LISTT ; tail recursion
; }
; }
;
;listpr(y)
; PAIR y;
; {
LISTPR:
LD (Y),HL
; chrout('(');
LD A,'('
CALL CHROUT##
; eprint(y->left.list,empty);
LD HL,(Y)
CALL @LEFT##
LD DE,EMPTY
CALL EPRINT##
; for (y = y->right.list ; nelistp(y) ; y = y->right.list)
; {
LI4:
LD HL,(Y)
CALL @RIGHT##
LD (Y),HL
CALL NELP##
JR Z,LI3
; msg("\r\n\t");
LD HL,LI4MSG
DSEG
LI4MSG: DB CR,LF,HT,0
CSEG
CALL MSG##
; eprint(y->left.list,empty);
LD HL,(Y)
CALL @LEFT
LD DE,EMPTY
CALL EPRINT##
; }
JR LI4
LI3:
; msg(")\r\n");
LD HL,LI3MSG
DSEG
LI3MSG: DB ')',CR,LF,0
CSEG
JP MSG##
; }
; ==================== LOAD ====================
; LOAD command
;
; load from given disk file
; default filetype 'PRO'
_LOAD::
CALL DOIN##
CALL NORE
LD A,(INF##)
DEC A
JP NZ,RETT ; not a disk file
LD A,(INFCB##+9)
CP ' ' ; no filetype?
JR NZ,LOAD1
LD HL,APRO## ; use default 'PRO'
?COPY INFCB##+9
LOAD1: JP LOADX
; ==================== OPEN ====================
; OPEN command
;
; opens an existing file as input
_OPEN::
CALL DOIN##
CALL NORE
LD A,(INF##)
DEC A
JP NZ,RETT ; not a disk file
LOADX: LD DE,INFCB##
LD C,15 ; open file
CALL BDOS
INC A ; file found?
JR NZ,OPEN1 ; yes
XOR A
LD (INF##),A
JP RETF
OPEN1: XOR A
LD (INFCB##+32),A ; zero current record
LD HL,INE## ; pointer beyond end
LD (INP##),HL
JP RETT
; ==================== READ ====================
;_read(rest,ast,ls,pbst)
; PAIR rest;
; ALPHASTATE * ast;
; LSUBST ls;
; BETASTATE ** pbst;
; {
; PAIR x;
_READ::
LD (REST),HL
LD (LS),DE
; noretry(ast);
CALL NORE
; x = makepair(gtoken(),empty);
CALL GTOKEN##
JR READX
; ==================== READCHAR ====================
;_readc(rest,ast,ls,pbst)
; PAIR rest;
; ALPHASTATE * ast;
; LSUBST ls;
; BETASTATE ** pbst;
; {
; PAIR x;
;
_READC::
LD (REST),HL
LD (LS),DE
; noretry(ast);
CALL NORE
; rdchar();
CALL RDCHAR##
; x = makepair(character,empty);
LD A,(CHR##)
LD L,A
LD H,0
READX: LD DE,EMPTY
CALL MKPAIR##
LD (X),HL
; *pbst = makebeta(ast,empty);
LD HL,EMPTY
CALL MKBETA##
; if (unify(rest,ls,x,empty))
; return TRUE;
LD HL,(X)
LD DE,EMPTY
EXX
LD HL,(REST)
LD DE,(LS)
CALL UNIFY##
JP NZ,RETT
; release(x);
LD HL,(X)
CALL RLS##
; return FALSE;
JP RETF
; }
; ==================== READLIST ====================
;_readl(rest,ast,ls,pbst)
; PAIR rest;
; ALPHASTATE * ast;
; LSUBST ls;
; BETASTATE ** pbst;
; {
; PAIR x;
;
_READL::
LD (REST),HL
LD (LS),DE
; noretry(ast);
CALL NORE
; opar = 0;
XOR A
LD (OPAR##),A
; x = makepair(rdg1(),empty);
CALL RDG1##
JR READX
; ==================== SAVE ====================
; SAVE command
;
; saves database to named file
; default filetype 'PRO'
_SAVE::
PUSH HL
PUSH DE
CALL NORE
CALL CLOSE## ; close existing output file
POP DE
POP HL
CALL DOOUT##
LD A,(OUTFCB##+9)
CP ' ' ; no filetype?
JR NZ,SAVE1
LD HL,APRO## ; use default 'PRO'
?COPY OUTFCB##+9
SAVE1: CALL SAVEX ; create the file for output
CALL LISTX ; send listing to file
JP CLOSEX ; close file
SAVEX:
LD A,(OUTF##)
DEC A
RET NZ ; not disk file
LD DE,OUTFCB##
LD C,19 ; delete file
CALL BDOS
LD DE,OUTFCB##
LD C,22 ; make file
CALL BDOS
INC A
JP Z,RETF ; unsuccessful
LD HL,OUTDMA##
LD (OUTP##),HL
RET
; ==================== WRITE ====================
;_write(rest,ast,ls,pbst)
; PAIR rest;
; ALPHASTATE * ast;
; LSUBST ls;
; BETASTATE ** pbst;
; {
; static SUBVAL sv;
_WRITE::
LD (REST),HL
LD (LS),DE
; noretry(ast);
CALL NORE
; if (varp(rest))
LD HL,(REST)
CALL VARP##
JR Z,WR1
; {
; if (substp(sv.val = value(vf(rest,ls))))
; ;
LD DE,(LS)
CALL VF##
CALL VALUE##
LD (SV),HL
CALL SUBSTP##
JR NZ,WR1
; else
; {
; rest = sv.assgn->sexp.list;
CALL @EXPR##
LD (REST),HL
; ls = sv.assgn->slist;
LD HL,(SV)
CALL @SLIST##
LD (LS),HL
; }
; }
WR1:
; while (nelistp(rest))
LD HL,(REST)
CALL NELP##
JR Z,WR2
; {
; eprint(rest->left.list,ls);
CALL @LEFT
LD DE,(LS)
CALL EPRINT##
; rest = rest->right.list;
LD HL,(REST)
CALL @RIGHT##
LD (REST),HL
; if (varp(rest))
CALL VARP##
JR Z,WR3
; {
; if (substp(sv.val = value(vf(rest,ls))))
; ;
LD DE,(LS)
CALL VF##
CALL VALUE##
LD (SV),HL
CALL SUBSTP##
JR NZ,WR3
; else
; {
; rest = sv.assgn->sexp.list;
CALL @EXPR##
LD (REST),HL
; ls = sv.assgn->slist;
LD HL,(SV)
CALL @SLIST##
LD (LS),HL
; }
; }
WR3 EQU WR1
JR WR1
; }
WR2:
; return TRUE;
JP RETT
; }
; ==================== WRITECHAR ====================
;_wrch(rest,ast,ls,pbst)
; PAIR rest;
; ALPHASTATE * ast;
; LSUBST ls;
; BETASTATE ** pbst;
; {
; NUMBER x;
_WRCH::
LD (REST),HL
LD (LS),DE
; noretry(ast);
CALL NORE
; x = vnext(&rest,&ls);
LD HL,REST
LD DE,LS
CALL VNEXT
; if (! numbp(x))
; return FALSE;
CALL NUMBP##
JP Z,RETF
; if (x > 255)
; return FALSE;
LD DE,256
CALL CPHL##
JP NC,RETF
; putc(x,outfile);
LD A,L
CALL CHROUT##
; return TRUE;
JP RETT
; }
END