You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
436 lines
9.9 KiB
436 lines
9.9 KiB
page ,132
|
|
;/*
|
|
; * Microsoft Confidential
|
|
; * Copyright (C) Microsoft Corporation 1991
|
|
; * All Rights Reserved.
|
|
; */
|
|
; SCCSID = @(#)cparse.asm 1.1 85/05/14
|
|
; SCCSID = @(#)cparse.asm 1.1 85/05/14
|
|
INCLUDE comsw.asm
|
|
|
|
.xlist
|
|
.xcref
|
|
INCLUDE DOSSYM.INC
|
|
INCLUDE DEVSYM.INC
|
|
INCLUDE comseg.asm
|
|
INCLUDE comequ.asm
|
|
.list
|
|
.cref
|
|
|
|
|
|
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
|
|
EXTRN BADCD_PTR:WORD ;AC022;
|
|
EXTRN BADCPMES_ptr:word ;AC000;
|
|
TRANDATA ENDS
|
|
|
|
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
|
|
EXTRN comma:byte
|
|
EXTRN cpyflag:byte
|
|
EXTRN CURDRV:BYTE
|
|
EXTRN ELCNT:BYTE
|
|
EXTRN ELPOS:BYTE
|
|
EXTRN EXPAND_STAR:BYTE
|
|
EXTRN SKPDEL:BYTE
|
|
EXTRN STARTEL:WORD
|
|
EXTRN SWITCHAR:BYTE
|
|
EXTRN switch_list:byte
|
|
EXTRN TPA:WORD
|
|
TRANSPACE ENDS
|
|
|
|
TRANCODE SEGMENT PUBLIC BYTE
|
|
|
|
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING
|
|
|
|
EXTRN CERROR:NEAR
|
|
|
|
PUBLIC BADCDERR ;AC022;
|
|
PUBLIC CPARSE
|
|
|
|
SWCOUNT EQU 6 ; Must agree with length of switch_list
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; ENTRY: ;
|
|
; DS:SI Points input buffer ;
|
|
; ES:DI Points to the token buffer ;
|
|
; BL Special delimiter for this call ;
|
|
; Always checked last ;
|
|
; set it to space if there is no special delimiter ;
|
|
; EXIT: ;
|
|
; DS:SI Points to next char in the input buffer ;
|
|
; ES:DI Points to the token buffer ;
|
|
; [STARTEL] Points to start of last element of path in token ;
|
|
; points to a NUL for no element strings 'd:' 'd:/' ;
|
|
; CX Character count ;
|
|
; BH Condition Code ;
|
|
; Bit 1H of BH set if switch character ;
|
|
; Token buffer contains char after ;
|
|
; switch character ;
|
|
; BP has switch bits set (ORing only) ;
|
|
; Bit 2H of BH set if ? or * in token ;
|
|
; if * found element ? filled ;
|
|
; Bit 4H of BH set if path sep in token ;
|
|
; Bit 80H of BH set if the special delimiter ;
|
|
; was skipped at the start of this token ;
|
|
; Token buffer always starts d: for non switch tokens ;
|
|
; CARRY SET ;
|
|
; if CR on input ;
|
|
; token buffer not altered ;
|
|
; ;
|
|
; DOES NOT RETURN ON BAD PATH, OR TRAILING SWITCH CHAR ERROR ;
|
|
; MODIFIES: ;
|
|
; CX, SI, AX, BH, DX and the Carry Flag ; ;
|
|
; ;
|
|
; -----------------------------------------------------------------------;
|
|
;---------------
|
|
; Modifications to cparse: recognition of right and left parentheses
|
|
; as integral tokens, and removal of automatic upper-case conversion code.
|
|
;
|
|
; Both modifications were installed in the course of adding a coherent
|
|
; command-line parser to COMMAND.COM which builds a UNIX-style argv[]/argc
|
|
; structure for command-line arguments. This parser relies on cparse to
|
|
; recognize individual tokens.
|
|
;
|
|
; To process for-loops correctly, parentheses must therefore be
|
|
; recognized as tokens. The upper-case conversion code was removed so
|
|
; that commands (such as for and echo) would be able to use the "original"
|
|
; text of the command line.
|
|
;
|
|
; Note also the modification to prevent the automatic conversion of colons
|
|
; into spaces WITHIN THE SOURCE TEXT!
|
|
;
|
|
; Also note that BP is also clobbered if cparse recognizes any switches
|
|
; on the command line.
|
|
;
|
|
; Alan L, OS/MSDOS 14 August 1983
|
|
;---------------
|
|
|
|
CPARSE:
|
|
ASSUME DS:TRANGROUP,ES:TRANGROUP
|
|
|
|
xor ax,ax
|
|
mov [STARTEL],DI ; No path element (Is DI correct?)
|
|
mov [ELPOS],al ; Start in 8 char prefix
|
|
mov [SKPDEL],al ; No skip delimiter yet
|
|
mov bh,al ; Init nothing
|
|
pushf ; save flags
|
|
push di ; save the token buffer addrss
|
|
xor cx,cx ; no chars in token buffer
|
|
mov comma,cl ;g reset comma flag
|
|
moredelim:
|
|
LODSB
|
|
INVOKE DELIM
|
|
JNZ SCANCDONE
|
|
CMP AL,' '
|
|
JZ moredelim
|
|
CMP AL,9
|
|
JZ moredelim
|
|
xchg al,[SKPDEL]
|
|
or al,al
|
|
jz moredelim ; One non space/tab delimiter allowed
|
|
test bh,080h ;g has a special char been found?
|
|
jz no_comma ;g no - just exit
|
|
mov comma,1 ;g set comma flag
|
|
no_comma:
|
|
JMP x_done ; Nul argument
|
|
|
|
SCANCDONE:
|
|
|
|
;;;; IFNDEF DBCS 3/3/KK
|
|
;---------------
|
|
; Mod to avoid upper-case conversion.
|
|
; cmp cpyflag,1 3/3/KK
|
|
; jnz cpcont1 3/3/KK
|
|
; invoke UPCONV 3/3/KK
|
|
cpcont1:
|
|
;---------------
|
|
;;;; ENDIF 3/3/KK
|
|
|
|
cmp al,bl ; Special delimiter?
|
|
jnz nospec
|
|
or bh,80H
|
|
jmp short moredelim
|
|
|
|
nospec:
|
|
cmp al,0DH ; a CR?
|
|
jne ncperror
|
|
jmp cperror
|
|
|
|
ncperror:
|
|
cmp al,[SWITCHAR] ; is the char the switch char?
|
|
jne na_switch ; yes, process...
|
|
jmp a_switch
|
|
|
|
na_switch:
|
|
mov dl,':'
|
|
cmp byte ptr [si],dl
|
|
jne anum_chard ; Drive not specified
|
|
|
|
;;;; IFDEF DBCS 3/3/KK
|
|
;---------------
|
|
; Mod to avoid upper-case conversion.
|
|
cmp cpyflag,1
|
|
jnz cpcont2
|
|
invoke UPCONV
|
|
cpcont2:
|
|
;---------------
|
|
;;;; ENDIF 3/3/KK
|
|
|
|
call move_char
|
|
lodsb ; Get the ':'
|
|
call move_char
|
|
mov [STARTEL],di
|
|
mov [ELCNT],0
|
|
jmp anum_test
|
|
|
|
anum_chard:
|
|
mov [STARTEL],di
|
|
mov [ELCNT],0 ; Store of this char sets it to one
|
|
cmp cpyflag,1 ; Was CPARSE called from COPY?
|
|
jnz anum_char ; No, don't add drive spec.
|
|
invoke PATHCHRCMP ; Starts with a pathchar?
|
|
jnz anum_char ; no
|
|
push ax
|
|
mov al,[CURDRV] ; Insert drive spec
|
|
add al,capital_A
|
|
call move_char
|
|
mov al,':'
|
|
call move_char
|
|
pop ax
|
|
mov [STARTEL],di
|
|
mov [ELCNT],0
|
|
|
|
anum_char:
|
|
|
|
;;;; IFDEF DBCS 3/3/KK
|
|
invoke TESTKANJ
|
|
jz NOTKANJ ;AC048;
|
|
ifdef NEC_98
|
|
if BUGFIX
|
|
|
|
cmp byte ptr [si],' '
|
|
jb NOTKANJ
|
|
endif
|
|
endif ;NEC_98
|
|
call move_char
|
|
lodsb
|
|
jmp short notspecial
|
|
|
|
NOTKANJ: ;AN048; If not kanji
|
|
cmp cpyflag,1 ;AN048; and if we're in COPY
|
|
jnz testdot ;AN048;
|
|
invoke upconv ;AN048; upper case the char
|
|
|
|
TESTDOT:
|
|
;;;; ENDIF 3/3/KK
|
|
|
|
cmp al,dot_chr
|
|
jnz testquest
|
|
inc [ELPOS] ; flag in extension
|
|
mov [ELCNT],0FFH ; Store of the '.' resets it to 0
|
|
|
|
testquest:
|
|
cmp al,'?'
|
|
jnz testsplat
|
|
or bh,2
|
|
|
|
testsplat:
|
|
cmp al,star
|
|
jnz testpath
|
|
or bh,2
|
|
cmp byte ptr [expand_star],0
|
|
jnz expand_filename
|
|
jmp SHORT testpath
|
|
|
|
badperr2j:
|
|
jmp short badperr2
|
|
|
|
expand_filename:
|
|
mov ah,7
|
|
cmp [ELPOS],0
|
|
jz gotelcnt
|
|
mov ah,2
|
|
|
|
gotelcnt:
|
|
mov al,'?'
|
|
sub ah,[ELCNT]
|
|
jc badperr2j
|
|
xchg ah,cl
|
|
jcxz testpathx
|
|
|
|
qmove:
|
|
xchg ah,cl
|
|
call move_char
|
|
xchg ah,cl
|
|
loop qmove
|
|
|
|
testpathx:
|
|
xchg ah,cl
|
|
|
|
testpath:
|
|
invoke PATHCHRCMP
|
|
jnz notspecial
|
|
or bh,4
|
|
cmp byte ptr [expand_star],0
|
|
jz no_err_check
|
|
test bh,2 ; If just hit a '/', cannot have ? or * yet
|
|
jnz badperr
|
|
|
|
no_err_check:
|
|
mov [STARTEL],di ; New element
|
|
INC [STARTEL] ; Point to char after /
|
|
mov [ELCNT],0FFH ; Store of '/' sets it to 0
|
|
mov [ELPOS],0
|
|
|
|
notspecial:
|
|
call move_char ; just an alphanum string
|
|
anum_test:
|
|
|
|
lodsb
|
|
|
|
;;;; IFNDEF DBCS 3/3/KK
|
|
;---------------
|
|
; Mod to avoid upper-case conversion.
|
|
; cmp cpyflag,1 3/3/KK
|
|
; jnz cpcont3 3/3/KK
|
|
; invoke UPCONV 3/3/KK
|
|
cpcont3:
|
|
;---------------
|
|
;;;; ENDIF 3/3/KK
|
|
|
|
INVOKE DELIM
|
|
je x_done
|
|
|
|
cmp al,0DH
|
|
je x_done
|
|
cmp al,[SWITCHAR]
|
|
je x_done
|
|
cmp al,bl
|
|
je x_done
|
|
cmp al,':' ; ':' allowed as trailer because
|
|
; of devices
|
|
;;;; IFDEF DBCS 3/3/KK
|
|
je FOO15
|
|
jmp anum_char
|
|
FOO15:
|
|
;;; ELSE 3/3/KK
|
|
;;; jne anum_charj 3/3/KK
|
|
;;; ENDIF 3/3/KK
|
|
|
|
;---------------
|
|
; Modification made for parseline.
|
|
; Why would it be necessary to change colons to spaces? In this
|
|
; case, EVERY colon is changed to a space; e.g., 'f:' yields 'f ',
|
|
; but so does 'echo foo:bar' yield 'echo foo bar'.
|
|
;---------------
|
|
cmp cpyflag,2 ; Is CPARSE parsing the 1st token from
|
|
; from PARSELINE?
|
|
jnz cpcont4 ; No, continue
|
|
call move_char ; Yes, save the ':' and go get another
|
|
jmp anum_test ; character.
|
|
|
|
cpcont4:
|
|
inc si ;Skip the ':'
|
|
jmp short x_done
|
|
|
|
anum_charj:
|
|
jmp anum_char
|
|
|
|
badperr2:
|
|
mov dx,offset trangroup:BADCPMES_ptr
|
|
jmp CERROR
|
|
|
|
badperr:
|
|
BADCDERR: ;AC022; Issue "Invalid Directory"
|
|
MOV DX,OFFSET TRANGROUP:BADCD_ptr ;AC022; message
|
|
JMP CERROR ;AC022;
|
|
|
|
cperror:
|
|
dec si ; adjust the pointer
|
|
pop di ; retrive token buffer address
|
|
popf ; restore flags
|
|
stc ; set the carry bit
|
|
return
|
|
|
|
x_done:
|
|
dec si ; adjust for next round
|
|
;---------------
|
|
; Mod to recognize right and left parens as integral tokens.
|
|
x_done2:
|
|
;---------------
|
|
jmp short out_token
|
|
|
|
a_switch:
|
|
OR BH,1 ; Indicate switch
|
|
OR BP,fSwitch
|
|
INVOKE SCANOFF
|
|
INC SI
|
|
invoke testkanj ;AN057; See if DBCS lead byte
|
|
jz a_switch_notkanj ;AN057; no - continue processing
|
|
ifdef NEC_98
|
|
if BUGFIX
|
|
cmp byte ptr [si],' '
|
|
jb a_switch_notkanj ;AN057; no - continue processing
|
|
endif
|
|
endif ;NEC_98
|
|
call move_char ;AN057; DBCS - store first byte
|
|
lodsb ;AN057; get second byte
|
|
call move_char ;AN057; store second byte
|
|
or bp,fBadSwitch ;AN057; DBCS switch is invalid
|
|
jmp short out_token ;AN057; don't bother checking switch
|
|
a_switch_notkanj: ;AN057;
|
|
cmp al,0DH
|
|
jne Store_swt
|
|
mov al,0
|
|
stosb ; null at the end
|
|
OR BP,fBadSwitch
|
|
jmp cperror ; Trailing switch character error
|
|
; BP = fSwitch but no switch
|
|
; bit is set (unknown switch)
|
|
Store_swt:
|
|
call move_char ; store the character
|
|
;
|
|
;---------------
|
|
; This upconv call must stay. It is used to identify copy-switches
|
|
; on the command line, and won't store anything into the output buffer.
|
|
invoke UPCONV
|
|
;---------------
|
|
;
|
|
PUSH ES
|
|
PUSH DI
|
|
PUSH CX
|
|
PUSH CS
|
|
POP ES
|
|
ASSUME ES:TRANGROUP
|
|
MOV DI,OFFSET TRANGROUP:switch_list
|
|
MOV CX,SWCOUNT
|
|
OR BP,fBadSwitch
|
|
REPNE SCASB
|
|
JNZ out_tokenp
|
|
AND BP,NOT fBadSwitch
|
|
MOV AX,1
|
|
SHL AX,CL
|
|
OR BP,AX
|
|
|
|
out_tokenp:
|
|
POP CX
|
|
POP DI
|
|
POP ES
|
|
|
|
ASSUME ES:NOTHING
|
|
out_token:
|
|
mov al,0
|
|
stosb ; null at the end
|
|
pop di ; restore token buffer pointer
|
|
popf
|
|
clc ; clear carry flag
|
|
return
|
|
|
|
move_char:
|
|
stosb ; store char in token buffer
|
|
inc cx ; increment char count
|
|
inc [ELCNT] ; increment element count for * substi
|
|
return
|
|
|
|
TRANCODE ENDS
|
|
END
|
|
|