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
/
SIMTEL
/
CPMUG
/
CPMUG052.ARK
/
BATCH.1
< prev
next >
Wrap
Text File
|
1984-04-29
|
12KB
|
412 lines
$This is program BATCH.
$Operation of this program is described in the BATCH Reference Manual.
$This program is entered into the public domain by its author, Daniel
$Ross. Please do not remove this notice.
$The mixed-upper-lower-case version of this file constitutes the 1st
$module of program BATCH. The upper-case-only version of this file
$constitutes the 2nd module of program BATCH.
$Coded by Daniel Ross, in the computer language SIL80Z80, starting
$Jan. 20, 1981.
$Revised Feb. 12, 1981
$For more information contact:
$Daniel Ross
$Succinct Systems
$1346 River St.
$Santa Cruz, Calif. 95060
$Phone (408) 426-4197
DEF FALSE = 0;
DEF TRUE = 1;
IGNORE1STSPACE 1;
DEF OPTIMIZED_COMPILATION = TRUE;
DEF NoInitialValue = 0;
XREF OF NoInitialValue : 0;
DEF PatchMe = 0;
$ASCII characters
DEF EndOfText = #03; $Ctrl-C
DEF Bell = #07;
DEF LineFeed = #0A;
DEF CarriageReturn = #0D;
DEF NegativeAck = #15; $Ctrl-U
DEF Substitute = #1A; $Ctrl-Z
DEF RecordSeparator = #1E;
DEF NonexistentChar = #80;
DEF TextTerminator = NonexistentChar + RecordSeparator;
DEF AdrOf_JMP_WBOOT = #0001;$Addr. of the JMP WBOOT
$instruction in the table at
$the beginning of BIOS
DEF WarmBoot = #0000;$Entry addr. of procedure WBOOT
DEF CPMProgramStart = #0100;$Starting addr. of all CP/M
$user programs
ASM IF ^ = 0; $Assemble if this is the model which will be copied
$into safe memory
DEF ^ = CPMProgramStart;
:Start GO. Main;
:SafeMemory WORD PatchMe;
$Addr. of the start of safe
$memory
:SizeOfSafeMemory WORD PatchMe;
$Size in bytes of safe memory
:SizeOfCodeInSafeMemory WORD SizeOfModel;
$Do not alter the contents of
$this word; just examine it.
$This is the size of safe
$memory needed just to hold the
$code, not including any batch
$text. If you have insufficient
$safe memory, this program will
$not execute correctly.
:AdrOfModels WORD Model, MODEL;
$Do not alter the contents of
$these words; just examine them.
$They contain the starting
$addresses for corresponding
$patches in each of the models.
:AdrOfYourPatchProc WORD YourPatchProc;
$Do not alter the contents of
$this word; just examine it to
$determine where your patch
$procedure should be located
:DiagnosticInfo WORD 0,0,0,0;
$This space may be used as
$desired, to hold diagnostic
$info. in case of error
:JUST_BEFORE_MODEL
END ASMIF;
$If this is the model which is used to discover relocatable addresses,
$make sure that both bytes of the addresses will differ from those of
$the model which will be copied into safe memory.
ASM IF
(<>(^ - JUST_BEFORE_MODEL) ~= 0) & (><(^ - JUST_BEFORE_MODEL) = 0);
SKIP OVER 1; $Force the LSB of the addresses
$to differ
END ASMIF;
$**********************************************************************
:Model
SHOW ^; $'Start of a model module
$The following variables and/or constants may be patched to change their
$initial/permanent values
:BatchCONSTReport BYTE 0;
$This byte contains the value of
$the output param from CONST,
$when batched chars. are being
$read
:RingForAttn BYTE FALSE;
$0 means quiet, any nonzero
$value means ring for attention
$when the user must start typing
$in chars.
:Escape BYTE #01; $StartOfHeading, Ctrl-A
$This must be the 1st char. of
$any 2-char. command to BATCH
$Table of valid 2nd chars., for 2-char. commands to BATCH, and the
$addresses of their interpretation procedures
:TableOf2ndChars
BYTE "I"; WORD RequestTypedInput;
BYTE "B"; WORD RequestBatchInput;
BYTE "R"; WORD RequestRingForAttn;
BYTE "Q"; WORD RequestQuiet;
BYTE "Y"; WORD RequestYesFromCONST;
BYTE "N"; WORD RequestNoFromCONST;
BYTE "X"; WORD NoOp;
:TerminationCommandChar
BYTE "Z"; WORD TerminateBatchProcessing;
:AfterTableOf2ndChars
:AdrOf_JMP_CONST WORD NoInitialValue;
:GO_OriginalCONST GO. NoInitialValue;
:GO_OriginalCONIN GO. NoInitialValue;
:GO_OriginalCONOUT GO. NoInitialValue;
:AfterGO_Original
:MiddleOfInputLine BYTE FALSE;
$0 means input is at the start
$of a line, any nonzero value
$means input is in the middle of
$a line
:UnsolicitedCharWasTypedIn BYTE FALSE;
$0 means there has not been an
$unsolicited char. typed in, any
$nonzero value means an
$unsolicited char. was typed in
:UnsolicitedChar BYTE NonexistentChar;
$If an unsolicited char. ~= the
$escape char. was typed in, and
$detected during a call of
$CONST, this byte will contain
$the char.; otherwise this byte
$will contain NonexistentChar
:NormalSourceForCurrentLine BYTE 0;$0 means batch input, any
$nonzero value means typed
$input
:NormalSourceForNextLine BYTE 0;$0 means batch input, any
$nonzero value means typed
$input
:BatchInputCursor WORD AfterModel;
$Addr. of the next batch input
$char.
:BatchCONST
PROCEDURE;
CALL DiscoverNormalSourceForCurrentLine;
IF 0 THEN;
CALL GO_OriginalCONST; A >> ?;
IF 0 THEN;
A <- . BatchCONSTReport;
ELSE;
CALL Input1Char;
HL <- Escape; A - .HL >> ?;
IF = THEN;
CALL InputAndInterpretCommandChar;
A <- . BatchCONSTReport;
ELSE;
A -> . UnsolicitedChar;
A <- #FF;
END IF;
END IF;
ELSE;
CALL GO_OriginalCONST;
END IF;
A >> ?;
END PROCEDURE;
:BatchCONIN
PROCEDURE;
? << A <- . MiddleOfInputLine;
IF 0 THEN;
$Starting a new input line
IF;
CALL DiscoverNormalSourceForCurrentLine;
IS 0 AND;
CALL DiscoverNormalSourceForNextLine;
IS ~0 AND;
CALL GO_OriginalCONST; A >> ?;
IS 0 THEN;
CALL RingBellIfEnabled;
END IF;
A <- . NormalSourceForNextLine;
A -> . NormalSourceForCurrentLine;
END IF;
CALL Input1Char;
HL <- Escape; A - .HL >> ?;
IF = THEN;
CALL InputAndInterpretCommandChar;
REPEAT;
END IF;
A -> B; $Copy the char. that was input
CALL TestWhetherUnsolicitedCharForcesSourceToBeConsole;
IF ~0 THEN;
A -> . NormalSourceForCurrentLine;
A -> . NormalSourceForNextLine;
0 -> A; A -> . UnsolicitedCharWasTypedIn;
END IF;
CALL DiscoverNormalSourceForCurrentLine;
IF ~0 THEN;
B -> A; $Copy the char. that was typed
$in
? << A - CarriageReturn;
IF = THEN;
0 -> A; A -> . NormalSourceForNextLine;
END IF;
? << A - LineFeed;
IF = THEN;
B <- CarriageReturn; $Change the input char.
END IF;
END IF;
B -> A; $Copy the char. that was input
IF;
? << A - CarriageReturn;
IS = OR;
? << A - NegativeAck;
IS = OR;
? << A - EndOfText;
IS = THEN;
$The next char. will start an input line
0 -> A;
ELSE;
$The next char. will be in the middle of an input line
A <- TRUE; $Just in case the char. was Null
END IF;
A -> . MiddleOfInputLine;
B -> A; $Copy the char. that was input
END PROCEDURE;
:TestWhetherUnsolicitedCharForcesSourceToBeConsole
PROCEDURE;
? << A <- . UnsolicitedCharWasTypedIn;
PROCEDURE;
:DiscoverNormalSourceForNextLine
PROCEDURE;
? << A <- . NormalSourceForNextLine;
END PROCEDURE;
:DiscoverNormalSourceForCurrentLine
PROCEDURE;
? << A <- . NormalSourceForCurrentLine;
END PROCEDURE;
:Input1Char
PROCEDURE;
HL <- UnsolicitedChar; .HL -> A; ? << A - NonexistentChar;
IF ~= THEN;
.HL <- NonexistentChar;
EXIT;
END IF;
IF;
CALL DiscoverNormalSourceForCurrentLine;
IS 0 AND;
CALL GO_OriginalCONST; A >> ?;
IF ~0 THEN;
A -> . UnsolicitedCharWasTypedIn;
END IF;
IS 0 THEN;
HL <- . BatchInputCursor; .HL -> A; HL + 1 -> HL;
HL -> . BatchInputCursor;
ELSE;
CALL GO_OriginalCONIN;
? << A - EndOfText;
IF = THEN;
CALL TestWhetherUnsolicitedCharForcesSourceToBeConsole;
IF ~0 CALL TerminateBatchProcessing;
A <- EndOfText;
END IF;
END IF;
END PROCEDURE;
:InputAndInterpretCommandChar
PROCEDURE;
$The char. must be input from the same source as the escape char.,
$regardless of any new unsolicited typed input
IF;
CALL DiscoverNormalSourceForCurrentLine;
IS 0 AND;
CALL TestWhetherUnsolicitedCharForcesSourceToBeConsole;
IS 0 THEN;
HL <- . BatchInputCursor; .HL -> A; HL + 1 -> HL;
HL -> . BatchInputCursor;
ELSE;
CALL GO_OriginalCONIN;
END IF;
$Look up the char. in the table
HL <- TableOf2ndChars;
B <- (AfterTableOf2ndChars - TableOf2ndChars) / 3;
DO;
A - .HL >> ?;
IF = THEN;
$Interpret the char.
HL + 1 -> HL; .HL -> E; HL + 1 -> HL; .HL -> D;
HL <-> DE; $Addr. of interpretation
$procedure -> HL
CALL GO_rHL;
CALL TestWhetherUnsolicitedCharForcesSourceToBeConsole;
IF ~0 THEN;
0 -> A; A -> . UnsolicitedCharWasTypedIn;
END IF;
EXIT InputAndInterpretCommandChar;
END IF;
HL + 1 -> HL; HL + 1 -> HL; HL + 1 -> HL;
B - 1 -> B; IF ~0 REPEAT;
END DO;
$If execution passes through here, no match was found
C <- Bell; CALL GO_OriginalCONOUT;
C <- "E"; CALL GO_OriginalCONOUT;
C <- "R"; CALL GO_OriginalCONOUT;
C <- "R"; CALL GO_OriginalCONOUT;
$Test whether the erroneous command char. was input from batch
$text
IF;
CALL DiscoverNormalSourceForCurrentLine;
IS 0 AND;
CALL TestWhetherUnsolicitedCharForcesSourceToBeConsole;
IS 0 THEN;
CALL TerminateBatchProcessing;
END IF;
REPEAT;
END PROCEDURE;
:GO_rHL GO .HL;
:RingBellIfEnabled
PROCEDURE;
? << A <- . RingForAttn; IF 0 EXIT;
C <- Bell; CALL GO_OriginalCONOUT;
END PROCEDURE;
:RequestTypedInput
PROCEDURE;
A <- 1; A -> . NormalSourceForNextLine;
CALL TestWhetherUnsolicitedCharForcesSourceToBeConsole;
IF 0 THEN;
CALL DiscoverNormalSourceForCurrentLine;
IF 0 CALL RingBellIfEnabled;
A <- 1; A -> . NormalSourceForCurrentLine;
END IF;
END PROCEDURE;
:RequestBatchInput
PROCEDURE;
0 -> A; A -> . NormalSourceForCurrentLine;
A -> . NormalSourceForNextLine;
END PROCEDURE;
:TerminateBatchProcessing
PROCEDURE;
CALL RingBellIfEnabled;
HL <- . AdrOf_JMP_CONST; DE <- GO_OriginalCONST; HL <-> DE;
B <- AFTER_GO_BATCH - GO_BATCH_CONST;
DO;
.HL -> A; A -> .DE;
HL + 1 -> HL; DE + 1 -> DE;
B - 1 -> B; IF ~0 REPEAT;
END DO;
A <- 1; A -> . NormalSourceForCurrentLine;
A -> . NormalSourceForNextLine;
END PROCEDURE;
:NoOp
PROCEDURE;
END PROCEDURE;
:RequestYesFromCONST
PROCEDURE;
A <- #FF; A -> . BatchCONSTReport;
END PROCEDURE;
:RequestNoFromCONST
PROCEDURE;
0 -> A; A -> . BatchCONSTReport;
END PROCEDURE;
:RequestRingForAttn
PROCEDURE;
A <- TRUE; A -> . RingForAttn;
END PROCEDURE;
:RequestQuiet
PROCEDURE;
0 -> A; A -> . RingForAttn;
END PROCEDURE;
:AfterModel
$**********************************************************************