3016 lines
99 KiB
NASM
3016 lines
99 KiB
NASM
PAGE ;AN000;
|
|
; $SALUT (4,4,8,41)
|
|
;(deleted).XLIST
|
|
;(deleted)INCLUDE STRUC.INC ;AN020;structured macro definitions for .IF,.ELSE etc.
|
|
;(deleted).LIST
|
|
;
|
|
;Revision History
|
|
;================
|
|
;
|
|
; M029 02/15/91 SR Bug #5699. In SysParse, reinitialize $P_FileSp_Char
|
|
; everytime because this is in the non-checksum region
|
|
; and can get corrupted without the checksum region
|
|
; getting corrupted. Yet another data structure that
|
|
; should have been in the checksum region but isnt.
|
|
;
|
|
|
|
|
|
;
|
|
; NOTE: basesw must be set properly to allow the PARSER to access psdata.
|
|
; - basesw undefined means CS seg. override for psdata access.
|
|
; - basesw = 1 means DS seg. override for psdata access &
|
|
; DS must point to psdata.
|
|
; - basesw = 0 means ES seg. override for psdata access &
|
|
; ES must point to psdata.
|
|
;
|
|
;
|
|
IFNDEF basesw ;AN022;
|
|
psdata_seg EQU CS ;AN022;
|
|
ELSE ;AN022;
|
|
IF basesw ;AN022;IF "basesw EQU 1" specified by caller THEN
|
|
psdata_seg EQU DS ;AN022;
|
|
ELSE ;AN022;
|
|
psdata_seg EQU ES ;AN022;ELSE only other choice is ES (basesw EQU 0)
|
|
ENDIF ;AN022;
|
|
ENDIF ;AN022;
|
|
|
|
ifndef incsw ;AN000; (tm03) Someone doesn't want to include psdata
|
|
incsw equ 1 ;AN000; include psdata.inc (tm03)
|
|
endif ;AN000; (tm03)
|
|
if incsw ;AN000; If incsw = 1 then (tm03)
|
|
include psdata.inc ;AN000; include psdata.inc (tm03)
|
|
endif ;AN000; endif (tm03)
|
|
PAGE ;AN000;
|
|
IF1 ;AN000;
|
|
; %OUT INCLUDING COMP=COMMON DSN=PARSE.ASM...;AN000;
|
|
ENDIF ;AN000;
|
|
;***********************************************************************
|
|
; SysParse;
|
|
;
|
|
; Function : Parser Entry
|
|
;
|
|
; Input: DS:SI -> command line
|
|
; ES:DI -> parameter block
|
|
; psdata_seg -> psdata.inc
|
|
; CX = operand ordinal
|
|
;
|
|
; Note: ES is the segment containing all the control blocks defined
|
|
; by the caller, except for the DOS COMMAND line parms, which
|
|
; is in DS.
|
|
;
|
|
; Output: CY = 1 error of caller, means invalid parameter block or
|
|
; invalid value list. But this parser does NOT implement
|
|
; this feature. Therefore CY always zero.
|
|
;
|
|
; CY = 0 AX = return code
|
|
; BL = terminated delimiter code
|
|
; CX = new operand ordinal
|
|
; SI = set past scaned operand
|
|
; DX = selected result buffer
|
|
;
|
|
; Use: $P_Skip_Delim, $P_Chk_EOL, $P_Chk_Delim, $P_Chk_DBCS
|
|
; $P_Chk_Swtch, $P_Chk_Pos_Control, $P_Chk_Key_Control
|
|
; $P_Chk_Sw_Control, $P_Fill_Result
|
|
;
|
|
; Vars: $P_Ordinal(RW), $P_RC(RW), $P_SI_Save(RW), $P_DX(R), $P_Terminator(R)
|
|
; $P_SaveSI_Cmpx(W), $P_Flags(RW), $P_Found_SYNONYM(R), $P_Save_EOB(W)
|
|
;
|
|
;-------- Modification History -----------------------------------------
|
|
;
|
|
; 4/04/87 : Created by K. K,
|
|
; 4/28/87 : $P_Val_YH assemble error (tm01)
|
|
; : JMP SHORT assemble error (tm02)
|
|
; 5/14/87 : Someone doesn't want to include psdata (tm03)
|
|
; 6/12/87 : $P_Bridge is missing when TimeSw equ 0 and (CmpxSw equ 1 or
|
|
; DateSW equ 1) (tm04)
|
|
; 6/12/87 : $P_SorD_Quote is missing when QusSw equ 0 and CmpxSW equ 1
|
|
; (tm05) in PSDATA.INC
|
|
; 6/12/87 : $P_FileSp_Char and $P_FileSP_Len are missing
|
|
; when FileSW equ 0 and DrvSW equ 1 (tm06) in PSDATA.INC
|
|
; 6/18/87 : $VAL1 and $VAL3, $VAL2 and $VAL3 can be used in the same
|
|
; value-list block (tm07)
|
|
; 6/20/87 : Add $P_SW to check if there's an omiting parameter after
|
|
; switch (keyword) or not. If there is, backup si for next call
|
|
; (tm08)
|
|
; 6/24/87 : Complex Item checking does not work correctly when CmpSW equ 1
|
|
; and DateSW equ 0 and TimeSW equ 0 (tm09)
|
|
; 6/24/87 : New function flag $P_colon_is_not_necessary for switch
|
|
; /+15 and /+:15 are allowed for user (tm10)
|
|
; 6/29/87 : ECS call changes DS register but it causes the address problem
|
|
; in user's routines. $P_Chk_DBCS (tm11)
|
|
; 7/10/87 : Switch with no_match flag (0x0000H) does not work correctly
|
|
; (tm12)
|
|
; 7/10/87 : Invalid switch/keyword does not work correctly
|
|
; (tm13)
|
|
; 7/10/87 : Drive_only breaks 3 bytes after the result buffer
|
|
; (tm14)
|
|
; 7/12/87 : Too_Many_Operands sets DX=0 as the PARSE result
|
|
; (tm15)
|
|
; 7/24/87 : Negative lower bound on numeric ranges cause trouble
|
|
|
|
; 7/24/87 : Quoted strings being returned with quotes.
|
|
|
|
; 7/28/87 : Kerry S (;AN018;)
|
|
; Non optional value on switch (match flags<>0 and <>1) not flagged
|
|
; as an error when missing. Solution: return error 2. Modules
|
|
; affected: $P_Chk_SW_Control.
|
|
|
|
; 7/29/87 : Kerry S (;AN019;)
|
|
; Now allow the optional bit in match flags for switches. This
|
|
; allows the switch to be encountered with a value or without a
|
|
; value and no error is returned.
|
|
;
|
|
|
|
; 8/28/87 : Ed K, Kerry S (;AN020;)
|
|
; 9/14/87 In PROC $P_Get_DecNum, when checking for field separators
|
|
; within a date response, instead of checking just for the one
|
|
; character defined by the COUNTRY DEPENDENT INFO, check for
|
|
; all three chars, "-", "/", and ".". Change $P_Chk_Switch to allow
|
|
; slashes in date strings when DateSw (assembler switch) is set.
|
|
|
|
; 9/1/87 : Kerry S (;AN021)
|
|
; In PROC $P_String_Comp, when comparing the switch or keyword on
|
|
; the command line with the string in the control block the
|
|
; comparing was stopping at a colon (switch) or equal (keyword)
|
|
; on the command line and assuming a match. This allowed a shorter
|
|
; string on the command line than in the synonym list in the control
|
|
; block. I put in a test for a null in the control block so the
|
|
; string in the control block must be the same length as the string
|
|
; preceeding the colon or equal on the command line.
|
|
|
|
; 8/28/87 : Kerry S (;AN022;)
|
|
; All references to data in PSDATA.INC had CS overrides. This caused
|
|
; problems for people who included it themselves in a segment other
|
|
; than CS. Added switch to allow including PSDATA.INC in any
|
|
; segment.
|
|
|
|
; 9/16/87 : Ed K (;AN023;) PTM1040
|
|
; in $p_set_cdi PROC, it assumes CS points to psdata. Change Push CS
|
|
; into PUSH PSDATA_SEG. In $P_Get_DecNum PROC, fix AN020
|
|
; forced both TIME and DATE to use the delims, "-","/",".".
|
|
; Created FLag, in $P_time_Format PROC, to request the delim in
|
|
; BL be used if TIME is being parsed.
|
|
|
|
; 9/24/87 : Ed K
|
|
; Removed the include to STRUC.INC. Replaced the STRUC macro
|
|
; invocations with their normally expanded code; made comments
|
|
; out of the STRUC macro invocation statements to maintain readability.
|
|
|
|
; 9/24/87 : Ed K (;AN024;) PTM1222
|
|
; When no CONTROL for a keyword found, tried to fill in RESULT
|
|
; pointed to by non-existant CONTROL.
|
|
|
|
; 10/15/87 : Ed K (;AN025;) PTM1672
|
|
; A quoted text string can be framed only by double quote. Remove
|
|
; support to frame quoted text string with single quote.
|
|
; (apostrophe) $P_SorD_Quote is removed from PSDATA.INC.
|
|
; $P_SQuote EQU also removed from PSDATA.INC. Any references to
|
|
; single quote in PROC prologues are left as is for history reasons.
|
|
|
|
; This fixes another bug, not mentioned in p1672, in that two
|
|
; quote chars within a quoted string is supposed to be reported as
|
|
; one quote character, but is reported as two quotes. This changed
|
|
; two instructions in PROC $P_Quoted_Str.
|
|
|
|
; Also fixed are several JMP that caused a NOP, these changed to
|
|
; have the SHORT operator to avoid the unneeded NOP.
|
|
|
|
; The code and PSDATA.INC have been aligned for ease of reading.
|
|
|
|
; 10/26/87 : Ed K (;AN026;) PTM2041, DATE within SWITCH, BX reference to
|
|
; psdata buffer should have psdata_seg.
|
|
|
|
; 10/27/87 : Ed K (;AN027;) PTM2042 comma between keywords implies
|
|
; positional missing.
|
|
|
|
; 11/06/87 : Ed K (;AN028;) PTM 2315 Parser should not use line feed
|
|
; as a line delimiter, should use carriage return.
|
|
; Define switch: LFEOLSW, if on, accept LF as end of line char.
|
|
|
|
; 11/11/87 : Ed K (;AN029;) PTM 1651 GET RID OF WHITESPACE AROUND "=".
|
|
|
|
; 11/18/87 : Ed K (;AN030;) PTM 2551 If filename is just "", then
|
|
; endless loop since SI is returned still pointing to start
|
|
; of that parm.
|
|
|
|
; 11/19/87 : Ed K (;AN031;) PTM 2585 date & time getting bad values.
|
|
; Vector to returned string has CS instead of Psdata_Seg, but
|
|
; when tried to fix it on previous version, changed similar
|
|
; but wrong place.
|
|
|
|
; 12/09/87 : Bill L (;AN032;) PTM 2772 colon and period are now valid
|
|
; delimiters between hours, minutes, seconds for time. And period
|
|
; and comma are valid delimiters between seconds and 100th second.
|
|
|
|
; 12/14/87 : Bill L (;AN033;) PTM 2722 if illegal delimiter characters
|
|
; in a filespec, then flag an error.
|
|
|
|
; 12/22/87 : Bill L (;AN034;) All local data to parser is now
|
|
; indexed off of the psdata_seg equate instead of the DS register.
|
|
; Using this method, DS can point to the segment of PSP or to psdata
|
|
; --> local parser data. Why were some references to local data changed
|
|
; to do this before, but not all ?????
|
|
|
|
; 02/02/88 : Ed K (;AC035;) INSPECT utility, suggests optimizations.
|
|
|
|
; 02/05/88 : Ed K (;AN036;) P3372-UPPERCASE TRANSLATION, PSDATA_SEG HOSED.
|
|
;
|
|
; 02/08/88 : Ed K (;AN037;) P3410-AVOID POP OF CS, CHECK BASESW FIRST.
|
|
|
|
; 02/19/88 : Ed K (;AN038;) p3524 above noon and "am" should be error
|
|
|
|
; 02/23/88 : Ed K (;AN039;) p3518 accept "comma" and "period" as decimal
|
|
; separator in TIME before hundredths field.
|
|
;
|
|
; 08/09/90 : SA M005 Prevented parser from recognizing '=' signs within
|
|
; strings as keywords.
|
|
;
|
|
;***********************************************************************
|
|
IF FarSW ;AN000;(Check if need far return)
|
|
SysParse proc far ;AN000;
|
|
ELSE ;AN000;
|
|
SysParse proc near ;AN000;
|
|
ENDIF ;AN000;(of FarSW)
|
|
; $SALUT (4,9,17,41)
|
|
mov psdata_seg:$P_Flags,0 ;AC034; Clear all internal flags
|
|
IF TimeSw ;AN039; FOR TIME ONLY
|
|
MOV PSDATA_SEG:$P_ORIG_ORD,CX ;AN039; ORIGINAL ORDINAL FROM CX
|
|
MOV PSDATA_SEG:$P_ORIG_STACK,SP ;AN039; ORIGINAL VALUE OF STACK FROM SP
|
|
MOV PSDATA_SEG:$P_ORIG_SI,SI ;AN039; ORIGINAL START PARSE POINTER FROM SI
|
|
$P_REDO_TIME: ;AN039; try to parse time again
|
|
ENDIF ;AN039; FOR TIME ONLY
|
|
cld ;AN000; confirm forward direction
|
|
mov psdata_seg:$P_ordinal,cx ;AC034; save operand ordinal
|
|
mov psdata_seg:$P_RC,$P_No_Error ;AC034; Assume no error
|
|
mov psdata_seg:$P_Found_SYNONYM,0 ;AC034; initalize synonym pointer
|
|
|
|
mov word ptr psdata_seg:$P_DX,0 ;AC034; (tm15)
|
|
|
|
;M029 -- Begin changes
|
|
; The table of special chars $P_FileSp_Char should be initialized on every
|
|
;entry to SysParse. This is in the non-checksum region and any program that
|
|
;corrupts this table but does not corrupt the checksum region will leave
|
|
;command.com parsing in an inconsistent state.
|
|
; NB: The special characters string has been hardcoded here. If any change
|
|
;is made to it in psdata.inc, a corresponding change needs to be made here.
|
|
;
|
|
IF FileSW + DrvSW
|
|
|
|
mov word ptr psdata_seg:$P_FileSp_Char, ']['
|
|
mov word ptr psdata_seg:$P_FileSp_Char+2, '<|'
|
|
mov word ptr psdata_seg:$P_FileSp_Char+4, '+>'
|
|
mov word ptr psdata_seg:$P_FileSp_Char+6, ';='
|
|
|
|
ENDIF
|
|
;
|
|
;M029 -- End of changes
|
|
;
|
|
|
|
IF KeySW ;AN029;
|
|
;IN CASE THE USER PUT OPTIONAL WHITESPACE CHARS AROUND THE "=" USED IN
|
|
;KEYWORD DEFINITIONS, SCAN THE COMMAND LINE AND COMPRESS OUT ANY WHITESPACES
|
|
;NEXT TO "=" BEFORE STARTING THE USUAL PARSING.
|
|
push cx ;AN029;
|
|
push dx ;AN029;
|
|
push di ;AN029;
|
|
|
|
push si ;AN029; remember where command line starts
|
|
mov cx,-1 ;AN029; init counter
|
|
; $do
|
|
$P_loc_eol: ;AN029;
|
|
inc cx ;AN029; bump counter of chars up to EOL
|
|
lodsb ;AN029; get a char from command line
|
|
CALL $P_Chk_EOL ;AN029; see if AL is EOL char
|
|
|
|
; enddo z
|
|
jnz $P_loc_EOL ;AN029; not found that EOL char
|
|
|
|
mov psdata_seg:$P_count_to_EOL,cx ;AN029;AC034;; save count of chars up to EOL
|
|
pop si ;AN029; restore start of command line
|
|
|
|
;scan command string for combinations including "=",
|
|
; and replace each with just the simple "="
|
|
|
|
;REPEAT UNTIL ONE PASS IS MADE WHEREIN NO CHANGES WERE MADE
|
|
; $do
|
|
$P_DO1: ;AN029;
|
|
push si ;AN029; remember where string started
|
|
MOV CX,psdata_seg:$P_COUNT_TO_EOL ;AN029;AC034;; set count to no. chars in string,
|
|
;AN029; not counting the EOL char
|
|
XOR BX,BX ;AN029;SET $P_REG_BL_DQ_SW TO "NOT IN QUOTES", AND...
|
|
;AN029;SET $P_REG_BH_CG_SW TO "NO CHANGES MADE"
|
|
;MAKE ONE PASS THRU THE STRING, LOOKING AT EACH CHARACTER
|
|
; $do ;AN029;
|
|
$P_DO2: ;AN029;
|
|
cmp BYTE PTR [SI],$P_double_quote ;AN029;
|
|
; $if e ;AN029;if a double quote was found
|
|
JNE $P_IF3 ;AN029;
|
|
NOT $P_REG_BL_DQ_SW ;AN029;TOGGLE THE DOUBLE QUOTE STATE SWITCH
|
|
; $endif ;AN029;
|
|
$P_IF3: ;AN029;
|
|
OR $P_REG_BL_DQ_SW,$P_REG_BL_DQ_SW ;AN029;IS THE DOUBLE QUOTE SWITCH SET?
|
|
; $if Z ;AN029;IF NOT IN DOUBLE QUOTES
|
|
JNZ $P_IF5 ;AN029;
|
|
mov ax,word ptr [si] ;AN029; get pair to be checked out
|
|
cmp ax,$P_BL_EQ ;AN029;" ="
|
|
; $if e,or ;AN029;
|
|
JE $P_LL6 ;AN029;
|
|
cmp ax,$P_EQ_BL ;AN029;"= "
|
|
; $if e,or ;AN029;
|
|
JE $P_LL6 ;AN029;
|
|
cmp ax,$P_EQ_TB ;AN029; "=<tab>"
|
|
; $if e,or ;AN029;
|
|
JE $P_LL6 ;AN029;
|
|
cmp ax,$P_TB_EQ ;AN029;"<tab>="
|
|
; $if e ;AN029;if this pair to be replaced with a single "="
|
|
JNE $P_IF6 ;AN029;
|
|
$P_LL6: ;AN029;
|
|
mov BYTE PTR [SI],$P_Keyword ;AN029; "="
|
|
inc si ;AN029;point to next char after the new "="
|
|
mov di,si ;AN029;move target right after new "="
|
|
|
|
push si ;AN029;remember where i am, right after new "="
|
|
PUSH CX ;AN029;SAVE CURRENT COUNT
|
|
inc si ;AN029;source is one beyond that
|
|
push es ;AN029;remember the extra segment
|
|
push ds ;AN029;temporarily, set source seg and
|
|
pop es ;AN029; target seg to the command line seg
|
|
rep movsb ;AN029;move chars left one position
|
|
pop es ;AN029;restore the extra segment
|
|
POP CX ;AN029;RESTORE CURRENT COUNT
|
|
pop si ;AN029;back to where I was
|
|
|
|
DEC SI ;AN029;LOOK AT FIRST CHAR JUST MOVED
|
|
MOV $P_REG_BH_CG_SW,-1 ;AN029;set switch to say "a change was made"
|
|
DEC psdata_seg:$P_COUNT_TO_EOL ;AN029;AC034;;because just threw away a char
|
|
dec CX ;AN029;DITTO
|
|
; $endif ;AN029;comparand pair found?
|
|
$P_IF6: ;AN029;
|
|
; $endif ;AN029;double quote switch?
|
|
$P_IF5: ;AN029;
|
|
inc si ;AN029;bump index to look at next char in command string
|
|
dec CX ;AN029;one less char to look at
|
|
;(deleted ;AC035;) CMP CX,0 ;AN029;is char count all gone yet?
|
|
; $enddo LE ;AN029;quit if no more chars
|
|
JNLE $P_DO2 ;AN029;
|
|
pop si ;AN029;remember where string started
|
|
OR $P_REG_BH_CG_SW,$P_REG_BH_CG_SW ;AN029;WAS "A CHANGE MADE"?
|
|
; $enddo Z ;AN029;QUIT when no changes were made
|
|
JNZ $P_DO1 ;AN029;
|
|
pop di ;AN029;
|
|
pop dx ;AN029;
|
|
pop cx ;AN029;
|
|
|
|
;NOW THAT ALL WHITESPACE SURROUNDING "=" HAVE BEEN COMPRESSED OUT,
|
|
;RESUME NORMAL PARSING...
|
|
ENDIF ;AN029; KEYWORDS SUPPORTED?
|
|
call $P_Skip_Delim ;AN000; Move si to 1st non white space
|
|
jnc $P_Start ;AN000; If EOL is not encountered, do parse
|
|
|
|
;--------------------------- End of Line
|
|
mov ax,$P_RC_EOL ;AN000; set exit code to -1
|
|
push bx ;AN000;
|
|
mov bx,es:[di].$P_PARMSX_Address ;AN000; Get the PARMSX address to
|
|
cmp cl,es:[bx].$P_MinP ;AN000; check ORDINAL to see if the minimum
|
|
jae $P_Fin ;AN000; positional found.
|
|
|
|
mov ax,$P_Op_Missing ;AN000; If no, set exit code to missing operand
|
|
$P_Fin: ;AN000;
|
|
pop bx ;AN000;
|
|
jmp $P_Single_Exit ;AN000; return to the caller
|
|
|
|
;---------------------------
|
|
$P_Start: ;AN000;
|
|
mov psdata_seg:$P_SaveSI_Cmpx,si ;AN000;AC034; save ptr to command line for later use by complex,
|
|
push bx ;AN000; quoted string or file spec.
|
|
push di ;AN000;
|
|
push bp ;AN000;
|
|
lea bx,psdata_seg:$P_STRING_BUF ;AC034; set buffer to copy from command string
|
|
test psdata_seg:$P_Flags2,$P_Extra ;AC034; 3/9 extra delimiter encountered ?
|
|
jne $P_Pack_End ;AN000; 3/9 if yes, no need to copy
|
|
|
|
$P_Pack_Loop: ;AN000;
|
|
lodsb ;AN000; Pick a operand from buffer
|
|
call $P_Chk_Switch ;AN000; Check switch character
|
|
jc $P_Pack_End_BY_EOL ;AN020; if carry set found delimiter type slash, need backup si, else continue
|
|
|
|
call $P_Chk_EOL ;AN000; Check EOL character
|
|
je $P_Pack_End_BY_EOL ;AN000; need backup si
|
|
|
|
call $P_Chk_Delim ;AN000; Check delimiter
|
|
jne $P_PL01 ;AN000; If no, process next byte
|
|
|
|
test psdata_seg:$P_Flags2,$P_Extra ;AC034; 3/9 If yes and white spec,
|
|
; (tm08)jne $P_Pack_End ;AN000; 3/9 then
|
|
jne $P_Pack_End_backup_si ;AN000; (tm08)
|
|
|
|
call $P_Skip_Delim ;AN000; skip subsequent white space,too
|
|
jmp short $P_Pack_End ;AN000; finish copy by placing NUL at end
|
|
|
|
$P_PAck_End_backup_si: ;AN000; (tm08)
|
|
test psdata_seg:$P_Flags2,$P_SW+$P_equ ;AN000;AC034; (tm08)
|
|
je $P_Pack_End ;AN000; (tm08)
|
|
|
|
dec si ;AN000; (tm08)
|
|
jmp short $P_Pack_End ;AN025; (tm08)
|
|
|
|
$P_PL01: ;AN000;
|
|
mov psdata_seg:[bx],al ;AN000; move byte to STRING_BUF
|
|
cmp al,$P_Keyword ;AN000; if it is equal character,
|
|
jne $P_PL00 ;AN000; then
|
|
|
|
or psdata_seg:$P_Flags2,$P_equ ;AC034; remember it in flag
|
|
$P_PL00: ;AN000;
|
|
inc bx ;AN000; ready to see next byte
|
|
call $P_Chk_DBCS ;AN000; was it 1st byte of DBCS ?
|
|
jnc $P_Pack_Loop ;AN000; if no, process to next byte
|
|
|
|
lodsb ;AN000; if yes, store
|
|
mov psdata_seg:[bx],al ;AN000; 2nd byte of DBCS
|
|
inc bx ;AN000; update pointer
|
|
jmp short $P_Pack_Loop ;AN000; process to next byte
|
|
|
|
$P_Pack_End_BY_EOL: ;AN000;
|
|
dec si ;AN000; backup si pointer
|
|
$P_Pack_End: ;AN000;
|
|
mov psdata_seg:$P_SI_Save,si ;AC034; save next pointer, SI
|
|
mov byte ptr psdata_seg:[bx],$P_NULL ;AN000; put NULL at the end
|
|
mov psdata_seg:$P_Save_EOB,bx ;AC034; 3/17/87 keep the address for later use of complex
|
|
mov bx,es:[di].$P_PARMSX_Address ;AN000; get PARMSX address
|
|
lea si,psdata_seg:$P_STRING_BUF ;AC034;
|
|
cmp byte ptr psdata_seg:[si],$P_Switch ;AN000; the operand begins w/ switch char ?
|
|
je $P_SW_Manager ;AN000; if yes, process as switch
|
|
|
|
cmp byte ptr psdata_seg:[si],$P_DQuote ;M005;is it a string?
|
|
je $P_Positional_Manager ;M005;if so, process as one!
|
|
|
|
test psdata_seg:$P_Flags2,$P_equ ;AC034; the operand includes equal char ?
|
|
jne $P_Key_manager ;AN000; if yes, process as keyword
|
|
|
|
$P_Positional_Manager: ;AN000; else process as positional
|
|
mov al,es:[bx].$P_MaxP ;AN000; get maxp
|
|
xor ah,ah ;AN000; ax = maxp
|
|
cmp psdata_seg:$P_ORDINAL,ax ;AC034; too many positional ?
|
|
jae $P_Too_Many_Error ;AN000; if yes, set exit code to too many
|
|
|
|
mov ax,psdata_seg:$P_ORDINAL ;AC034; see what the current ordinal
|
|
shl ax,1 ;AN000; ax = ax*2
|
|
inc bx ;AC035; add '2' to
|
|
inc bx ;AC035; BX reg
|
|
;AN000; now bx points to 1st CONTROL
|
|
;(changed ;AC035;) add bx,2 ;AN000; now bx points to 1st CONTROL
|
|
add bx,ax ;AN000; now bx points to specified CONTROL address
|
|
mov bx,es:[bx] ;AN000; now bx points to specified CONTROL itself
|
|
call $P_Chk_Pos_Control ;AN000; Do process for positional
|
|
jmp short $P_Return_to_Caller ;AN000; and return to the caller
|
|
|
|
$P_Too_Many_Error: ;AN000;
|
|
mov psdata_seg:$P_RC,$P_Too_Many ;AC034; set exit code
|
|
jmp short $P_Return_to_Caller ;AN000; and return to the caller
|
|
;
|
|
$P_SW_Manager: ;AN000;
|
|
mov al,es:[bx].$P_MaxP ;AN000; get maxp
|
|
xor ah,ah ;AN000; ax = maxp
|
|
inc ax ;AN000;
|
|
shl ax,1 ;AN000; ax = (ax+1)*2
|
|
add bx,ax ;AN000; now bx points to maxs
|
|
mov cl,es:[bx] ;AN000;
|
|
xor ch,ch ;AN000; cx = maxs
|
|
or cx,cx ;AN000; at least one switch ?
|
|
je $P_SW_Not_Found ;AN000;
|
|
|
|
inc bx ;AN000; now bx points to 1st CONTROL address
|
|
|
|
$P_SW_Mgr_Loop: ;AN000;
|
|
push bx ;AN000;
|
|
mov bx,es:[bx] ;AN000; bx points to Switch CONTROL itself
|
|
call $P_Chk_SW_Control ;AN000; do process for switch
|
|
pop bx ;AN000;
|
|
jnc $P_Return_to_Caller ;AN000; if the CONTROL is for the switch, exit
|
|
|
|
inc bx ;AC035; add '2' to
|
|
inc bx ;AC035; BX reg
|
|
;AN000; else bx points to the next CONTROL
|
|
;(changed ;AC035;) add bx,2 ;AN000; else bx points to the next CONTROL
|
|
loop $P_SW_Mgr_Loop ;AN000; and loop
|
|
|
|
$P_SW_Not_Found: ;AN000;
|
|
mov psdata_seg:$P_RC,$P_Not_In_SW ;AC034; here no CONTROL for the switch has
|
|
jmp short $P_Return_to_Caller0 ;AN000; not been found, means error.
|
|
;
|
|
$P_Key_Manager: ;AN000;
|
|
mov al,es:[bx].$P_MaxP ;AN000; get maxp
|
|
xor ah,ah ;AN000; ax = maxp
|
|
inc ax ;AN000;
|
|
shl ax,1 ;AN000; ax = (ax+1)*2
|
|
add bx,ax ;AN000; now bx points to maxs
|
|
mov al,es:[bx] ;AN000;
|
|
xor ah,ah ;AN000; ax = maxs
|
|
shl ax,1 ;AN000;
|
|
inc ax ;AN000; ax = ax*2+1
|
|
add bx,ax ;AN000; now bx points to maxk
|
|
mov cl,es:[bx] ;AN000;
|
|
xor ch,ch ;AN000; cx = maxk
|
|
or cx,cx ;AN000; at least one keyword ?
|
|
je $P_Key_Not_Found ;AN000;
|
|
|
|
inc bx ;AN000; now bx points to 1st CONTROL
|
|
|
|
$P_Key_Mgr_Loop: ;AN000;
|
|
push bx ;AN000;
|
|
mov bx,es:[bx] ;AN000; bx points to keyword CONTROL itself
|
|
call $P_Chk_Key_Control ;AN000; do process for keyword
|
|
pop bx ;AN000;
|
|
jnc $P_Return_to_Caller ;AN000; if the CONTROL is for the keyword, exit
|
|
|
|
inc bx ;AC035; add '2' to
|
|
inc bx ;AC035; BX reg
|
|
;AN000; else bx points to the next CONTROL
|
|
;(changed ;AC035;) add bx,2 ;AN000; else bx points to the next CONTROL
|
|
loop $P_Key_Mgr_Loop ;AN000; and loop
|
|
|
|
$P_Key_Not_Found: ;AN000;
|
|
mov psdata_seg:$P_RC,$P_Not_In_Key ;AC034; here no CONTROL for the keyword has
|
|
$P_Return_to_Caller0: ;AN000; not been found, means error.
|
|
|
|
;(deleted ;AN024;) mov bx,es:[bx-2] ;AN000; (tm13) backup bx
|
|
|
|
;(deleted ;AN024;) mov al,$P_String ;AN000; Set
|
|
;(deleted ;AN024;) mov ah,$P_No_Tag ;AN000; result
|
|
;(deleted ;AN024;) call $P_Fill_Result ;AN000; buffer
|
|
|
|
$P_Return_to_Caller: ;AN000;
|
|
pop bp ;AN000;
|
|
pop di ;AN000;
|
|
pop bx ;AN000;
|
|
mov cx,psdata_seg:$P_Ordinal ;AC034; return next ordinal
|
|
mov ax,psdata_seg:$P_RC ;AC034; return exit code
|
|
mov si,psdata_seg:$P_SI_Save ;AC034; return next operand pointer
|
|
mov dx,psdata_seg:$P_DX ;AC034; return result buffer address
|
|
mov bl,psdata_seg:$P_Terminator ;AC034; return delimiter code found
|
|
$P_Single_Exit: ;AN000;
|
|
clc ;AN000;
|
|
ret ;AN000;
|
|
SysParse endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_Chk_Pos_Control
|
|
;
|
|
; Function: Parse CONTROL block for a positional
|
|
;
|
|
; Input: ES:BX -> CONTROL block
|
|
; psdata_seg:SI -> $P_STRING_BUF
|
|
;
|
|
; Output: None
|
|
;
|
|
; Use: $P_Fill_Result, $P_Check_Match_Flags
|
|
;
|
|
; Vars: $P_Ordinal(W), $P_RC(W)
|
|
;***********************************************************************
|
|
$P_Chk_Pos_Control proc ;AN000;
|
|
push ax ;AN000;
|
|
mov ax,es:[bx].$P_Match_Flag ;AN000;
|
|
test ax,$P_Repeat ;AN000; repeat allowed ?
|
|
jne $P_CPC00 ;AN000; then do not increment ORDINAL
|
|
|
|
inc psdata_seg:$P_ORDINAL ;AC034; update the ordinal
|
|
$P_CPC00: ;AN000;
|
|
cmp byte ptr psdata_seg:[si],$P_NULL ;AN000; no data ?
|
|
jne $P_CPC01 ;AN000;
|
|
|
|
test ax,$P_Optional ;AN000; yes, then is it optional ?
|
|
jne $P_CPC02 ;AN000;
|
|
|
|
mov psdata_seg:$P_RC,$P_Op_Missing ;AC034; no, then error 3/17/87
|
|
jmp short $P_CPC_Exit ;AN000;
|
|
|
|
$P_CPC02: ;AN000;
|
|
push ax ;AN000;
|
|
mov al,$P_String ;AN000; if it is optional return NULL
|
|
mov ah,$P_No_Tag ;AN000; no item tag indication
|
|
call $P_Fill_Result ;AN000;
|
|
pop ax ;AN000;
|
|
jmp short $P_CPC_Exit ;AN000;
|
|
|
|
$P_CPC01: ;AN000;
|
|
call $P_Check_Match_Flags ;AN000;
|
|
$P_CPC_Exit: ;AN000;
|
|
pop ax ;AN000;
|
|
ret ;AN000;
|
|
$P_Chk_Pos_Control endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_Chk_Key_Control
|
|
;
|
|
; Function: Parse CONTROL block for a keyword
|
|
;
|
|
; Input: ES:BX -> CONTROL block
|
|
; psdata_seg:SI -> $P_STRING_BUF
|
|
;
|
|
; Output: CY = 1 : not match
|
|
;
|
|
; Use: $P_Fill_Result, $P_Search_KEYorSW, $P_Check_Match_Flags
|
|
;
|
|
; Vars: $P_RC(W), $P_SaveSI_Cmpx(W), $P_KEYorSW_Ptr(R), $P_Flags(W)
|
|
;***********************************************************************
|
|
$P_Chk_Key_Control proc ;AN000;
|
|
IF KeySW ;AN000;(Check if keyword is supported)
|
|
or psdata_seg:$P_Flags2,$P_Key_Cmp ;AC034; Indicate keyword for later string comparison
|
|
call $P_Search_KEYorSW ;AN000; Search the keyword in the CONTROL block
|
|
jc $P_Chk_Key_Err0 ;AN000; not found, then try next CONTROL
|
|
|
|
and psdata_seg:$P_Flags2,0ffh-$P_Key_Cmp ;AC034; reset the indicator previously set
|
|
;
|
|
push ax ;AN000; keyword=
|
|
mov ax,psdata_seg:$P_KEYorSW_Ptr ;AC034; ^ ^
|
|
sub ax,si ;AN000; SI KEYorSW
|
|
add psdata_seg:$P_SaveSI_Cmpx,ax ;AC034; update for complex, quoted or file spec.
|
|
pop ax ;AN000;
|
|
;
|
|
mov si,psdata_seg:$P_KEYorSW_Ptr ;AC034; set si just after equal char
|
|
cmp byte ptr psdata_seg:[si],$P_NULL ;AN000; any data after equal ?
|
|
je $P_Chk_Key_Err1 ;AN000; if no, syntax error
|
|
|
|
call $P_Check_Match_Flags ;AN000; else, process match flags
|
|
clc ;AN000;
|
|
jmp short $P_Chk_Key_Exit ;AN000;
|
|
|
|
$P_Chk_Key_Err0: ;AN000;
|
|
stc ;AN000; not found in keyword synonym list
|
|
jmp short $P_Chk_Key_Exit ;AN000;
|
|
|
|
$P_Chk_Key_Err1: ;AN000;
|
|
mov psdata_seg:$P_RC,$P_Syntax ;AC034; no parameter is not specified after "="
|
|
$P_Chk_Key_ErrExit: ;AN000;
|
|
push ax ;AN000;
|
|
mov al,$P_String ;AN000; set
|
|
mov ah,$P_No_Tag ;AN000; result
|
|
call $P_Fill_Result ;AN000; buffer
|
|
pop ax ;AN000;
|
|
clc ;AN000;
|
|
$P_Chk_Key_Exit: ;AN000;
|
|
ret ;AN000;
|
|
ELSE ;AN000;(of IF KeySW)
|
|
stc ;AN000;this logic works when the KeySW
|
|
ret ;AN000;is reset.
|
|
ENDIF ;AN000;(of KeySW)
|
|
$P_Chk_Key_Control endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
IF KeySW+SwSW ;AN000;(Check if keyword or switch is supported)
|
|
; $P_Search_KEYorSW:
|
|
;
|
|
; Function: Seach specified keyword or switch from CONTROL
|
|
;
|
|
; Input: ES:BX -> CONTROL block
|
|
; psdata_seg:SI -> $P_STRING_BUF
|
|
;
|
|
; Output: CY = 1 : not match
|
|
;
|
|
; Use: $P_String_Comp, $P_MoveBP_NUL, $P_Found_SYNONYM
|
|
;***********************************************************************
|
|
$P_Search_KEYorSW proc ;AN000;
|
|
push bp ;AN000;
|
|
push cx ;AN000;
|
|
mov cl,es:[bx].$P_nid ;AN000; Get synonym count
|
|
xor ch,ch ;AN000; and set it to cx
|
|
or cx,cx ;AN000; No synonyms specified ?
|
|
je $P_KEYorSW_Not_Found ;AN000; then indicate not found by CY
|
|
|
|
lea bp,es:[bx].$P_KEYorSW ;AN000; BP points to the 1st synonym
|
|
$P_KEYorSW_Loop: ;AN000;
|
|
call $P_String_Comp ;AN000; compare string in buffer w/ the synonym
|
|
jnc $P_KEYorSW_Found ;AN000; If match, set it to synonym pointer
|
|
|
|
call $P_MoveBP_NUL ;AN000; else, bp points to the next string
|
|
loop $P_KEYorSW_Loop ;AN000; loop nid times
|
|
$P_KEYorSW_Not_Found: ;AN000;
|
|
stc ;AN000; indicate not found in synonym list
|
|
jmp short $P_KEYorSW_Exit ;AN000; and exit
|
|
|
|
$P_KEYorSW_Found: ;AN000;
|
|
mov psdata_seg:$P_Found_SYNONYM,bp ;AC034; set synonym pointer
|
|
clc ;AN000; indicate found
|
|
$P_KEYorSW_Exit: ;AN000;
|
|
pop cx ;AN000;
|
|
pop bp ;AN000;
|
|
ret ;AN000;
|
|
$P_Search_KEYorSW endp ;AN000;
|
|
;***********************************************************************
|
|
; $P_MoveBP_NUL
|
|
;***********************************************************************
|
|
$P_MoveBP_NUL proc ;AN000;
|
|
$P_MBP_Loop: ;AN000;
|
|
cmp byte ptr es:[bp],$P_NULL ;AN000; Increment BP that points
|
|
je $P_MBP_Exit ;AN000; to the synomym list
|
|
|
|
inc bp ;AN000; until
|
|
jmp short $P_MBP_Loop ;AN000; NULL encountered.
|
|
|
|
$P_MBP_Exit: ;AN000;
|
|
inc bp ;AN000; bp points to next to NULL
|
|
ret ;AN000;
|
|
$P_MoveBP_NUL endp ;AN000;
|
|
ENDIF ;AN000;(of KeySW+SwSW)
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_Chk_SW_Control
|
|
;
|
|
; Function: Parse CONTROL block for a switch
|
|
;
|
|
; Input: ES:BX -> CONTROL block
|
|
; psdata_seg:SI -> $P_STRING_BUF
|
|
;
|
|
; Output: CY = 1 : not match
|
|
;
|
|
; Use: $P_Fill_Result, $P_Search_KEYorSW, $P_Check_Match_Flags
|
|
;
|
|
; Vars: $P_SaveSI_Cmpx(W), $P_KEYorSW_Ptr(R), $P_Flags(W)
|
|
;***********************************************************************
|
|
$P_Chk_SW_Control proc ;AN000;
|
|
|
|
|
|
IF SwSW ;AN000;(Check if switch is supported)
|
|
or psdata_seg:$P_Flags2,$P_Sw_Cmp ;AC034; Indicate switch for later string comparison
|
|
call $P_Search_KEYorSW ;AN000; Search the switch in the CONTROL block
|
|
jc $P_Chk_SW_Err0 ;AN000; not found, then try next CONTROL
|
|
|
|
and psdata_seg:$P_Flags2,0ffh-$P_Sw_Cmp ;AC034; reset the indicator previously set
|
|
;
|
|
push ax ;AN000; /switch:
|
|
mov ax,psdata_seg:$P_KEYorSW_Ptr ;AC034; ^ ^
|
|
sub ax,si ;AN000; SI KEYorSW
|
|
add psdata_seg:$P_SaveSI_Cmpx,ax ;AC034; update for complex list
|
|
pop ax ;AN000;
|
|
;
|
|
mov si,psdata_seg:$P_KEYorSW_Ptr ;AC034; set si at the end or colon
|
|
cmp byte ptr psdata_seg:[si],$P_NULL ;AN000; any data after colon
|
|
jne $P_CSW00 ;AN000; if yes, process match flags
|
|
|
|
cmp byte ptr psdata_seg:[si-1],$P_Colon ;AN000; if no, the switch terminated by colon ?
|
|
jne $P_Chk_if_data_required ;AN000; if yes,
|
|
|
|
mov psdata_seg:$P_RC,$P_Syntax ;AC034; return syntax error
|
|
jmp short $P_Chk_SW_Exit ;AN000;
|
|
|
|
$P_Chk_if_data_required: ;AN018; no data, no colon
|
|
cmp es:[bx].$P_Match_Flag,0 ;AN018; should have data? zero match flag means switch followed by nothing is OK
|
|
je $P_Chk_SW_Exit ;AN018; match flags not zero so should have something if optional bit is not on
|
|
|
|
test es:[bx].$P_Match_Flag,$P_Optional ;AN019; see if no value is valid
|
|
jnz $P_Chk_SW_Exit ;AN019; if so, then leave, else yell
|
|
|
|
mov psdata_seg:$P_RC,$P_Op_Missing ;AC034; return required operand missing
|
|
jmp short $P_Chk_SW_Exit ;AN018;
|
|
|
|
$P_CSW00: ;AN000;
|
|
call $P_Check_Match_Flags ;AN000; process match flag
|
|
clc ;AN000; indicate match
|
|
jmp short $P_Chk_SW_Single_Exit ;AN000;
|
|
|
|
$P_Chk_SW_Err0: ;AN000;
|
|
stc ;AN000; not found in switch synonym list
|
|
jmp short $P_Chk_SW_Single_Exit ;AN000;
|
|
|
|
$P_Chk_SW_Exit: ;AN000;
|
|
push ax ;AN000;
|
|
mov al,$P_String ;AN000; set
|
|
mov ah,$P_No_Tag ;AN000; result
|
|
call $P_Fill_Result ;AN000; buffer
|
|
pop ax ;AN000;
|
|
clc ;AN000;
|
|
$P_Chk_SW_Single_Exit: ;AN000;
|
|
ret ;AN000;
|
|
ELSE ;AN000;(of IF SwSW)
|
|
stc ;AN000; this logic works when the SwSW
|
|
ret ;AN000; is reset.
|
|
ENDIF ;AN000;(of SwSW)
|
|
$P_Chk_SW_Control endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_Fill_Result
|
|
;
|
|
; Function: Fill the result buffer
|
|
;
|
|
; Input: AH = Item tag
|
|
; AL = type
|
|
; AL = 1: CX,DX has 32bit number (CX = high)
|
|
; AL = 2: DX has index(offset) into value list
|
|
; AL = 6: DL has driver # (1-A, 2-B, ... , 26 - Z)
|
|
; AL = 7: DX has year, CL has month and CH has date
|
|
; AL = 8: DL has hours, DH has minutes, CL has secondsn,
|
|
; amd CH has hundredths
|
|
; AL = else: psdata_seg:SI points to returned string buffer
|
|
; ES:BX -> CONTROL block
|
|
;
|
|
; Output: None
|
|
;
|
|
; Use: $P_Do_CAPS_String, $P_Remove_Colon, $P_Found_SYNONYM
|
|
;
|
|
; Vars: $P_DX(W)
|
|
;***********************************************************************
|
|
$P_Fill_Result proc ;AN000;
|
|
push di ;AN000;
|
|
mov di,es:[bx].$P_Result_Buf ;AN000; di points to result buffer
|
|
mov psdata_seg:$P_DX,di ;AC034; set returned result address
|
|
mov es:[di].$P_Type,al ;AN000; store type
|
|
mov es:[di].$P_Item_Tag,ah ;AN000; store item tag
|
|
push ax ;AN000;
|
|
mov ax,psdata_seg:$P_Found_SYNONYM ;AC034; if yes,
|
|
mov es:[di].$P_SYNONYM_Ptr,ax ;AN000; then set it to the result
|
|
pop ax ;AN000;
|
|
$P_RLT04: ;AN000;
|
|
cmp al,$P_Number ;AN000; if number
|
|
jne $P_RLT00 ;AN000;
|
|
|
|
$P_RLT02: ;AN000;
|
|
mov word ptr es:[di].$P_Picked_Val,dx ;AN000; then store 32bit
|
|
mov word ptr es:[di+2].$P_Picked_Val,cx ;AN000; number
|
|
jmp short $P_RLT_Exit ;AN000;
|
|
|
|
$P_RLT00: ;AN000;
|
|
cmp al,$P_List_Idx ;AN000; if list index
|
|
jne $P_RLT01 ;AN000;
|
|
|
|
mov word ptr es:[di].$P_Picked_Val,dx ;AN000; then store list index
|
|
jmp short $P_RLT_Exit ;AN000;
|
|
|
|
$P_RLT01: ;AN000;
|
|
cmp al,$P_Date_F ;AN000; Date format ?
|
|
je $P_RLT02 ;AN000;
|
|
|
|
cmp al,$P_Time_F ;AN000; Time format ?
|
|
je $P_RLT02 ;AN000;
|
|
;
|
|
cmp al,$P_Drive ;AN000; drive format ?
|
|
jne $P_RLT03 ;AN000;
|
|
|
|
mov byte ptr es:[di].$P_Picked_Val,dl ;AN000; store drive number
|
|
jmp short $P_RLT_Exit ;AN000;
|
|
|
|
$P_RLT03: ;AN000;
|
|
cmp al,$P_Complex ;AN000; complex format ?
|
|
jne $P_RLT05 ;AN000;
|
|
|
|
mov ax,psdata_seg:$P_SaveSI_Cmpx ;AC034; then get pointer in command buffer
|
|
inc ax ;AN000; skip left Parentheses
|
|
mov word ptr es:[di].$P_Picked_Val,ax ;AN000; store offset
|
|
mov word ptr es:[di+2].$P_Picked_Val,ds ;AN000; store segment
|
|
jmp short $P_RLT_Exit ;AN000;
|
|
|
|
$P_RLT05: ;AN000;
|
|
;------------------------ AL = 3, 5, or 9
|
|
mov word ptr es:[di].$P_Picked_Val,si ;AN000; store offset of STRING_BUF
|
|
;(replaced ;AN031;) mov word ptr es:[di+word].$P_Picked_Val,cs ;AN000; store segment of STRING_BUF
|
|
mov word ptr es:[di+2].$P_Picked_Val,Psdata_Seg ;AN031; store segment of STRING_BUF
|
|
;
|
|
push ax ;AN000;
|
|
test byte ptr es:[bx].$P_Function_Flag,$P_CAP_File ;AN000; need CAPS by file table?
|
|
je $P_RLT_CAP00 ;AN000;
|
|
|
|
mov al,$P_DOSTBL_File ;AN000; use file upper case table
|
|
jmp short $P_RLT_CAP02 ;AN000;
|
|
|
|
$P_RLT_CAP00: ;AN000;
|
|
test byte ptr es:[bx].$P_Function_Flag,$P_CAP_Char ;AN000; need CAPS by char table ?
|
|
je $P_RLT_CAP01 ;AN000;
|
|
|
|
mov al,$P_DOSTBL_Char ;AN000; use character upper case table
|
|
$P_RLT_CAP02: ;AN000;
|
|
call $P_Do_CAPS_String ;AN000; process CAPS along the table
|
|
$P_RLT_CAP01: ;AN000;
|
|
pop ax ;AN000;
|
|
test byte ptr es:[bx].$P_Function_Flag,$P_Rm_Colon ;AN000; removing colon at end ?
|
|
je $P_RLT_Exit ;AN000;
|
|
|
|
call $P_Remove_Colon ;AN000; then process it.
|
|
$P_RLT_Exit: ;AN000;
|
|
pop di ;AN000;
|
|
ret ;AN000;
|
|
$P_Fill_Result endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_Check_Match_Flags
|
|
;
|
|
; Function: Check the mutch_flags and make the exit code and set the
|
|
; result buffer
|
|
;
|
|
; Check for types in this order:
|
|
; Complex
|
|
; Date
|
|
; Time
|
|
; Drive
|
|
; Filespec
|
|
; Quoted String
|
|
; Simple String
|
|
;
|
|
; Input: psdata_seg:SI -> $P_STRING_BUF
|
|
; ES:BX -> CONTROL block
|
|
;
|
|
; Output: None
|
|
;
|
|
; Use: $P_Value, P$_SValue, $P_Simple_String, $P_Date_Format
|
|
; $P_Time_Format, $P_Complex_Format, $P_File_Foemat
|
|
; $P_Drive_Format
|
|
;***********************************************************************
|
|
$P_Check_Match_Flags proc ;AN000;
|
|
mov psdata_seg:$P_err_flag,$P_NULL ;AN033;AC034;; clear filespec error flag.
|
|
push ax ;AN000;
|
|
mov ax,es:[bx].$P_Match_Flag ;AN000; load match flag(16bit) to ax
|
|
|
|
or ax,ax ;AC035; test ax for zero
|
|
;(changed ;AC035;) cmp ax,0 ;AN000; (tm12)
|
|
jne $P_Mat ;AN000; (tm12)
|
|
|
|
push ax ;AN000; (tm12)
|
|
push bx ;AN000; (tm12)
|
|
push dx ;AN000; (tm12)
|
|
push di ;AN000; (tm12)
|
|
mov psdata_seg:$P_RC,$P_Syntax ;AC034; (tm12)
|
|
mov ah,$P_No_Tag ;AN000; (tm12)
|
|
mov al,$P_String ;AN000; (tm12)
|
|
call $P_Fill_Result ;AN000; (tm12)
|
|
pop di ;AN000; (tm12)
|
|
pop dx ;AN000; (tm12)
|
|
pop bx ;AN000; (tm12)
|
|
pop ax ;AN000; (tm12)
|
|
jmp short $P_Bridge ;AC035; (tm12)
|
|
|
|
$P_Mat: ;AN000; (tm12)
|
|
|
|
IF CmpxSW ;AN000;(Check if complex item is supported)
|
|
test ax,$P_Cmpx_S ;AN000; Complex string
|
|
je $P_Match01 ;AN000;
|
|
|
|
mov psdata_seg:$P_RC,$P_No_Error ;AC034; assume no error
|
|
call $P_Complex_Format ;AN000; do process
|
|
cmp psdata_seg:$P_RC,$P_Syntax ;AC034; if error, examine the next type
|
|
jne $P_Bridge ;AN000;
|
|
|
|
$P_Match01: ;AN000;
|
|
ENDIF ;AN000;(of CmpxSW)
|
|
IF DateSW ;AN000;(Check if date format is supported)
|
|
test ax,$P_Date_S ;AN000; Date string
|
|
je $P_Match02 ;AN000;
|
|
|
|
mov psdata_seg:$P_RC,$P_No_Error ;AC034; assume no error
|
|
call $P_Date_Format ;AN000; do process
|
|
cmp psdata_seg:$P_RC,$P_Syntax ;AC034; if error, examine the next type
|
|
jne $P_Bridge ;AN000;
|
|
|
|
$P_Match02: ;AN000;
|
|
ENDIF ;AN000;(of DateSW)
|
|
IF TimeSW ;AN000;(Check if time format is supported)
|
|
test ax,$P_Time_S ;AN000; Time string
|
|
je $P_Match03 ;AN000;
|
|
|
|
mov psdata_seg:$P_RC,$P_No_Error ;AC034; assume no error
|
|
call $P_Time_Format ;AN000; do process
|
|
cmp psdata_seg:$P_RC,$P_Syntax ;AC034; if error, examine the next type
|
|
; je $P_Match03 ;AN000:
|
|
|
|
jne $P_Bridge ;AN000; (tm09)
|
|
|
|
ENDIF ;AN000;(of TimeSW) (tm04)
|
|
jmp short $P_Match03 ;AN025; (tm09)
|
|
|
|
$P_Bridge: ;AN000;
|
|
; jmp short $P_Match_Exit (tm02)
|
|
|
|
jmp $P_Match_Exit ;AN000; (tm02)
|
|
|
|
$P_Match03: ;AN000;
|
|
; ENDIF ;AN000;(of TimeSW) (tm04)
|
|
IF NumSW ;AN000;(Check if numeric value is supported)
|
|
test ax,$P_Num_Val ;AN000; Numeric value
|
|
je $P_Match04 ;AN000;
|
|
|
|
mov psdata_seg:$P_RC,$P_No_Error ;AC034; assume no error
|
|
call $P_Value ;AN000; do process
|
|
cmp psdata_seg:$P_RC,$P_Syntax ;AC034; if error, examine the next type
|
|
jne $P_Match_Exit ;AN000;
|
|
|
|
$P_Match04: ;AN000;
|
|
test ax,$P_SNUM_Val ;AN000; Signed numeric value
|
|
je $P_Match05 ;AN000;
|
|
|
|
mov psdata_seg:$P_RC,$P_No_Error ;AC034; assume no error
|
|
call $P_SValue ;AN000; do process
|
|
cmp psdata_seg:$P_RC,$P_Syntax ;AC034; if error, examine the next type
|
|
jne $P_Match_Exit ;AN000;
|
|
|
|
$P_Match05: ;AN000;
|
|
ENDIF ;AN000;(of NumSW)
|
|
IF DrvSW ;AN000;(Check if drive only is supported)
|
|
test ax,$P_Drv_Only ;AN000; Drive only
|
|
je $P_Match06 ;AN000;
|
|
|
|
mov psdata_seg:$P_RC,$P_No_Error ;AC034; assume no error
|
|
call $P_File_Format ;AN000; 1st, call file format
|
|
call $P_Drive_Format ;AN000; check drive format, next
|
|
cmp psdata_seg:$P_RC,$P_Syntax ;AC034; if error, examinee the next type
|
|
jne $P_Match_Exit ;AN000;
|
|
|
|
$P_Match06: ;AN000;
|
|
ENDIF ;AN000;(of DrvSW)
|
|
IF FileSW ;AN000;(Check if file spec is supported)
|
|
test ax,$P_File_Spc ;AN000; File spec
|
|
je $P_Match07 ;AN000;
|
|
|
|
mov psdata_seg:$P_RC,$P_No_Error ;AC034; assume no error
|
|
call $P_File_Format ;AN000; do process
|
|
cmp psdata_seg:$P_RC,$P_Syntax ;AC034; if error, examine the next type
|
|
jne $P_Match_Exit ;AN000;
|
|
|
|
$P_Match07: ;AN000;
|
|
ENDIF ;AN000;(of FileSW)
|
|
IF QusSW ;AN000;(Check if quoted string is supported)
|
|
test ax,$P_Qu_String ;AN000; Quoted string
|
|
je $P_Match08 ;AN000;
|
|
|
|
mov psdata_seg:$P_RC,$P_No_Error ;AC034; assume no error
|
|
call $P_Quoted_Format ;AN000; do process
|
|
cmp psdata_seg:$P_RC,$P_Syntax ;AC034; if error, examine the next type
|
|
jne $P_Match_Exit ;AN000;
|
|
|
|
$P_Match08: ;AN000;
|
|
ENDIF ;AN000;(of QusSW)
|
|
test ax,$P_Simple_S ;AN000; Simple string
|
|
je $P_Match09 ;AN000;
|
|
|
|
mov psdata_seg:$P_RC,$P_No_Error ;AC034; assume no error
|
|
call $P_Simple_String ;AN000; do process
|
|
;;;; cmp psdata_seg:$P_RC,$P_Syntax ;AC034; These two lines will be alive
|
|
;;;; jne $P_Match_Exit ;when extending the match_flags.
|
|
$P_Match09: ;AN000;
|
|
$P_Match_Exit: ;AN000;
|
|
cmp psdata_seg:$P_err_flag,$P_error_filespec ;AC034; bad filespec ?
|
|
jne $P_Match2_Exit ;AN033; no, continue
|
|
cmp psdata_seg:$P_RC,$P_No_Error ;AN033;AC034;; check for other errors ?
|
|
jne $P_Match2_Exit ;AN033; no, continue
|
|
mov psdata_seg:$P_RC,$P_Syntax ;AN033;AC034;; set error flag
|
|
$P_Match2_Exit: ;AN033;
|
|
pop ax ;AN000;
|
|
ret ;AN000;
|
|
$P_Check_Match_Flags endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_Remove_Colon;
|
|
;
|
|
; Function: Remove colon at end
|
|
;
|
|
; Input: psdata_seg:SI points to string buffer to be examineed
|
|
;
|
|
; Output: None
|
|
;
|
|
; Use: $P_Chk_DBCS
|
|
;***********************************************************************
|
|
$P_Remove_Colon proc ;AN000;
|
|
push ax ;AN000;
|
|
push si ;AN000;
|
|
$P_RCOL_Loop: ;AN000;
|
|
mov al,psdata_seg:[si] ;AN000; get character
|
|
or al,al ;AN000; end of string ?
|
|
je $P_RCOL_Exit ;AN000; if yes, just exit
|
|
|
|
cmp al,$P_Colon ;AN000; is it colon ?
|
|
jne $P_RCOL00 ;AN000;
|
|
|
|
cmp byte ptr psdata_seg:[si+byte],$P_NULL ;AN000; if so, next is NULL ?
|
|
jne $P_RCOL00 ;AN000; no, then next char
|
|
|
|
mov byte ptr psdata_seg:[si],$P_NULL ;AN000; yes, remove colon
|
|
jmp short $P_RCOL_Exit ;AN000; and exit.
|
|
|
|
$P_RCOL00: ;AN000;
|
|
call $P_Chk_DBCS ;AN000; if not colon, then check if
|
|
jnc $P_RCOL01 ;AN000; DBCS leading byte.
|
|
|
|
inc si ;AN000; if yes, skip trailing byte
|
|
$P_RCOL01: ;AN000;
|
|
inc si ;AN000; si points to next byte
|
|
jmp short $P_RCOL_Loop ;AN000; loop until NULL encountered
|
|
|
|
$P_RCOL_Exit: ;AN000;
|
|
pop si ;AN000;
|
|
pop ax ;AN000;
|
|
ret ;AN000;
|
|
$P_Remove_Colon endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_Do_CAPS_String;
|
|
;
|
|
; Function: Perform capitalization along with the file case map table
|
|
; or character case map table.
|
|
;
|
|
; Input: AL = 2 : Use character table
|
|
; AL = 4 : Use file table
|
|
; psdata_seg:SI points to string buffer to be capitalized
|
|
;
|
|
; Output: None
|
|
;
|
|
; Use: $P_Do_CAPS_Char, $P_Chk_DBCS
|
|
;***********************************************************************
|
|
$P_Do_CAPS_String proc ;AN000;
|
|
push si ;AN000;
|
|
push dx ;AN000;
|
|
mov dl,al ;AN000; save info id
|
|
|
|
$P_DCS_Loop: ;AN000;
|
|
mov al,psdata_seg:[si] ;AN000; load charater and
|
|
call $P_Chk_DBCS ;AN000; check if DBCS leading byte
|
|
jc $P_DCS00 ;AN000; if yes, do not need CAPS
|
|
|
|
or al,al ;AN000; end of string ?
|
|
je $P_DCS_Exit ;AN000; then exit.
|
|
|
|
call $P_Do_CAPS_Char ;AN000; Here a SBCS char need to be CAPS
|
|
mov psdata_seg:[si],al ;AN000; stored upper case char to buffer
|
|
jmp short $P_DCS01 ;AN000; process nexit
|
|
$P_DCS00: ;AN000;
|
|
inc si ;AN000; skip DBCS leading and trailing byte
|
|
$P_DCS01: ;AN000;
|
|
inc si ;AN000; si point to next byte
|
|
jmp short $P_DCS_Loop ;AN000; loop until NULL encountered
|
|
$P_DCS_Exit: ;AN000;
|
|
pop dx ;AN000;
|
|
pop si ;AN000;
|
|
ret ;AN000;
|
|
$P_Do_CAPS_String endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_Do_CAPS_Char;
|
|
;
|
|
; Function: Perform capitalization along with the file case map table
|
|
; or character case map table.
|
|
;
|
|
; Input: DL = 2 : Use character table
|
|
; DL = 4 : Use file table
|
|
; AL = character to be capitalized
|
|
;
|
|
; Output: None
|
|
;
|
|
; Use: INT 21h /w AH=65h
|
|
;***********************************************************************
|
|
$P_Do_CAPS_Char proc ;AN000;
|
|
cmp al,$P_ASCII80 ;AN000; need upper case table ?
|
|
jae $P_DCC_Go ;AN000;
|
|
|
|
cmp al,"a" ;AN000; if no,
|
|
jb $P_CAPS_Ret ;AN000; check if "a" <= AL <= "z"
|
|
|
|
cmp al,"z" ;AN000;
|
|
ja $P_CAPS_Ret ;AN000; if yes, make CAPS
|
|
|
|
and al,$P_Make_Upper ;AN000; else do nothing.
|
|
jmp short $P_CAPS_Ret ;AN000;
|
|
|
|
$P_DCC_Go: ;AN000;
|
|
push bx ;AN000;
|
|
push es ;AN000;
|
|
push di ;AN000;
|
|
IF CAPSW ;AN000;(Check if uppercase conversion is supported)
|
|
lea di,psdata_seg:$P_File_CAP_Ptr ;AC034;
|
|
cmp dl,$P_DOSTBL_File ;AN000; Use file CAPS table ?
|
|
je $P_DCC00 ;AN000;
|
|
|
|
ENDIF ;AN000;(of CAPSW)
|
|
lea di,psdata_seg:$P_Char_CAP_Ptr ;AC034; or use char CAPS table ?
|
|
$P_DCC00: ;AN000;
|
|
cmp psdata_seg:[di],dl ;AN000; already got table address ?
|
|
je $P_DCC01 ;AN000; if no,
|
|
|
|
;In this next section, ES will be used to pass a 5 byte workarea to INT 21h,
|
|
; the GET COUNTYRY INFO call. This usage of ES is required by the function
|
|
; call, regardless of what base register is currently be defined as PSDATA_SEG.
|
|
;BASESW EQU 0 means that ES is the psdata_seg reg.
|
|
|
|
IFDEF BASESW ;AN037; If BASESW has been defined, and
|
|
IFE BASESW ;AN037; If ES is psdata base
|
|
push PSDATA_SEG ;AN037; save current base reg
|
|
ENDIF ;AN037;
|
|
ENDIF ;AN037;
|
|
|
|
push ax ;AN000; get CAPS table thru DOS call
|
|
push cx ;AN000;
|
|
push dx ;AN000;
|
|
|
|
|
|
push PSDATA_SEG ;AC036; pass current base seg into
|
|
;(Note: this used to push CS. BUG...
|
|
pop es ;AN000; ES reg, required for
|
|
;get extended country information
|
|
mov ah,$P_DOS_Get_TBL ;AN000; get extended CDI
|
|
mov al,dl ;AN000; upper case table
|
|
mov bx,$P_DOSTBL_Def ;AN000; get active CON
|
|
mov cx,$P_DOSTBL_BL ;AN000; buffer length
|
|
mov dx,$P_DOSTBL_Def ;AN000; get for default code page
|
|
;DI already set to point to buffer
|
|
int 21h ;AN000; es:di point to buffer that
|
|
;now has been filled in with info
|
|
pop dx ;AN000;
|
|
pop cx ;AN000;
|
|
pop ax ;AN000;
|
|
IFDEF BASESW ;AN037; If BASESW has been defined, and
|
|
IFE BASESW ;AN037; If ES is psdata base
|
|
pop PSDATA_SEG ;AN037; restore current base reg
|
|
ENDIF ;AN037;
|
|
ENDIF ;AN037;
|
|
$P_DCC01: ;AN000;
|
|
|
|
;In this next section, ES will be used as the base of the XLAT table, provided
|
|
; by the previous GET COUNTRY INFO DOS call. This usage of ES is made
|
|
; regardless of which base reg is currently the PSDATA_SEG reg.
|
|
|
|
IFDEF BASESW ;AN037; If BASESW has been defined, and
|
|
IFE BASESW ;AN037; If ES is psdata base
|
|
push PSDATA_SEG ;AN037; save current base reg
|
|
ENDIF ;AN037;
|
|
ENDIF ;AN037;
|
|
mov bx,psdata_seg:[di+$P_DOS_TBL_Off] ;AN000; get offset of table
|
|
mov es,psdata_seg:[di+$P_DOS_TBL_Seg] ;AN000; get segment of table
|
|
inc bx ;AC035; add '2' to
|
|
inc bx ;AC035; BX reg
|
|
;AN000; skip length field
|
|
;(changed ;AN035;) add bx,word ;AN000; skip length field
|
|
sub al,$P_ASCII80 ;AN000; make char to index
|
|
xlat es:[bx] ;AN000; perform case map
|
|
|
|
IFDEF BASESW ;AN037; If BASESW has been defined, and
|
|
IFE BASESW ;AN037; If ES is psdata base
|
|
pop PSDATA_SEG ;AN037; restore current base reg
|
|
ENDIF ;AN037;
|
|
ENDIF ;AN037;
|
|
pop di ;AN000;
|
|
pop es ;AN000;
|
|
pop bx ;AN000;
|
|
$P_CAPS_Ret: ;AN000;
|
|
ret ;AN000;
|
|
$P_Do_CAPS_Char endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
IF NumSW ;AN000;(Check if numeric value is supported)
|
|
; $P_Value / $P_SValue
|
|
;
|
|
; Function: Make 32bit value from psdata_seg:SI and see value list
|
|
; and make result buffer.
|
|
; $P_SValue is an entry point for the signed value
|
|
; and this will simply call $P_Value after the handling
|
|
; of the sign character, "+" or "-"
|
|
;
|
|
; Input: psdata_seg:SI -> $P_STRING_BUF
|
|
; ES:BX -> CONTROL block
|
|
;
|
|
; Output: None
|
|
;
|
|
; Use: $P_Fill_Result, $P_Check_OVF
|
|
;
|
|
; Vars: $P_RC(W), $P_Flags(RW)
|
|
;***********************************************************************
|
|
$P_SValue proc ;AN000; when signed value here
|
|
push ax ;AN000;
|
|
or psdata_seg:$P_Flags2,$P_Signed ;AC034; indicate a signed numeric
|
|
and psdata_seg:$P_Flags2,0ffh-$P_Neg ;AC034; assume positive value
|
|
mov al,psdata_seg:[si] ;AN000; get sign
|
|
cmp al,$P_Plus ;AN000; "+" ?
|
|
je $P_SVal00 ;AN000;
|
|
|
|
cmp al,$P_Minus ;AN000; "-" ?
|
|
jne $P_Sval01 ;AN000; else
|
|
|
|
or psdata_seg:$P_Flags2,$P_Neg ;AC034; set this is negative value
|
|
$P_SVal00: ;AN000;
|
|
inc si ;AN000; skip sign char
|
|
$P_Sval01: ;AN000;
|
|
call $P_Value ;AN000; and process value
|
|
pop ax ;AN000;
|
|
ret ;AN000;
|
|
$P_SValue endp ;AN000;
|
|
;***********************************************************************
|
|
$P_Value proc ;AN000;
|
|
push ax ;AN000;
|
|
push cx ;AN000;
|
|
push dx ;AN000;
|
|
push si ;AN000;
|
|
xor cx,cx ;AN000; cx = higher 16 bits
|
|
xor dx,dx ;AN000; dx = lower 16 bits
|
|
push bx ;AN000; save control pointer
|
|
$P_Value_Loop: ;AN000;
|
|
mov al,psdata_seg:[si] ;AN000; get character
|
|
or al,al ;AN000; end of line ?
|
|
je $P_Value00 ;AN000;
|
|
|
|
call $P_0099 ;AN000; make asc(0..9) to bin(0..9)
|
|
jc $P_Value_Err0 ;AN000;
|
|
|
|
xor ah,ah ;AN000;
|
|
mov bp,ax ;AN000; save binary number
|
|
shl dx,1 ;AN000; to have 2*x
|
|
rcl cx,1 ;AN000; shift left w/ carry
|
|
call $P_Check_OVF ;AN000; Overflow occurred ?
|
|
jc $P_Value_Err0 ;AN000; then error, exit
|
|
|
|
mov bx,dx ;AN000; save low(2*x)
|
|
mov ax,cx ;AN000; save high(2*x)
|
|
shl dx,1 ;AN000; to have 4*x
|
|
rcl cx,1 ;AN000; shift left w/ carry
|
|
call $P_Check_OVF ;AN000; Overflow occurred ?
|
|
jc $P_Value_Err0 ;AN000; then error, exit
|
|
|
|
shl dx,1 ;AN000; to have 8*x
|
|
rcl cx,1 ;AN000; shift left w/ carry
|
|
call $P_Check_OVF ;AN000; Overflow occurred ?
|
|
jc $P_Value_Err0 ;AN000; then error, exit
|
|
|
|
add dx,bx ;AN000; now have 10*x
|
|
adc cx,ax ;AN000; 32bit ADD
|
|
call $P_Check_OVF ;AN000; Overflow occurred ?
|
|
jc $P_Value_Err0 ;AN000; then error, exit
|
|
|
|
add dx,bp ;AN000; Add the current one degree decimal
|
|
adc cx,0 ;AN000; if carry, add 1 to high 16bit
|
|
call $P_Check_OVF ;AN000; Overflow occurred ?
|
|
jc $P_Value_Err0 ;AN000; then error, exit
|
|
|
|
inc si ;AN000; update pointer
|
|
jmp short $P_Value_Loop ;AN000; loop until NULL encountered
|
|
;
|
|
$P_Value_Err0: ;AN000;
|
|
pop bx ;AN000;
|
|
jmp $P_Value_Err ;AN000; Bridge
|
|
;
|
|
$P_Value00: ;AN000;
|
|
pop bx ;AN000; restore control pointer
|
|
test psdata_seg:$P_Flags2,$P_Neg ;AC034; here cx,dx = 32bit value
|
|
je $P_Value01 ;AN000; was it negative ?
|
|
|
|
not cx ;AN000; +
|
|
not dx ;AN000; |- Make 2's complement
|
|
add dx,1 ;AN000; |
|
|
adc cx,0 ;AN000; +
|
|
$P_Value01: ;AN000; / nval =0
|
|
mov si,es:[bx].$P_Value_List ;AN000; si points to value list
|
|
mov al,es:[si] ;AN000; get nval
|
|
cmp al,$P_nval_None ;AN000; no value list ?
|
|
jne $P_Value02 ;AN000;
|
|
|
|
mov al,$P_Number ;AN000; Set type
|
|
mov ah,$P_No_Tag ;AN000; No ITEM_TAG set
|
|
jmp $P_Value_Exit ;AN000;
|
|
|
|
$P_Value02: ;AN000; / nval = 1
|
|
IF Val1SW ;AN000;(Check if value list id #1 is supported)
|
|
;(tm07) cmp al,$P_nval_Range ;AN000; have range list ?
|
|
;(tm07) jne $P_Value03 ;AN000;
|
|
|
|
inc si ;AN000;
|
|
mov al,es:[si] ;AN000; al = number of range
|
|
cmp al,$P_No_nrng ;AN000; (tm07)
|
|
je $P_Value03 ;AN000; (tm07)
|
|
|
|
inc si ;AN000; si points to 1st item_tag
|
|
$P_Val02_Loop: ;AN000;
|
|
test psdata_seg:$P_Flags2,$P_Signed ;AC034;
|
|
jne $P_Val02_Sign ;AN000;
|
|
|
|
cmp cx,es:[si+$P_Val_XH] ;AN000; comp cx with XH
|
|
jb $P_Val02_Next ;AN000;
|
|
|
|
ja $P_Val_In ;AN000;
|
|
|
|
cmp dx,es:[si+$P_Val_XL] ;AN000; comp dx with XL
|
|
jb $P_Val02_Next ;AN000;
|
|
|
|
$P_Val_In: ;AN000;
|
|
;;;;;; cmp cx,es:$P_Val_YH] ; comp cx with YH (tm01)
|
|
cmp cx,es:[si+$P_Val_YH] ;AN000; comp cx with YH (tm01)
|
|
ja $P_Val02_Next ;AN000;
|
|
|
|
jb $P_Val_Found ;AN000;
|
|
|
|
cmp dx,es:[si+$P_Val_YL] ;AN000; comp dx with YL
|
|
ja $P_Val02_Next ;AN000;
|
|
|
|
jmp short $P_Val_Found ;AN000;
|
|
|
|
$P_Val02_Sign: ;AN000;
|
|
cmp cx,es:[si+$P_Val_XH] ;AN000; comp cx with XH
|
|
jl $P_Val02_Next ;AN000;
|
|
|
|
jg $P_SVal_In ;AN000;
|
|
|
|
cmp dx,es:[si+$P_Val_XL] ;AN000; comp dx with XL
|
|
jl $P_Val02_Next ;AN000;
|
|
|
|
$P_SVal_In: ;AN000;
|
|
cmp cx,es:[si+$P_Val_YH] ;AN000; comp cx with YH
|
|
jg $P_Val02_Next ;AN000;
|
|
|
|
jl $P_Val_Found ;AN000;
|
|
|
|
cmp dx,es:[si+$P_Val_YL] ;AN000; comp dx with YL
|
|
jg $P_Val02_Next ;AN000;
|
|
|
|
jmp short $P_Val_Found ;AN000;
|
|
|
|
$P_Val02_Next: ;AN000;
|
|
add si,$P_Len_Range ;AN000;
|
|
dec al ;AN000; loop nrng times in AL
|
|
jne $P_Val02_Loop ;AN000;
|
|
; / Not found
|
|
mov psdata_seg:$P_RC,$P_Out_of_Range ;AC034;
|
|
mov al,$P_Number ;AN000;
|
|
mov ah,$P_No_Tag ;AN000; No ITEM_TAG set
|
|
jmp short $P_Value_Exit ;AN000;
|
|
|
|
ENDIF ;AN000;(of Val1SW)
|
|
IF Val1SW+Val2SW ;AN000;(Check if value list id #1 or #2 is supported)
|
|
$P_Val_Found: ;AN000;
|
|
mov al,$P_Number ;AN000;
|
|
mov ah,es:[si] ;AN000; found ITEM_TAG set
|
|
jmp short $P_Value_Exit ;AN000;
|
|
|
|
ENDIF ;AN000;(of Val1SW+Val2SW)
|
|
$P_Value03: ;AN000; / nval = 2
|
|
IF Val2SW ;AN000;(Check if value list id #2 is supported)
|
|
;;;; cmp al,$P_nval_Value ; have match list ? ASSUME nval=2,
|
|
;;;; jne $P_Value04 ; even if it is 3 or more.
|
|
;(tm07) inc si ;AN000;
|
|
;(tm07) mov al,es:[si] ;AN000; al = nrng
|
|
mov ah,$P_Len_Range ;AN000;
|
|
mul ah ;AN000; Skip nrng field
|
|
inc ax ;AN000;
|
|
add si,ax ;AN000; si points to nnval
|
|
mov al,es:[si] ;AN000; get nnval
|
|
inc si ;AN000; si points to 1st item_tag
|
|
$P_Val03_Loop: ;AN000;
|
|
cmp cx,es:[si+$P_Val_XH] ;AN000; comp cx with XH
|
|
jne $P_Val03_Next ;AN000;
|
|
|
|
cmp dx,es:[si+$P_Val_XL] ;AN000; comp dx with XL
|
|
je $P_Val_Found ;AN000;
|
|
|
|
$P_Val03_Next: ;AN000;
|
|
add si,$P_Len_Value ;AN000; points to next value choice
|
|
dec al ;AN000; loop nval times in AL
|
|
jne $P_Val03_Loop ;AN000;
|
|
;AN000; / Not found
|
|
mov psdata_seg:$P_RC,$P_Not_in_Val ;AC034;
|
|
mov al,$P_Number ;AN000;
|
|
mov ah,$P_No_Tag ;AN000; No ITEM_TAG set
|
|
jmp short $P_Value_Exit ;AN000;
|
|
|
|
ENDIF ;AN000;(of Val2SW)
|
|
$P_Value04: ;AN000; / nval = 3 or else
|
|
$P_Value_Err: ;AN000;
|
|
mov psdata_seg:$P_RC,$P_Syntax ;AC034;
|
|
mov al,$P_String ;AN000; Set type
|
|
mov ah,$P_No_Tag ;AN000; No ITEM_TAG set
|
|
$P_Value_Exit: ;AN000;
|
|
call $P_Fill_Result ;AN000;
|
|
pop si ;AN000;
|
|
pop dx ;AN000;
|
|
pop cx ;AN000;
|
|
pop ax ;AN000;
|
|
ret ;AN000;
|
|
$P_Value endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_Check_OVF
|
|
;
|
|
; Function: Check if overflow is occurred with consideration of
|
|
; signed or un-signed numeric value
|
|
;
|
|
; Input: Flag register
|
|
;
|
|
; Output: CY = 1 : Overflow
|
|
;
|
|
; Vars: $P_Flags(R)
|
|
;***********************************************************************
|
|
$P_Check_OVF proc ;AN000;
|
|
pushf ;AN000;
|
|
test psdata_seg:$P_Flags2,$P_Neg ;AC034; is it negative value ?
|
|
jne $P_COVF ;AN000; if no, check overflow
|
|
|
|
popf ;AN000; by the CY bit
|
|
ret ;AN000;
|
|
|
|
$P_COVF: ;AN000;
|
|
popf ;AN000; else,
|
|
jo $P_COVF00 ;AN000; check overflow by the OF
|
|
|
|
clc ;AN000; indicate it with CY bit
|
|
ret ;AN000; CY=0 means no overflow
|
|
|
|
$P_COVF00: ;AN000;
|
|
stc ;AN000; and CY=1 means overflow
|
|
ret ;AN000;
|
|
$P_Check_OVF endp ;AN000;
|
|
ENDIF ;AN000;(of FarSW)
|
|
;***********************************************************************
|
|
; $P_0099;
|
|
;
|
|
; Function: Make ASCII 0-9 to Binary 0-9
|
|
;
|
|
; Input: AL = character code
|
|
;
|
|
; Output: CY = 1 : AL is not number
|
|
; CY = 0 : AL contains binary value
|
|
;***********************************************************************
|
|
$P_0099 proc ;AN000;
|
|
cmp al,"0" ;AN000;
|
|
jb $P_0099Err ;AN000; must be 0 =< al =< 9
|
|
|
|
cmp al,"9" ;AN000;
|
|
ja $P_0099Err ;AN000; must be 0 =< al =< 9
|
|
|
|
sub al,"0" ;AN000; make char -> bin
|
|
clc ;AN000; indicate no error
|
|
ret ;AN000;
|
|
|
|
$P_0099Err: ;AN000;
|
|
stc ;AN000; indicate error
|
|
ret ;AN000;
|
|
$P_0099 endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_Simple_String
|
|
;
|
|
; Function: See value list for the simple string
|
|
; and make result buffer.
|
|
;
|
|
; Input: psdata_seg:SI -> $P_STRING_BUF
|
|
; ES:BX -> CONTROL block
|
|
;
|
|
; Output: None
|
|
;
|
|
; Use: $P_Fill_Result, $P_String_Comp
|
|
;
|
|
; Vars: $P_RC(W)
|
|
;***********************************************************************
|
|
$P_Simple_String proc ;AN000;
|
|
push ax ;AN000;
|
|
push bx ;AN000;
|
|
push dx ;AN000;
|
|
push di ;AN000;
|
|
mov di,es:[bx].$P_Value_List ;AN000; di points to value list
|
|
mov al,es:[di] ;AN000; get nval
|
|
or al,al ;AN000; no value list ?
|
|
jne $P_Sim00 ;AN000; then
|
|
|
|
mov ah,$P_No_Tag ;AN000; No ITEM_TAG set
|
|
jmp short $P_Sim_Exit ;AN000; and set result buffer
|
|
|
|
$P_Sim00: ;AN000;
|
|
IF Val3SW+KeySW ;AN000;(Check if keyword or value list id #3 is supported)
|
|
cmp al,$P_nval_String ;AN000; String choice list provided ?
|
|
jne $P_Sim01 ;AN000; if no, syntax error
|
|
|
|
inc di ;AN000;
|
|
mov al,es:[di] ;AN000; al = nrng
|
|
mov ah,$P_Len_Range ;AN000;
|
|
mul ah ;AN000; Skip nrng field
|
|
inc ax ;AN000; ax = (nrng*9)+1
|
|
add di,ax ;AN000; di points to nnval
|
|
mov al,es:[di] ;AN000; get nnval
|
|
mov ah,$P_Len_Value ;AN000;
|
|
mul ah ;AN000; Skip nnval field
|
|
inc ax ;AN000; ax = (nnval*5)+1
|
|
add di,ax ;AN000; di points to nstrval
|
|
mov al,es:[di] ;AN000; get nstrval
|
|
inc di ;AC035; add '2' to
|
|
inc di ;AC035; DI reg
|
|
;AN000; di points to 1st string in list
|
|
;(replaced ;AC035;) add di,2 ;AN000; di points to 1st string in list
|
|
$P_Sim_Loop: ;AN000;
|
|
mov bp,es:[di] ;AN000; get string pointer
|
|
call $P_String_Comp ;AN000; compare it with operand
|
|
jnc $P_Sim_Found ;AN000; found on list ?
|
|
|
|
add di,$P_Len_String ;AN000; if no, point to next choice
|
|
dec al ;AN000; loop nstval times in AL
|
|
jne $P_Sim_Loop ;AN000;
|
|
;AN000; / Not found
|
|
mov psdata_seg:$P_RC,$P_Not_In_Str ;AC034;
|
|
mov ah,$P_No_Tag ;AN000; No ITEM_TAG set
|
|
jmp short $P_Sim_Exit ;AN000;
|
|
|
|
$P_Sim_Found: ;AN000;
|
|
mov ah,es:[di-1] ;AN000; set item_tag
|
|
mov al,$P_List_Idx ;AN000;
|
|
mov dx,es:[di] ;AN000; get address of STRING
|
|
jmp short $P_Sim_Exit0 ;AN000;
|
|
ENDIF ;AN000;(of Val3SW+KeySW)
|
|
$P_Sim01: ;AN000;
|
|
mov psdata_seg:$P_RC,$P_Syntax ;AC034;
|
|
mov ah,$P_No_Tag ;AN000; No ITEM_TAG set
|
|
$P_Sim_Exit: ;AN000;
|
|
mov al,$P_String ;AN000; Set type
|
|
$P_Sim_Exit0: ;AN000;
|
|
call $P_Fill_Result ;AN000;
|
|
pop di ;AN000;
|
|
pop dx ;AN000;
|
|
pop bx ;AN000;
|
|
pop ax ;AN000;
|
|
ret ;AN000;
|
|
$P_Simple_String endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_String_Comp:
|
|
;
|
|
; Function: Compare two string
|
|
;
|
|
; Input: psdata_seg:SI -> 1st string
|
|
; ES:BP -> 2nd string (Must be upper case)
|
|
; ES:BX -> CONTROL block
|
|
;
|
|
; Output: CY = 1 if not match
|
|
;
|
|
; Use: $P_Chk_DBCS, $P_Do_CAPS_Char
|
|
;
|
|
; Vars: $P_KEYor_SW_Ptr(W), $P_Flags(R). $P_KEYorSW_Ptr
|
|
;***********************************************************************
|
|
$P_String_Comp proc ;AN000;
|
|
push ax ;AN000;
|
|
push bp ;AN000;
|
|
push dx ;AN000;
|
|
push si ;AN000;
|
|
mov dl,$P_DOSTBL_Char ;AN000; use character case map table
|
|
$P_SCOM_Loop: ;AN000;
|
|
mov al,psdata_seg:[si] ;AN000; get command character
|
|
call $P_Chk_DBCS ;AN000; DBCS ?
|
|
jc $P_SCOM00 ;AN000; yes,DBCS
|
|
|
|
call $P_Do_CAPS_Char ;AN000; else, upper case map before comparison
|
|
IF KeySW+SwSW ;AN000;(Check if keyword or switch is supported)
|
|
test psdata_seg:$P_Flags2,$P_Key_Cmp ;AC034; keyword search ?
|
|
je $P_SCOM04 ;AN000;
|
|
|
|
cmp al,$P_Keyword ;AN000; "=" is delimiter
|
|
jne $P_SCOM03 ;AN000;IF "=" on command line AND (bp+1=> char after the "=" in synonym list)
|
|
|
|
cmp byte ptr es:[bp+1],$P_NULL ;AN021; at end of keyword string in the control block THEN
|
|
jne $P_SCOM_DIFFER ;AN021;
|
|
|
|
jmp short $P_SCOM05 ;AN000; keyword found in synonym list
|
|
|
|
$P_SCOM04: ;AN000;
|
|
test psdata_seg:$P_Flags2,$P_SW_Cmp ;AC034; switch search ?
|
|
je $P_SCOM03 ;AN000;
|
|
|
|
cmp al,$P_Colon ;AN000; ":" is delimiter, at end of switch on command line
|
|
jne $P_SCOM03 ;AN000; continue compares
|
|
|
|
cmp byte ptr es:[bp],$P_NULL ;AN021; IF at end of switch on command AND
|
|
jne $P_SCOM_DIFFER ;AN021; at end of switch string in the control block THEN
|
|
|
|
$P_SCOM05: ;AN000; found a match
|
|
inc si ;AN000; si points to just after "=" or ":"
|
|
jmp short $P_SCOM_Same ;AN000; exit
|
|
|
|
$P_SCOM03: ;AN000;
|
|
ENDIF ;AN000;(of KeySW+SwSW)
|
|
cmp al,es:[bp] ;AN000; compare operand w/ a synonym
|
|
jne $P_SCOM_Differ0 ;AN000; if different, check ignore colon option
|
|
|
|
or al,al ;AN000; end of line
|
|
je $P_SCOM_Same ;AN000; if so, exit
|
|
|
|
inc si ;AN000; update operand pointer
|
|
inc bp ;AN000; and synonym pointer
|
|
jmp short $P_SCOM01 ;AN000; loop until NULL or "=" or ":" found in case
|
|
|
|
$P_SCOM00: ;AN000; Here al is DBCS leading byte
|
|
cmp al,es:[bp] ;AN000; compare leading byte
|
|
jne $P_SCOM_Differ ;AN000; if not match, say different
|
|
|
|
inc si ;AN000; else, load next byte
|
|
mov al,psdata_seg:[si] ;AN000; and
|
|
inc bp ;AN000;
|
|
cmp al,es:[bp] ;AN000; compare 2nd byte
|
|
jne $P_SCOM_Differ ;AN000; if not match, say different, too
|
|
|
|
inc si ;AN000; else update operand pointer
|
|
inc bp ;AN000; and synonym pointer
|
|
$P_SCOM01: ;AN000;
|
|
jmp short $P_SCOM_Loop ;AN000; loop until NULL or "=" or "/" found in case
|
|
|
|
$P_SCOM_Differ0: ;AN000;
|
|
|
|
IF SwSW ;AN000;(tm10)
|
|
test psdata_seg:$P_Flags2,$P_SW ;AC034;(tm10)
|
|
je $P_not_applicable ;AN000;(tm10)
|
|
|
|
test es:[bx].$P_Function_Flag,$P_colon_is_not_necessary ;AN000;(tm10)
|
|
je $P_not_applicable ;AN000;(tm10)
|
|
|
|
cmp byte ptr es:[bp],$P_NULL ;AN000;(tm10)
|
|
;(deleted ;AN025;) jne $P_not_applicable ;AN000;(tm10)
|
|
je $P_SCOM_Same ;AN025;(tm10)
|
|
|
|
$P_not_applicable: ;AN000;(tm10)
|
|
ENDIF ;AN000;(tm10)
|
|
|
|
test es:[bx].$P_Match_Flag,$P_Ig_Colon ;AN000; ignore colon option specified ?
|
|
je $P_SCOM_Differ ;AN000; if no, say different.
|
|
|
|
cmp al,$P_Colon ;AN000; End up with ":" and
|
|
jne $P_SCOM02 ;AN000; subseqently
|
|
|
|
cmp byte ptr es:[bp],$P_NULL ;AN000; NULL ?
|
|
jne $P_SCOM_Differ ;AN000; if no, say different
|
|
|
|
jmp short $p_SCOM_Same ;AN000; else, say same
|
|
|
|
$P_SCOM02: ;AN000;
|
|
cmp al,$P_NULL ;AN000; end up NULL and :
|
|
jne $P_SCOM_Differ ;AN000;
|
|
|
|
cmp byte ptr es:[bp],$P_Colon ;AN000; if no, say different
|
|
je $p_SCOM_Same ;AN000; else, say same
|
|
|
|
$P_SCOM_Differ: ;AN000;
|
|
stc ;AN000; indicate not found
|
|
jmp short $P_SCOM_Exit ;AN000;
|
|
|
|
$P_SCOM_Same: ;AN000;
|
|
mov psdata_seg:$P_KEYorSW_Ptr,si ;AC034; for later use by keyword or switch
|
|
clc ;AN000; indicate found
|
|
$P_SCOM_Exit: ;AN000;
|
|
pop si ;AN000;
|
|
pop dx ;AN000;
|
|
pop bp ;AN000;
|
|
pop ax ;AN000;
|
|
ret ;AN000;
|
|
$P_String_Comp endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
IF DateSW ;AN000;(Check if date format is supported)
|
|
; $P_Date_Format
|
|
;
|
|
; Function: Convert a date string to DOS date format for int 21h
|
|
; with format validation.
|
|
;
|
|
; Input: psdata_seg:SI -> $P_STRING_BUF
|
|
; ES:BX -> CONTROL block
|
|
;
|
|
; Output: None
|
|
;
|
|
; Use: $P_Fill_Result, $P_Set_CDI, $P_Get_DecNum
|
|
;
|
|
; Vars: $P_RC(W), $P_1st_Val(RW), $P_2nd_Val(RW), $P_3rd_Val(RW)
|
|
;***********************************************************************
|
|
$P_Date_Format proc ;AN000;
|
|
push ax ;AN000;
|
|
push cx ;AN000;
|
|
push dx ;AN000;
|
|
push si ;AN000;
|
|
push bx ;AN000;
|
|
push si ;AN000;
|
|
call $P_Set_CDI ;AN000; set country dependent information before process
|
|
; mov bl,psdata_seg:[si].$P_CDI_DateS ;load date separator ;AN020; (deleted)
|
|
; note: the country info is still needed
|
|
; to determine the order of the fields,
|
|
; but the separator char is no longer used.
|
|
pop si ;AN000;
|
|
mov psdata_seg:$P_1st_Val,0 ;AC034; set initial value
|
|
mov psdata_seg:$P_2nd_Val,0 ;AC034; set initial value
|
|
mov psdata_seg:$P_3rd_Val,0 ;AC034; set initial value
|
|
call $P_Get_DecNum ;AN000; get 1st number
|
|
jc $P_DateF_Err0 ;AN000;-----------------------+
|
|
|
|
mov psdata_seg:$P_1st_Val,ax ;AC034; |
|
|
or bl,bl ;AN000; end of line ? |
|
|
je $P_DateF_YMD ;AN000; |
|
|
|
|
call $P_Get_DecNum ;AN000; get 2nd number |
|
|
jc $P_DateF_Error ;AN000; |
|
|
|
|
mov psdata_seg:$P_2nd_Val,ax ;AC034; |
|
|
or bl,bl ;AN000; end of line ? |
|
|
je $P_DateF_YMD ;AN000; |
|
|
|
|
call $P_Get_DecNum ;AN000; get 3rd number |
|
|
$P_DateF_Err0: ;AN000; Bridge <-----------+
|
|
jc $P_DateF_Error ;AN000;
|
|
|
|
mov psdata_seg:$P_3rd_Val,ax ;AC034;
|
|
or bl,bl ;AN000; end of line ?
|
|
jne $P_DateF_Error ;AN000;
|
|
|
|
$P_DateF_YMD: ;AN000;
|
|
mov bx,psdata_seg:$P_Country_Info.$P_CDI_DateF ;AC034; get date format
|
|
cmp bx,$P_Date_YMD ;AN000;
|
|
je $P_DateF00 ;AN000;
|
|
|
|
mov ax,psdata_seg:$P_1st_Val ;AC034;
|
|
or ah,ah ;AN000;
|
|
jne $P_DateF_Error ;AN000;
|
|
|
|
mov cl,al ;AN000; set month
|
|
mov ax,psdata_seg:$P_2nd_Val ;AC034;
|
|
or ah,ah ;AN000; if overflow, error.
|
|
jne $P_DateF_Error ;AN000;
|
|
|
|
mov ch,al ;AN000; set date
|
|
mov dx,psdata_seg:$P_3rd_Val ;AC034; set year
|
|
cmp bx,$P_Date_DMY ;AN000; from here format = MDY
|
|
jne $P_DateF01 ;AN000; if it is DMY
|
|
|
|
xchg ch,cl ;AN000; then swap M <-> D
|
|
$P_DateF01: ;AN000;
|
|
jmp short $P_DateF02 ;AN000;
|
|
|
|
$P_DateF00: ;AN000; / here format = YMD
|
|
mov dx,psdata_seg:$P_1st_Val ;AC034; set year
|
|
mov ax,psdata_seg:$P_2nd_Val ;AC034;
|
|
or ah,ah ;AN000; if overflow, error
|
|
jne $P_DateF_Error ;AN000;
|
|
|
|
mov cl,al ;AN000; set month
|
|
mov ax,psdata_seg:$P_3rd_Val ;AC034;
|
|
or ah,ah ;AN000; if overflow, error
|
|
jne $P_DateF_Error ;AN000;
|
|
|
|
mov ch,al ;AN000; set date
|
|
$P_DateF02: ;AN000;
|
|
cmp dx,100 ;AN000; year is less that 100 ?
|
|
jae $P_DateF03 ;AN000;
|
|
|
|
add dx,1900 ;AN000; set year 19xx
|
|
$P_DateF03: ;AN000;
|
|
pop bx ;AN000; recover CONTROL block
|
|
pop si ;AN000; recover string pointer
|
|
mov ah,$P_No_Tag ;AN000; set
|
|
mov al,$P_Date_F ;AN000; result
|
|
call $P_Fill_Result ;AN000; buffer
|
|
jmp short $P_Date_Format_Exit ;AN000; to Date
|
|
|
|
$P_DateF_Error: ;AN000;
|
|
pop bx ;AN000; recover CONTROL block
|
|
pop si ;AN000; recover string pointer
|
|
mov ah,$P_No_Tag ;AN000; set
|
|
mov al,$P_String ;AN000; result
|
|
call $P_Fill_Result ;AN000; buffer to string
|
|
mov psdata_seg:$P_RC,$P_Syntax ;AC034; indicate syntax error
|
|
$P_Date_Format_Exit: ;AN000;
|
|
pop dx ;AN000;
|
|
pop cx ;AN000;
|
|
pop ax ;AN000;
|
|
ret ;AN000;
|
|
$P_Date_Format endp ;AN000;
|
|
ENDIF ;AN000;(of DateSW)
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
IF TimeSW+DateSW ;AN000;(Check if time or date format is supported)
|
|
; $P_Set_CDI:
|
|
;
|
|
; Function: Read CDI from DOS if it has not been read yet
|
|
;
|
|
; Input: None
|
|
;
|
|
; Output: psdata_seg:SI -> CDI
|
|
;
|
|
; Use: INT 21h w/ AH = 38h
|
|
;***********************************************************************
|
|
$P_Set_CDI proc ;AN000;
|
|
lea si,psdata_seg:$P_Country_Info ;AC034;
|
|
ifndef BILINGUAL
|
|
cmp psdata_seg:[si].$P_CDI_DateF,$P_NeedToBeRead ;AN000; already read ?
|
|
je $P_Read_CDI ;AN000;
|
|
|
|
jmp short $P_Set_CDI_Exit ;AN000; then do nothing
|
|
endif
|
|
|
|
$P_Read_CDI: ;AN000; else read CDI thru DOS
|
|
push ds ;AN000;
|
|
push dx ;AN000;
|
|
push ax ;AN000;
|
|
push PSDATA_SEG ;AC023;
|
|
pop ds ;AN000; set segment register
|
|
mov ax,$P_DOS_Get_CDI ;AN000; get country information
|
|
mov dx,si ;AN000; set offset of CDI in local data area
|
|
int 21h ;AN000;
|
|
pop ax ;AN000;
|
|
pop dx ;AN000;
|
|
pop ds ;AN000;
|
|
$P_Set_CDI_Exit: ;AN000;
|
|
ret ;AN000;
|
|
$P_Set_CDI endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_Get_DecNum:
|
|
;
|
|
; Function: Read a chcrater code from psdata_seg:SI until specified delimiter
|
|
; or NULL encountered. And make a decimal number.
|
|
;
|
|
; Input: psdata_seg:SI -> $P_STRING_BUF
|
|
;
|
|
; Output: BL = delimiter code or NULL
|
|
; AX = Decimal number
|
|
; SI advanced to the next number
|
|
; CY = 1 : Syntax error, AL = Latest examineed number
|
|
;
|
|
; Use: $P_0099
|
|
;***********************************************************************
|
|
$P_Get_DecNum proc ;AN000;
|
|
push cx ;AN000;
|
|
push dx ;AN000;
|
|
xor cx,cx ;AN000; cx will have final value
|
|
$P_GetNum_Loop: ;AN000;
|
|
mov al,psdata_seg:[si] ;AN000; load character
|
|
or al,al ;AN000; end of line ?
|
|
je $P_GetNum00 ;AN000; if yes, exit
|
|
|
|
cmp psdata_seg:$P_Got_Time,0 ;AC034; ;is this numeric in a time field? ;AC023
|
|
je $P_Do_Date_Delims ;AN000;no, go check out Date delimiters ;AC023
|
|
|
|
; Determine which delimiter(s) to check for. Colon & period or period only
|
|
cmp bl,$P_colon_period ;AN032; ;Time
|
|
jne $P_Do_Time_Delim1 ;AN032; ;only check for period
|
|
|
|
cmp al,$P_Colon ;AN032; ;Is this a valid delimiter ?
|
|
je $P_GetNum01 ;AN032; ;yes, exit
|
|
|
|
$P_Do_Time_Delim1: ;AN000;
|
|
cmp al,$P_Period ;;AC032;;AC023;Is this a valid delimiter ?
|
|
je $P_GetNum01 ;AC023; yes, exit
|
|
|
|
jmp short $P_Neither_Delims ;AN023;
|
|
|
|
$P_Do_Date_Delims: ;AN000;
|
|
;Regardless of the date delimiter character specified in the country
|
|
;dependent information, check for the presence of any one of these
|
|
;three field delimiters: "-", "/", or ".".
|
|
cmp al,$P_Minus ;AN020;is this a date delimiter character?
|
|
je $P_GetNum01 ;AN020;if yes, exit
|
|
|
|
cmp al,$P_Slash ;AN020;is this a date delimiter character?
|
|
je $P_GetNum01 ;AN020;if yes, exit
|
|
|
|
cmp al,$P_Period ;AN020;is this a date delimiter character?
|
|
je $P_GetNum01 ;AN000; if yes, exit
|
|
|
|
$P_Neither_Delims: ;AN023;
|
|
|
|
call $P_0099 ;AN000; convert it to binary
|
|
jc $P_GetNum_Exit ;AN000; if error exit
|
|
|
|
mov ah,0 ;AN000;
|
|
xchg ax,cx ;AN000;
|
|
mov dx,10 ;AN000;
|
|
mul dx ;AN000; ax = ax * 10
|
|
or dx,dx ;AN000; overflow
|
|
jne $P_GetNum02 ;AN000; then exit
|
|
|
|
add ax,cx ;AN000;
|
|
jc $P_GetNum_Exit ;AN000;
|
|
|
|
xchg ax,cx ;AN000;
|
|
inc si ;AN000;
|
|
jmp short $P_GetNum_Loop ;AN000;
|
|
|
|
$P_GetNum00: ;AN000;
|
|
mov bl,al ;AN000; set bl to NULL
|
|
clc ;AN000; indicate no error
|
|
jmp short $P_GetNum_Exit ;AN000;
|
|
|
|
$P_GetNum01: ;AN000;
|
|
inc si ;AN000; si points to next number
|
|
clc ;AN000; indicate no error
|
|
jmp short $P_GetNum_Exit ;AN000;
|
|
|
|
$P_GetNum02: ;AN000;
|
|
stc ;AN000; indicate error
|
|
$P_GetNum_Exit: ;AN000;
|
|
mov ax,cx ;AN000;return value
|
|
pop dx ;AN000;
|
|
pop cx ;AN000;
|
|
ret ;AN000;
|
|
$P_Get_DecNum endp ;AN000;
|
|
ENDIF ;AN000;(of TimeSW+DateSW)
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
IF TimeSW ;AN000;(Check if time format is supported)
|
|
; $P_Time_Format
|
|
;
|
|
; Function: Convert a time string to DOS time format for int 21h
|
|
; with format validation.
|
|
;
|
|
; Input: psdata_seg:SI -> $P_STRING_BUF
|
|
; ES:BX -> CONTROL block
|
|
;
|
|
; Output: None
|
|
;
|
|
; Use: $P_Fill_Result, $P_Set_CDI, $P_Get_DecNum, $P_Time_2412
|
|
;
|
|
; Vars: $P_RC(W), $P_Flags(R), $P_1st_Val(RW), $P_2nd_Val(RW)
|
|
; $P_3rd_Val(RW), $P_4th_Val(RW)
|
|
;***********************************************************************
|
|
$P_Time_Format proc ;AN000;
|
|
push ax ;AN000;
|
|
push cx ;AN000;
|
|
push dx ;AN000;
|
|
push si ;AN000;
|
|
push bx ;AN000;
|
|
push si ;AN000;
|
|
call $P_Set_CDI ;AN000; Set country independent
|
|
; information before process
|
|
;(AN032; deleted) mov bl,psdata_seg:[si].$P_CDI_TimeS ;load time separator
|
|
;(AN032; deleted) mov bh,psdata_seg:[si].$P_CDI_Dec ;load decimal separator
|
|
test byte ptr psdata_seg:[si].$P_CDI_TimeF,1 ;AN000; 24 hour system
|
|
pop si ;AN000;
|
|
jne $P_TimeF00 ;AN000; if no, means 12 hour system
|
|
|
|
call $P_Time_2412 ;AN000; this routine handle "am" "pm"
|
|
$P_TimeF00: ;AN000;
|
|
mov psdata_seg:$P_1st_Val,0 ;AC034; set initial value
|
|
mov psdata_seg:$P_2nd_Val,0 ;AC034; set initial value
|
|
mov psdata_seg:$P_3rd_Val,0 ;AC034; set initial value
|
|
mov psdata_seg:$P_4th_Val,0 ;AC034; set initial value
|
|
mov psdata_seg:$P_Got_Time,1 ;AN023;AC034;; use time delimiter
|
|
mov bl,$P_colon_period ;AN032; flag, indicates use of
|
|
; delimiters between hours,
|
|
; minutes,seconds
|
|
call $P_Get_DecNum ;AN000; get 1st number
|
|
jc $P_TimeF_Err0 ;AN000;
|
|
|
|
mov psdata_seg:$P_1st_Val,ax ;AC034;
|
|
or bl,bl ;AN000; end of line ?
|
|
je $P_TimeF_Rlt ;AN000;
|
|
|
|
call $P_Get_DecNum ;AN000; get 2nd number
|
|
jc $P_TimeF_Err0 ;AC038; if OK
|
|
|
|
mov psdata_seg:$P_2nd_Val,ax ;AC034;
|
|
or bl,bl ;AN000; end of line ?
|
|
je $P_TimeF_Rlt ;AN000;
|
|
|
|
;(;AN032; deleted) mov bl,bh ;set decimal separator
|
|
mov bl,$P_period_only ;AN032; flag, which to decimal separator
|
|
call $P_Get_DecNum ;AN000; get 3rd number
|
|
jc $P_TimeF_Err0 ;AC039; if problem, bridge to error
|
|
|
|
mov psdata_seg:$P_3rd_Val,ax ;AC034;
|
|
or bl,bl ;AN000; end of line ?
|
|
;(DELETED ;AN039;) je $P_TimeF_Rlt ;AN000;
|
|
jne $P_Time_4 ;AN039; NOT END OF LINE,
|
|
;AN039; GO TO 4TH NUMBER
|
|
test psdata_seg:$P_Flags1,$P_Time_Again ;AN039; HAS TIME PARSE
|
|
;AN039; BEEN REPEATED?
|
|
jnz $P_TimeF_Rlt ;AN039; yes, this is really
|
|
;AN039; the end of line
|
|
;AN039; no, time has not been repeated
|
|
mov si,psdata_seg:$P_SI_Save ;AN039; get where parser quit
|
|
;AN039; in command line
|
|
cmp byte ptr [si-1],$P_Comma ;AN039; look at delimiter
|
|
;AN039; from command line
|
|
jne $P_TimeF_Rlt ;AN039; was not a comma, this is
|
|
;AN039; really end of line
|
|
;AN039; is comma before hundredths,
|
|
;AN039; redo TIME
|
|
mov byte ptr [si-1],$P_Period ;AN039; change that ambiguous
|
|
;AN039; comma to a decimal point
|
|
;AN039; parse can understand
|
|
mov psdata_seg:$P_Flags,0 ;AN039; Clear all internal flags
|
|
or psdata_seg:$P_Flags1,$P_Time_Again ;AN039; indicate TIME
|
|
;AN039; is being repeated
|
|
mov cx,psdata_seg:$P_ORIG_ORD ;AN039; ORIGINAL ORDINAL FROM CX
|
|
mov sp,psdata_seg:$P_ORIG_STACK ;AN039; ORIGINAL VALUE
|
|
;AN039; OF STACK FROM SP
|
|
mov si,psdata_seg:$P_ORIG_SI ;AN039; ORIGINAL START
|
|
;AN039; PARSE POINTER FROM SI
|
|
jmp $P_Redo_Time ;AN039; go try TIME again
|
|
; ===============================================================
|
|
$P_Time_4: ;AN039; READY FOR 4TH (HUNDREDTHS) NUMBER
|
|
call $P_Get_DecNum ;AN000; get 4th number
|
|
$P_TimeF_Err0: ;AN000; Bridge
|
|
jc $P_TimeF_Error ;AN000;
|
|
|
|
mov psdata_seg:$P_4th_Val,ax ;AC034;
|
|
or bl,bl ;AN000; After hundredth, no data allowed
|
|
jne $P_TimeF_Error ;AN000; if some, then error
|
|
|
|
$P_TimeF_RLT: ;AN000;
|
|
mov ax,psdata_seg:$P_1st_Val ;AC034;
|
|
or ah,ah ;AN000; if overflow then error
|
|
jne $P_TimeF_Err ;AN000;
|
|
|
|
test psdata_seg:$P_Flags1,$P_Time12am ;AN038;if "am" specified
|
|
jz $P_Time_notAM ;AN038;skip if no "AM" specified
|
|
;since "AM" was specified,
|
|
cmp al,12 ;AN038: if hour specified as later than noon
|
|
ja $P_TimeF_Err ;AN038; error if "AM" on more than noon
|
|
jne $P_Time_notAM ;AN038; for noon exactly,
|
|
|
|
xor al,al ;AN038; set hour = zero
|
|
$P_Time_notAM: ;AN038;
|
|
test psdata_seg:$P_Flags2,$P_Time12 ;AC034; if 12 hour system and pm is specified
|
|
je $P_TimeSkip00 ;AN000; then
|
|
|
|
cmp al,12 ;AN038; if 12:00 o'clock already
|
|
je $P_TimeSkip00 ;AN038; it is PM already
|
|
|
|
add al,12 ;AN000; add 12 hours to make it afternoon
|
|
jc $P_TimeF_Err ;AN000; if overflow then error
|
|
|
|
cmp al,24 ;AN038; after adding 12, now cannot be >24
|
|
ja $P_TimeF_Err ;AN038; if too big, error
|
|
|
|
$P_TimeSkip00: ;AN000;
|
|
mov dl,al ;AN000; set hour
|
|
mov ax,psdata_seg:$P_2nd_Val ;AC034;
|
|
or ah,ah ;AN000; if overflow then error
|
|
jne $P_TimeF_Err ;AN000;
|
|
|
|
mov dh,al ;AN000; set minute
|
|
mov ax,psdata_seg:$P_3rd_Val ;AC034;
|
|
or ah,ah ;AN000; if overflow then error
|
|
jne $P_TimeF_Err ;AN000;
|
|
|
|
mov cl,al ;AN000; set second
|
|
mov ax,psdata_seg:$P_4th_Val ;AC034;
|
|
or ah,ah ;AN000; if overflow then error
|
|
jne $P_TimeF_Err ;AN000;
|
|
|
|
mov ch,al ;AN000; set hundredth
|
|
pop bx ;AN000; recover CONTROL block
|
|
pop si ;AN000; recover string pointer
|
|
mov ah,$P_No_Tag ;AN000; set
|
|
mov al,$P_Time_F ;AN000; result
|
|
call $P_Fill_Result ;AN000; buffer
|
|
jmp short $P_Time_Format_Exit ;AN000; to time
|
|
|
|
$P_TimeF_Error: ;AN000;
|
|
$P_TimeF_Err: ;AN000;
|
|
pop bx ;AN000; recover CONTROL block
|
|
pop si ;AN000; recover string pointer
|
|
mov ah,$P_No_Tag ;AN000; set
|
|
mov al,$P_String ;AN000; result
|
|
call $P_Fill_Result ;AN000; buffer to string
|
|
mov psdata_seg:$P_RC,$P_Syntax ;AC034; return syntax error
|
|
$P_Time_Format_Exit: ;AN000;
|
|
mov psdata_seg:$P_Got_Time,0 ;AN023;AC034;; finished with this time field
|
|
pop dx ;AN000;
|
|
pop cx ;AN000;
|
|
pop ax ;AN000;
|
|
ret ;AN000;
|
|
$P_Time_Format endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_Time_2412:
|
|
;
|
|
; Function: Remove "a", "p", "am", or "pm" from the end of stinrg
|
|
;
|
|
; Input: psdata_seg:SI -> $P_STRING_BUF
|
|
;
|
|
; Output: Set $P_Time12 flag when the string is terminated by "p"
|
|
; or "pm"
|
|
;
|
|
; Vars: $P_Flags(W)
|
|
;***********************************************************************
|
|
$P_Time_2412 proc ;AN000;
|
|
push ax ;AN000;
|
|
push si ;AN000;
|
|
$P_T12_Loop: ;AN000;
|
|
mov al,psdata_seg:[si] ;AN000; Move
|
|
inc si ;AN000; si
|
|
or al,al ;AN000; to
|
|
jne $P_T12_Loop ;AN000; end of string
|
|
|
|
mov al,psdata_seg:[si-word] ;AN000; get char just before NULL
|
|
or al,$P_Make_Lower ;AN000; lower case map
|
|
cmp al,"p" ;AN000; only "p" of "pm" ?
|
|
je $P_T1200 ;AN000;
|
|
|
|
cmp al,"a" ;AN000; only "a" of "am" ?
|
|
je $P_T1201 ;AN000;
|
|
|
|
cmp al,"m" ;AN000; "m" of "am" or "pm"
|
|
jne $P_T12_Exit ;AN000;
|
|
|
|
dec si ;AN000;
|
|
mov al,psdata_seg:[si-word] ;AN000;
|
|
or al,$P_Make_lower ;AN000; lower case map
|
|
cmp al,"p" ;AN000; "p" of "pm" ?
|
|
je $P_T1200 ;AN000;
|
|
|
|
cmp al,"a" ;AN000; "a" of "am" ?
|
|
je $P_T1201 ;AN000; go process "a"
|
|
|
|
jmp short $P_T12_Exit ;AN000; no special chars found
|
|
|
|
$P_T1200: ;AN000; "P" found
|
|
or psdata_seg:$P_Flags2,$P_Time12 ;AC034; flag "PM" found
|
|
jmp short $P_Tclr_chr ;AN038; go clear the special char
|
|
|
|
$P_T1201: ;AN000; "A" found
|
|
or psdata_seg:$P_Flags1,$P_Time12AM ;AN038; flag "AM" found
|
|
$P_Tclr_chr: ;AN038;
|
|
mov byte ptr psdata_seg:[si-2],$P_NULL ;AN000; null out special char
|
|
$P_T12_Exit: ;AN000;
|
|
pop si ;AN000;
|
|
pop ax ;AN000;
|
|
ret ;AN000;
|
|
$P_Time_2412 endp ;AN000;
|
|
ENDIF ;AN000;(of TimeSW)
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
IF CmpxSW ;AN000;(Check if complex item is supported)
|
|
; $P_Complex_Format:
|
|
;
|
|
; Function: Check if the input string is valid complex format.
|
|
; And set the result buffer.
|
|
;
|
|
; Input: psdata_seg:SI -> $P_STRING_BUF
|
|
; ES:BX -> CONTROL block
|
|
;
|
|
; Output: None
|
|
;
|
|
; Use: $P_Fill_Result, $P_Chk_DBCS, $P_Chk_EOL, $P_Skip_Delim
|
|
; $P_Quoted_str, $P_Chk_DSQuote
|
|
;
|
|
; Vars: $P_RC(W), $P_SI_Save(W), $P_SaveSI_Cmpx(R), $P_Save_EOB(R)
|
|
;***********************************************************************
|
|
$P_Complex_Format proc ;AN000;
|
|
push ax ;AN000;
|
|
push bx ;AN000;
|
|
push si ;AN000;
|
|
mov bx,psdata_seg:$P_SaveSI_Cmpx ;AC034; bx points to user buffer
|
|
cmp byte ptr [bx],$P_Lparen ;AN000; 1st char = left parentheses
|
|
jne $P_Cmpx_Err ;AN000;
|
|
|
|
xor ah,ah ;AN000; ah = parentheses counter
|
|
$P_Cmpx_Loop: ;AN000;
|
|
mov al,[bx] ;AN000; load character from command buffer
|
|
call $P_Chk_EOL ;AN000; if it is one of EOL
|
|
je $P_CmpxErr0 ;AN000; then error exit.
|
|
|
|
cmp al,$P_Lparen ;AN000; left parentheses ?
|
|
jne $P_Cmpx00 ;AN000; then
|
|
|
|
inc ah ;AC035; add '1' to AH reg
|
|
;AN000; increment parentheses counter
|
|
;(replaced ;AC035;) add ah,1 ;AN000; increment parentheses counter
|
|
jc $P_CmpxErr0 ;AN000; if overflow, error
|
|
$P_Cmpx00: ;AN000;
|
|
cmp al,$P_Rparen ;AN000; right parentheses ?
|
|
jne $P_Cmpx01 ;AN000; then
|
|
|
|
dec ah ;AC035; subtract '1' from AH reg
|
|
;AN000; decrement parentheses counter
|
|
;(changed ;AC035;) sub ah,1 ;AN000; decrement parentheses counter
|
|
jc $P_CmpxErr0 ;AN000; if overflow error
|
|
|
|
je $P_Cmpx03 ;AN000; ok, valid complex
|
|
|
|
$P_Cmpx01: ;AN000;
|
|
;(deleted ;AN025;) call $P_Chk_DSQuote ;AN000; double or single quotation mark ? 3/17/KK
|
|
cmp al,$P_DQuote ;AN025; double quotation mark?
|
|
jne $P_Cmpx04 ;AN000; 3/17/KK
|
|
|
|
mov psdata_seg:[si],al ;AN000; here quoted string is found in the complex list.
|
|
inc si ;AN000;
|
|
inc bx ;AN000; bx points to 2nd character
|
|
call $P_Quoted_Str ;AN000; skip pointers until closing of quoted string
|
|
jc $P_CmpxErr0 ;AN000; if error in quoted string syntax then exit
|
|
|
|
jmp short $P_Cmpx05 ;AN000;
|
|
|
|
$P_Cmpx04: ;AN000;
|
|
call $P_Chk_DBCS ;AN000; was it a lead byte of DBCS ?
|
|
jnc $P_Cmpx02 ;AN000;
|
|
|
|
mov psdata_seg:[si],al ;AN000; then store 1st byte
|
|
inc si ;AN000;
|
|
inc bx ;AN000;
|
|
mov al,[bx] ;AN000; load 2nd byte
|
|
$P_Cmpx02: ;AN000;
|
|
mov psdata_seg:[si],al ;AN000; store SBCS or 2nd byte of DBCS
|
|
$P_Cmpx05: ;AN000;
|
|
inc si ;AN000;
|
|
inc bx ;AN000;
|
|
jmp short $P_Cmpx_Loop ;AN000; loop
|
|
;---- ;AN000;
|
|
$P_Cmpx03: ;AN000;
|
|
mov byte ptr psdata_seg:[si],al ;AN000;
|
|
mov byte ptr psdata_seg:[si+byte],$P_NULL ;AN000;
|
|
mov byte ptr [bx],$P_NULL ;AN000; replace right parentheses with NULL
|
|
mov si,bx ;AN000; skip whitespaces
|
|
inc si ;AN000; after
|
|
call $P_Skip_Delim ;AN000; right parentheses
|
|
mov psdata_seg:$P_SI_Save,si ;AC034; save next pointer, SI
|
|
jmp short $P_Cmpx_Exit ;AN000;
|
|
|
|
$P_CmpxErr0: ;AN000;
|
|
mov si,psdata_seg:$P_Save_EOB ;AC034; if EOF encountered, restore
|
|
mov byte ptr psdata_seg:[si],$P_NULL ;AN000; EOB mark
|
|
$P_Cmpx_Err: ;AN000;
|
|
mov psdata_seg:$P_RC,$P_Syntax ;AC034;
|
|
$P_Cmpx_Exit: ;AN000;
|
|
mov ah,$P_No_Tag ;AN000;
|
|
mov al,$P_Complex ;AN000;
|
|
pop si ;AN000;
|
|
pop bx ;AN000;
|
|
call $P_Fill_Result ;AN000;
|
|
pop ax ;AN000;
|
|
ret ;AN000;
|
|
$P_Complex_Format endp ;AN000;
|
|
ENDIF ;AN000;(of CpmxSW)
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
IF QusSW ;AN000;(Check if quoted string is supported)
|
|
; $P_Quoted_Format:
|
|
;
|
|
; Function: Check if the input string is valid quoted string format.
|
|
; And set the result buffer.
|
|
;
|
|
; Input: psdata_seg:SI -> $P_STRING_BUF
|
|
; ES:BX -> CONTROL block
|
|
;
|
|
; Output: None
|
|
;
|
|
; Use: $P_Fill_Result, $P_Chk_DBCS, $P_Chk_EOL, $P_Skip_Delim
|
|
; $P_Chk_DSQuote, $P_Quoted_Str
|
|
;
|
|
; Vars: $P_RC(W), $P_SI_Save(W), $P_SaveSI_Cmpx(R),$P_Save_EOB(R)
|
|
;***********************************************************************
|
|
$P_Quoted_Format proc ;AN000;
|
|
push ax ;AN000;
|
|
push bx ;AN000;
|
|
push si ;AN000;
|
|
mov bx,psdata_seg:$P_SaveSI_Cmpx ;AC034; bx points to user buffer
|
|
mov al,byte ptr [bx] ;AN000; get 1st character
|
|
;(deleted ;AN025;) call $P_Chk_DSQuote ;AN000; is it single or double quote ?
|
|
cmp al,$P_DQuote ;AN025; double quotation mark?
|
|
jne $P_Qus_Err ;AN000; if no, error
|
|
|
|
; mov psdata_seg:[si],al ;AN000; move it to internal buffer
|
|
; inc si ;AN000;
|
|
inc bx ;AN000; bx points to 2nd character
|
|
call $P_Quoted_Str ;AN000; skip pointers to the closing of quoted string
|
|
jc $P_Qus_Err0 ;AN000; if invali quoted string syntax, exit
|
|
|
|
mov byte ptr psdata_seg:[si+byte],$P_NULL ;AN000; end up with NULL
|
|
mov si,bx ;AN000;
|
|
inc si ;AN000;
|
|
call $P_Skip_Delim ;AN000; skip whitespaces after closing quote
|
|
mov psdata_seg:$P_SI_Save,si ;AC034; save next pointer, SI
|
|
jmp short $P_Qus_Exit ;AN000;
|
|
|
|
$P_Qus_Err0: ;AN000;
|
|
mov si,psdata_seg:$P_Save_EOB ;AC034; if EOF encountered, restore
|
|
mov byte ptr psdata_seg:[si],$P_NULL ;AN000; EOB mark
|
|
$P_Qus_Err: ;AN000;AN000
|
|
mov psdata_seg:$P_RC,$P_Syntax ;AC034; indicate syntax error
|
|
$P_Qus_Exit: ;AN000;
|
|
mov ah,$P_No_Tag ;AN000; set
|
|
mov al,$P_Quoted_String ;AN000; result
|
|
pop si ;AN000; buffer
|
|
pop bx ;AN000; to
|
|
call $P_Fill_Result ;AN000; quoted string
|
|
pop ax ;AN000;
|
|
ret ;AN000;
|
|
$P_Quoted_Format endp ;AN000;
|
|
ENDIF ;AN000;(of QusSW)
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_Chk_DSQuote;
|
|
;
|
|
; Function: Check if AL is double quotation or single quotation
|
|
;
|
|
; Input: AL = byte to be examineed
|
|
;
|
|
; Output: ZF on if AL is single or double quotetaion
|
|
;
|
|
; Vars: $P_SorD_Quote(W)
|
|
;***********************************************************************
|
|
IF QusSW+CmpxSW ;AN000;(Check if quoted string or complex item is supported)
|
|
;(deleted ;AN025;) $P_Chk_DSQuote proc ;
|
|
;(deleted ;AN025;) mov $P_SorD_Quote,$P_SQuote ; 3/17/87 assume single quote
|
|
;(deleted ;AN025;) cmp al,$P_DQuote ; 1st char = double quotation ?
|
|
;(deleted ;AN025;) jne $P_CDSQ00 ; 3/17/87
|
|
;(deleted ;AN025;) mov $P_SorD_Quote,al ; 3/17/87 set bigning w/ double quote
|
|
;(deleted ;AN025;) ret ; 3/17/87
|
|
;(deleted ;AN025;) $P_CDSQ00: ; 3/17/87
|
|
;(deleted ;AN025;) cmp al,$P_SQuote ; 1st char = single quotation ?
|
|
;(deleted ;AN025;) ret ;
|
|
;(deleted ;AN025;) $P_Chk_DSQuote endp ;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_Quoted_Str:
|
|
;
|
|
; Function: Copy chracacter from ES:BX to psdata_seg:SI until closing single
|
|
; (double) quotation found.
|
|
;
|
|
; Input: psdata_seg:SI -> $P_STRING_BUF
|
|
; ES:BX -> Operand in command buffer
|
|
;
|
|
; Output: CY on indicates EOF encounterd before closing quotation
|
|
; BX and SI
|
|
;
|
|
;
|
|
; Vars: $P_SorD_Quote(R)
|
|
;***********************************************************************
|
|
$P_Quoted_Str proc ;AN000;
|
|
push ax ;AN000;
|
|
$P_Qus_Loop: ;AN000;
|
|
mov ax,[bx] ;AN000; 3/17/87
|
|
call $P_Chk_EOL ;AN000;
|
|
je $P_Qustr_Err0 ;AN000;
|
|
|
|
;(deleted ;AN025;) cmp al,$P_SorD_Quote ;AN000; quotation ? 3/17/87
|
|
cmp al,$P_DQuote ;AN025; double quote?
|
|
jne $P_Qus00 ;AN000;
|
|
|
|
;(deleted ;AN025;) cmp ah,$P_SorD_Quote ;AN000; contiguous quotation 3/17/87
|
|
cmp ah,$P_DQuote ;AN025; double quote?
|
|
jne $P_Qus02 ;AN000;
|
|
|
|
;(deleted ;AN025:) mov word ptr psdata_seg:[si],ax ;AN000; 3/17/87
|
|
mov byte ptr psdata_seg:[si],al ;AN025; save one of the quotes
|
|
;(deleted ;AN025:) add si,2 ;AN000;
|
|
|
|
inc si ;AC035; add '1' to SI reg
|
|
;AN025; adjust target index
|
|
;(changed ;AC035;) add si,1 ;AN025; adjust target index
|
|
inc bx ;AC035; add '2' to
|
|
inc bx ;AC035; BX reg
|
|
;AN000; adjust source index by 2 to skip extra quote
|
|
;(changed ;AC035;) add bx,2 ;AN000; adjust source index by 2 to skip extra quote
|
|
jmp short $P_Qus_Loop ;AN000;
|
|
|
|
$P_Qus00: ;AN000;
|
|
call $P_Chk_DBCS ;AN000; was it a lead byte of DBCS ?
|
|
jnc $P_Qus01 ;AN000;
|
|
|
|
mov psdata_seg:[si],al ;AN000; store 1st byte
|
|
inc si ;AN000;
|
|
inc bx ;AN000;
|
|
mov al,[bx] ;AN000; load 2nd byte
|
|
$P_Qus01: ;AN000;
|
|
mov psdata_seg:[si],al ;AN000; store SBCS or 2nd byte of DBCS
|
|
inc si ;AN000;
|
|
inc bx ;AN000;
|
|
jmp short $P_Qus_Loop ;AN000;
|
|
|
|
$P_Qustr_Err0: ;AN000;
|
|
stc ;AN000; indicate error
|
|
jmp short $P_Quoted_Str_Exit ;AN000;
|
|
|
|
$P_Qus02: ;AN000;
|
|
mov byte ptr psdata_seg:[si],0 ;AN000;
|
|
clc ;AN000; indicate no error
|
|
$P_Quoted_Str_Exit: ;AN000;
|
|
pop ax ;AN000;
|
|
ret ;AN000;
|
|
$P_Quoted_Str endp ;AN000;
|
|
ENDIF ;AN000;(of QusSW+CmpxSW)
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
IF FileSW+DrvSW ;AN000;(Check if file spec or drive only is supported)
|
|
; $P_File_Format;
|
|
;
|
|
; Function: Check if the input string is valid file spec format.
|
|
; And set the result buffer.
|
|
;
|
|
; Input: psdata_seg:SI -> $P_STRING_BUF
|
|
; ES:BX -> CONTROL block
|
|
;
|
|
; Output: None
|
|
;
|
|
; Use: $P_Fill_Result, $P_Chk_DBCS, $P_FileSp_Chk
|
|
;
|
|
; Vars: $P_RC(W), $P_SI_Save(W), $P_Terminator(W), $P_SaveSI_Cmpx(R)
|
|
; $P_SaveSI_Cmpx(R)
|
|
;***********************************************************************
|
|
$P_File_Format proc ;AN000;
|
|
push ax ;AN000;
|
|
push di ;AN000;
|
|
push si ;AN000;
|
|
mov di,psdata_seg:$P_SaveSI_cmpx ;AC034; get user buffer address
|
|
$P_FileF_Loop0: ;AN000; / skip special characters
|
|
mov al,psdata_seg:[si] ;AN000; load character
|
|
or al,al ;AN000; end of line ?
|
|
je $P_FileF_Err ;AN000; if yes, error exit
|
|
|
|
call $P_FileSp_Chk ;AN000; else, check if file special character
|
|
jne $P_FileF03 ;AN000; if yes,
|
|
|
|
;AN033; deleted inc di ;skip
|
|
;AN033; deleted inc si ; the
|
|
;AN033; deleted jmp short $P_FileF_Loop0 ; character
|
|
mov psdata_seg:$P_err_flag,$P_error_filespec ;AN033;AC034;; set error flag- bad char.
|
|
pop si ;AN033;
|
|
mov byte ptr psdata_seg:[si],$P_NULL ;AN033;
|
|
pop di ;AN033;
|
|
jmp short $P_FileF02 ;AN033;
|
|
|
|
|
|
$P_FileF_Err: ;AN000;
|
|
pop si ;AN000;
|
|
mov byte ptr psdata_seg:[si],$P_NULL ;AN000;
|
|
;(deleted ;AN030;) mov di,$P_SaveSI_cmpx ;AN000; get user buffer address
|
|
;(deleted ;AN030;) mov $P_SI_Save,di ;AN000; update pointer to user buffer
|
|
pop di ;AN000;
|
|
test es:[bx].$P_Match_Flag,$P_Optional ;AN000; is it optional ?
|
|
jne $P_FileF02 ;AN000;
|
|
|
|
mov psdata_seg:$P_RC,$P_Op_Missing ;AC034; 3/17/87
|
|
jmp short $P_FileF02 ;AN000;
|
|
|
|
$P_FileF03: ;AN000;
|
|
pop ax ;AN000; discard save si
|
|
push si ;AN000; save new si
|
|
$P_FileF_Loop1: ;AN000;
|
|
mov al,psdata_seg:[si] ;AN000; load character (not special char)
|
|
or al,al ;AN000; end of line ?
|
|
je $P_FileF_RLT ;AN000;
|
|
|
|
call $P_FileSp_Chk ;AN000; File special character ?
|
|
je $P_FileF00 ;AN000;
|
|
|
|
call $P_Chk_DBCS ;AN000; no, then DBCS ?
|
|
jnc $P_FileF01 ;AN000;
|
|
inc di ;AN000; if yes, skip next byte
|
|
inc si ;AN000;
|
|
$P_FileF01: ;AN000;
|
|
inc di ;AN000;
|
|
inc si ;AN000;
|
|
jmp short $P_FileF_Loop1 ;AN000;
|
|
;
|
|
$P_FileF00: ;AN000;
|
|
mov psdata_seg:$P_Terminator,al ;AC034;
|
|
mov byte ptr psdata_seg:[si],$P_NULL ;AN000; update end of string
|
|
inc di ;AN000;
|
|
mov psdata_seg:$P_SI_Save,di ;AC034; update next pointer in command line
|
|
$P_FileF_RLT: ;AN000;
|
|
pop si ;AN000;
|
|
pop di ;AN000;
|
|
$P_FileF02: ;AN000;
|
|
|
|
pop ax ;AN000; (tm14)
|
|
test ax,$P_File_Spc ;AN000; (tm14)
|
|
je $P_Drv_Only_Exit ;AN000; (tm14)
|
|
|
|
push ax ;AN000; (tm14)
|
|
|
|
mov ah,$P_No_Tag ;AN000; set
|
|
mov al,$P_File_Spec ;AN000; result
|
|
call $P_Fill_Result ;AN000; buffer to file spec
|
|
pop ax ;AN000;
|
|
|
|
$P_Drv_Only_Exit: ;AN000; (tm14)
|
|
|
|
ret ;AN000;
|
|
$P_File_Format endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_FileSp_Chk
|
|
;
|
|
; Function: Check if the input byte is one of file special characters
|
|
;
|
|
; Input: psdata_seg:SI -> $P_STRING_BUF
|
|
; AL = character code to be examineed
|
|
;
|
|
; Output: ZF = 1 , AL is one of special characters
|
|
;***********************************************************************
|
|
$P_FileSp_Chk proc ;AN000;
|
|
push bx ;AN000;
|
|
push cx ;AN000;
|
|
lea bx,psdata_seg:$P_FileSp_Char ;AC034; special character table
|
|
mov cx,$P_FileSp_Len ;AN000; load length of it
|
|
$P_FileSp_Loop: ;AN000;
|
|
cmp al,psdata_seg:[bx] ;AN000; is it one of special character ?
|
|
je $P_FileSp_Exit ;AN000;
|
|
|
|
inc bx ;AN000;
|
|
loop $P_FileSp_Loop ;AN000;
|
|
|
|
inc cx ;AN000; reset ZF
|
|
$P_FileSp_Exit: ;AN000;
|
|
pop cx ;AN000;
|
|
pop bx ;AN000;
|
|
ret ;AN000;
|
|
$P_FileSp_Chk endp ;AN000;
|
|
ENDIF ;AN000;(of FileSW+DrvSW)
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
IF DrvSW ;AN000;(Check if drive only is supported)
|
|
; $P_Drive_Format;
|
|
;
|
|
; Function: Check if the input string is valid drive only format.
|
|
; And set the result buffer.
|
|
;
|
|
; Input: psdata_seg:SI -> $P_STRING_BUF
|
|
; ES:BX -> CONTROL block
|
|
;
|
|
; Output: None
|
|
;
|
|
; Use: $P_Fill_Result, $P_Chk_DBCS
|
|
;
|
|
; Vars: $P_RC(W)
|
|
;***********************************************************************
|
|
$P_Drive_Format proc ;AN000;
|
|
push ax ;AN000;
|
|
push dx ;AN000;
|
|
mov al,psdata_seg:[si] ;AN000;
|
|
or al,al ;AN000; if null string
|
|
je $P_Drv_Exit ;AN000; do nothing
|
|
|
|
call $P_Chk_DBCS ;AN000; is it leading byte ?
|
|
jc $P_Drv_Err ;AN000;
|
|
|
|
cmp word ptr psdata_seg:[si+byte],$P_Colon ;AN000; "d", ":", 0 ?
|
|
je $P_DrvF00 ;AN000;
|
|
|
|
test es:[bx].$P_Match_Flag,$P_Ig_Colon ;AN000; colon can be ignored?
|
|
je $P_Drv_Err ;AN000;
|
|
|
|
cmp byte ptr psdata_seg:[si+byte],$P_NULL ;AN000; "d", 0 ?
|
|
jne $P_Drv_Err ;AN000;
|
|
|
|
$P_DrvF00: ;AN000;
|
|
or al,$P_Make_Lower ;AN000; lower case
|
|
cmp al,"a" ;AN000; drive letter must
|
|
jb $P_Drv_Err ;AN000; in range of
|
|
|
|
cmp al,"z" ;AN000; "a" - "z"
|
|
ja $P_Drv_Err ;AN000; if no, error
|
|
|
|
sub al,"a"-1 ;AN000; make text drive to binary drive
|
|
mov dl,al ;AN000; set
|
|
mov ah,$P_No_Tag ;AN000; result
|
|
mov al,$P_Drive ;AN000; buffer
|
|
call $P_Fill_Result ;AN000; to drive
|
|
jmp short $P_Drv_Exit ;AN000;
|
|
|
|
$P_Drv_Err: ;AN000;
|
|
mov psdata_seg:$P_RC,$P_Syntax ;AC034;
|
|
$P_Drv_Exit: ;AN000;
|
|
pop dx ;AN000;
|
|
pop ax ;AN000;
|
|
ret ;AN000;
|
|
$P_Drive_Format endp ;AN000;
|
|
ENDIF ;AN000;(of DrvSW)
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_Skip_Delim;
|
|
;
|
|
; Function: Skip delimiters specified in the PARMS list, white space
|
|
; and comma.
|
|
;
|
|
; Input: DS:SI -> Command String
|
|
; ES:DI -> Parameter List
|
|
;
|
|
; Output: CY = 1 if the end of line encounterd
|
|
; CY = 0 then SI move to 1st non-delimiter character
|
|
; AL = Last examineed character
|
|
;
|
|
; Use: $P_Chk_EOL, $P_Chk_Delim,
|
|
;
|
|
; Vars: $P_Flags(R)
|
|
;***********************************************************************
|
|
$P_Skip_Delim proc ;AN000;
|
|
$P_Skip_Delim_Loop: ;AN000;
|
|
LODSB ;AN000;
|
|
call $P_Chk_EOL ;AN000; is it EOL character ?
|
|
je $P_Skip_Delim_CY ;AN000; if yes, exit w/ CY on
|
|
|
|
call $P_Chk_Delim ;AN000; is it one of delimiters ?
|
|
jne $P_Skip_Delim_NCY ;AN000; if no, exit w/ CY off
|
|
|
|
test psdata_seg:$P_Flags2,$P_Extra ;AC034; extra delim or comma found ?
|
|
je $P_Skip_Delim_Loop ;AN000; if no, loop
|
|
|
|
test psdata_seg:$P_Flags2,$P_SW+$P_equ ;AC034; /x , or xxx=zzz , (tm08)
|
|
je short $P_Exit_At_Extra ;AN000; no switch, no keyword (tm08)
|
|
|
|
dec si ;AN000; backup si for next call (tm08)
|
|
jmp short $P_Exit_At_Extra ;AN000; else exit w/ CY off
|
|
|
|
$P_Skip_Delim_CY: ;AN000;
|
|
stc ;AN000; indicate EOL
|
|
jmp short $P_Skip_Delim_Exit ;AN000;
|
|
|
|
$P_Skip_Delim_NCY: ;AN000;
|
|
clc ;AN000; indicate non delim
|
|
$P_Skip_Delim_Exit: ;AN000; in this case, need
|
|
dec si ;AN000; backup index pointer
|
|
ret ;AN000;
|
|
|
|
$P_Exit_At_Extra: ;AN000;
|
|
clc ;AN000; indicate extra delim
|
|
ret ;AN000;
|
|
$P_Skip_Delim endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_Chk_EOL;
|
|
;
|
|
; Function: Check if AL is one of End of Line characters.
|
|
;
|
|
; Input: AL = character code
|
|
; ES:DI -> Parameter List
|
|
;
|
|
; Output: ZF = 1 if one of End of Line characters
|
|
;**********************************************************************
|
|
$P_Chk_EOL proc ;AN000;
|
|
push bx ;AN000;
|
|
push cx ;AN000;
|
|
cmp al,$P_CR ;AN000; Carriage return ?
|
|
je $P_Chk_EOL_Exit ;AN000;
|
|
|
|
cmp al,$P_NULL ;AN000; zero ?
|
|
je $P_Chk_EOL_Exit ;AN000;
|
|
|
|
IF LFEOLSW ;AN028; IF LF TO BE ACCEPTED AS EOL
|
|
cmp al,$P_LF ;AN000; Line feed ?
|
|
je $P_Chk_EOL_Exit ;AN000;
|
|
ENDIF ;AN028;
|
|
|
|
cmp byte ptr es:[di].$P_Num_Extra,$P_I_Have_EOL ;AN000; EOL character specified ?
|
|
jb $P_Chk_EOL_Exit ;AN000;
|
|
|
|
xor bx,bx ;AN000;
|
|
mov bl,es:[di].$P_Len_Extra_Delim ;AN000; get length of delimiter list
|
|
add bx,$P_Len_PARMS ;AN000; skip it
|
|
cmp byte ptr es:[bx+di],$P_I_Use_Default ;AN000; No extra EOL character ?
|
|
je $P_Chk_EOL_NZ ;AN000;
|
|
|
|
xor cx,cx ;AN000; Get number of extra chcracter
|
|
mov cl,es:[bx+di] ;AN000;
|
|
$P_Chk_EOL_Loop: ;AN000;
|
|
inc bx ;AN000;
|
|
cmp al,es:[bx+di] ;AN000; Check extra EOL character
|
|
je $P_Chk_EOL_Exit ;AN000;
|
|
|
|
loop $P_Chk_EOL_Loop ;AN000;
|
|
|
|
$P_Chk_EOL_NZ: ;AN000;
|
|
cmp al,$P_CR ;AN000; reset ZF
|
|
$P_Chk_EOL_Exit: ;AN000;
|
|
pop cx ;AN000;
|
|
pop bx ;AN000;
|
|
ret ;AN000;
|
|
$P_Chk_EOL endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_Chk_Delim;
|
|
;
|
|
; Function: Check if AL is one of delimiter characters.
|
|
; if AL+[si] is DBCS blank, it is replaced with two SBCS
|
|
; blanks.
|
|
;
|
|
; Input: AL = character code
|
|
; DS:SI -> Next Character
|
|
; ES:DI -> Parameter List
|
|
;
|
|
; Output: ZF = 1 if one of delimiter characters
|
|
; SI points to the next character
|
|
; Vars: $P_Terminator(W), $P_Flags(W)
|
|
;***********************************************************************
|
|
$P_Chk_Delim proc ;AN000;
|
|
push bx ;AN000;
|
|
push cx ;AN000;
|
|
mov psdata_seg:$P_Terminator,$P_Space ;AC034; Assume terminated by space
|
|
and psdata_seg:$P_Flags2,0ffh-$P_Extra ;AC034;
|
|
cmp al,$P_Space ;AN000; Space ?
|
|
je $P_Chk_Delim_Exit ;AN000;
|
|
|
|
cmp al,$P_TAB ;AN000; TAB ?
|
|
je $P_Chk_Delim_Exit ;AN000;
|
|
|
|
cmp al,$P_Comma ;AN000; Comma ?
|
|
je $P_Chk_Delim_Exit0 ;AN000;
|
|
|
|
$P_Chk_Delim00: ;AN000;
|
|
cmp al,$P_DBSP1 ;AN000; 1st byte of DBCS Space ?
|
|
jne $P_Chk_Delim01 ;AN000;
|
|
|
|
cmp byte ptr [si],$P_DBSP2 ;AN000; 2nd byte of DBCS Space ?
|
|
jne $P_Chk_Delim01 ;AN000;
|
|
|
|
mov al,$P_Space ;AN000;
|
|
inc si ;AN000; make si point to next character
|
|
cmp al,al ;AN000; Set ZF
|
|
jmp short $P_Chk_Delim_Exit ;AN000;
|
|
|
|
$P_Chk_Delim01: ;AN000;
|
|
cmp byte ptr es:[di].$P_Num_Extra,$P_I_Have_Delim ;AN000; delimiter character specified ?
|
|
jb $P_Chk_Delim_Exit ;AN000;
|
|
|
|
xor cx,cx ;AN000;
|
|
mov cl,es:[di].$P_Len_Extra_Delim ;AN000; get length of delimiter list
|
|
or cx,cx ;AN000; No extra Delim character ?
|
|
je $P_Chk_Delim_NZ ;AN000;
|
|
|
|
mov bx,$P_Len_PARMS-1 ;AN000; set bx to 1st extra delimiter
|
|
$P_Chk_Delim_Loop: ;AN000;
|
|
inc bx ;AN000;
|
|
cmp al,es:[bx+di] ;AN000; Check extra Delim character
|
|
je $P_Chk_Delim_Exit0 ;AN000;
|
|
|
|
loop $P_Chk_Delim_Loop ;AN000; examine all extra delimiter
|
|
|
|
$P_Chk_Delim_NZ: ;AN000;
|
|
cmp al,$P_Space ;AN000; reset ZF
|
|
$P_Chk_Delim_Exit: ;AN000;
|
|
;;;; jne $P_ChkDfin
|
|
;;;; mov psdata_seg:$P_Terminator,al ;AN034;
|
|
$P_ChkDfin: ;AN000;
|
|
pop cx ;AN000;
|
|
pop bx ;AN000;
|
|
ret ;AN000;
|
|
|
|
$P_Chk_Delim_Exit0: ;AN000;
|
|
mov psdata_seg:$P_Terminator,al ;AC034; keep terminated delimiter
|
|
test psdata_seg:$P_Flags2,$P_Equ ;AN027;AC034;; if terminating a key=
|
|
jnz $P_No_Set_Extra ;AN027; then do not set the EXTRA bit
|
|
|
|
or psdata_seg:$P_Flags2,$P_Extra ;AC034; flag terminated extra delimiter or comma
|
|
$P_No_Set_Extra: ;AN027;
|
|
cmp al,al ;AN000; set ZF
|
|
jmp short $P_Chk_Delim_Exit ;AN000;
|
|
|
|
$P_Chk_Delim endp ;AN000;
|
|
PAGE ;AN000;
|
|
;***********************************************************************
|
|
; $P_Chk_Switch;
|
|
;
|
|
; Function: Check if AL is the switch character not in first position of
|
|
; $P_STRING_BUF
|
|
;
|
|
; Input: AL = character code
|
|
; BX = current pointer within $P_String_Buf
|
|
; SI =>next char on command line (following the one in AL)
|
|
;
|
|
; Output: CF = 1 (set)if AL is switch character, and not in first
|
|
; position, and has no chance of being part of a date string,
|
|
; i.e. should be treated as a delimiter.
|
|
|
|
; CF = 0 (reset, cleared) if AL is not a switch char, is in the first
|
|
; position, or is a slash but may be part of a date string, i.e.
|
|
; should not be treated as a delimiter.
|
|
;
|
|
; Vars: $P_Terminator(W)
|
|
|
|
; Use: $P_0099
|
|
;***********************************************************************
|
|
$P_Chk_Switch proc ;AN000;
|
|
|
|
;AN020;; Function: Check if AL is the switch character from 2nd position of $P_STRING_BUF
|
|
;AN020;; Output: ZF = 1 if switch character
|
|
;AN020;; lea bp,$P_STRING_BUF ;AN000;
|
|
;AN020;; cmp bx,bp ;AN000; 1st position ?
|
|
;AN020;; je $P_Chk_S_Exit_1 ;AN000;
|
|
;AN020;; cmp al,$P_Switch ;AN000;
|
|
;AN020;; jmp short $P_Chk_S_Exit_0 ;AN000;
|
|
;AN020;;$P_Chk_S_Exit_1: ;AN000;
|
|
;AN020;; cmp al,$P_Switch ;AN000; (tm08)
|
|
;AN020;; jne $P_Nop ;AN000; (tm08)
|
|
;AN020;; or $P_Flags2,$P_SW ;AN000; (tm08) It could be valid switch
|
|
;AN020;;$P_Nop: ;AN000; (tm08)
|
|
;AN020;; inc bp ;AN000;
|
|
;AN020;; cmp bx,bp ;AN000; reset ZF
|
|
;AN020;;$P_Chk_S_Exit_0: ;AN000;
|
|
;AN020;; jne $P_Chk_S_Exit ;AN000;
|
|
;AN020;; mov $P_Terminator,al ;AN000; store switch character
|
|
;AN020;;$P_Chk_S_Exit: ;AN000;
|
|
|
|
LEA BP,psdata_seg:$P_String_Buf ;AN020;AC034; BP=OFFSET of $P_String_Buf even in group addressing
|
|
; .IF <BX NE BP> THEN ;AN020;IF not first char THEN
|
|
cmp BX,BP ;AN000;
|
|
je $P_STRUC_L2 ;AN000;
|
|
|
|
; .IF <AL EQ $P_Switch> THEN ;AN020;otherwise see if a slash
|
|
cmp AL,$P_Switch ;AN000;
|
|
jne $P_STRUC_L5 ;AN000;
|
|
|
|
STC ;AN020;not in first position and is slash, now see if might be in date string
|
|
IF DateSw ;AN020;caller looking for date, see if this may be part of one
|
|
PUSH AX ;AN020;save input char
|
|
MOV AL,PSDATA_SEG:[BX-1] ;AN026;AL=char before the current char
|
|
CALL $P_0099 ;AN020;return carry set if not numeric
|
|
; .IF NC ;AND ;AN020;IF previous char numeric AND
|
|
jc $P_STRUC_L7 ;AN000;
|
|
|
|
MOV AL,[SI] ;AN020;AL=char after the current char
|
|
CALL $P_0099 ;AN020;return carry set if not numeric
|
|
;(deleted) .IF NC THEN ;AN020;IF next char numeric THEN could be a date
|
|
;(deleted) CLC ;AN020;reset CF so "/" not treated as a delimiter
|
|
;(deleted) .ENDIF ;AN026;
|
|
; .ENDIF ;AN020;ENDIF looks like date (number/number)
|
|
$P_STRUC_L7: ;AN000;
|
|
POP AX ;AN020;restore AL to input char
|
|
ENDIF ;AN020;DateSw
|
|
; .ELSE ;AN020;
|
|
jmp short $P_STRUC_L1 ;AN000;
|
|
|
|
$P_STRUC_L5: ;AN000;
|
|
CLC ;AN020;not a slash
|
|
; .ENDIF ;AN020;
|
|
; .ELSE ;AN020;is first char in the buffer, ZF=0
|
|
jmp short $P_STRUC_L1 ;AN000;
|
|
|
|
$P_STRUC_L2: ;AN000;
|
|
; .IF <AL EQ $P_Switch> THEN ;AN020;
|
|
cmp AL,$P_Switch ;AN000;
|
|
jne $P_STRUC_L12 ;AN000;
|
|
|
|
OR psdata_seg:$P_Flags2,$P_SW ;AN020;AC034;;could be valid switch, first char and is slash
|
|
; .ENDIF ;AN020;
|
|
$P_STRUC_L12: ;AN000;
|
|
CLC ;AN020;CF=0 indicating first char
|
|
; .ENDIF ;AN020;
|
|
$P_STRUC_L1: ;AN000;
|
|
|
|
ret ;AN000;
|
|
$P_Chk_Switch endp ;AN000;
|
|
PAGE ;AN000;
|
|
;**************************************************************************
|
|
; $P_Chk_DBCS:
|
|
;
|
|
; Function: Check if a specified byte is in ranges of the DBCS lead bytes
|
|
;
|
|
; Input:
|
|
; AL = Code to be examineed
|
|
;
|
|
; Output:
|
|
; If CF is on then a lead byte of DBCS
|
|
;
|
|
; Use: INT 21h w/AH=63
|
|
;
|
|
; Vars: $P_DBCSEV_Seg(RW), $P_DBCSEV_Off(RW)
|
|
;***************************************************************************
|
|
$P_Chk_DBCS PROC ;AN000;
|
|
;
|
|
PUSH DS ;AN000;
|
|
PUSH SI ;AN000;
|
|
PUSH bx ;AN000; (tm11)
|
|
CMP psdata_seg:$P_DBCSEV_SEG,0 ;AC034; ALREADY SET ?
|
|
JNE $P_DBCS00 ;AN000;
|
|
|
|
PUSH AX ;AN000;
|
|
; PUSH BX ;AN000; (tm11)
|
|
PUSH ds ;AN000; (tm11)
|
|
PUSH CX ;AN000;
|
|
PUSH DX ;AN000;
|
|
PUSH DI ;AN000;
|
|
PUSH BP ;AN000;
|
|
PUSH ES ;AN000;
|
|
XOR SI,SI ;AN000;
|
|
MOV DS,SI ;AN000;
|
|
MOV AX,$P_DOS_GetEV ;AN000; GET DBCS EV CALL
|
|
INT 21H ;AN000;
|
|
|
|
; MOV AX,DS ;AN000; (tm11)
|
|
; OR AX,AX ;AN000; (tm11)
|
|
MOV bx,DS ;AN000; (tm11)
|
|
OR bx,bx ;AN000; (tm11)
|
|
POP ES ;AN000;
|
|
POP BP ;AN000;
|
|
POP DI ;AN000;
|
|
POP DX ;AN000;
|
|
POP CX ;AN000;
|
|
; POP BX ;AN000; (tm11)
|
|
POP ds ;AN000; (tm11)
|
|
POP AX ;AN000;
|
|
JE $P_NON_DBCS ;AN000;
|
|
|
|
$P_DBCS02: ;AN000;
|
|
MOV psdata_seg:$P_DBCSEV_OFF,SI ;AC034; save EV offset
|
|
; MOV psdata_seg:$P_DBCSEV_SEG,DS ;AC034; save EV segment
|
|
MOV psdata_seg:$P_DBCSEV_SEG,bx ;AC034; save EV segment (tm11)
|
|
$P_DBCS00: ;AN000;
|
|
MOV SI,psdata_seg:$P_DBCSEV_OFF ;AC034; load EV offset
|
|
MOV DS,psdata_seg:$P_DBCSEV_SEG ;AC034; and segment
|
|
|
|
$P_DBCS_LOOP: ;AN000;
|
|
CMP WORD PTR [SI],0 ;AN000; zero vector ?
|
|
JE $P_NON_DBCS ;AN000; then exit
|
|
|
|
CMP AL,[SI] ;AN000;
|
|
JB $P_DBCS01 ;AN000; Check if AL is in
|
|
|
|
CMP AL,[SI+BYTE] ;AN000; range of
|
|
JA $P_DBCS01 ;AN000; the vector
|
|
|
|
STC ;AN000; if yes, indicate DBCS and exit
|
|
JMP short $P_DBCS_EXIT ;AN000;
|
|
|
|
$P_DBCS01: ;AN000;
|
|
INC SI ;AC035; add '2' to
|
|
INC SI ;AC035; SI reg
|
|
;AN000; get next vector
|
|
;(changed ;AC035;) ADD SI,2 ;AN000; get next vector
|
|
JMP short $P_DBCS_LOOP ;AN000; loop until zero vector found
|
|
|
|
$P_NON_DBCS: ;AN000;
|
|
CLC ;AN000; indicate SBCS
|
|
$P_DBCS_EXIT: ;AN000;
|
|
POP bx ;AN000; (tm11)
|
|
POP SI ;AN000;
|
|
POP DS ;AN000;
|
|
RET ;AN000;
|
|
$P_Chk_DBCS ENDP ;AN000;
|