923 lines
22 KiB
NASM
923 lines
22 KiB
NASM
page ,132
|
||
; SCCSID = @(#)tmisc1.asm 4.1 85/09/22
|
||
; SCCSID = @(#)tmisc1.asm 4.1 85/09/22
|
||
TITLE Part7 COMMAND Transient Routines
|
||
;/*
|
||
; * Microsoft Confidential
|
||
; * Copyright (C) Microsoft Corporation 1991
|
||
; * All Rights Reserved.
|
||
; */
|
||
|
||
;
|
||
; Revision History
|
||
; ================
|
||
; M003 SR 07/16/90 Made Execute public to jump to it for
|
||
; LoadHigh support
|
||
;
|
||
; M025 SR 9/12/90 Removed calls to SetStdInOn,SetStdInOff
|
||
; SetStdOutOn & SetStdOutOff.
|
||
;
|
||
|
||
|
||
; More misc routines
|
||
|
||
.xlist
|
||
.xcref
|
||
include comsw.asm
|
||
include dossym.inc
|
||
include syscall.inc
|
||
include comseg.asm
|
||
include comequ.asm
|
||
.list
|
||
.cref
|
||
|
||
|
||
|
||
CODERES SEGMENT PUBLIC BYTE ;AC000;
|
||
;; EXTRN RSTACK:BYTE
|
||
CodeRes ENDS
|
||
|
||
DATARES SEGMENT PUBLIC BYTE ;AC000;
|
||
EXTRN CALL_FLAG:BYTE
|
||
EXTRN EchoFlag:BYTE
|
||
EXTRN EXEC_BLOCK:BYTE
|
||
EXTRN EXTCOM:BYTE
|
||
EXTRN LenMsgOrPathBuf:ABS
|
||
EXTRN PIPEFLAG:BYTE
|
||
EXTRN PIPEPTR:WORD
|
||
EXTRN PIPESTR:BYTE
|
||
EXTRN RESTDIR:BYTE
|
||
EXTRN RE_OUT_APP:BYTE
|
||
EXTRN RE_OUTSTR:BYTE
|
||
EXTRN SAFEPATHBUFFER:BYTE
|
||
|
||
extrn RStack:word
|
||
|
||
ifdef BETA3WARN
|
||
%out Take this out before we ship
|
||
EXTRN Beta3Warned:byte
|
||
EXTRN TrnSeg:word
|
||
endif
|
||
|
||
|
||
DATARES ENDS
|
||
|
||
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
|
||
EXTRN BADDRV_PTR:WORD
|
||
EXTRN BADNAM_PTR:WORD
|
||
EXTRN COMTAB:BYTE ;AC000;
|
||
EXTRN extend_buf_ptr:word ;AN000;
|
||
EXTRN msg_disp_class:byte ;AN000;
|
||
|
||
ifdef BETA3WARN
|
||
%out Take this out before we ship
|
||
EXTRN Beta3WarnMsg:byte
|
||
endif
|
||
|
||
TRANDATA ENDS
|
||
|
||
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
|
||
EXTRN arg:byte ; the arg structure!
|
||
EXTRN ALLSWITCH:WORD
|
||
EXTRN APPEND_EXEC:BYTE ;AN041;
|
||
EXTRN CHKDRV:BYTE
|
||
EXTRN COMBUF:BYTE
|
||
EXTRN COMSW:WORD
|
||
EXTRN EXECPATH:BYTE
|
||
EXTRN EXEC_ADDR:DWORD
|
||
EXTRN FILTYP:BYTE
|
||
EXTRN IDLEN:BYTE
|
||
EXTRN KPARSE:BYTE ;AC000;
|
||
EXTRN PARM1:BYTE
|
||
EXTRN PARM2:BYTE
|
||
EXTRN PathPos:word
|
||
EXTRN RESSEG:WORD
|
||
EXTRN RE_INSTR:BYTE
|
||
EXTRN SPECDRV:BYTE
|
||
EXTRN SWITCHAR:BYTE
|
||
EXTRN switch_list:byte
|
||
EXTRN TRAN_TPA:WORD
|
||
|
||
EXTRN EXECPATH_SIZE:WORD
|
||
EXTRN EXECEXT_TYPE:WORD
|
||
IF IBM
|
||
EXTRN ROM_CALL:BYTE
|
||
EXTRN ROM_CS:WORD
|
||
EXTRN ROM_IP:WORD
|
||
ENDIF
|
||
|
||
TRANSPACE ENDS
|
||
|
||
TRANCODE SEGMENT PUBLIC byte
|
||
|
||
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
|
||
|
||
EXTRN APPEND_PARSE:NEAR ;AN010;
|
||
EXTRN BATCOM:NEAR
|
||
EXTRN DOCOM1:NEAR
|
||
EXTRN PIPEERRSYN:NEAR
|
||
EXTRN TCOMMAND:NEAR
|
||
|
||
IF IBM
|
||
EXTRN ROM_EXEC:NEAR
|
||
EXTRN ROM_SCAN:NEAR
|
||
ENDIF
|
||
|
||
PUBLIC CERROR
|
||
PUBLIC DRVBAD
|
||
PUBLIC EXTERNAL
|
||
PUBLIC FNDCOM
|
||
PUBLIC PRESCAN
|
||
PUBLIC SWITCH
|
||
|
||
public Lh_Execute ; M051
|
||
|
||
|
||
ASSUME DS:TRANGROUP
|
||
|
||
;---------------------------
|
||
; We can get rid of this switch processing code if we can take
|
||
; care of the remaining two calls to switch, later in the file.
|
||
; However, I have not checked whether or not any other files use
|
||
; switch -- after all, it IS public!
|
||
;---------------------------
|
||
|
||
SWCOUNT EQU 6 ; Length of switch_list
|
||
|
||
RETSW:
|
||
XCHG AX,BX ; Put switches in AX
|
||
return
|
||
|
||
SWITCH:
|
||
XOR BX,BX ; Initialize - no switches set
|
||
SWLOOP:
|
||
INVOKE SCANOFF ; Skip any delimiters
|
||
CMP AL,[SWITCHAR] ; Is it a switch specifier?
|
||
JNZ RETSW ; No -- we're finished
|
||
OR BX,fSwitch ; Indicate there is a switch specified
|
||
INC SI ; Skip over the switch character
|
||
INVOKE SCANOFF
|
||
CMP AL,0DH
|
||
JZ RETSW ; Oops
|
||
INC SI
|
||
; Convert lower case input to upper case
|
||
INVOKE UPCONV
|
||
MOV DI,OFFSET TRANGROUP:switch_list
|
||
MOV CX,SWCOUNT
|
||
REPNE SCASB ; Look for matching switch
|
||
JNZ BADSW
|
||
MOV AX,1
|
||
SHL AX,CL ; Set a bit for the switch
|
||
OR BX,AX
|
||
JMP SHORT SWLOOP
|
||
|
||
BADSW:
|
||
JMP SHORT SWLOOP
|
||
|
||
DRVBAD:
|
||
MOV DX,OFFSET TRANGROUP:BADDRV_ptr
|
||
JMP CERROR
|
||
|
||
externalj:
|
||
jmp EXTERNAL
|
||
|
||
fndcom: ; search the internal command table
|
||
OR AL,AL ; Get real length of first arg
|
||
jz externalj ; If 0, it must begin with "\" so has
|
||
; to be external.
|
||
; barryf code starts here
|
||
|
||
ifndef NEC_98
|
||
IF IBM
|
||
call test_append ; see if APPEND installed
|
||
je contcom ; not loaded
|
||
|
||
append_internal:
|
||
mov cl,TRANGROUP:IDLEN
|
||
mov ch,0
|
||
mov pathpos,cx
|
||
inc append_exec ;AN041; set APPEND to ON
|
||
|
||
invoke ioset ; re-direct the o'l io
|
||
|
||
mov SI, offset TRANGROUP:IDLEN ; address command name, DS already set
|
||
mov DX,-1 ; set invoke function
|
||
mov di,offset TRANGROUP:APPEND_PARSE;AN010; Get the entry point for PARSE for APPEND
|
||
mov AX,0AE01H
|
||
int 2FH ; execute command
|
||
cmp TRANGROUP:IDLEN,0 ; execute requested
|
||
;; je Cmd_done
|
||
jne contcom
|
||
jmp Cmd_done
|
||
|
||
contcom: ; continue with internal scan
|
||
ENDIF
|
||
else ;NEC_98
|
||
call test_append ; see if APPEND installed
|
||
je contcom ; not loaded
|
||
|
||
append_internal:
|
||
mov cl,TRANGROUP:IDLEN
|
||
mov ch,0
|
||
mov pathpos,cx
|
||
inc append_exec ;AN041; set APPEND to ON
|
||
|
||
invoke ioset ; re-direct the o'l io
|
||
|
||
mov SI, offset TRANGROUP:IDLEN ; address command name, DS already set
|
||
mov DX,-1 ; set invoke function
|
||
mov di,offset TRANGROUP:APPEND_PARSE;AN010; Get the entry point for PARSE for APPEND
|
||
mov AX,0AE01H
|
||
int 2FH ; execute command
|
||
cmp TRANGROUP:IDLEN,0 ; execute requested
|
||
;; je Cmd_done
|
||
jne contcom
|
||
jmp Cmd_done
|
||
|
||
contcom: ; continue with internal scan
|
||
endif ;NEC_98
|
||
|
||
; barryf code ends here
|
||
|
||
mov DI, OFFSET TRANGROUP:COMTAB
|
||
XOR CX,CX
|
||
|
||
findcom:
|
||
mov SI, offset TRANGROUP:IDLEN+1 ; pointer to command argument
|
||
mov CL, [DI] ; load length of internal command
|
||
inc di ; advance past length
|
||
jcxz externalj ; if it's zero, we're out of internals
|
||
cmp CL, IDLEN ; that of the command argument
|
||
jnz abcd ; lengths not equal ==> strings not eq
|
||
MOV PathPos,CX ; store length of command
|
||
repz cmpsb
|
||
|
||
abcd:
|
||
lahf ; save the good ol' flags
|
||
add DI, CX ; skip over remaining internal, if any
|
||
mov AL, BYTE PTR [DI] ; load drive-check indicator byte (DCIB)
|
||
mov [CHKDRV], AL ; save command flag byte in chkdrv
|
||
inc DI ; increment DI (OK, OK, I'll stop)
|
||
mov BX, WORD PTR [DI] ; load internal command address
|
||
inc DI ; skip over the puppy
|
||
inc DI
|
||
mov DX, WORD PTR [DI] ; load ptr to help msg #s
|
||
inc DI
|
||
inc DI
|
||
sahf ; remember those flags?
|
||
jnz findcom ; well, if all the cmps worked...
|
||
;
|
||
; All messages get redirected.
|
||
;
|
||
cmp append_exec,0 ;AN041; APPEND just executed?
|
||
jnz dont_set_io ;AN041; Yes - this junk is already set
|
||
invoke ioset ; re-direct the ol' i/o
|
||
|
||
dont_set_io: ;AN041;
|
||
;
|
||
; Check for /?. Certain commands, flagged fLimitHelp,
|
||
; respond to /? only if it is the only command-line argument.
|
||
;
|
||
mov ax,[COMSW] ; AX = switches after command
|
||
or ax,[ALLSWITCH] ; AX = all switches
|
||
and ax,SwitchQues
|
||
jz drive_check ; /? not in command line
|
||
|
||
test [CHKDRV],fLimitHelp
|
||
jz do_help ; /? allowed in combination
|
||
;
|
||
; Make sure /? is the only argument on the command line.
|
||
;
|
||
cmp [arg.argvcnt],2
|
||
jne drive_check ; /? not only arg - ignore
|
||
;
|
||
; Note: this is all the check we need, even against things like /??.
|
||
; Our argv parser breaks /?? into two args, /? and ?.
|
||
;
|
||
|
||
do_help:
|
||
|
||
; DX = ptr to word list of msg #s, terminated by zero word
|
||
|
||
mov si,dx ; SI = ptr to list of msg #s
|
||
mov ax,NO_SUBST ; AL = no subst's code
|
||
push ax ; build subst block on stack
|
||
|
||
next_help_msg:
|
||
lodsw ; AX = help msg # or zero
|
||
or ax,ax
|
||
jz help_done
|
||
push ax ; SS:SP = ptr to subst block
|
||
; (msg # and no_subst byte)
|
||
; We assume DS = SS.
|
||
|
||
mov dx,sp ; DS:DX = ptr to subst block
|
||
invoke Std_PrintF ; display help message
|
||
pop ax ; remove msg # from stack
|
||
jmp next_help_msg
|
||
|
||
help_done:
|
||
pop ax ; clean up stack
|
||
jmp TCommand
|
||
|
||
drive_check:
|
||
test [CHKDRV], fCheckDrive ; did we wanna check those drives?
|
||
jz nocheck
|
||
mov AL, [PARM1] ; parse_file_descriptor results tell
|
||
or AL, [PARM2] ; us whether those drives were OK
|
||
cmp AL, -1
|
||
jnz nocheck
|
||
jmp drvbad
|
||
|
||
|
||
;
|
||
; The user may have omitted the space between the command and its arguments.
|
||
; We need to copy the remainder of the user's command line into the buffer.
|
||
; Note that thisdoes not mess up the arg structure; it points into COMBUF not
|
||
; into the command line at 80.
|
||
;
|
||
nocheck:
|
||
call cmd_copy
|
||
|
||
switcheck:
|
||
test [CHKDRV], fSwitchAllowed ; Does the command take switches
|
||
jnz realwork ; Yes, process the command
|
||
call noswit ; No, check to see if any switches
|
||
jnz realwork ; None, process the command
|
||
mov msg_disp_class,parse_msg_class ;AN000; set up parse error msg class
|
||
MOV DX,OFFSET TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
|
||
mov Extend_Buf_ptr,BadSwt_ptr ;AN000; get "Invalid switch" message number
|
||
jmp CERROR ; Print error and chill out...
|
||
realwork:
|
||
call BX ; do some real work, at last
|
||
|
||
; See if we're in a batch CALL command. If we are, reprocess the command line,
|
||
; otherwise, go get another command.
|
||
|
||
Cmd_done:
|
||
push cs ; g restore data segment
|
||
pop ds ; g
|
||
push ds ; g save data segment
|
||
mov ds,[resseg] ; g get segment containing call flag
|
||
ASSUME ds:resgroup
|
||
cmp call_flag, call_in_progress ; G Is a call in progress?
|
||
mov call_flag, 0 ; G Either way, reset flag
|
||
pop ds ; g get data segment back
|
||
jz incall ; G
|
||
jmp tcommand ; chill out...
|
||
|
||
incall:
|
||
JMP DOCOM1
|
||
|
||
noswit:
|
||
push di ; Save di
|
||
mov di,81h ; di = ptr to command args
|
||
mov si,80h ; Get address of length of command args
|
||
lodsb ; Load length
|
||
mov cl,al ; Move length to cl
|
||
xor ch,ch ; Zero ch
|
||
mov al,[SWITCHAR] ; al = switch character
|
||
cmp al,0 ; Turn off ZF
|
||
repnz scasb ; Scan for a switch character and return
|
||
pop di ; with ZF set if one was found
|
||
ret
|
||
|
||
EXTERNAL:
|
||
|
||
ifndef NEC_98
|
||
IF IBM
|
||
call test_append ; check to see if append installed
|
||
je not_barryf ; no - truly external command
|
||
jmp append_internal ; yes - go to Barryf code
|
||
|
||
not_barryf:
|
||
|
||
ENDIF
|
||
else ;NEC_98
|
||
call test_append ; check to see if append installed
|
||
je not_barryf ; no - truly external command
|
||
jmp append_internal ; yes - go to Barryf code
|
||
|
||
not_barryf:
|
||
|
||
endif ;NEC_98
|
||
|
||
MOV [FILTYP],0
|
||
MOV DL,[SPECDRV]
|
||
MOV [IDLEN],DL
|
||
IF IBM
|
||
MOV [ROM_CALL],0
|
||
PUSH DX
|
||
MOV DX,OFFSET TRANGROUP:IDLEN
|
||
CALL ROM_SCAN
|
||
POP DX
|
||
JNC DO_SCAN
|
||
INC [ROM_CALL]
|
||
JMP short PostSave
|
||
DO_SCAN:
|
||
ENDIF
|
||
IF IBM
|
||
PostSave:
|
||
ENDIF
|
||
|
||
;
|
||
; when ntvdm execs via GetNextVdmCommand, execpath is already
|
||
; fully qualified application name. We know this because the
|
||
; vdminfo is filled
|
||
;
|
||
; Note that EXECPATH_SIZE is used only once(the one we got it from
|
||
; CMDGETNEXTCMD bop). And that is why we reset it everytime after
|
||
; we have accessed it. For other executables, we do the regular
|
||
; search(processing a batch file, for example).
|
||
;
|
||
; Two pieces of information we got from 32bits:
|
||
; (1). the application full path name(in EXECPATH)
|
||
; (2). the application file extention type(in EXECEXT_TYPE)
|
||
; EXECEXT_TYPE 2 -> .BAT
|
||
; 4 -> .EXE
|
||
; 8 -> .COM
|
||
; >8 -> unknown
|
||
; for unknown extention type, we simply launch it because
|
||
; (1). DOS doesn't impose any extention on program file.
|
||
; (2). If we ever get here, we are sure that the program file
|
||
; is a valid DOS executable(otherwise, CreateProcess would
|
||
; have failed and we won't have any file to execute).
|
||
;
|
||
;
|
||
|
||
xor ax, ax
|
||
xchg ax, [EXECPATH_SIZE] ;get and set
|
||
or ax, ax ;do we have appname already?
|
||
mov ax, [EXECEXT_TYPE] ;
|
||
jnz execute_with_type ;yes, No search
|
||
|
||
MOV DI,OFFSET TRANGROUP:EXECPATH
|
||
MOV BYTE PTR [DI],0 ; Initialize to current directory
|
||
IF IBM
|
||
CMP [ROM_CALL],0
|
||
JNZ NeoExecute
|
||
ENDIF
|
||
invoke path_search ; find the mother (result in execpath)
|
||
|
||
execute_with_type:
|
||
or AX, AX ; did we find anything?
|
||
je badcomj45 ; null means no (sob)
|
||
cmp AX, 04H ; 04H and 08H are .exe and .com
|
||
; sixteen-bit machine ought
|
||
jnl execute ; to be able to handle a SIXTEEN-BIT
|
||
; DISPLACEMENT!!
|
||
jmp batcom ; 02H is .bat
|
||
BADCOMJ45:
|
||
ifdef BETA3WARN
|
||
JMP BADCOM
|
||
else
|
||
JMP short BADCOM
|
||
endif
|
||
|
||
ASSUME DS:TRANGROUP,ES:TRANGROUP
|
||
|
||
EXECUTE:
|
||
NeoExecute:
|
||
invoke IOSET
|
||
;M051
|
||
; Previously LoadHigh was jumping to the execute label above. This was wrong
|
||
;because IOSET was getting invoked twice resulting in 2 sets of redirections.
|
||
;After a close, this would still leave one open active resulting in sharing
|
||
;errors on subsequent opens of the redirected file.
|
||
;
|
||
Lh_Execute: ;M051
|
||
|
||
MOV ES,[TRAN_TPA]
|
||
MOV AH,DEALLOC
|
||
INT 21h ; Now running in "free" space
|
||
MOV ES,[RESSEG]
|
||
ASSUME ES:RESGROUP
|
||
INC [EXTCOM] ; Indicate external command
|
||
MOV [RESTDIR],0 ; Since USERDIR1 is in transient, insure
|
||
; this flag value for re-entry to COMMAND
|
||
MOV SI,OFFSET TRANGROUP:EXECPATH
|
||
MOV DI,OFFSET RESGROUP:SAFEPATHBUFFER
|
||
MOV CX,LenMsgOrPathBuf
|
||
CLD
|
||
LE_copy_loop:
|
||
lodsb
|
||
stosb
|
||
cmp al, 0
|
||
je LE_copy_done
|
||
loop LE_copy_loop
|
||
;; the program name is too long, terminate it with
|
||
;; null character. The Exec call will fail and we will print out error message
|
||
;; see command1.asm
|
||
mov byte ptr es:[di - 1], 0
|
||
LE_copy_done:
|
||
|
||
MOV DI,FCB
|
||
MOV SI,DI
|
||
MOV CX,052H ; moving (100h-5Ch)/2 = 80h-2Eh
|
||
REP MOVSW ; Transfer parameters to resident header
|
||
MOV DX,OFFSET RESGROUP:SAFEPATHBUFFER
|
||
PUSH ES
|
||
POP DS
|
||
ASSUME DS:RESGROUP
|
||
MOV BX,OFFSET RESGROUP:EXEC_BLOCK
|
||
MOV AX,EXEC SHL 8
|
||
IF IBM
|
||
TEST [ROM_CALL],-1
|
||
JZ OK_EXEC
|
||
JMP ROM_EXEC
|
||
OK_EXEC:
|
||
ENDIF
|
||
;
|
||
; we are now running in free space. anything we do from here on may get
|
||
; trashed. Move the stack (also in free space) to allocated space because
|
||
; since EXEC restores the stack, somebody may trash what is on the stack.
|
||
;
|
||
MOV CX,ES
|
||
MOV SS,CX
|
||
MOV SP,OFFSET DATARES:RStack
|
||
|
||
ifdef BETA3WARN
|
||
%out Take this out before we ship
|
||
|
||
cmp Beta3Warned, 0
|
||
jne NoWarning
|
||
mov Beta3Warned, 0ffh
|
||
push ax
|
||
push cx
|
||
push dx
|
||
push ds
|
||
|
||
mov ah, 2ah ; get date
|
||
int 21h
|
||
cmp cx, 1991
|
||
jb nwx
|
||
ja bwarn
|
||
|
||
cmp dh, 4
|
||
jb nwx
|
||
bwarn:
|
||
mov ds, trnseg
|
||
assume ds:trangroup
|
||
mov dx, offset trangroup:Beta3WarnMsg
|
||
mov ah, 9
|
||
int 21h
|
||
|
||
; wait till a key is hit
|
||
|
||
@@:
|
||
mov ah, 6 ; console I/O
|
||
mov dl, 0ffh ; Read
|
||
int 21h
|
||
jz @b
|
||
nwx:
|
||
pop ds
|
||
assume ds:resgroup
|
||
pop dx
|
||
pop cx
|
||
pop ax
|
||
NoWarning:
|
||
endif
|
||
JMP [EXEC_ADDR] ; Jmp to the EXEC in the resident
|
||
|
||
ASSUME DS:TRANGROUP
|
||
BADCOM:
|
||
PUSH CS
|
||
POP DS
|
||
MOV DX,OFFSET TRANGROUP:BADNAM_ptr
|
||
|
||
CERROR:
|
||
INVOKE std_eprintf
|
||
JMP TCOMMAND
|
||
|
||
;
|
||
; Prescan converts the input buffer into a canonicalized form. All
|
||
; redirections and pipes are removed.
|
||
;
|
||
PRESCAN: ; Cook the input buffer
|
||
|
||
ASSUME DS:TRANGROUP,ES:TRANGROUP
|
||
|
||
XOR CX,CX
|
||
MOV ES,[RESSEG]
|
||
ASSUME ES:RESGROUP
|
||
MOV SI,OFFSET TRANGROUP:COMBUF+2
|
||
MOV DI,SI
|
||
|
||
CountQuotes:
|
||
LODSB ; get a byte
|
||
CMP AL,22h ; is it a quote?
|
||
JNZ CountEnd ; no, try for end of road
|
||
INC CH ; bump count
|
||
JMP CountQuotes ; go get next char
|
||
|
||
CountEnd:
|
||
CMP AL,13 ; end of road?
|
||
JNZ CountQuotes ; no, go back for next char
|
||
|
||
;;;; IFDEF DBCS 3/3/KK
|
||
PUSH CX ; save count
|
||
MOV SI,DI ; get back beginning of buffer
|
||
|
||
KanjiScan:
|
||
LODSB ; get a byte
|
||
INVOKE TestKanj ; is it a leadin byte
|
||
JZ KanjiQuote ; no, check for quotes
|
||
ifdef NEC_98
|
||
if BUGFIX
|
||
cmp byte ptr [si],' '
|
||
jb kanjiQuote
|
||
endif
|
||
endif ;NEC_98
|
||
MOV AH,AL ; save leadin
|
||
LODSB ; get trailing byte
|
||
CMP AX,DB_SPACE ; is it Kanji space
|
||
JNZ KanjiScan ; no, go get next
|
||
MOV [SI-2],2020h ; replace with spaces
|
||
JMP KanjiScan ; go get next char
|
||
|
||
KanjiQuote:
|
||
CMP AL,22h ; beginning of quoted string
|
||
JNZ KanjiEnd ; no, check for end
|
||
DEC CH ; drop count
|
||
JZ KanjiScan ; if count is zero, no quoting
|
||
|
||
KanjiQuoteLoop:
|
||
LODSB ; get next byte
|
||
CMP AL,22h ; is it another quote
|
||
JNZ KanjiQuoteLoop ; no, get another
|
||
DEC CH ; yes, drop count
|
||
JMP KanjiScan ; go get next char
|
||
|
||
KanjiEnd:
|
||
CMP AL,13 ; end of line character?
|
||
JNZ KanjiScan ; go back to beginning
|
||
POP CX ; get back original count
|
||
;;;; ENDIF 3/3/KK
|
||
|
||
MOV SI,DI ; restore pointer to begining
|
||
|
||
PRESCANLP:
|
||
LODSB
|
||
|
||
;;;; IFDEF DBCS 3/3/KK
|
||
INVOKE TESTKANJ
|
||
JZ NOTKANJ6
|
||
ifdef NEC_98
|
||
if BUGFIX
|
||
cmp byte ptr [si],' '
|
||
jb NOTKANJ6
|
||
endif
|
||
endif ;NEC_98
|
||
MOV [DI],AL
|
||
INC DI ; fake STOSB into DS
|
||
LODSB ; grab second byte
|
||
MOV [DI],AL ; fake stosb into DS
|
||
INC DI
|
||
INC CL
|
||
INC CL
|
||
JMP PRESCANLP
|
||
|
||
NOTKANJ6:
|
||
;;;; ENDIF 3/3/KK
|
||
|
||
CMP AL,'"' ; " character
|
||
JNZ TRYGREATER
|
||
DEC CH
|
||
JZ TRYGREATER
|
||
|
||
QLOOP:
|
||
MOV [DI],AL
|
||
INC DI
|
||
INC CL
|
||
LODSB
|
||
CMP AL,'"' ; " character
|
||
JNZ QLOOP
|
||
DEC CH
|
||
|
||
TRYGREATER:
|
||
CMP AL,rabracket
|
||
JNZ NOOUT
|
||
;
|
||
; We have found a ">" char. We need to see if there is another ">"
|
||
; following it.
|
||
;
|
||
CMP BYTE PTR [SI],al
|
||
JNZ NOAPPND
|
||
LODSB
|
||
INC [RE_OUT_APP] ; Flag >>
|
||
|
||
NOAPPND:
|
||
;
|
||
; Now we attempt to find the file name. First, scan off all whitespace
|
||
;
|
||
INVOKE SCANOFF
|
||
CMP AL,labracket ;AN040; was there no filename?
|
||
JZ REOUT_ERRSET ;AN040; yes - set up error
|
||
CMP AL,0DH
|
||
JNZ GOTREOFIL
|
||
;
|
||
; There was no file present. Set us up at end-of-line.
|
||
;
|
||
REOUT_ERRSET: ;AN040; set up for an error
|
||
mov byte ptr [di], 0dh ; Clobber first ">"
|
||
MOV WORD PTR [RE_OUTSTR],09H ; Cause an error later
|
||
JMP PRESCANEND
|
||
|
||
GOTREOFIL:
|
||
PUSH DI
|
||
MOV DI,OFFSET RESGROUP:RE_OUTSTR
|
||
MOV BX,DI
|
||
PUSH ES
|
||
|
||
SETREOUTSTR: ; Get the output redirection name
|
||
|
||
; MSKK06 07/14/89
|
||
push cx ; save cx
|
||
mov cx,64+13 ; CX = max string length
|
||
|
||
SETREOUTSTR_LOOP:
|
||
|
||
LODSB
|
||
CMP AL,0DH
|
||
JZ GOTRESTR_J
|
||
INVOKE DELIM
|
||
JZ GOTRESTR_J
|
||
CMP AL,[SWITCHAR]
|
||
JZ GOTRESTR_J
|
||
CMP AL,'"' ;AN033; Is the character a quote?
|
||
JZ PIPEERRSYNJ5_J ;AN033; Yes - get out quick - or system crashes
|
||
CMP AL,labracket ;AN002; Is char for input redirection
|
||
JZ ABRACKET_TERM ;AN002; yes - end of string
|
||
CMP AL,rabracket ;AN002; Is char for output redirection
|
||
JNZ NO_ABRACKET ;AN002; no - not end of string
|
||
|
||
ABRACKET_TERM: ;AN002; have end of string by < or >
|
||
DEC SI ;AN002; back up over symbol
|
||
MOV AL,BLANK ;AN002; show delimiter as char
|
||
GOTRESTR_J:
|
||
pop cx ; MSKK06 07/14/89
|
||
JMP SHORT GOTRESTR ;AN002; go process it
|
||
|
||
NO_ABRACKET: ;AN002; NOT AT END OF STRING
|
||
STOSB ; store it into resgroup
|
||
|
||
ifdef DBCS
|
||
invoke testkanj
|
||
jz @f ; if not lead byte of DBCS
|
||
jcxz gotrestr_j ; if no tail byte
|
||
lodsb
|
||
cmp al,0dh
|
||
jz gotrestr_j ; if tail byte does't come and ends
|
||
stosb ; copy tail byte
|
||
dec cx
|
||
@@:
|
||
endif
|
||
|
||
LOOP SETREOUTSTR_LOOP ; MSKK06 07/14/89
|
||
jmp GOTRESTR_j
|
||
|
||
PIPEERRSYNJ5_J:
|
||
pop cx ; recover CX
|
||
jmp short PIPEERRSYNJ5
|
||
|
||
NOOUT:
|
||
CMP AL,labracket
|
||
JNZ CHKPIPE
|
||
mov bx,si ; Save loc of "<"
|
||
INVOKE SCANOFF
|
||
CMP AL,rabracket ;AN040; was there no filename?
|
||
JZ REIN_ERRSET ;AN040; yes - set up error
|
||
CMP AL,0DH
|
||
JNZ GOTREIFIL
|
||
|
||
REIN_ERRSET: ;AN040; set up for error
|
||
mov byte ptr [di],0dh ; Clobber "<"
|
||
MOV WORD PTR [RE_INSTR],09H ; Cause an error later
|
||
JMP SHORT PRESCANEND
|
||
|
||
GOTREIFIL:
|
||
PUSH DI
|
||
MOV DI,OFFSET TranGROUP:RE_INSTR
|
||
MOV BX,DI
|
||
PUSH ES
|
||
PUSH CS
|
||
POP ES ; store in TRANGROUP
|
||
JMP SHORT SETREOUTSTR ; Get the input redirection name
|
||
|
||
CHKPIPE:
|
||
MOV AH,AL
|
||
CMP AH,AltPipeChr
|
||
JZ IsPipe3
|
||
CMP AH,vbar
|
||
JNZ CONTPRESCAN
|
||
|
||
IsPipe3:
|
||
;
|
||
; Only push the echo flag if we are entering the pipe for the first time.
|
||
;
|
||
CMP PipeFlag,0
|
||
JNZ NoEchoPush
|
||
SHL EchoFlag,1 ; push echo state and turn it off
|
||
NoEchoPush:
|
||
INC [PIPEFLAG]
|
||
INVOKE SCANOFF
|
||
CMP AL,0DH
|
||
JZ PIPEERRSYNJ5
|
||
CMP AL,AltPipeChr
|
||
JZ PIPEERRSYNJ5
|
||
CMP AL,vbar ; Double '|'?
|
||
JNZ CONTPRESCAN
|
||
|
||
PIPEERRSYNJ5:
|
||
PUSH ES
|
||
POP DS ; DS->RESGROUP
|
||
JMP PIPEERRSYN
|
||
|
||
;
|
||
; Trailing :s are allowed on devices. Check to be sure that there is more
|
||
; than just a : in the redir string.
|
||
;
|
||
GOTRESTR:
|
||
XCHG AH,AL
|
||
mov al,':'
|
||
SUB BX,DI ; compute negatinve of number of chars
|
||
CMP BX,-1 ; is there just a :?
|
||
JZ NotTrailCol ; yep, don't change
|
||
CMP BYTE PTR ES:[DI-1],al ; Trailing ':' OK on devices
|
||
JNZ NOTTRAILCOL
|
||
DEC DI ; Back up over trailing ':'
|
||
|
||
NOTTRAILCOL:
|
||
XOR AL,AL
|
||
STOSB ; NUL terminate the string
|
||
POP ES
|
||
POP DI ; Remember the start
|
||
|
||
CONTPRESCAN:
|
||
MOV [DI],AH ; "delete" the redirection string
|
||
INC DI
|
||
CMP AH,0DH
|
||
JZ PRESCANEND
|
||
INC CL
|
||
JMP PRESCANLP
|
||
|
||
PRESCANEND:
|
||
CMP [PIPEFLAG],0
|
||
JZ ISNOPIPE
|
||
MOV DI,OFFSET RESGROUP:PIPESTR
|
||
MOV [PIPEPTR],DI
|
||
MOV SI,OFFSET TRANGROUP:COMBUF+2
|
||
INVOKE SCANOFF
|
||
|
||
PIPESETLP: ; Transfer the pipe into the resident
|
||
LODSB ; pipe buffer
|
||
STOSB
|
||
CMP AL,0DH
|
||
JNZ PIPESETLP
|
||
|
||
ISNOPIPE:
|
||
MOV [COMBUF+1],CL
|
||
CMP [PIPEFLAG],0
|
||
PUSH CS
|
||
POP ES
|
||
return
|
||
|
||
cmd_copy proc near
|
||
|
||
MOV SI,OFFSET TRANGROUP:COMBUF+2
|
||
INVOKE Scanoff ; advance past separators...
|
||
add si,PathPos
|
||
mov di,81h
|
||
xor cx,cx
|
||
|
||
CmdCopy:
|
||
lodsb
|
||
stosb
|
||
cmp al,0dh
|
||
jz CopyDone
|
||
inc cx
|
||
jmp CmdCopy
|
||
|
||
CopyDone:
|
||
mov byte ptr ds:[80h],cl ; Store count
|
||
|
||
ret
|
||
cmd_copy endp
|
||
|
||
|
||
test_append proc near
|
||
|
||
mov BX,offset TRANGROUP:COMBUF ; barry can address
|
||
mov SI, offset TRANGROUP:IDLEN ; address command name, DS already set
|
||
mov DX,-1 ; set install check function
|
||
mov AX,0AE00H
|
||
int 2FH ; see if loaded
|
||
cmp AL,00H
|
||
|
||
ret
|
||
|
||
test_append endp
|
||
|
||
TRANCODE ENDS
|
||
END
|
||
|