.title 'Overlay Shell with Command History' ; ; History Shell for use as an Overlay Command Processor ; with Backgrounder ii running under ZCPR3 ; ; Frank Cringle, 20 May 1987 ; ;vers equ 10 ; Initial release ;vers equ 11 ; (29 May 1987) Fixed prompt for user > 10 ;vers equ 12 ; (8 June 1987) Simplified history stack ; (null byte delimiters rather than ; pre- and post-length bytes). ; Also fixed display bug when ctrl-char ; overwrites normal char within line, and ; enabled forward-line from last history ; line to empty current line, and cleaned ; up handling of mcl overflow. ;vers equ 13 ; (5 August 1987) Fixed bug where matching ; prefix caused spurious nulls to be ; included in history. vers equ 14 ; (5 September 1987) Converted to use ; ZAS/ZLINK v3.0 (simplifies linkage). ; Pause history list when screen is full. bell equ 7 bs equ 8 tab equ 9 lf equ 10 cr equ 13 fcb equ 5ch ext z3init,qshell,getsh1,shpush,shpop,putcst,putzex ext print,pstr,cin,condin,cout,crlf,compb,caps ext getcrt,getcl1,putud,getud,retud,dundr,bdos,zfname,z3log head: db 'OCP' ; module type db vers ; module id wrtflg: db 1 ; save module on exit cmdsiz: db 4 ; max # of characters in a command cmdtbl: oshnm: db 'OSH ' dw entry db 'WILD' dw wild db 0 ; insert mode flag insmod: db 1 ; 0 = overwrite, 1 = insert entry: call z3init ; save environment pointer call qshell ; normal or shell execution ? jr z,exec ; called as a normal command - check for operand ld a,(fcb+1) ; just look at 1st character cp ' ' ; no operand - install shell jr z,inst cp 'O' ; OSH OFF ? jr z,off cp 'R' ; must be RESET history ld hl,iomsg jr nz,prmsg ; invalid operand ld hl,hbase ld (htop),hl ; reset the history pointer ret off: call oshin ; is osh the top shell? ld hl,namsg jr nz,prmsg call shpop ; get rid of OSH ld hl,exmsg jr prmsg inst: call oshin ; already present? ld hl,aamsg ; report osh already active jr z,prmsg ld hl,name call shpush ; put name onto shell stack ld hl,hdmsg jr z,prmsg ; display installed message ld hl,sfmsg ; or stack full message prmsg: push hl ld hl,stmsg ; newline and command name call pstr pop hl ; tail of message jp pstr ; print and return to system ; called as shell exec: ld a,(wtask) ; wild repeat in progress? or a jp nz,dowild call inicl ; initialise command line xor a call putcst ; next command is normal ld a,1 call putzex ; tell zex this is command input time call getcmd ; get next command xor a call putzex ; zex back to normal ret ; test if OSH is at the top of the shell stack ; return Z set if so oshin: call getsh1 ; get address of stack ld de,name ld b,nmlen jp compb getcmd: call prompt ; prompt user for command input xor a ld (done),a ; not finished yet ld hl,(htop) ; top of history stack ld (hcurs),hl ; initialise cursor ld (hl),a ; end of new line gc1: call cin ; get character or a ; ignore nulls jr z,gc1 ld hl,gc5 ; where to return to after action push hl ; pseudo return address ld hl,keytab ; table to interpret keystrokes by ld b,a ; save character gc2: ld a,(hl) inc hl or a ; end of table jr z,gc4 cp b ; match? jr z,gc3 inc hl ; skip action address inc hl jr gc2 ; try next entry gc3: ld a,(hl) ; pick up address inc hl ld h,(hl) ; high bits ld l,a ; low bits ld a,b ; input character in A jp (hl) ; go do action (continue at gc5) gc4: ld a,b ; char back to A jp putcc ; enter normal character in line gc5: ld a,(done) ; line complete? or a jr z,gc1 ld hl,(htop) ld a,(hl) or a ; empty line? jr c,getcmd ; try again ret ; that's it ; test whether cursor is at start of line ; Z = yes, NZ = no atbeg: push hl push bc ; make space ld c,a ; save character ld hl,(hcurs) dec hl ; look at preceding entry ld a,(hl) ; is it a null? or a ld a,c ; retrieve character without smashing flags pop bc pop hl ret ; does character in A need a ^ prefix when displayed? ; Z = yes, NZ = no chkctr: push bc ld c,a cp ' ' ; control char? jr c,chkcy cp 7fh ; DEL? jr z,chkce or 1 ; set NZ jr chkce chkcy: xor a ; set Z chkce: ld a,c pop bc ret ; move cursor right (unless at end of line) ; return with new cursor char in A and Z set if was end of line forward: ld hl,(hcurs) ld a,(hl) or a ret z inc hl ld (hcurs),hl call ccout ; output character (expand ctrl chars) or 1 ; set NZ ld a,(hl) ; new cursor char in A ret ; move cursor left (unless at start of line) ; return with new cursor char in A and Z set if was start of line backup: ld hl,(hcurs) dec hl ld a,(hl) or a ret z ld (hcurs),hl call chkctr ; ^ prefix? ld a,bs call z,cout ; extra backspace for '^' call cout ld a,(hl) ; get char back into A or a ret ; is the character in A alphanumeric? ; return Z if so inword: push bc ld c,a cp '0' jr c,wrdno ; less than zero cp '9'+1 jr c,wrdyes ; digit or ' ' ; fold case cp 'a' jr c,wrdno ; less than letter cp 'z'+1 jr nc,wrdno ; more than letter wrdyes: xor a ; set Z jr wrdret wrdno: or 1 ; set NZ wrdret: ld a,c ; restore character to A pop bc ret ; move screen cursor so that hcurs = HL gotohl: ld de,(hcurs) ; present pos or a sbc hl,de ; distance ret z ; already there jr c,gobck ; backwards ld b,l gofor: call forward ; forwards ret z ; end of line? (shouldn't happen) djnz gofor ret gobck: ld a,l neg ld b,a gobck1: call backup ret z ; start of line? (shouldn't happen) djnz gobck1 ret ; move hl to point to start of next word rtwrd: ld a,(hl) call inword ; skip over word chars jr nz,rtwrd1 inc hl jr rtwrd rtwrd1: ld a,(hl) or a ret z ; end of line call inword ret z ; start of word inc hl jr rtwrd1 ; move hl to point to start of previous word lfwrd: dec hl ld a,(hl) or a jr z,lfwrd2 call inword ; skip separators jr nz,lfwrd lfwrd1: dec hl ld a,(hl) call inword ; skip word jr z,lfwrd1 lfwrd2: inc hl ret ; move hl to start of next command rtcmd: ld a,(hl) or a ret z cp ';' inc hl jr nz,rtcmd ret ; move hl to start of previous command lfcmd: dec hl ld a,(hl) or a ; start of line? jr z,lfcmd1 cp ';' ; start of command? jr nz,lfcmd lfcmd1: inc hl ret ; delete C characters from present position delc: ld hl,(hcurs) call strlen ; length remaining cp c ; less than count? jr nc,delc1 ld c,a ; limit count to that available delc1: ld a,c or a ret z ; nothing to do ld hl,(hcurs) push hl ld d,h ld e,l push bc ; save delete count ld b,0 ; clear ctrl char counter delc2: ld a,(hl) ; step hl forward and count ^'s inc hl call chkctr jr nz,delc3 inc b ; b counts extras due to ^ delc3: dec c jr nz,delc2 delc4: ld a,(hl) ; copy tail down ld (de),a or a jr z,delc5 inc hl inc de jr delc4 delc5: call forward ; display new tail jr nz,delc5 ld a,b ; extras pop bc ; normal count add a,c ; total number of redundant chars ld b,a push bc ld a,' ' delc6 call cout ; wipe redundant chars at end djnz delc6 pop bc ld a,bs delc7 call cout ; and back up again djnz delc7 pop hl ; retrieve old hcurs value jp gotohl ; and move back there ; key action routines ; backward word bckwrd: ld hl,(hcurs) ; current position call lfwrd ; left to start of word jp gotohl ; move cursor there ; reboot if start of line ctrlc: call atbeg ; at beginning of line? jp nz,putcc ; no - just enter into buffer call dellin ; yes - delete line call print db '^C',0 ; echo ctrl C rst 0 ; warm boot ; backup line bcklin: ld hl,(hmark) ; line pointer call prevl ; move back jr z,recall ; is there a previous line? ring: ld a,bell ; ring bell jp cout ; recall a previous line ; HL points to it recall: ld (hmark),hl ; remember this line ld bc,0 ; offset of next char to copy from mark push bc call strlen ; get length push af call dellin ; clean up display recal1: pop af pop bc or a ; any left? ret z dec a ld hl,(hmark) ; note: mark may move as we go round loop add hl,bc inc bc push bc push af ld a,(hl) call putcc ; put char in current line jr recal1 ; There is a hole in the logic of the above code: ; If the line being recalled is the oldest and it is longer than ; the space available at htop, it will be squeezed out during the ; copying process. phist constrains hmark to be at least hbase, ; so this rather unlikely bug will show up as the new line having ; a bogus tail. ; forward word forwrd: ld hl,(hcurs) ; current position call rtwrd ; right to start of word jp gotohl ; move cursor there ; delete character to the left of the cursor delcl: call backup ; move left ret z ; at left margin? ; ... fall through ... ; delete character under cursor delcr: ld c,1 ; one character jp delc ; delete it ; show history showh: call getcrt inc hl inc hl ld c,(hl) ; lines of text on screen inc c ld hl,hbase ; start here ld b,c showh1: call crlf djnz showh2 ; count down visible lines call print db '[pause]',0 call cin ; wait for acknowledge (any character) call print db cr,tab,cr,0 ; clean line ld b,c showh2: ex de,hl ld hl,(htop) or a sbc hl,de ; at top of stack? jr z,regen ex de,hl showh3: ld a,(hl) inc hl or a jr z,showh1 call ccout jr showh3 ; regenerate current line regen: call prompt ld hl,(hcurs) ; save where we are at push hl ld de,(htop) ld (hcurs),de ; reset cursor to start regen1: call forward ; display everything jr nz,regen1 pop hl jp gotohl ; cursor back to where we were ; look for previous matching command look: ld hl,(hcurs) ld a,(hl) ld (hl),0 ; temporarily truncate line ld de,(htop) or a sbc hl,de push hl ; save cursor offset push af ; and cursor char ld hl,(hmark) call prefix ; is there a candidate? pop de push hl ld hl,(hcurs) ld (hl),d ; restore cursor char pop hl pop de jp nz,ring ; no match push de call recall ; recall matching line pop de ld hl,(htop) add hl,de jp gotohl ; put cursor back where it was ; end of line eolin: call forward ; make sure cursor is at end of line jr nz,eolin ld a,1 ld (done),a ; set flag ld hl,(htop) ; start of command eol1: ld a,(hl) inc hl or a ; ignore empty lines jr z,eol2 cp ';' ; and comment lines jr z,eol2 cp ' ' ; skip leading spaces jr nz,eol3 ; found a significant character jr eol1 eol2: ld hl,(htop) ld (hl),0 ; zero length ret eol3: ld hl,(htop) call putcl ; put line in command buffer call strlen ; get length of current line ld c,a eol3a: call prefix ; is there already a similar line? jr nz,eol4 call strlen cp c ; and is it the same length? jr nz,eol3a call elim ; then get rid of it eol4: ld hl,(htop) ld b,0 add hl,bc ; address at end of new line inc hl ; start address for next line ld (htop),hl ; incorporate new line in history ld (hmark),hl ld a,cr ; echo jp cout ; quote next character quote: call cin ; get next char or a ; can't handle nulls ret z jp putcc ; insert literal ; backup command bckcmd: ld hl,(hcurs) ; current position call lfcmd ; move to start of command jp gotohl ; move cursor there ; forward command forcmd: ld hl,(hcurs) ; current position call rtcmd ; move to start of next command jp gotohl ; move cursor there ; delete word at left of cursor delwl: call atbeg ; start of line? ret z call bckwrd ; move back one word ; ... fall through ... ; delete word to right of cursor delwr: ld hl,(hcurs) call rtwrd ld de,(hcurs) or a sbc hl,de ; number of chars to delete ld c,l jp delc ; delete entire line dellin: ld hl,(htop) ; first position call gotohl ; go there ld hl,(hcurs) call strlen ; how long is line? ld c,a jp delc ; delete the lot ; toggle insert mode insert: ld hl,insmod ld a,(hl) xor 1 ; switch between insert and overwrite ld (hl),a ret ; forward line forlin: ld hl,(hmark) forl1: ld a,(hl) inc hl ; move to beginning of next line or a jr nz,forl1 ex de,hl ld hl,(htop) scf sbc hl,de ; at top of history ? ex de,hl jp nc,recall ld hl,(htop) ld (hmark),hl jr dellin ; delete to end of line delel: ld hl,(hcurs) call strlen ; length of tail ld c,a jp delc ; delete it ; delete command delcmd: ld hl,(hcurs) call lfcmd ; to start of cmd push hl ; save position call rtcmd ; to start of next pop de or a sbc hl,de ; length to delete ld c,l ex de,hl ; start to hl call gotohl ; go there jp delc ; delete ; prompt for command input prompt: call crlf ; newline call retud ; get disk/user inc b ; make drive A = 1 call dundr ; lookup directory name jr nz,pmt4 ; found a name - display it ld a,b ; disk number add '@' call culout ; case dependant display ld a,c ; user number ld b,0 ; tens accumulator pmt1: cp a,10 ; less than ten? jr c,pmt2 sub a,10 inc b ; increment tens count jr pmt1 pmt2: ld c,a ; save remainder (units) ld a,b or a ; any tens? jr z,pmt3 add '0' call cout ; display tens pmt3: ld a,c add '0' call cout ; display units jr pmt6 pmt4: ld b,8 ; max length of directory name inc hl inc hl ; skip to name in NDR entry pmt5: ld a,(hl) cp ' ' ; end of name? jr z,pmt6 call culout ; display upper or lower case inc hl djnz pmt5 pmt6: ld a,'>' ; end of prompt jp cout ; output a character, expanding control chars to ^x ccout: push af cp ' ' ; below space? jr c,ccout1 cp 7fh ; del? jr nz,ccout2 ld a,'_'-'@' ; so del will be ^_ ccout1: push af ; save character ld a,'^' call cout ; display ^ pop af add '@' ; ready to display visible char ccout2: call cout ; display char pop af ret ; display prompt character ; letters are forced to lower case if we are in the lower task culout: cp 'A' ; is it a letter? jr c,ccout cp 'Z'+1 jr nc,ccout call task ; which task is active? jr c,ccout add a,'a'-'A' ; shift to lower case jr ccout ; insert the byte in A into the new command line at htop ; limits length above htop to size of command line buffer ; Returns with NC if ok, C if mcl overflow phist: push de push hl push af ld hl,(htop) call strlen ; length of new line ld d,0 ld e,a call getcl1 ; get size of buffer in A and 0fch ; kludge lest mcl size is 255 cp e jr nc,phist2 ; overflow? call ring ; ring bell pop af ; and ignore pop hl pop de scf ; return with Carry set ret phist2: ld hl,(htop) add hl,de ; end of new line ld de,hlimit-2 ; last legal position with space for new char sbc hl,de ; end of available space? jr c,phist3 ld hl,hbase ; start of entry to eliminate call elim ; delete oldest entry phist3: ld hl,(hcurs) ; where to insert byte inc hl ld (hcurs),hl dec hl pop de ; new character into d push de phist4: ld a,(hl) ; get old value ld (hl),d ; deposit new value ld d,a inc hl or a ; was it end of line? jr nz,phist4 ld (hl),a ; terminating null pop af pop hl pop de or a ; return with Carry clear ret ; put character into new command line putcc: push hl push bc push af ld c,a ld hl,(hcurs) ld a,(hl) or a jr z,putcc1 ; at end of line? ld a,(insmod) and 1 jr nz,putcc1 ; inserting? ld (hl),c ; overwrite cursor char inc hl ld (hcurs),hl ; increment cursor jr putcc2 putcc1: ld a,c call phist ; insert it into buffer jr c,putcc4 ; overflow? putcc2: ld a,c call ccout ; display char ld hl,(hcurs) push hl putcc3: call forward ; display rest of line jr nz,putcc3 call print db ' ',bs,0 ; in case we overwrote a ctrl-char pop hl call gotohl ; replace cursor putcc4: pop af pop bc pop hl ret ; search back from HL for line with same prefix as current line prefix: push de push bc push af ld de,(htop) ; de points to start of text to be matched pref1: call prevl ; hl back to start of previous line jr nz,pref2 ; no previous line? call match jr nz,pref1 pref2: pop bc ; really AF ld a,b ; restore A but not F pop bc pop de ret ; case-independant string compare ; .HL :: .DE match: push hl push de push bc push af match1: ld a,(de) ; get current line char inc de or a ; end of current line? jr z,matchy ; match if so call caps ; capitalize ld c,a ; save in C ld a,(hl) ; get previous line char inc hl call caps ; capitalize cp c ; same? jr z,match1 matchy: pop bc ; really AF ld a,b ; restore A pop bc pop de pop hl ret ; move HL to previous line ; set NZ if no previous line prevl: push de push af ld de,hbase ex de,hl or a sbc hl,de ; at hbase? ex de,hl jr z,prevn dec hl ; end of previous line prevl1: dec hl ld a,(hl) or a ; end of line before that? jr nz,prevl1 inc hl preve: pop de ; really AF ld a,d pop de ret prevn: or 1 ; set NZ jr preve ; delete an entry from the history stack ; hl points to the entry to be deleted elim: push af push bc push de push hl call strlen ; length of entry inc a ; +1 for terminating null ld c,a ld b,0 ; entry length in BC ld hl,(htop) ; adjust htop or a sbc hl,bc ld (htop),hl ld hl,(hcurs) ; and hcurs or a sbc hl,bc ld (hcurs),hl ld hl,(hmark) ; check hmark is not already at hbase ld de,hbase ex de,hl or a sbc hl,de jr z,elim1 ex de,hl or a sbc hl,bc ; adjust hmark ld (hmark),hl elim1: pop hl ; retrieve entry pointer push hl add hl,bc ; hl = start + length (i.e. source) ex de,hl ld hl,hlimit ; end of stack area or a sbc hl,de ; length of move ld b,h ld c,l ; move length in BC pop hl ; get start back in HL push hl ex de,hl ldir ; move contents down to cover old entry pop hl pop de pop bc pop af ret ; find out which foreground task we are in (see BGii manual, Appendix H) ; return C = upper, NC = lower task: push hl push de push af ld hl,(1) ; bios warm boot entry ld de,-1602h ; offset to usual ccp entry add hl,de ld a,(hl) ; pick up address inc hl ld h,(hl) ld l,a dec hl ; back one ld a,(hl) ; this is where BGii hides its status and 2 ; test upper/lower bit jr z,taskl scf taskl: pop hl ; retrieve AF ld a,h ; restore A pop de pop hl ret ; find length of string pointed to by hl ; length returned in A (overflows if > 255) strlen: push hl push bc ld b,-1 strl1: ld a,(hl) inc hl inc b or a jr nz,strl1 ld a,b pop bc pop hl ret ; Wild card command repeat wild: jr z,wild1 ; foreground or background? xor a ld (wtask),a ; de-activate wild if called in backgr. ret wild1: call z3init ; save environment pointer call oshin ; ensure OSH is running ld hl,namsg jp nz,prmsg call task ; which task? sbc a ; upper = -1, lower = 0 inc a inc a ; upper = 1, lower = 2 ld (wtask),a ; remember which task is running wild ld hl,0 ld (wfile),hl ; clear wild file index ; come here from shell entry too dowild: call task ; check it's the same task sbc a inc a inc a ld hl,wtask cp (hl) jp nz,off ; can't handle - drop shell in this task call putud ; save current user / disk call inicl ; initialise command line ld a,-1 ld (fcb),a ; remember we haven't seen a wildcard yet ld hl,(htop) call prevl ; point to wild line call rtwrd ; skip 'WILD ' ex de,hl dwld0: ld a,(de) or a jr nz,dwld1 ; finished? ld a,(fcb) ; seen any wildcards? inc a jr nz,dwld0a ld (wtask),a ; de-activate WILD if not dwld0a: call getud ; back to original user / disk call prompt ; display prompt call getcl1 ld de,4 add hl,de call pstr ; and echo command line ld a,cr jp cout dwld1: cp '*' ; wildcard? jr z,dwld2 cp '?' jr nz,dwld9 dwld2: ld a,(fcb) ; already seen a wild token? inc a jr nz,dwld9 dwld3: dec de ; move back to start of name ld a,(de) cp ' ' jr z,dwld5 cp ':' jr z,dwld4 call del1cl ; remove char from mcl jr dwld3 dwld4: dec de ; skip back over dir name ld a,(de) cp ' ' jr nz,dwld4 dwld5: inc de ; DE points to start of token ex de,hl ld de,fcb call zfname ; parse putative filename into fcb push hl ; where to continue copying call z3log ; login to user / disk ld hl,(wfile) inc hl ld (wfile),hl ; increment file index push hl ; save index for counting down ld c,17 ; search for 1st match call bdos inc a ; found file? jr nz,dwld7 ld hl,nmmsg ; no match dwld6: pop af ; discard index pop af ; and continue address call getud ; back to original user / disk call inicl ; clear mcl xor a ld (wtask),a ; reset mode jp prmsg ; print and quit dwld7: pop hl ; file index push af ; save directory index dec hl ld a,h or l jr z,dwld8 ; required file? pop af ; discard directory index push hl ld c,18 ; search for next call bdos inc a ; found one? jr nz,dwld7 ld hl,wfmsg ; wild finished jr dwld6 ; quit dwld8: pop af ; directory index of found file dec a rrca rrca rrca add 81h ; position in default buffer ld l,a ld h,0 ld b,8 ; name length call cpfn ; copy name part into mcl ld a,'.' call put1cl ; dot ld b,3 call cpfn ; copy extension pop de ; where to continue copying from dwld9: ld a,(de) call put1cl inc de jp dwld0 ; copy part of a filename into the mcl cpfn: ld a,(hl) inc hl cp ' ' jr z,cpfn1 call put1cl cpfn1: djnz cpfn ret ; The following routines allow characters to be entered into ; the multiple command line buffer one by one, ; and also taken out again if necessary. ; initilialise command line to empty inicl: push hl push de push af call getcl1 ; where is it? push hl inc hl ; skip to current length byte inc hl inc hl xor a ld (hl),a ; clear current length inc hl ld (hl),a ; terminate line ex de,hl ; pointer to line in DE pop hl ; base of cmdline ld (hl),e inc hl ld (hl),d pop af pop de pop hl ret ; delete a character from the end of the mcl del1cl: push hl push de push af call getcl1 ; where is mcl? inc hl inc hl inc hl ; point to current size ld e,(hl) ld d,0 dec (hl) ; size-- add hl,de ld (hl),0 ; move terminator back pop af pop de pop hl ret ; append 1 character to the mcl (excess chars are discarded) put1cl: push hl push de push af call getcl1 ; where is mcl? inc hl inc hl inc hl ; point to current size sub (hl) ; max - current cp 3 ; room for new byte and terminator? jr c,p1cl1 ld e,(hl) ld d,0 inc (hl) ; size++ add hl,de inc hl ; where new byte should go pop af push af call caps ; force upper case ld (hl),a inc hl ld (hl),0 ; terminate line p1cl1: pop af pop de pop hl ret ; put string into command line putcl push hl push af putcl1: ld a,(hl) inc hl or a jr z,putcl2 call put1cl jr putcl1 putcl2: pop af pop hl ret ; key action table keytab: db 'A'-'@' dw bckwrd ; backup word db 'C'-'@' dw ctrlc ; reboot if start of line db 'D'-'@' dw forward ; forward character db 'E'-'@' dw bcklin ; backup line db 'F'-'@' dw forwrd ; forward wword db 'G'-'@' dw delcr ; delete character under cursor db 'H'-'@' dw delcl ; delete character to left of cursor db 'J'-'@' dw eolin ; same as db 'K'-'@' dw showh ; show history db 'L'-'@' dw look ; look for previous matching command db 'M'-'@' dw eolin ; end of line db 'P'-'@' dw quote ; quote next character db 'Q'-'@' dw bckcmd ; backup command db 'R'-'@' dw forcmd ; forward command db 'S'-'@' dw backup ; backup character db 'T'-'@' dw delwr ; delete word right db 'U'-'@' dw dellin ; delete line db 'V'-'@' dw insert ; toggle insert mode db 'W'-'@' dw delwl ; delete word left db 'X'-'@' dw forlin ; forward line db 'Y'-'@' dw delel ; delete to end of line db 'Z'-'@' dw delcmd ; delete command db 7fh dw delcl ; delete character left db 0 ; end of table stmsg: db cr,lf ; newline, then name name: db 'OSH',0 nmlen equ $-name hdmsg: db ' ',vers/10+'0','.',[vers mod 10]+'0',' installed',0 aamsg: db ': already active',0 sfmsg: db ': stack full',0 iomsg: db ': invalid operand',0 namsg: db ': not active',0 exmsg: db ': terminated',0 nmmsg: db ': no match',0 wfmsg: db ': WILD complete',0 done: db 0 ; flag set when line complete ; wildcard processing state ; wtask = 0 -- no wild card repeat in progress ; wtask = 1 -- wild card repeat in upper task ; wtask = 2 -- wild card repeat in lower task wtask: db 0 wfile: dw 0 ; index of last wildcard match ; Command history stack ; ; The history stack consists of zero or more entries, each of which ; is a command line terminated by a null byte. 'htop' points just ; past the most recent entry, at the area in which a new command ; is built up. The oldest entry starts at 'hbase', and is the ; one which will be pushed out if more space is needed. 'hlimit' ; is one past the highest address available for history storage. ; 'hcurs' is the cursor location within the new line being built ; up starting at 'htop'. A null byte precedes 'hbase' to simulate ; the end of a non-existant previous line. hmark: dw hbase ; pointer to last recall hcurs: dw hbase ; pointer within current line htop: dw hbase ; top of history stack hlimit equ head+1000h ; end of history stack ; Note: we rely on the fact that none of the library routines use ; the data seg, and because ZLINK puts the data at the end of the ; program, the data is followed immediately by free space. dseg db 0 hbase: equ $ end