public comnd, cmcfrm, prserr, repars, cmgtch, drives, comand, fcbcpy include msdefs.h datas segment public 'datas' extrn flags:byte, trans:byte, fcb:byte, buff:byte extrn taklev:byte, takadr:word, dosnum:byte comand cmdinfo <> cmer00 db cr,lf,'?Program error Invalid COMND call$' cmer01 db cr,lf,'?Ambiguous$' cmer02 db cr,lf,'?Illegal input file spec$' cmer03 db cr,lf,'?Invalid command$' ; [19e] cmer04 db cr,lf,'?Invalid command or operand$' ; [1] cmer06 db cr,lf,'?Wildcard not allowed$' ; [21a] cmer07 db cr,lf,'?Invalid drive specificaton$' ; [21a] cmin00 db ' Confirm with carriage return$' cmin01 db ' One of the following:',cr,lf,'$' cmthlp dw 0 ; Text of help message for random input. drives db 0 ; How many drives we have. [21a] crlf db cr,lf,'$' ctcmsg db '^C$' prsp db ' $' ; Print a space. hlpmsg dw 0 ; Address of help message. spchar db 24H,26H,23H,40H,21H,25H,27H,28H,29H,2DH db 3CH,3EH,7BH,7DH,5FH,5CH,5EH,7EH,7CH,60H spclen equ $-spchar spchar2 db 24H,26H,23H,40H,21H,25H,27H,28H,29H,2DH db 7BH,7DH,5FH,5EH,7EH,60H spc2len equ $-spchar2 escspc db 10O,' ',10O,'$' ; Clear escape. clrspc db ' ',10O,'$' ; Clear space. filbuf db 60H DUP(?) ; Character buffer. tbuff db 80 DUP(?) cmdstk dw ? datas ends code segment public extrn dodel:near, ctlu:near, cmblnk:near, locate:near, takrd:near extrn clearl:near assume cs:code,ds:datas,es:datas ; This routine parses the specified function in AH. Any additional ; information is in DX and BX. ; Returns +1 on success ; +4 on failure (assumes a JMP follows the call) CMND PROC NEAR comnd: mov comand.cmstat,ah ; Save what we are presently parsing. mov cmdstk,sp ; save stack ptr locally. call cminbf ; Get chars until an action or a erase char. mov ah,comand.cmstat ; Restore 'ah' for upcoming checks. cmp ah,cmcfm ; Parse a confirm? jz cmcfrm ; Go get one. cmp ah,cmkey ; Parse a keyword? jnz cm1 jmp cmkeyw ; Try and get one. cm1: cmp ah,cmifi ; Parse an input file spec? jnz cm2 jmp cmifil ; Go get one. cm2: cmp ah,cmofi ; Output file spec? jnz cm3 jmp cmofil ; Go get one. cm3: cmp ah,cmtxt ; Parse arbitrary text. [8] jnz cm4 jmp cmtext cm4: mov ah,prstr ; Else give error. mov dx,offset cmer00 ; "?Unrecognized COMND call" int dos ret ; This routine gets a confirm. cmcfrm: call cmgtch ; Get a char. cmp ah,0 ; Is it negative (a terminator; a space or ; a tab will not be returned here as they ; will be seen as leading white space.) js cmcfr0 ret ; If not, return failure. cmcfr0: and ah,7FH ; Turn off the minus bit. cmp ah,esc ; Is it an escape? jne cmcfr2 mov ah,conout mov dl,bell ; Get a bell. int dos mov ah,0 mov comand.cmaflg,ah ; Turn off the action flag. mov bx,comand.cmcptr ; Move the pointer to before thee scape. dec bx mov comand.cmcptr,bx mov comand.cmdptr,bx dec comand.cmccnt ; Decremrnt the char count. jmp cmcfrm ; Try again. cmcfr2: cmp ah,'?' ; Curious? jne cmcfr3 mov ah,prstr ; Print something useful. mov dx,offset cmin00 int dos mov ah,prstr mov dx,offset crlf ; Print a crlf. int dos mov ah,prstr mov dx,comand.cmprmp ; Reprint the prompt. int dos mov bx,comand.cmdptr ; Get the pointer into the buffer. mov ah,'$' ; Put a $ there for printing. mov [bx],ah mov bx,comand.cmcptr dec bx ; Decrement & save the buffer pointer. mov comand.cmcptr,bx mov ah,prstr mov dx,offset comand.cmdbuf int dos mov ah,0 ; Turn off the action flag. mov comand.cmaflg,ah jmp repars ; Reparse everything. cmcfr3: cmp ah,ff ; Is it a form feed? jne cmcfr4 call cmblnk ; If so blank the screen. cmcfr4: jmp rskp ; This routine parses a keyword from the table pointed ; to in DX. The format of the table is as follows: ; ; addr: db n ; Where n is the # of entries in the table. ; db m ; M is the size of the keyword. ; db 'string$' ; Where string is the keyword. ; dw ab ; Where ab is data to be returned. ; ; The keywords must be in alphabetical order. cmkeyw: mov comand.cmhlp,bx ; Save the help. mov comand.cmptab,dx ; Save the beginning of keyword table. mov bx,dx mov ch,[bx] ; Get number of entries in table. inc bx mov dx,comand.cmdptr ; Save command pointer. mov comand.cmsptr,dx ; Save pointer's here. cmky1: cmp ch,0 ; Any commands left to check? jne cmky2 jmp cmky41 ; no, go complain cmky2: dec ch mov cl,0 ; Keep track of how many chars read in so far. call cmgtch ; Get a char. cmp ah,0 ; Do we have a terminator? jns cmky2x jmp cmky4 ; Negative number means we do. cmky2x: inc bx ; Point to first letter of keyword. inc cl ; Read in another char. mov al,[bx] cmp ah,'a' ; Less than a? jl cmky21 ; If so, don't capitalize. cmp ah,'z'+1 ; More than z? jns cmky21 and ah,137O ; Capitalize the letter. cmky21: cmp ah,al je cmky3 jg cmky2y jmp cmky41 ; Fail if ah preceeds al alphabetically. cmky2y: jmp cmky6 ; Not this keyword - try the next. cmky3: inc bx ; We match here, how 'bout next char? mov al,[bx] cmp al,'$' ; End of keyword? jne cmky3x jmp cmky7 ; Succeed. cmky3x: mov dl,al ; Save al's char here. call cmgtch inc cl ; Read in another char. mov al,dl cmp ah,'a' jl cmky31 cmp ah,'z'+1 jns cmky31 and ah,137O cmky31: cmp ah,esc+80H ; Escape Recognition (escape w/minus bit on)? je cmky3y cmp ah,'?'+80H ; A question mark? [3] je cmky3y cmp ah,' '+80H ; A space? je cmky3y cmp ah,cr+80H ; Carriage return? je cmky3y jmp cmky38 cmky3y: mov comand.cmkptr,bx ; Save bx here. mov comand.cmsiz,cx ; Save size info. mov comand.cmchr,ah ; Save char for latter. call cmambg ; See if input is ambiguous or not. jmp cmky32 ; Succeeded (not ambiguous). mov ah,comand.cmchr cmp ah,esc+80H ; Escape? je cmky3z cmp ah,'?'+80H ; maybe question mark? je cmkyj1 ; yes, go handle jmp cmky41 ; Else fail. cmky3z: mov ah,conout ; Ring a bell. mov dl,bell int dos mov bx,comand.cmcptr ; Move pointer to before the escape. dec bx mov comand.cmcptr,bx mov comand.cmdptr,bx dec comand.cmccnt ; Decrement char count. mov bx,comand.cmkptr ; Failed - pretend user never typed .... mov cx,comand.cmsiz ; ... in a char. dec cl ; Don't count the escape. dec bx mov comand.cmaflg,0 ; Reset the action flag. jmp cmky3 ; Keep checking. ; ambiguous. Print out all the keywords that match cmkyj1: mov dx,offset cmin01 mov ah,prstr int dos mov bx,comand.cmkptr ; this is current keyword mov cx,comand.cmsiz ; we are cl chars into it mov ch,0 sub bx,cx ; back up to beginning inc bx ; not counting ? mov comand.cmkptr,bx ; save beginning of kw cmkyj2: mov dl,tab ; put a tab before each keyword mov ah,conout int dos mov dx,comand.cmkptr ; get current keyword mov ah,prstr int dos ; print it mov bx,comand.cmkptr ; get keyword back dec bx mov al,[bx] ; get length mov ah,0 add ax,5 ; skip length, $, value, next length add bx,ax ; this is next keyword mov si,bx mov di,comand.cmkptr ; compare with last keyword mov comand.cmkptr,bx ; update this mov cx,comand.cmsiz dec ch ; are we at end of table? jl cmkyj3 ; yes, don't go on mov comand.cmsiz,cx ; else update count mov ch,0 dec cl ; this includes ? jcxz cmkyj2 ; empty, just print it repe cmpsb ; compare to previous string je cmkyj2 ; same, go print this one cmkyj3: jmp cmky50 ; else go finish up cmky32: mov cx,comand.cmsiz ; Restore info. mov bx,comand.cmkptr ; Our place in the keyword table. cmp comand.cmchr,0A0H ; Space? je cmky35 cmp comand.cmchr,0BFH ; Question mark? [3] je cmky35 cmp comand.cmchr,8DH ; Carriage return? je cmky35 dec comand.cmcptr ; Pointer into buffer of input. mov dx,comand.cmcptr cmky33: mov ah,[bx] ; Get next char in keyword. cmp ah,'$' ; Are we done yet? jz cmky34 mov di,dx mov [di],ah inc bx inc dx inc comand.cmccnt jmp cmky33 cmky34: mov ah,' ' mov di,dx mov [di],ah ; Put a blank in the buffer. inc dx mov cx,comand.cmcptr ; Remember where we were. mov comand.cmcptr,dx ; Update our pointers. mov comand.cmdptr,dx mov ah,'$' mov di,dx mov [di],ah ; Add '$' for printing. mov ah,prstr mov dx,cx ; Point to beginning of filled in data. int dos inc bx ; Point to address we'll need. mov bx,[bx] mov comand.cmaflg,0 ; Turn off action flag. jmp rskp cmky35: inc bx mov ah,[bx] ; Find end of keyword. cmp ah,'$' jne cmky35 inc bx mov bx,[bx] ; Address of next routine to call. ; mov comand.cmaflg,0 ; Zero the action flag. jmp rskp cmky38: cmp ah,al je cmky39 jmp cmky6 ; Go to end of keyword and try next. cmky39: jmp cmky3 ; Check next letter. cmky4: and ah,7FH ; Turn off minus bit. cmp ah,'?' ; Need help? je cmky5 cmp ah,' ' ; Just a space - no error. je cmky51 cmp ah,cr je cmky51 cmp ah,tab je cmky51 cmp ah,esc ; Ignore escape? je cmky43 cmky41: mov ah,prstr mov dx,offset cmer03 int dos jmp prserr ; Parse error - give up. cmky43: mov ah,conout ; Ring a bell. mov dl,bell int dos dec comand.cmcptr ;[ESC] don't trash BX here. dec comand.cmdptr ;[ESC] ditto dec comand.cmccnt ; Don't count the escape. mov comand.cmaflg,0 ; Reset action flag. inc ch ; Account for a previous 'dec'. jmp cmky1 ; Start over. cmky5: inc bx ; point to actual keyword mov comand.cmkptr,bx ; remember current kw mov cl,1 ; code above expects to count ? mov comand.cmsiz,cx ; and size mov dx,comand.cmhlp or dx,dx ; was any help given? jnz cmky5a ; yes, use it jmp cmkyj1 ; else make our own message cmky5a: mov ah,prstr int dos cmky50: mov ah,prstr mov dx,offset crlf int dos mov dx,comand.cmprmp ; Address of prompt. int dos mov bx,comand.cmdptr ; Get pointer into buffer. mov al,'$' mov [bx],al ; Add dollar sign for printing. mov dx,offset comand.cmdbuf int dos dec comand.cmcptr ; Don't keep it in the buffer. dec comand.cmccnt ; Don't conut it. mov comand.cmaflg,0 ; Turn off the action flag. jmp repars cmky51: cmp comand.cmcr,1 ; Are bare CR's allowed? je cmky52 ; Yes. mov ah,prstr mov dx,offset cmer04 ; Complain. int dos cmky52: jmp prserr cmky6: inc bx ; Find end of keyword. mov al,[bx] cmp al,'$' jne cmky6 inc bx ; Beginning of next command. inc bx inc bx mov dx,comand.cmsptr ; Get old cmdptr. mov comand.cmdptr,dx ; Restore. mov comand.cmsflg,0FFH jmp cmky1 ; Keep trying. cmky7: call cmgtch ; Get char. cmp ah,0 js cmky71 ; Ok if a terminator. dec bx jmp cmky6 ; No match - try next keyword. cmky71: inc bx ; Get necessary data. mov bx,[bx] cmp ah,9BH ; An escape? jne cmky72 mov ah,prstr mov dx,offset prsp ; Print a space. int dos mov di,comand.cmcptr dec di mov ah,20H mov [di],ah ; Replace escape char with space. mov comand.cmaflg,0 mov comand.cmsflg,0FFH ; Pretend they typed a space. cmky72: jmp rskp ; See if keyword is unambiguous or not from what the user has typed in. cmambg: cmp ch,0 ; Any keywords left to check? jne cmamb0 ret ; If not then not ambiguous. cmamb0: inc bx ; Go to end of keyword ... mov al,[bx] ; So we can check the next one. cmp al,'$' jne cmamb0 add bx,4 ; Point to start of next keyword. dec cl ; Don't count escape. mov dx,comand.cmsptr ; Buffer with input typed by user. cmamb1: mov ah,[bx] ; Keyword char. mov di,dx mov al,[di] ; Input char. cmp al,'a' ; Do capitalizing. jl cmam11 cmp al,'z'+1 jns cmam11 and al,137O cmam11: cmp ah,al ; Keyword bigger than input (alphabetically)? jle cmamb2 ; No - keep checking. ret ; Yes - not ambiguous. cmamb2: inc bx ; Advance one char. inc dx dec cl jnz cmamb1 jmp rskp ; Fail - it's ambiguous. cmifil: mov hlpmsg,bx ; Address of help message. mov bx,dx ; Get the fcb address in bx. mov comand.cmfcb,bx ; Save it. mov ch,0 ; Initialize char count. mov ah,0 mov [bx],ah ; Set the drive to default to current. inc bx mov comand.cmfcb2,bx mov cl,' ' cmifi0: mov [bx],cl ; Blank the FCB. inc bx inc ah cmp ah,0BH ; Twelve? jl cmifi0 cmifi1: call cmgtch ; Get another char. cmp ah,0 ; Is it an action character. js cmif1x ; Jump out of range. [21a] jmp cmifi2 ; Ditto. [21a] cmif1x: and ah,7FH ; Turn off the action bit. [21a] cmp ah,'?' ; A question mark? jne cmif12 mov al,0 mov comand.cmaflg,al ; Blank the action flag. dec comand.cmcptr ; Decrement the buffer pointer. dec comand.cmccnt ; Decrement count. mov ah,prstr mov dx,hlpmsg ; Help message. int dos mov dx,offset crlf int dos mov dx,comand.cmprmp int dos mov bx,comand.cmdptr mov al,'$' mov [bx],al ; Put in dollar sign for printing. mov dx,offset comand.cmdbuf int dos jmp repars cmif12: cmp ah,esc ; An escape? je cm12x jmp cmif13 cm12x: mov comand.cmaflg,0 ; Turn off the action flag. dec comand.cmcptr ; Move pointers to before the escape. dec comand.cmdptr dec comand.cmccnt ; Decrement char count. mov comand.cmchr,ch ; Save current character count. cmp ch,9 ; Past '.'? jl cmf120 ; No. dec ch ; Yes, don't count point. cmf120: mov di,comand.cmfcb2 ; Fill the rest with CP/M wildcards. mov ah,'?' cmf121: cmp ch,11 ; Done? jge cmf122 ; Yes. mov [di],ah inc di inc ch jmp cmf121 cmf122: mov ah,sfirst ; Find first matching file? mov dx,comand.cmfcb ;[jd] use pointer to PASSED fcb int dos cmp al,0FFH ; Any found? jne cmf123 ; Yes. jmp cmf12b ; No, lose. cmf123: mov di,offset filbuf ; Copy first file spec from DTA to buffer. mov bx,offset buff+1 mov cl,11 call fcbcpy mov di,offset filbuf+10H ; Get another copy (if not ambiguous). mov bx,offset buff+1 mov cl,11 call fcbcpy mov ah,snext ; More matching specs? mov dx,comand.cmfcb ;[jd] use PASSED fcb... int dos cmp al,0FFH je cmf124 ; Only one. mov di,offset filbuf+10H ; Copy second file spec. mov bx,offset buff+1 mov cl,11 call fcbcpy cmf124: mov si,offset filbuf ; Start comparing file names. mov bx,offset filbuf+10H mov di,comand.cmcptr ; Command buffer pointer mov cl,comand.cmchr ; Bypass characters typed. cmp cl,9 ; Past '.'? jl cmf125 ; No. dec cl ; Yes, don't count point. cmf125: mov ch,0 ; Adjust pointers. add si,cx add bx,cx mov ch,cl ; Update character count cmf126: cmp ch,11 ; All done? jne cmf127 ; No. jmp cmf12a ; Yes. cmf127: cmp ch,8 ; End of file name? jne cmf128 ; No. cmp comand.cmchr,9 ; Exactly at point? je cmf128 ; Yes, don't output a second point. mov ah,'.' ; Output separator. mov [di],ah inc di inc comand.cmccnt cmf128: mov ah,[si] ; Get a character from first file spec. inc si mov al,[bx] ; Get another from second spec. inc bx cmp ah,al ; Compare. jne cmf12a ; Ambiguous. inc ch ; Same, count. cmp ah,' ' ; Blank? je cmf129 ; Yes, don't output. mov [di],ah inc di inc comand.cmccnt cmf129: jmp cmf126 ; Repeat. cmf12a: mov comand.cmchr,ch ; Save count of characters processed. mov ah,'$' ; Put terminator into buffer. mov [di],ah mov comand.cmcptr,di ; Save pointer for recognized characters. mov ah,prstr mov dx,comand.cmdptr int dos mov ch,comand.cmchr ; Characters processed. cmp ch,11 ; Complete file name. je cmf12c ; Yes, don't beep. cmf12b: mov ah,conout ; Beep, if not recognized. mov dl,bell int dos ; Ring the bell. cmf12c: jmp repars cmif13: mov ah,ch ; It must be a terminator. cmp ah,0 ; Test the length of the file name. jnz cmf3x cmp comand.cmcr,1 ; Is zero length OK? [21a] je cmf3z ; Return successfully. [21a] jmp cmifi9 ; If zero complain. cmf3x: cmp ah,0DH js cmf3y jmp cmifi9 ; If too long complain. cmf3y: jmp rskp ; Otherwise we have succeeded. cmf3z: push es mov ax,ds mov es,ax mov di,comand.cmfcb inc di mov cx,11 mov al,'?' repne stosb pop es mov flags.wldflg,0FFH ; Remember we had a wildcard. jmp rskp cmifi2: cmp ah,'.' jne cmifi3 inc ch mov ah,ch cmp ah,1H ; Any chars yet? jnz cmf2x jmp cmifi9 ; No, give error. cmf2x: cmp ah,0AH ; Tenth char? js cmf2y jmp cmifi9 ; Past it, give an error. cmf2y: mov dl,9H mov dh,0 mov bx,comand.cmfcb add bx,dx ; Point to file type field. mov comand.cmfcb2,bx mov ch,9H ; Say we've gotten nine. jmp cmifi1 ; Get the next char. cmifi3: cmp ah,':' jne cmifi4 inc ch cmp ch,2H ; Is it in right place for a drive? je cmif3x jmp cmifi9 ; If not, complain. cmif3x: mov ch,0 ; Reset char count. mov flags.droflg,1 ; Override default drive. [21a] mov flags.nmoflg,0 ; Not so fast. [21a] mov bx,comand.cmfcb2 mov al,':' ; Use for parsing drive name. mov [bx],al dec bx ; Point to drive spec. mov si,bx push es mov ax,ds mov es,ax mov di,offset tbuff ; Borrow this buffer. mov ah,prsfcb int dos pop es cmp al,0 ; OK return code? je cmif3y ; Yes, keep going. ; mov ah,[bx] ; Get the drive name. ; sub ah,'@' ; Get the drive number. ; cmp ah,drives ; Did user specify a non-existant drive? [21a] ; jle cmif3y ; Nope, so continue. [21a] mov dx,offset cmer07 ; Fail with this error message. [21a] jmp cmif9x ; [21a] cmif3y: mov comand.cmfcb2,bx ; Put rest of filename starting here. [21a] mov ah,[bx] ; Pick up drive specified. sub ah,'@' ; Get real value. mov bx,comand.cmfcb mov [bx],ah ; Put it in the fcb. push bx mov al,' ' ; Overwrite the drive and ":". inc bx mov [bx],al inc bx mov [bx],al pop bx jmp cmifi1 cmifi4: cmp ah,'*' jne cmifi7 cmp comand.cmrflg,1 ; In receive mode? [21a] jne cmif4x ; Jump out of range. [21a] mov dx,offset cmer06 ; Set the error message. [21a] jmp cmif9x ; Fail - no wildcard allowed. [21a] cmif4x: mov ah,ch ; [21a] cmp ah,8H ; Is this in the name or type field? jns cmifi5 ; Type. mov cl,8H ; Say we have eight chars. js cmifi6 ; Name field. jmp cmifi9 ; If its where the dot should be give up. cmifi5: mov cl,0CH ; Three chars. cmifi6: mov flags.wldflg,0FFH ; Remember we had a wildcard. mov bx,comand.cmfcb2 ; Get a pointer into the FCB. mov ah,'?' mov [bx],ah ; Put a question mark in. inc bx mov comand.cmfcb2,bx inc ch mov ah,ch cmp ah,cl jl cmifi6 ; Go fill in another. jmp cmifi1 ; Get the next char. cmifi7: cmp ah,03DH ; Equals sign (wildcard)? jne cmif7x cmp comand.cmrflg,1 ; In receive mode? [21a] jne cmif7y ; No, so it's ok. [21a] mov dx,offset cmer06 ; Set the error message. [21a] jmp cmif9x ; Fail - no wildcard allowed. [21a] cmif7y: mov ah,'?' ; New label. [21a] mov flags.wldflg,0FFH ; Say we have a wildcard. jmp cmifi8 ; Put into FCB. cmif7x: cmp ah,'0' jl cmif8x cmp ah,'z'+1 jns cmif8x cmp ah,'A' ; Don't capitalize non-alphabetics. jl cmifi8 and ah,137O ; Capitalize. cmifi8: mov bx,comand.cmfcb2 ; Get the pointer into the FCB. mov [bx],ah ; Put the char there. inc bx mov comand.cmfcb2,bx mov flags.nmoflg,1 ; Overriding name from host. [21a] inc ch jmp cmifi1 cmif8x: push es mov cx,ds mov es,cx ; Scan uses ES register. mov di,offset spchar ; Special chars. mov cx,spclen ; How many of them. cmp dosnum,0 ; Under version 2.0 je cmif8y mov di,offset spchar2 mov cx,spc2len cmif8y: mov al,ah ; Char is in al. repnz scasb ; Search string for input char. cmp cx,0 ; Was it there? pop es jnz cmifi8 cmifi9: mov dx,offset cmer02 cmif9x: mov ah,prstr int dos mov flags.droflg,0 ; Not overriding drive. [21a] mov flags.nmoflg,0 ; Or name to save file under. [21a] mov comand.cmrflg,0 ; Reset this flag too. [21a] ret cmofil: jmp cmifil ; For now, the same as CMIFI. ; Parse arbitrary text up to a CR. Put chars into data buffer sent to ; the host (pointed to by BX). Called with text of help message in DX. ; Return updated pointer in BX and input size in AH. cmtext: mov comand.cmptab,bx ; Save pointer to data buffer. [8 start] mov cmthlp,dx ; Save the help message. mov cl,0 ; Init the char count. cmtxt1: mov comand.cmsflg,0 ; Get all spaces. [25] call cmgtch ; Get a char. test ah,80H ; is high-order bit on? jz cmtxt5 ; Nope, put into the buffer. and ah,07FH cmp ah,' ' je cmtxt5 cmp ah,esc ; An escape? jne cmtxt2 mov ah,conout mov dl,bell ; Ring a bell. int dos mov comand.cmaflg,0 ; Reset action flag. dec comand.cmcptr ; Move pointer to before the escape. dec comand.cmdptr dec comand.cmccnt ; Decrement count. jmp cmtxt1 ; Try again. cmtxt2: cmp ah,'?' ; Asking a question? jz cmtx30 cmp ah,ff ; Formfeed? jne cmtx2x call cmblnk cmtx2x: mov ah,cl ; Return count in AH. mov bx,comand.cmptab ; Return updated pointer. jmp rskp cmtx30: mov comand.cmaflg,0 ; Reset action flag to zero. inc comand.cmdptr ; count the ? cmp cl,0 ; Is "?" first char? jne cmtxt5 ; No, just add to buffer. dec comand.cmcptr ;[ESC] (moved 3 lines) Don't keep in buffer. dec comand.cmccnt ;[ESC] Don't conut it. dec comand.cmdptr ;[ESC] don't count if printing help. mov ah,prstr ; Else, give some help. mov dx,cmthlp ; Address of help message. int dos mov ah,prstr mov dx,offset crlf ; Print a crlf. int dos mov ah,prstr mov dx,comand.cmprmp ; Reprint the prompt. int dos mov bx,comand.cmdptr ; Get the pointer into the buffer. mov byte ptr [bx],'$' mov ah,prstr mov dx,offset comand.cmdbuf int dos jmp cmtxt1 ; And keep going. cmtxt5: inc cl ; Increment the count. mov bx,comand.cmptab ; Pointer into destination array. mov [bx],ah ; Put char into the buffer. inc bx mov comand.cmptab,bx jmp cmtxt1 ; [8 end] cmgetc: cmp taklev,0 jne cmget1 jmp cmge10 ; no take file, get from keyboard cmget1: push bx push si mov bx,takadr mov ax,[bx].takcnt or ax,[bx].takcnt+2 jnz cmget5 cmget2: mov al,byte ptr [bx].takfcb ; get first byte of fcb cmp al,0ffh ; is it really a macro? je cmget4 ; yes, better not try to close it cmp al,0feh ; or maybe a file handle? je cmget3 ; yes, close w/2.0 call mov ah,closf lea dx,[bx].takfcb int dos jmp short cmget4 ; skip over alternate close cmget3: mov bx,word ptr [bx].takfcb+1 ; this is where file handle is stored mov ah,close2 ; use 2.0 close int dos cmget4: dec taklev sub takadr,size takinfo pop si pop bx mov al,cr ; end with carriage return... ret cmget5: cmp [bx].takchl,0 ; Any chars left in buffer? jne cmget6 call takrd cmget6: dec [bx].takchl sub [bx].takcnt,1 ; DEC doesn't set carry!! sbb [bx].takcnt+2,0 mov si,[bx].takptr lodsb mov [bx].takptr,si cmp al,ctlz ; maybe control-z? je cmget2 ; yes, close take file (has to be before pops) pop si pop bx cmp al,lf ; linefeed? jne cmget7 cmp flags.takflg,0 je cmgetc ; yes, ignore it cmget7: cmp al,';' ; maybe a semicolon? je cmget9 cmp flags.takflg,0 ; Echo contents of take file? je cmget8 push dx mov dl,al mov ah,conout int dos pop dx cmget8: ret ; else just return... ; semicolon seen, ignore chars until cr cmget9: call cmgetc ; get a character? cmp al,cr ; carriage return? jne cmget9 ; no, keep reading ret ; else return it cmge10: mov ah,coninq ; Get a char. cmp flags.debug,0 ; in debug mode? je cmge11 ; yes, go on mov ah,8 ; else use read that recognizes ^C cmge11: int dos push ax ; save the char cmp al,bs ; backspace? je cmge13 ; yes, skip echo cmp al,' ' ; printable? jae cmge12 ; yes, no translation needed cmp al,cr ; this is printable je cmge12 cmp al,lf je cmge12 cmp al,tab je cmge12 mov al,' ' ; else echo a space cmge12: mov dl,al ; put char here mov ah,conout int dos ; echo it ourselves... cmge13: pop ax ; and return it cmp al,'C'-40H ; control-C? je cmge15 ; yes, go handle cmp al,';' ; semicolon? je cmget9 ; yes, ignore rest of line... cmp al,tab jne cmge14 mov al,' ' cmge14: ret cmge15: mov dx,offset ctcmsg mov ah,prstr int dos mov flags.cxzflg,'C' ; remember ^C'd mov sp,cmdstk ; restore command stack ptr ret ; and fail ; Come here is user types ^W when during input. cntrlw: mov ah,prstr mov dx,offset escspc int dos dec comand.cmccnt ; Don't include it in the count. dec comand.cmcptr ; Back up past the ^W. mov cl,comand.cmccnt mov ch,0 jcxz ctlw2 pushf push es std ; Scan backwards. mov ax,ds mov es,ax ; Point to the data area. mov di,comand.cmcptr ; Looking from here. dec di mov al,' ' repe scasb ; Look for non-space. je ctlw1 ; All spaces, nothing else to do inc di ; move back to non-space inc cx repne scasb ; look for a space jne ctlw1 ; no space, leave ptrs alone inc di inc cx ; skip back over space ctlw1: inc di mov comand.cmccnt,cl ; update count mov cx,comand.cmcptr ; remember old ptr mov comand.cmcptr,di ; update pointer sub cx,di ; this is characters moved mov al,bs ; backspace cld mov di,offset tbuff ; temporary buffer rep stosb ; put enough spaces in mov byte ptr [di],'$' ; end buffer mov dx,offset tbuff mov ah,prstr int dos ; back up cursor call clearl ; clear line pop es popf ret ; and return ctlw2: mov ah,conout mov dl,bell int dos ret cminbf: push dx push bx mov cx,dx ; Save value here too. mov ah,comand.cmaflg ; Is the action char flag set? cmp ah,0 je cminb1 jmp cminb9 ; If so get no more chars. cminb1: inc comand.cmccnt ; Increment the char count. call cmgetc mov ah,al ; Keep char in 'ah'. mov bx,comand.cmcptr ; Get the pointer into the buffer. mov [bx],ah ; Put it in the buffer. inc bx mov comand.cmcptr,bx cmp ah,'W'-64 ; Is it a ^W? jne cmnb11 call cntrlw ; Kill the previous word. jmp repars cmnb11: cmp ah,25O ; Is it a ^U? jne cminb2 cmnb12: call ctlu ; Clear out the line. mov ah,prstr mov dx,comand.cmprmp ; Print the prompt. int dos mov bx,offset comand.cmdbuf mov comand.cmcptr,bx ; Reset the point to the start. mov comand.cmccnt,0 ; Zero the count. mov dx,cx ; Preserve original value of dx. jmp repars ; Go start over. cminb2: cmp ah,bs ; Or backspace? jz cminb3 cmp ah,del ; Delete? jne cminb4 cminb3: call dodel ; Delete a character. mov ah,comand.cmccnt ; Decrement the char count by two. dec ah dec ah cmp ah,0 ; Have we gone too far? jns cmnb32 ; If not proceed. mov ah,conout ; Ring the bell. mov dl,bell int dos jmp cmnb12 ; Go reprint prompt and reparse. cmnb32: mov comand.cmccnt,ah ; Save the new char count. mov ah,prstr ; Erase the character. mov dx,offset clrspc int dos mov bx,comand.cmcptr ; Get the pointer into the buffer. dec bx ; Back up in the buffer. dec bx mov comand.cmcptr,bx jmp repars ; Go reparse everything. cminb4: cmp ah,'?' ; Is it a question mark. jz cminb6 cmp ah,esc ; Is it an escape? jz cminb8 cmp ah,cr ; Is it a carriage return? jz cminb5 cmp ah,lf ; Is it a line feed? jz cminb5 cmp ah,ff ; Is it a formfeed? jne cminb7 call cmblnk call locate cminb5: mov ah,comand.cmccnt ; Have we parsed any chars yet? cmp ah,1 jnz cminb6 jmp prserr ; If not, just start over. cminb6: mov ah,0FFH ; Set the action flag. mov comand.cmaflg,ah jmp cminb9 cminb7: jmp cminb1 ; Get another char. cminb8: mov ah,prstr ; Don't print the escape char. mov dx,offset escspc int dos jmp cminb6 cminb9: pop bx pop dx ret cmgtch: push cx push bx push dx cmgtc1: mov ah,comand.cmaflg cmp ah,0 ; Is it set. jne cmgt10 call cminbf ; If the action char flag is not set get more. cmgt10: mov bx,comand.cmdptr ; Get a pointer into the buffer. mov ah,[bx] ; Get the next char. inc bx mov comand.cmdptr,bx cmp ah,' ' ; Is it a space? jz cmgtc2 cmp ah,tab ; Or a tab? jne cmgtc3 cmgtc2: mov ah,comand.cmsflg ; Get the space flag. cmp ah,0 ; Was the last char a space? jne cmgtc1 ; Yes, get another char. mov ah,0FFH ; Set the space flag. mov comand.cmsflg,ah mov ah,' ' pop dx pop bx jmp cmgtc5 cmgtc3: mov al,0 mov comand.cmsflg,al ; Zero the space flag. pop dx pop bx cmp ah,esc jz cmgtc5 cmp ah,'?' ; Is the user curious? jz cmgtc4 cmp ah,cr jz cmgtc4 cmp ah,lf jz cmgtc4 cmp ah,ff je cmgtc4 pop cx ret ; Not an action char, just return. cmgtc4: dec comand.cmdptr cmgtc5: or ah,80H ; Make the char negative to indicate pop cx ret ; it is a terminator. CMND ENDP ; This address is jumped to on reparse. PARSE PROC NEAR repars: mov sp,comand.cmostp ; new sp <-- old sp mov bx,offset comand.cmdbuf mov comand.cmdptr,bx mov ah,0FFH mov comand.cmsflg,ah jmp comand.cmrprs ; go back to reparse address ; This address can be jumped to on a parsing error. prserr: mov sp,comand.cmostp ; Set new sp to old one. mov bx,offset comand.cmdbuf mov comand.cmcptr,bx ; Initialize the command pointer. mov comand.cmdptr,bx mov ah,0 mov comand.cmaflg,ah ; Zero the flags. mov comand.cmccnt,ah mov comand.cmsflg,0FFH cmp taklev,0 ; in take cmd? jne prser1 ; yes, don't print prompt mov ah,prstr mov dx,offset crlf int dos mov ah,prstr ; Print the prompt. mov dx,comand.cmprmp ; Get the prompt. int dos ; Instead return to before the prompt call. prser1: jmp comand.cmrprs PARSE ENDP ; FCB must be remembered if found "*" in filename. [7 start] ; Copy from place addressed by BX to place addressed by DI. ; Also use to get the filename to the FCB from the DTA. FCBCPY PROC NEAR push es push si mov ax,ds mov es,ax ; make sure destination segment is correct mov ch,0 ; high-order part of length jcxz fcbcp1 ; zero argument (is this necessary???) mov si,bx ; this is source rep movsb ; copy the whole thing fcbcp1: pop si pop es ret ; and return FCBCPY ENDP ; Jumping to this location is like retskp. It assumes the instruction ; after the call is a jmp addr. RSKP PROC NEAR pop bp add bp,3 push bp ret RSKP ENDP ; Jumping here is the same as a ret. R PROC NEAR ret R ENDP code ends end