💾 Archived View for mirrors.apple2.org.za › archive › www.textfiles.com › apple › ANATOMY › cmdexec.… captured on 2023-01-29 at 11:41:00.
View Raw
More Information
-=-=-=-=-=-=-
- *****************************************************************
- *
- EXEC comand handler *
- *
- ----------------------------------------------------------------*
- *
- The EXEC command is one of the most powerful commands in *
- DOS. Its command handler (CMDEXEC, $A5C6) reads data from a *
- text file and interprets the information contained in that *
- file as if it was typed in from the keyboard in the immediate *
- mode. If a command is read, it is executed immediately. If *
- the data are interpreted to be a program line, the line is *
- added to the program currently in memory. A filename must be *
- issued with the command. Volume, drive, slot and relative *
- field position parameters are optional. *
- The EXECCMD routine does not do any EXECing per se. It *
- simply opens the file, positions the file pointer and (most *
- importantly) SETS the EXECFLAG. Eventually the computer *
- returns to basic's RESTART routine ($D43C) where input is *
- requested. Because the input hook (CSW/+1; $36,$37) points at *
- DOS's input handler (INPTINCP, $9E81), DOS regains control. *
- During the execution of INPTINCP, the exec flag (EXECFLAG, *
- $AAB3) is tested and discovered to be set. Consequently, the *
- READEXEC routine ($A682) is used to read data from the disk. *
- As the data are read, they are placed in the input buffer *
- (BUFF200, $200) one byte at a time. Each time that a carriage *
- return is encountered, the buffer is parsed. If a DOS, *
- Applesoft or machine language instruction is recognized, the *
- command (instruction) is executed as if it were typed in from *
- the keyboard (ie. immediate mode). After the entire file is *
- read, the file is closed and the EXECFLAG is shut off. *
- *
- *****************************************************************
(A5C6)
CMDEXEC JSR CMDOPEN ;Go open the file to be EXECed.
(A2A3)
CMDOPEN LDA #0 ;0 = code for text file.
(A2A5) JMP OPNCKTYP ;Go open the file & check its type.
------------
(A3D5)
OPNCKTYP STA FILTYPFM ;Put code for file type in the FM parameter
(A3D8) PHA ;list & save it on the stack. ($00= Text,
;$02=Applesoft, $04=Binary, $08=S-type,
;$10=Relocatable, $20=A-type and $40=B-type.)
(A3D9) JSR HNDLCMD ;Use the file manager's command handler to
;open the file.
* Common file manager command handler code.
(A2A8)
HNDLCMD LDA #1 ;1 = Open opcode.
HNDLCMD1 STA TEMPBYT ;Store opcode in temporary location.
LDA LENPRSD ;Get L-parameter from parsed table.
BNE SAVLENFM ;Was a non-zero L-parm issued with cmd?
LDA LENPRSD+1
BNE SAVLENFM
LDA #1 ;Length was 0 so make it 1 instead.
STA LENPRSD
SAVLENFM LDA LENPRSD ;Put length in FM parameter list.
STA RECLENFM ;(Note: Record length = 1 for sequential files
LDA LENPRSD+1 ;else = parsed length for random access files.)
STA RECLENFM+1
CLSLOCBF JSR CMDCLOSE ;Close file if it is already open.
(A2C8)
(A2EA)
CMDCLOSE .
.
(See dis'mbly of CMDCLOSE for details.)
.
.
- Note that execution flows thru CMDCLOSE twice if the
file is already open.
- The first time thru, the matching DOS filename buffer is
located & then CLOSEONE is used to close the file.
- Execution then jumps back to the start of CMDCLOSE.
- On this second pass, a matching filename is not found
because the DOS filename buffer was released on the
first pass. Therefore, A5L/+1 is left pointing at the
highest numbered (lowest in memory) FREE DOS buffer
when CMDCLOSE is exited via EVENTXIT and CLOSERTS.
- If the file is not already open on the first entry to
CMDCLOSE, only one pass is made. This single pass
resembles the second pass mentioned above.
.
.
- If necessary, the CLOSE function updates the data
sector, T/S list sector & the VTOC. It also fixes
up links in the directory sectors and updates the
file size if needed.
.
.
(RTS)
(A2CB) LDA A5L+1 ;Hi byte of A5L/+1 pointer which points at
;the highest numbered (lowest in memory)
;free DOS name buffer (in chain).
(A2CD) BNE SAVFNPTR ;Branch if found a free buffer.
(A2CF) JMP NOBUFFER ;Go issue an out-of-buffers message.
------------ ;(See dis'mbly of errors.)
(A2D2)
SAVFNPTR STA A3L+1 ;Reset A3L/+1 to point at the DOS buffer
LDA A5L ;that we will use for the file name field
STA A3L ;buffer (in chain).
(A2D8) JSR CPYFN
* NOTE: This routine (re)assigns a DOS buffer
* to the file we want to open. The buffer used
* may or may not be the same one that was just
* released by the CLOSE command above. The
* highest numbered (lowest in memory) free DOS
* buffer is used.
(A743)
CPYFN LDY #29 ;30 bytes to copy (0 to 29).
CPYPRIM LDA PRIMFNBF,Y ;Copy the name of the file wanted from
STA (A3L),Y ;the primary filename buffer into the
DEY ;filename field buffer (in DOS chain).
BPL CPYPRIM ;More chars to get.
(A74D) RTS
(A2DB) JSR BUFS2PRM
* Get addresses of the various DOS buffers from the
* chain buffer & put them in the FM parameter list.
(A74E)
BUFS2PRM LDY #30 ;Get addr of FM work buf, T/S list
ADRINPRM LDA (A3L),Y ;buf, data sector buf & next DOS
STA WRKBUFFM-30,Y ;filename buf from chain
INY ;pointer buffer & put them in FM parm list.
CPY #38 ;(P.S. Addr of next DOS filename buffer
BNE ADRINPRM ;not used by DOS.)
(A75A) RTS
(A2DE) JSR CPY2PARM
* Put volume, drive & slot values plus the
* address of the primary filename buffer in
* the FM parameter list.
(A71A)
CPY2PARM LDA VOLPRSD ;From parsed table.
STA VOLFM
LDA DRVPRSD ;From parsed table.
STA DRVFM
LDA SLOTPRSD ;From parsed table.
STA SLOTFM
LDA ADRPFNBF ;Get the adr of the primary file
STA FNAMBUFM ;name buf from the constants table
LDA ADRPFNBF+1 ;and put it in the FM parm list.
STA FNAMBUFM+1
LDA A3L ;Save addr of current DOS filename
STA CURFNADR ;buf in table of DOS variables.
LDA A3L+1
STA CURFNADR+1
(A742) RTS
(A2E1) LDA TEMPBYT ;Get open opcode back from temporary buffer
STA OPCODEFM ;and put it in the FM parameter list.
(A2E7) JMP FMDRIVER
------------
* Use the file manager driver
* to do the OPEN function.
(A6A8)
FMDRIVER JSR FILEMGR ;Call the file manager to do the function.
* File manager proper.
(AB06)
FILEMGR TSX ;Save stk ptr so can later rtn 2 caller.
STX STKSAV
(AB0A) JSR RSTRFMWA
* Copy FM work buf (in DOS chain) to
* FM work area (not in DOS chain).
(AE6A)
RSTRFMWA JSR SELWKBUF
* Get adr of FM work
* buf from FM parm
* list & put it in
* the A4L/+1 pointer.
(AF08)
SELWKBUF LDX #0
(AF0A) BEQ PT2FMBUF
(AF12)
PT2FMBUF LDA WRKBUFFM,X
STA A4L
LDA WRKBUFFM+1,X
STA A4L+1
(AF1C) RTS
* Do the copying.
(AE6D) LDY #0 ;Zero out return code
(AE6F) STY RTNCODFM ;in FM parm list to
;signal no errors as
(AE72) ;default condition.
STORFMWK LDA (A4L),Y ;Copy FM work buf
STA FMWKAREA,Y ;to FM work area.
INY
CPY #45 ;45 bytes to copy
BNE STORFMWK ;(0 to 44).
CLC ;Why?????
(AE7D) RTS
(AB0D) LDA OPCODEFM ;Check if opcode is legal.
CMP #13 ;(Must be less than 13.)
BCS TOERROP ;Opcode too large so got range error.
ASL ;Double val of opcode & put it in (x)
TAX ;so it indexes tables of adrs.
LDA FMFUNCTB+1,X ;Stick adr of appropriate function
PHA ;handler on stack (hi byte first).
LDA FMFUNCTB,X
PHA
(AB1E) RTS ;DO STACK JUMP TO FUNCTION ENTRY POINT.
(AB22)
FNOPEN .
.
(See dis'mbly of OPEN function.)
.
.
- uses part of COMNOPEN routine.
- reads in VTOC to get link to 1rst directory.
- reads directory secs in & looks for file
description entry with matching filename.
- if matching name found, reads in the
first T/S list sector belonging to the file.
- if no match found, starts a new file:
(1) creates new file description entry
- copies name to 1rst available spc
in direc sec (if can't find spc, then
issues disk-full error message.
- allocates secs for file.
- writes updated VTOC to disk.
- puts link to first T/S list, file size, etc
in directory entry space.
- writes directory sector buffer to disk.
(2) creates new T/S list & writes it to disk.
- reads T/S list back into T/S list buffer.
.
.
(RTS)
============
TOERROP JMP RNGERROP ;Go handle range error.
(AB1F) ------------ ;(See dis'mbly of errors.)
* Return here after doing the OPEN function.
* (Cause after @ function is done, use stack
* to get back to the original caller.)
(A6AB)
AFTRFUNC BCC FMDRVRTN ;(c) = 0 = no errors.
LDA RTNCODFM ;Get error code from FM parameter list.
CMP #$5 ;End-of-data error?
(A6B2) BEQ TOAPPTCH ;Yes. Got a zeroed-out T/S link or a
;zeroed-out data pair list in a T/S list.
;(Not applicable to the open function.)
(A6B4) JMP OTHRERR ;No. (See dis'mbly of errors.)
------------
(A6C3)
FMDRVRTN RTS
(A3DC) PLA ;Get file type wanted off of stack.
(A3DD) JMP CHKFTYPE ;Go check if type wanted equals type found.
------------
* Check if file type wanted = file type found.
* (If using open command to open a pre-existing file,
* may get a type mismatch. However, a mismatch error
* is not possible when opening a new file.)
(A7C4)
CHKFTYPE EOR FILTYPFM ;Type found (via open function).
(A7C7) BEQ CKTYPRTN ;Branch if type wanted = type found.
* File types didn't match.
* Check if correct type but locked.
(A7C9) AND #%01111111 ;Maybe matched - disregard lock bit.
(A7CB) BEQ CKTYPRTN ;Branch if matched.
* Type wanted < > type found!!!
* So go close file & then issue a
* type-mismatch error message.
(A7CD) JSR CMDCLOSE ;Wrong kind of file so go close it.
;(See dis'mbly of close command.)
(A7D0) JMP TYPMISM ;(See dis'mbly of errors.
------------ ;(Eventually goes into DOS's warm start routine.)
CKTYPRTN RTS
(A7D3) ============
(A5C9) LDA CURFNADR ;Get the addr of the current file name buf
STA EXECBUFF ;and designate it as the Exec files name buf.
LDA CURFNADR+1
STA EXECBUFF+1
LDA PRIMFNBF ;Set the exec flag to a non-zero value.
STA EXECFLAG ;(Use first char of file name.)
(A5DB) BNE POSNCHKR ;ALWAYS - go position file pointer if
------------ ;necessary.
(A5EB)
POSNCHKR LDA CUMLOPTN ;Check to see if a non-zero R-parameter
AND #%00000100 ;was issued with the command.
(A5F0) BEQ DONEPOSN ;R-parameter was zero, so go exit (ie. don't
;move file pointer.)
- A non-zero R-parameter was issued, so
- go move the file porinter FORWARD by
- reading one-byte at a time. When a
- <cr> is encountered, reduce the count
- of the relative field position. When
- the count equals zero, done positioning.
(A5F2)
CKPSNDUN LDA RECPRSD ;Check count.
BNE POSNMORE
LDA RECPRSD+1
(A5FA) BEQ DONEPOSN ;R-parameter has been counted down to zero,
;so we are done positioning.
(A5FC) DEC RECPRSD+1 ;Reduce count of R-parameter (# of fields
POSNMORE DEC RECPRSD ;moved forward) for the next time around.
PSNFIELD JSR RDTXTBYT ;Go read a text file byte.
(A602)
(A68C)
RDTXTBYT LDA #3 ;Set READ opcode.
STA OPCODEFM
LDA #1 ;Set one-byte subcode.
STA SUBCODFM
(A696) JSR FMDRIVER ;Call the FM driver to read a data byte.
* Use the file manager driver
* to do the READ function.
(A6A8)
FMDRIVER JSR FILEMGR ;Call the file manager to do the function.
* File manager proper.
(AB06)
FILEMGR TSX ;Save stk ptr so can later rtn 2 caller.
STX STKSAV
(AB0A) JSR RSTRFMWA
* Copy FM work buf (in DOS chain) to
* FM work area (not in DOS chain).
(AE6A)
RSTRFMWA JSR SELWKBUF
* Get adr of FM work
* buf from FM parm
* list & put it in
* the A4L/+1 pointer.
(AF08)
SELWKBUF LDX #0
(AF0A) BEQ PT2FMBUF
(AF12)
PT2FMBUF LDA WRKBUFFM,X
STA A4L
LDA WRKBUFFM+1,X
STA A4L+1
(AF1C) RTS
* Do the copying.
(AE6D) LDY #0 ;Zero out return code
(AE6F) STY RTNCODFM ;in FM parm list to
;signal no errors as
(AE72) ;default condition.
STORFMWK LDA (A4L),Y ;Copy FM work buf
STA FMWKAREA,Y ;to FM work area.
INY
CPY #45 ;45 bytes to copy
BNE STORFMWK ;(0 to 44).
CLC ;Why?????
(AE7D) RTS
(AB0D) LDA OPCODEFM ;Check if opcode is legal.
CMP #13 ;(Must be less than 13.)
BCS TOERROP ;Opcode too large so got range error.
ASL ;Double val of opcode & put it in (x)
TAX ;so it indexes tables of adrs.
LDA FMFUNCTB+1,X ;Stick adr of appropriate function
PHA ;handler on stack (hi byte first).
LDA FMFUNCTB,X
PHA
(AB1E) RTS ;DO STACK JUMP TO FUNCTION ENTRY POINT.
(AC58)
FNREAD LDA SUBCODFM ;Check if subcode is legal.
CMP #5 ;(Must be < = 5.)
(AC5D) BCS TOERRSUB ;Error - illegal subcode.
;(Not applciable to exec command.)
(AC5F) ASL ;Subcode * 2, cause 2 bytes/address.
LDA RDSUBTBL+1,X ;Get address (minus 1) of subfunction
PHA ;entry point & stick it on the stack
LDA RDSUBTBL,X ;(hi byte first). Then do a "stack
PHA ;jump" to execute the given READ sub-
(AC69) RTS ;function. (Exec command ALWAYS uses
;the READ-ONE-BYTE subfunction.)
(AC8A)
READONE .
.
(See dis'mbly of the
read-one-byte subfunction.)
.
.
(RTS)
=============
TOERROP JMP RNGERROP ;Go handle range error.
(AB1F) ------------ ;(See dis'mbly of errors.)
TOERRSUB JMP RNGERRSB ;Go handle range error.
(AC6A) ------------ ;(See dis'mbly of errors.)
* Return here after doing the READ function.
* (Cause after @ function is done, use stack to get
* back to the original caller.) Note that (c) = 0 if a data
* byte was just read (regardless of whether that data byte
* was $00 or not).
(A6AB)
AFTRFUNC BCC FMDRVRTN ;(c) = 0 = no errors.
LDA RTNCODFM ;Get error code from FM parameter list.
CMP #$5 ;End-of-data error?
(A6B2) BEQ TOAPPTCH ;Yes - not handled like other errors!
;File ends at a full data sec and so we
;encountered a zeroed-out T/S link or a
;zeroed-out data pair (trk/sec vals for
;next data sec listed in a T/S list).
(A6B4) JMP OTHRERR ;No. Only take if got an error other than
;an end-of-data error. (See dis'mbly of
(A6B7) ;errors.)
TOAPPTCH JMP APNDPTCH ;(See dis'mbly of errors.)
NOP
BK2FMDRV JSR CKIFAPND ; <----- Note: APNDPTCH returns here.
(A6BB)
* Check if using Append command.
(BA69)
CKIFAPND LDX CMDINDEX ;Get command index.
CPX #$1C ;Are we APPENDing?
BEQ RTNCKAPN ;Yes - leave flag on.
LDX #0 ;No - turn off append flag.
STX APPNDFLG
RTNCKAPN RTS
(BA75)
(A6BE) LDX #0 ;Zero out the one-data-byte buffer in FM parm list.
STX ONEIOBUF ;(Also referred to as low byte of CURIOBUF.)
FMDRVRTN RTS
(A6C3)
(A699) LDA ONEIOBUF ;Load (a) with byte just read.
(A69C) RTS
(A605) BEQ ENDATERR ;If byte just read = $00, then ran out of data.
;A zero byte can be obtained from an
;incompletely filled data sector. Or, if
;a file ends on a sector boundary, a $00
;byte can also be obtained from a zeroed-out
;T/S link or a zeroed-out data pair (trk/sec
;values of next potential data sec listed in
;a T/S list).
(A607) CMP #$8D ;Was it a carriage return?
BNE PSNFILED ;No - go read the next byte in the same field.
(A60B) BEQ CKPSNDUN ;Yes - Got an end-of-field marker so branch
------------ ; back to reduce field count & see if
; we are done positioning yet.
DONEPOSN RTS ;Exit - either done positioning or else the
(A60D) ============ ; R-parameter was zero to start with
; and there4 no positioning is needed.
(A63F)
ENDATERR LDA #5
(A641) JMP ERRHNDLR ;(See dis'mbly of errors.)
------------
- -:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:*
- *
- Note: Actual EXECing of statements does not occur until *
- after the computer returns to BASIC's RESTART routine ($D43C). *
- *
- SEE DISASSEMBLY TITLED "CMDEXEC CONTINUED". *
- *
- -:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:-:*