home *** CD-ROM | disk | FTP | other *** search
- $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;
-
- DEF NrOfVariables = 10;
- DEF MaxDepthOfBatchStack = NrOfVariables;
-
- $ASCII characters
- DEF EndOfText = #03; $Ctrl-C
- DEF Bell = #07;
- DEF LineFeed = #0A;
- DEF CarriageReturn = #0D;
- DEF DataLinkEscape = #10; $Ctrl-P
- DEF NegativeAck = #15; $Ctrl-U
- DEF Substitute = #1A; $Ctrl-Z
- DEF FileSeparator = #1C;
- DEF RecordSeparator = #1E;
- DEF NonexistentChar = #80;
- DEF TextTerminator = NonexistentChar + RecordSeparator;
- DEF FileTerminator = NonexistentChar + FileSeparator;
-
- 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;
- BYTE "Z"; WORD TerminateBatchProcessing;
- BYTE "F"; WORD RequestFetchFromVariable;
- BYTE "O"; WORD RequestTypedOutput;
- BYTE "A"; WORD RequestAnswer;
- BYTE "V"; WORD RequestVariableVariable;
- BYTE "S"; WORD RequestStoreIntoVariable;
- BYTE FileTerminator; WORD TerminateBatchProcessing;
- :AfterTableOf2ndChars
-
- :AdrOf_JMP_CONST WORD NoInitialValue;
- :GO_OriginalCONST GO. NoInitialValue;
- :GO_OriginalCONIN GO. NoInitialValue;
- :GO_OriginalCONOUT GO. NoInitialValue;
- :AfterGO_Original
-
- :CommandErrRecoverySP WORD NoInitialValue;
-
- :ControlPByte BYTE DataLinkEscape, CarriageReturn;
- :ControlZByte BYTE Substitute, CarriageReturn;
- :ControlCByte BYTE EndOfText;
- :CarriageReturnByte BYTE CarriageReturn;
-
- :SelectedVariable BYTE NoInitialValue;
-
- :AdrsOfVariables ASM TIMES NrOfVariables - 3;
- WORD CarriageReturnByte;
- $Addr. of the value string of a
- $variable, initialized to the
- $addr. of the empty string
- END ASMTIMES;
- WORD ControlPByte;
- $Addr. of the value string of
- $the 3rd-highest-numbered
- $variable, initialized to the
- $addr. of a string consisting
- $of just Ctrl-P
- WORD ControlZByte;
- $Addr. of the value string of
- $the 2nd-highest-numbered
- $variable, initialized to the
- $addr. of a string consisting
- $of just Ctrl-Z
- WORD ControlCByte;
- $Addr. of the value string of
- $the highest-numbered variable,
- $initialized to the addr. of a
- $string consisting of just
- $Ctrl-C
-
- :CurrentDepthOfBatchStack BYTE 0;
- BYTE 0;$This is a constant byte
- $NOTE: The conceptually single "BatchStack" actually is implemented as
- $2 stacks which are pushed simultaneously, or popped simultaneously.
- $The 2 stacks are: NormalSourceForCurrentLine, and BatchInputCursor.
- DEF BatchStack = 0; $The definition merely provides
- $a symbol which can be cross-
- $referenced
-
- :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
-
- MENTION BatchStack; $The following is part of the
- $conceptual BatchStack
- :NormalSourceForCurrentLine BYTE 0;$0 means batch input, any
- $nonzero value means typed
- $input
- ASM TIMES MaxDepthOfBatchStack - 1;
- BYTE NoInitialValue;
- END ASMTIMES;
-
- :NormalSourceForNextLine BYTE 0;$0 means batch input, any
- $nonzero value means typed
- $input
- :AfterBatchText WORD NoInitialValue;
- $1st addr. after the end of
- $batch text, updated after
- $storing into a variable if the
- $source of char. input is the
- $console terminal
- :AfterSafeMemory WORD NoInitialValue;
-
- MENTION BatchStack; $The following is part of the
- $conceptual BatchStack
- :BatchInputCursor WORD AfterModel;
- $Addr. of the next batch input
- $char.
- ASM TIMES MaxDepthOfBatchStack - 1;
- WORD NoInitialValue;
- END ASMTIMES;
-
- :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;
- CALL AdrOfTopOfSourceStackToHL;
- A <- . NormalSourceForNextLine; A -> .HL;
- 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;
- CALL AdrOfTopOfSourceStackToHL; A -> .HL;
- 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;
- IF;
- B -> A; ? << A - LineFeed;
- IS = AND;
- CALL DiscoverCurrentDepthOfBatchStack;
- IS ~0 THEN;
- B <- CarriageReturn; $Change the input char.
- 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;
-
- :TypeOutChar_rC
- PROCEDURE;
- BC\/;
- CALL GO_OriginalCONOUT;
- /\BC; C -> A; ? << A - CarriageReturn;
- $Set the condition codes
- C <- LineFeed; IF = CALL GO_OriginalCONOUT;
- END PROCEDURE;
-
- :Input1CharFromConsoleAndEcho
- PROCEDURE;
- CALL GO_OriginalCONIN;
- A -> C; BC\/;
- CALL TypeOutChar_rC;
- /\BC; C -> A;
- END PROCEDURE;
-
- :DiscoverCurrentDepthOfBatchStack
- PROCEDURE;
- ? << A <- . CurrentDepthOfBatchStack;
- END PROCEDURE;
-
- :TestWhetherUnsolicitedCharForcesSourceToBeConsole
- PROCEDURE;
- ? << A <- . UnsolicitedCharWasTypedIn;
- END PROCEDURE;
-
- :DiscoverNormalSourceForNextLine
- PROCEDURE;
- ? << A <- . NormalSourceForNextLine;
- END PROCEDURE;
-
- :AdrOfTopOfSourceStackToHL
- PROCEDURE;
- HL <- . CurrentDepthOfBatchStack;
- DE <- NormalSourceForCurrentLine; HL + DE -> HL;
- END PROCEDURE;
-
- :AdrOfTopOfCursorStackToHL
- PROCEDURE;
- HL <- . CurrentDepthOfBatchStack; HL * 2 -> HL;
- DE <- BatchInputCursor; HL + DE -> HL;
- END PROCEDURE;
-
- :DiscoverNormalSourceForCurrentLine
- PROCEDURE;
- CALL AdrOfTopOfSourceStackToHL;
- ? << A <- .HL;
- END PROCEDURE;
-
- :CursorToDE
- PROCEDURE;
- CALL AdrOfTopOfCursorStackToHL;
- .HL -> E; HL + 1 -> HL; .HL -> D;
- END PROCEDURE;
-
- :Fetch1BatchCharAndAdvanceTheCursor
- PROCEDURE;
- CALL CursorToDE;
- .DE -> A; $Input char.
- DE + 1 -> DE; D -> .HL; HL - 1 -> HL; E -> .HL;
- $Advance the cursor
- END PROCEDURE;
-
- $Given rA containing the number of the designated variable, return with
- $rHL containing the addr. of the table entry for that variable
- :VariableNrToEntryAdr
- PROCEDURE;
- A -> L; H <- 0; HL * 2 -> HL; DE <- AdrsOfVariables;
- HL + DE -> HL;
- END PROCEDURE;
-
- $Given rA containing the number of the designated variable
- :PushTheBatchStack
- PROCEDURE;
- $There is no test for stack overflow. Overflow is extremely
- $unlikely under the anticipated conditions of use, and even if it
- $occurs, probably will not cause serious damage.
- HL <- CurrentDepthOfBatchStack; .HL + 1 -> .HL;
- CALL AdrOfTopOfSourceStackToHL; .HL <- 0;
- $Source of input will be batch
- $text
- CALL VariableNrToEntryAdr;
- .HL -> C; HL + 1 -> HL; .HL -> B;
- $Addr. of start of the
- $designated variable -> BC
- CALL AdrOfTopOfCursorStackToHL;
- C -> .HL; HL + 1 -> HL; B -> .HL;
- $Addr. of start of the
- $designated variable -> top of
- $cursor stack
- END PROCEDURE;
-
- :PopTheBatchStack
- PROCEDURE;
- $If this code is free of bugs, stack underflow is impossible
- HL <- CurrentDepthOfBatchStack; .HL - 1 -> .HL;
- END PROCEDURE;
-
- :Input1Char
- PROCEDURE;
- HL <- UnsolicitedChar; .HL -> A; ? << A - NonexistentChar;
- IF ~= THEN;
- .HL <- NonexistentChar;
- ? << A - CarriageReturn; IF ~= EXIT;
- $Test for the end of a variable
- CALL DiscoverCurrentDepthOfBatchStack;
- IF ~0 THEN;
- CALL PopTheBatchStack;
- REPEAT;
- END IF;
- A <- CarriageReturn;
- EXIT;
- END IF;
- IF;
- CALL DiscoverNormalSourceForCurrentLine;
- IS 0 AND;
- CALL GO_OriginalCONST; A >> ?;
- IF ~0 THEN;
- A -> . UnsolicitedCharWasTypedIn;
- END IF;
- IS 0 THEN;
- CALL Fetch1BatchCharAndAdvanceTheCursor;
- ELSE;
- CALL GO_OriginalCONIN;
- ? << A - EndOfText;
- IF = THEN;
- CALL TestWhetherUnsolicitedCharForcesSourceToBeConsole;
- IF ~0 CALL TerminateBatchProcessing;
- A <- EndOfText;
- END IF;
- END IF;
- ? << A - CarriageReturn; IF ~= EXIT;
- $Test for the end of a variable
- CALL DiscoverCurrentDepthOfBatchStack;
- IF ~0 THEN;
- CALL PopTheBatchStack;
- REPEAT;
- END IF;
- A <- CarriageReturn;
- END PROCEDURE;
-
- $This procedure is callable only during interpretation of a command
- :Input1CharFromSameSourceAsLastChar
- PROCEDURE;
- IF;
- CALL DiscoverNormalSourceForCurrentLine;
- IS 0 AND;
- CALL TestWhetherUnsolicitedCharForcesSourceToBeConsole;
- IS 0 THEN;
- CALL Fetch1BatchCharAndAdvanceTheCursor;
- ELSE;
- CALL GO_OriginalCONIN;
- END IF;
- END PROCEDURE;
-
- :SelectAVariable
- PROCEDURE;
- CALL Input1CharFromSameSourceAsLastChar;
- A <- A - "0"; IF - GO. ErrInCommand;
- ? << A - NrOfVariables; IF |>=| GO ErrInCommand;
- END PROCEDURE;
-
- :ErrInCommand $*** Not a procedure ***
- HL <- . CommandErrRecoverySP; HL -> SP;
- GO ReportAndRecoverFromCommandErr;
-
- :InputAndInterpretCommandChar
- PROCEDURE;
- HL <- 0; HL + SP -> HL; HL -> . CommandErrRecoverySP;
- $The char. must be input from the same source as the escape char.,
- $regardless of any new unsolicited typed input
- CALL Input1CharFromSameSourceAsLastChar;
- $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
- :ReportAndRecoverFromCommandErr
- CALL RingBell;
- 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;
-
- :RingBell
- PROCEDURE;
- C <- Bell; CALL GO_OriginalCONOUT;
- END PROCEDURE;
-
- :RingBellIfEnabled
- PROCEDURE;
- ? << A <- . RingForAttn; IF ~0 CALL RingBell;
- END PROCEDURE;
-
- :RingBellIfEnabledAndSourceWasBatchText
- PROCEDURE;
- CALL DiscoverNormalSourceForCurrentLine;
- IF 0 THEN;
- CALL TestWhetherUnsolicitedCharForcesSourceToBeConsole;
- IF 0 CALL RingBellIfEnabled;
- END IF;
- END PROCEDURE;
-
- :MakeSourceBeConsoleAndRingBellIfChangingAndEnabled
- PROCEDURE;
- CALL RingBellIfEnabledAndSourceWasBatchText;
- CALL AdrOfTopOfSourceStackToHL; .HL <- 1;
- END PROCEDURE;
-
- :RequestTypedInput
- PROCEDURE;
- A <- 1; A -> . NormalSourceForNextLine;
- CALL MakeSourceBeConsoleAndRingBellIfChangingAndEnabled;
- END PROCEDURE;
-
- :RequestBatchInput
- PROCEDURE;
- CALL AdrOfTopOfSourceStackToHL;
- 0 -> A; A -> .HL; A -> . NormalSourceForNextLine;
- END PROCEDURE;
-
- :FirstPartOfRequestStoreIntoVariable
- PROCEDURE;
- $It is forbidden to fetch from a variable and store into a
- $variable simultaneously. Otherwise, there would be no guarantee
- $that the source of character input is unchanging. If the source
- $could change, then any value string which is fetched from batch
- $text, would have to be stored a 2nd time in the batch text.
- CALL DiscoverCurrentDepthOfBatchStack; IF ~0 GO. ErrInCommand;
- $Error if fetching from a
- $variable
- CALL SelectAVariable; A -> . SelectedVariable;
- END PROCEDURE;
-
- :SecondPartOfRequestStoreIntoVariable
- PROCEDURE;
- A <- . SelectedVariable;
- CALL VariableNrToEntryAdr; HL\/; MENTION AdrsOfVariables;
- $Addr. of entry in table
- $Determine the source of character input
- IF;
- CALL DiscoverNormalSourceForCurrentLine;
- IS 0 AND;
- CALL TestWhetherUnsolicitedCharForcesSourceToBeConsole;
- IS 0 THEN;
- $The source of character input is batch text
- CALL CursorToDE; /\HL; E -> .HL; HL + 1 -> HL; D -> .HL;
- MENTION AdrsOfVariables; $Copy the current value of the
- $cursor, into the entry in
- $table AdrsOfVariables for the
- $designated variable
- $Input and disregard all chars. until the carriage return
- $that terminates the variable, except that it is necessary to
- $test for the end of batch text
- DO;
- CALL Fetch1BatchCharAndAdvanceTheCursor;
- ? << A - CarriageReturn; IF = EXIT;
- HL <- Escape; A - .HL >> ?; IF ~= REPEAT;
- CALL Fetch1BatchCharAndAdvanceTheCursor;
- ? << A - FileTerminator; IF ~= REPEAT;
- CALL TerminateBatchProcessing;
- END DO;
- ELSE;
- $The source of character input is the console terminal
- HL <- . AfterBatchText; HL\/; HL\/;
- $Addr. where the 1st char. of
- $the variable will be stored
- $Input and store all chars. until the carriage return that
- $terminates the variable. Do not interpret any chars.
- DO;
- CALL Input1CharFromConsoleAndEcho;
- $Verify that there is at least 1 available byte remaining
- $in safe memory
- /\DE; $Addr. where the char. will be
- $stored
- HL <- . AfterSafeMemory;
- IF;
- E -> A; A - L >> ?;
- IS = AND;
- D -> A; A - H >> ?;
- IS = THEN;
- GO. ErrInCommand;
- END IF;
- C -> A; A -> .DE; $Copy the char. into safe
- $memory
- DE + 1 -> DE; DE\/; $Addr. where next char. will
- $be stored
- ? << A - CarriageReturn; IF ~= REPEAT;
- /\HL; HL -> . AfterBatchText;
- /\DE; /\HL; E -> .HL; HL + 1 -> HL; D -> .HL;
- MENTION AdrsOfVariables;$Copy the addr. of the 1st
- $char. of the value, into the
- $entry in table AdrsOfVariables
- $for the designated variable
- END DO;
- END IF;
- 0 -> A; A -> . MiddleOfInputLine;
- END PROCEDURE;
-
- :RequestStoreIntoVariable
- PROCEDURE;
- CALL FirstPartOfRequestStoreIntoVariable;
- CALL SecondPartOfRequestStoreIntoVariable;
- END PROCEDURE;
-
- :RequestAnswer
- PROCEDURE;
- CALL FirstPartOfRequestStoreIntoVariable;
- CALL MakeSourceBeConsoleAndRingBellIfChangingAndEnabled;
- CALL SecondPartOfRequestStoreIntoVariable;
- END PROCEDURE;
-
- :RequestFetchFromVariable
- PROCEDURE;
- CALL SelectAVariable;
- CALL PushTheBatchStack;
- END PROCEDURE;
-
- :RequestVariableVariable
- PROCEDURE;
- CALL RingBellIfEnabledAndSourceWasBatchText;
- CALL Input1CharFromConsoleAndEcho;
- IF;
- A <- A - "0";
- IS - OR;
- ? << A - NrOfVariables;
- IS |>=| THEN;
- CALL RingBell;
- REPEAT;
- END IF;
- CALL PushTheBatchStack;
- END PROCEDURE;
-
- :RequestTypedOutput
- PROCEDURE;
- CALL Input1Char; A -> C;
- IF;
- ? << A - LineFeed;
- IS = AND;
- CALL DiscoverCurrentDepthOfBatchStack;
- IS ~0 THEN;
- C <- CarriageReturn; $Change the input char.
- END IF;
- BC\/;
- CALL TypeOutChar_rC; $Echo the char.
- /\BC; C -> A; $Copy the char.
- IF;
- HL <- Escape; A - .HL >> ?;
- IS = OR;
- IF;
- ? << A - EndOfText;
- IS = AND;
- IF;
- CALL DiscoverNormalSourceForCurrentLine;
- IS ~0 OR;
- CALL TestWhetherUnsolicitedCharForcesSourceToBeConsole;
- IS ~0 THEN;
- IF THE ABOVE THEN;
- IF THE ABOVE THEN;
- C -> A; A -> . UnsolicitedChar;
- $This will cause the char. to
- $be input again
- ELSE;
- REPEAT;
- END IF;
- 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