4 ;(deleted)INCLUDE STRUC.INC ;AN020;structured macro definitions for .IF,.ELSE etc.
7 ; NOTE: basesw must be set properly to allow the PARSER to access psdata.
8 ; - basesw undefined means CS seg. override for psdata access.
9 ; - basesw = 1 means DS seg. override for psdata access &
10 ; DS must point to psdata.
11 ; - basesw = 0 means ES seg. override for psdata access &
12 ; ES must point to psdata.
16 psdata_seg EQU
CS ;AN022;
18 IF basesw
;AN022;IF "basesw EQU 1" specified by caller THEN
19 psdata_seg EQU
DS ;AN022;
21 psdata_seg EQU
ES ;AN022;ELSE only other choice is ES (basesw EQU 0)
25 ifndef incsw
;AN000; (tm03) Someone doesn't want to include psdata
26 incsw equ
1 ;AN000; include psdata.inc (tm03)
28 if incsw
;AN000; If incsw = 1 then (tm03)
29 include psdata
.inc ;AN000; include psdata.inc (tm03)
30 endif
;AN000; endif (tm03)
33 %
OUT INCLUDING COMP
=COMMON DSN
=PARSE
.ASM
...;AN000;
35 ;***********************************************************************
38 ; Function : Parser Entry
40 ; Input: DS:SI -> command line
41 ; ES:DI -> parameter block
42 ; psdata_seg -> psdata.inc
43 ; CX = operand ordinal
45 ; Note: ES is the segment containing all the control blocks defined
46 ; by the caller, except for the DOS COMMAND line parms, which
49 ; Output: CY = 1 error of caller, means invalid parameter block or
50 ; invalid value list. But this parser does NOT implement
51 ; this feature. Therefore CY always zero.
53 ; CY = 0 AX = return code
54 ; BL = terminated delimiter code
55 ; CX = new operand ordinal
56 ; SI = set past scaned operand
57 ; DX = selected result buffer
59 ; Use: $P_Skip_Delim, $P_Chk_EOL, $P_Chk_Delim, $P_Chk_DBCS
60 ; $P_Chk_Swtch, $P_Chk_Pos_Control, $P_Chk_Key_Control
61 ; $P_Chk_Sw_Control, $P_Fill_Result
63 ; Vars: $P_Ordinal(RW), $P_RC(RW), $P_SI_Save(RW), $P_DX(R), $P_Terminator(R)
64 ; $P_SaveSI_Cmpx(W), $P_Flags(RW), $P_Found_SYNONYM(R), $P_Save_EOB(W)
66 ;-------- Modification History -----------------------------------------
68 ; 4/04/87 : Created by K. K,
69 ; 4/28/87 : $P_Val_YH assemble error (tm01)
70 ; : JMP SHORT assemble error (tm02)
71 ; 5/14/87 : Someone doesn't want to include psdata (tm03)
72 ; 6/12/87 : $P_Bridge is missing when TimeSw equ 0 and (CmpxSw equ 1 or
73 ; DateSW equ 1) (tm04)
74 ; 6/12/87 : $P_SorD_Quote is missing when QusSw equ 0 and CmpxSW equ 1
75 ; (tm05) in PSDATA.INC
76 ; 6/12/87 : $P_FileSp_Char and $P_FileSP_Len are missing
77 ; when FileSW equ 0 and DrvSW equ 1 (tm06) in PSDATA.INC
78 ; 6/18/87 : $VAL1 and $VAL3, $VAL2 and $VAL3 can be used in the same
79 ; value-list block (tm07)
80 ; 6/20/87 : Add $P_SW to check if there's an omiting parameter after
81 ; switch (keyword) or not. If there is, backup si for next call
83 ; 6/24/87 : Complex Item checking does not work correctly when CmpSW equ 1
84 ; and DateSW equ 0 and TimeSW equ 0 (tm09)
85 ; 6/24/87 : New function flag $P_colon_is_not_necessary for switch
86 ; /+15 and /+:15 are allowed for user (tm10)
87 ; 6/29/87 : ECS call changes DS register but it causes the address problem
88 ; in user's routines. $P_Chk_DBCS (tm11)
89 ; 7/10/87 : Switch with no_match flag (0x0000H) does not work correctly
91 ; 7/10/87 : Invalid switch/keyword does not work correctly
93 ; 7/10/87 : Drive_only breaks 3 bytes after the result buffer
95 ; 7/12/87 : Too_Many_Operands sets DX=0 as the PARSE result
97 ; 7/24/87 : Negative lower bound on numeric ranges cause trouble
99 ; 7/24/87 : Quoted strings being returned with quotes.
101 ; 7/28/87 : Kerry S (;AN018;)
102 ; Non optional value on switch (match flags<>0 and <>1) not flagged
103 ; as an error when missing. Solution: return error 2. Modules
104 ; affected: $P_Chk_SW_Control.
106 ; 7/29/87 : Kerry S (;AN019;)
107 ; Now allow the optional bit in match flags for switches. This
108 ; allows the switch to be encountered with a value or without a
109 ; value and no error is returned.
112 ; 8/28/87 : Ed K, Kerry S (;AN020;)
113 ; 9/14/87 In PROC $P_Get_DecNum, when checking for field separators
114 ; within a date response, instead of checking just for the one
115 ; character defined by the COUNTRY DEPENDENT INFO, check for
116 ; all three chars, "-", "/", and ".". Change $P_Chk_Switch to allow
117 ; slashes in date strings when DateSw (assembler switch) is set.
119 ; 9/1/87 : Kerry S (;AN021)
120 ; In PROC $P_String_Comp, when comparing the switch or keyword on
121 ; the command line with the string in the control block the
122 ; comparing was stopping at a colon (switch) or equal (keyword)
123 ; on the command line and assuming a match. This allowed a shorter
124 ; string on the command line than in the synonym list in the control
125 ; block. I put in a test for a null in the control block so the
126 ; string in the control block must be the same length as the string
127 ; preceeding the colon or equal on the command line.
129 ; 8/28/87 : Kerry S (;AN022;)
130 ; All references to data in PSDATA.INC had CS overrides. This caused
131 ; problems for people who included it themselves in a segment other
132 ; than CS. Added switch to allow including PSDATA.INC in any
135 ; 9/16/87 : Ed K (;AN023;) PTM1040
136 ; in $p_set_cdi PROC, it assumes CS points to psdata. Change Push CS
137 ; into PUSH PSDATA_SEG. In $P_Get_DecNum PROC, fix AN020
138 ; forced both TIME and DATE to use the delims, "-","/",".".
139 ; Created FLag, in $P_time_Format PROC, to request the delim in
140 ; BL be used if TIME is being parsed.
143 ; Removed the include to STRUC.INC. Replaced the STRUC macro
144 ; invocations with their normally expanded code; made comments
145 ; out of the STRUC macro invocation statements to maintain readability.
147 ; 9/24/87 : Ed K (;AN024;) PTM1222
148 ; When no CONTROL for a keyword found, tried to fill in RESULT
149 ; pointed to by non-existant CONTROL.
151 ; 10/15/87 : Ed K (;AN025;) PTM1672
152 ; A quoted text string can be framed only by double quote. Remove
153 ; support to frame quoted text string with single quote.
154 ; (apostrophe) $P_SorD_Quote is removed from PSDATA.INC.
155 ; $P_SQuote EQU also removed from PSDATA.INC. Any references to
156 ; single quote in PROC prologues are left as is for history reasons.
158 ; This fixes another bug, not mentioned in p1672, in that two
159 ; quote chars within a quoted string is supposed to be reported as
160 ; one quote character, but is reported as two quotes. This changed
161 ; two instructions in PROC $P_Quoted_Str.
163 ; Also fixed are several JMP that caused a NOP, these changed to
164 ; have the SHORT operator to avoid the unneeded NOP.
166 ; The code and PSDATA.INC have been aligned for ease of reading.
168 ; 10/26/87 : Ed K (;AN026;) PTM2041, DATE within SWITCH, BX reference to
169 ; psdata buffer should have psdata_seg.
171 ; 10/27/87 : Ed K (;AN027;) PTM2042 comma between keywords implies
172 ; positional missing.
174 ; 11/06/87 : Ed K (;AN028;) PTM 2315 Parser should not use line feed
175 ; as a line delimiter, should use carriage return.
176 ; Define switch: LFEOLSW, if on, accept LF as end of line char.
178 ; 11/11/87 : Ed K (;AN029;) PTM 1651 GET RID OF WHITESPACE AROUND "=".
180 ; 11/18/87 : Ed K (;AN030;) PTM 2551 If filename is just "", then
181 ; endless loop since SI is returned still pointing to start
184 ; 11/19/87 : Ed K (;AN031;) PTM 2585 date & time getting bad values.
185 ; Vector to returned string has CS instead of Psdata_Seg, but
186 ; when tried to fix it on previous version, changed similar
189 ; 12/09/87 : Bill L (;AN032;) PTM 2772 colon and period are now valid
190 ; delimiters between hours, minutes, seconds for time. And period
191 ; and comma are valid delimiters between seconds and 100th second.
193 ; 12/14/87 : Bill L (;AN033;) PTM 2722 if illegal delimiter characters
194 ; in a filespec, then flag an error.
196 ; 12/22/87 : Bill L (;AN034;) All local data to parser is now
197 ; indexed off of the psdata_seg equate instead of the DS register.
198 ; Using this method, DS can point to the segment of PSP or to psdata
199 ; --> local parser data. Why were some references to local data changed
200 ; to do this before, but not all ?????
202 ; 02/02/88 : Ed K (;AC035;) INSPECT utility, suggests optimizations.
204 ; 02/05/88 : Ed K (;AN036;) P3372-UPPERCASE TRANSLATION, PSDATA_SEG HOSED.
206 ; 02/08/88 : Ed K (;AN037;) P3410-AVOID POP OF CS, CHECK BASESW FIRST.
208 ; 02/19/88 : Ed K (;AN038;) p3524 above noon and "am" should be error
210 ; 02/23/88 : Ed K (;AN039;) p3518 accept "comma" and "period" as decimal
211 ; separator in TIME before hundredths field.
213 ;***********************************************************************
214 IF FarSW
;AN000;(Check if need far return)
215 SysParse proc
far ;AN000;
217 SysParse proc
near ;AN000;
218 ENDIF
;AN000;(of FarSW)
220 mov psdata_seg
:$P_Flags
,0 ;AC034; Clear all internal flags
221 IF TimeSw
;AN039; FOR TIME ONLY
222 MOV PSDATA_SEG
:$P_ORIG_ORD
,CX ;AN039; ORIGINAL ORDINAL FROM CX
223 MOV PSDATA_SEG
:$P_ORIG_STACK
,SP ;AN039; ORIGINAL VALUE OF STACK FROM SP
224 MOV PSDATA_SEG
:$P_ORIG_SI
,SI ;AN039; ORIGINAL START PARSE POINTER FROM SI
225 $P_REDO_TIME
: ;AN039; try to parse time again
226 ENDIF
;AN039; FOR TIME ONLY
227 cld ;AN000; confirm forward direction
228 mov psdata_seg
:$P_ordinal
,cx ;AC034; save operand ordinal
229 mov psdata_seg
:$P_RC
,$P_No_Error
;AC034; Assume no error
230 mov psdata_seg
:$P_Found_SYNONYM
,0 ;AC034; initalize synonym pointer
232 mov word ptr psdata_seg
:$P_DX
,0 ;AC034; (tm15)
234 ;IN CASE THE USER PUT OPTIONAL WHITESPACE CHARS AROUND THE "=" USED IN
235 ;KEYWORD DEFINITIONS, SCAN THE COMMAND LINE AND COMPRESS OUT ANY WHITESPACES
236 ;NEXT TO "=" BEFORE STARTING THE USUAL PARSING.
241 push si ;AN029; remember where command line starts
242 mov cx,-1 ;AN029; init counter
245 inc cx ;AN029; bump counter of chars up to EOL
246 lodsb ;AN029; get a char from command line
247 CALL $P_Chk_EOL
;AN029; see if AL is EOL char
250 jnz $P_loc_EOL
;AN029; not found that EOL char
252 mov psdata_seg
:$P_count_to_EOL
,cx ;AN029;AC034;; save count of chars up to EOL
253 pop si ;AN029; restore start of command line
255 ;scan command string for combinations including "=",
256 ; and replace each with just the simple "="
258 ;REPEAT UNTIL ONE PASS IS MADE WHEREIN NO CHANGES WERE MADE
261 push si ;AN029; remember where string started
262 MOV CX,psdata_seg
:$P_COUNT_TO_EOL
;AN029;AC034;; set count to no. chars in string,
263 ;AN029; not counting the EOL char
264 XOR BX,BX ;AN029;SET $P_REG_BL_DQ_SW TO "NOT IN QUOTES", AND...
265 ;AN029;SET $P_REG_BH_CG_SW TO "NO CHANGES MADE"
266 ;MAKE ONE PASS THRU THE STRING, LOOKING AT EACH CHARACTER
269 cmp BYTE PTR [SI],$P_double_quote
;AN029;
270 ; $if e ;AN029;if a double quote was found
272 NOT $P_REG_BL_DQ_SW
;AN029;TOGGLE THE DOUBLE QUOTE STATE SWITCH
275 OR $P_REG_BL_DQ_SW
,$P_REG_BL_DQ_SW
;AN029;IS THE DOUBLE QUOTE SWITCH SET?
276 ; $if Z ;AN029;IF NOT IN DOUBLE QUOTES
278 mov ax,word ptr [si] ;AN029; get pair to be checked out
279 cmp ax,$P_BL_EQ
;AN029;" ="
282 cmp ax,$P_EQ_BL
;AN029;"= "
285 cmp ax,$P_EQ_TB
;AN029; "=<tab>"
288 cmp ax,$P_TB_EQ
;AN029;"<tab>="
289 ; $if e ;AN029;if this pair to be replaced with a single "="
292 mov BYTE PTR [SI],$P_Keyword
;AN029; "="
293 inc si ;AN029;point to next char after the new "="
294 mov di,si ;AN029;move target right after new "="
296 push si ;AN029;remember where i am, right after new "="
297 PUSH CX ;AN029;SAVE CURRENT COUNT
298 inc si ;AN029;source is one beyond that
299 push es ;AN029;remember the extra segment
300 push ds ;AN029;temporarily, set source seg and
301 pop es ;AN029; target seg to the command line seg
302 rep movsb ;AN029;move chars left one position
303 pop es ;AN029;restore the extra segment
304 POP CX ;AN029;RESTORE CURRENT COUNT
305 pop si ;AN029;back to where I was
307 DEC SI ;AN029;LOOK AT FIRST CHAR JUST MOVED
308 MOV $P_REG_BH_CG_SW
,-1 ;AN029;set switch to say "a change was made"
309 DEC psdata_seg
:$P_COUNT_TO_EOL
;AN029;AC034;;because just threw away a char
311 ; $endif ;AN029;comparand pair found?
313 ; $endif ;AN029;double quote switch?
315 inc si ;AN029;bump index to look at next char in command string
316 dec CX ;AN029;one less char to look at
317 ;(deleted ;AC035;) CMP CX,0 ;AN029;is char count all gone yet?
318 ; $enddo LE ;AN029;quit if no more chars
320 pop si ;AN029;remember where string started
321 OR $P_REG_BH_CG_SW
,$P_REG_BH_CG_SW
;AN029;WAS "A CHANGE MADE"?
322 ; $enddo Z ;AN029;QUIT when no changes were made
328 ;NOW THAT ALL WHITESPACE SURROUNDING "=" HAVE BEEN COMPRESSED OUT,
329 ;RESUME NORMAL PARSING...
330 ENDIF
;AN029; KEYWORDS SUPPORTED?
331 call $P_Skip_Delim
;AN000; Move si to 1st non white space
332 jnc $P_Start
;AN000; If EOL is not encountered, do parse
334 ;--------------------------- End of Line
335 mov ax,$P_RC_EOL
;AN000; set exit code to -1
337 mov bx,es:[di].$P_PARMSX_Address
;AN000; Get the PARMSX address to
338 cmp cl,es:[bx].$P_MinP
;AN000; check ORDINAL to see if the minimum
339 jae $P_Fin
;AN000; positional found.
341 mov ax,$P_Op_Missing
;AN000; If no, set exit code to missing operand
344 jmp $P_Single_Exit
;AN000; return to the caller
346 ;---------------------------
348 mov psdata_seg
:$P_SaveSI_Cmpx
,si ;AN000;AC034; save ptr to command line for later use by complex,
349 push bx ;AN000; quoted string or file spec.
352 lea bx,psdata_seg
:$P_STRING_BUF
;AC034; set buffer to copy from command string
353 test psdata_seg
:$P_Flags2
,$P_Extra
;AC034; 3/9 extra delimiter encountered ?
354 jne $P_Pack_End
;AN000; 3/9 if yes, no need to copy
356 $P_Pack_Loop
: ;AN000;
357 lodsb ;AN000; Pick a operand from buffer
358 call $P_Chk_Switch
;AN000; Check switch character
359 jc $P_Pack_End_BY_EOL
;AN020; if carry set found delimiter type slash, need backup si, else continue
361 call $P_Chk_EOL
;AN000; Check EOL character
362 je $P_Pack_End_BY_EOL
;AN000; need backup si
364 call $P_Chk_Delim
;AN000; Check delimiter
365 jne $P_PL01
;AN000; If no, process next byte
367 test psdata_seg
:$P_Flags2
,$P_Extra
;AC034; 3/9 If yes and white spec,
368 ; (tm08)jne $P_Pack_End ;AN000; 3/9 then
369 jne $P_Pack_End_backup_si
;AN000; (tm08)
371 call $P_Skip_Delim
;AN000; skip subsequent white space,too
372 jmp short $P_Pack_End
;AN000; finish copy by placing NUL at end
374 $P_PAck_End_backup_si
: ;AN000; (tm08)
375 test psdata_seg
:$P_Flags2
,$P_SW
+$P_equ
;AN000;AC034; (tm08)
376 je $P_Pack_End
;AN000; (tm08)
378 dec si ;AN000; (tm08)
379 jmp short $P_Pack_End
;AN025; (tm08)
382 mov psdata_seg
:[bx],al ;AN000; move byte to STRING_BUF
383 cmp al,$P_Keyword
;AN000; if it is equal character,
384 jne $P_PL00
;AN000; then
386 or psdata_seg
:$P_Flags2
,$P_equ
;AC034; remember it in flag
388 inc bx ;AN000; ready to see next byte
389 call $P_Chk_DBCS
;AN000; was it 1st byte of DBCS ?
390 jnc $P_Pack_Loop
;AN000; if no, process to next byte
392 lodsb ;AN000; if yes, store
393 mov psdata_seg
:[bx],al ;AN000; 2nd byte of DBCS
394 inc bx ;AN000; update pointer
395 jmp short $P_Pack_Loop
;AN000; process to next byte
397 $P_Pack_End_BY_EOL
: ;AN000;
398 dec si ;AN000; backup si pointer
400 mov psdata_seg
:$P_SI_Save
,si ;AC034; save next pointer, SI
401 mov byte ptr psdata_seg
:[bx],$P_NULL
;AN000; put NULL at the end
402 mov psdata_seg
:$P_Save_EOB
,bx ;AC034; 3/17/87 keep the address for later use of complex
403 mov bx,es:[di].$P_PARMSX_Address
;AN000; get PARMSX address
404 lea si,psdata_seg
:$P_STRING_BUF
;AC034;
405 cmp byte ptr psdata_seg
:[si],$P_Switch
;AN000; the operand begins w/ switch char ?
406 je $P_SW_Manager
;AN000; if yes, process as switch
408 test psdata_seg
:$P_Flags2
,$P_equ
;AC034; the operand includes equal char ?
409 jne $P_Key_manager
;AN000; if yes, process as keyword
411 $P_Positional_Manager
: ;AN000; else process as positional
412 mov al,es:[bx].$P_MaxP
;AN000; get maxp
413 xor ah,ah ;AN000; ax = maxp
414 cmp psdata_seg
:$P_ORDINAL
,ax ;AC034; too many positional ?
415 jae $P_Too_Many_Error
;AN000; if yes, set exit code to too many
417 mov ax,psdata_seg
:$P_ORDINAL
;AC034; see what the current ordinal
418 shl ax,1 ;AN000; ax = ax*2
419 inc bx ;AC035; add '2' to
420 inc bx ;AC035; BX reg
421 ;AN000; now bx points to 1st CONTROL
422 ;(changed ;AC035;) add bx,2 ;AN000; now bx points to 1st CONTROL
423 add bx,ax ;AN000; now bx points to specified CONTROL address
424 mov bx,es:[bx] ;AN000; now bx points to specified CONTROL itself
425 call $P_Chk_Pos_Control
;AN000; Do process for positional
426 jmp short $P_Return_to_Caller
;AN000; and return to the caller
428 $P_Too_Many_Error
: ;AN000;
429 mov psdata_seg
:$P_RC
,$P_Too_Many
;AC034; set exit code
430 jmp short $P_Return_to_Caller
;AN000; and return to the caller
432 $P_SW_Manager
: ;AN000;
433 mov al,es:[bx].$P_MaxP
;AN000; get maxp
434 xor ah,ah ;AN000; ax = maxp
436 shl ax,1 ;AN000; ax = (ax+1)*2
437 add bx,ax ;AN000; now bx points to maxs
438 mov cl,es:[bx] ;AN000;
439 xor ch,ch ;AN000; cx = maxs
440 or cx,cx ;AN000; at least one switch ?
441 je $P_SW_Not_Found
;AN000;
443 inc bx ;AN000; now bx points to 1st CONTROL address
445 $P_SW_Mgr_Loop
: ;AN000;
447 mov bx,es:[bx] ;AN000; bx points to Switch CONTROL itself
448 call $P_Chk_SW_Control
;AN000; do process for switch
450 jnc $P_Return_to_Caller
;AN000; if the CONTROL is for the switch, exit
452 inc bx ;AC035; add '2' to
453 inc bx ;AC035; BX reg
454 ;AN000; else bx points to the next CONTROL
455 ;(changed ;AC035;) add bx,2 ;AN000; else bx points to the next CONTROL
456 loop $P_SW_Mgr_Loop
;AN000; and loop
458 $P_SW_Not_Found
: ;AN000;
459 mov psdata_seg
:$P_RC
,$P_Not_In_SW
;AC034; here no CONTROL for the switch has
460 jmp short $P_Return_to_Caller0
;AN000; not been found, means error.
462 $P_Key_Manager
: ;AN000;
463 mov al,es:[bx].$P_MaxP
;AN000; get maxp
464 xor ah,ah ;AN000; ax = maxp
466 shl ax,1 ;AN000; ax = (ax+1)*2
467 add bx,ax ;AN000; now bx points to maxs
468 mov al,es:[bx] ;AN000;
469 xor ah,ah ;AN000; ax = maxs
471 inc ax ;AN000; ax = ax*2+1
472 add bx,ax ;AN000; now bx points to maxk
473 mov cl,es:[bx] ;AN000;
474 xor ch,ch ;AN000; cx = maxk
475 or cx,cx ;AN000; at least one keyword ?
476 je $P_Key_Not_Found
;AN000;
478 inc bx ;AN000; now bx points to 1st CONTROL
480 $P_Key_Mgr_Loop
: ;AN000;
482 mov bx,es:[bx] ;AN000; bx points to keyword CONTROL itself
483 call $P_Chk_Key_Control
;AN000; do process for keyword
485 jnc $P_Return_to_Caller
;AN000; if the CONTROL is for the keyword, exit
487 inc bx ;AC035; add '2' to
488 inc bx ;AC035; BX reg
489 ;AN000; else bx points to the next CONTROL
490 ;(changed ;AC035;) add bx,2 ;AN000; else bx points to the next CONTROL
491 loop $P_Key_Mgr_Loop
;AN000; and loop
493 $P_Key_Not_Found
: ;AN000;
494 mov psdata_seg
:$P_RC
,$P_Not_In_Key
;AC034; here no CONTROL for the keyword has
495 $P_Return_to_Caller0
: ;AN000; not been found, means error.
497 ;(deleted ;AN024;) mov bx,es:[bx-2] ;AN000; (tm13) backup bx
499 ;(deleted ;AN024;) mov al,$P_String ;AN000; Set
500 ;(deleted ;AN024;) mov ah,$P_No_Tag ;AN000; result
501 ;(deleted ;AN024;) call $P_Fill_Result ;AN000; buffer
503 $P_Return_to_Caller
: ;AN000;
507 mov cx,psdata_seg
:$P_Ordinal
;AC034; return next ordinal
508 mov ax,psdata_seg
:$P_RC
;AC034; return exit code
509 mov si,psdata_seg
:$P_SI_Save
;AC034; return next operand pointer
510 mov dx,psdata_seg
:$P_DX
;AC034; return result buffer address
511 mov bl,psdata_seg
:$P_Terminator
;AC034; return delimiter code found
512 $P_Single_Exit
: ;AN000;
515 SysParse endp
;AN000;
517 ;***********************************************************************
520 ; Function: Parse CONTROL block for a positional
522 ; Input: ES:BX -> CONTROL block
523 ; psdata_seg:SI -> $P_STRING_BUF
527 ; Use: $P_Fill_Result, $P_Check_Match_Flags
529 ; Vars: $P_Ordinal(W), $P_RC(W)
530 ;***********************************************************************
531 $P_Chk_Pos_Control proc
;AN000;
533 mov ax,es:[bx].$P_Match_Flag
;AN000;
534 test ax,$P_Repeat
;AN000; repeat allowed ?
535 jne $P_CPC00
;AN000; then do not increment ORDINAL
537 inc psdata_seg
:$P_ORDINAL
;AC034; update the ordinal
539 cmp byte ptr psdata_seg
:[si],$P_NULL
;AN000; no data ?
542 test ax,$P_Optional
;AN000; yes, then is it optional ?
545 mov psdata_seg
:$P_RC
,$P_Op_Missing
;AC034; no, then error 3/17/87
546 jmp short $P_CPC_Exit
;AN000;
550 mov al,$P_String
;AN000; if it is optional return NULL
551 mov ah,$P_No_Tag
;AN000; no item tag indication
552 call $P_Fill_Result
;AN000;
554 jmp short $P_CPC_Exit
;AN000;
557 call $P_Check_Match_Flags
;AN000;
561 $P_Chk_Pos_Control endp
;AN000;
563 ;***********************************************************************
566 ; Function: Parse CONTROL block for a keyword
568 ; Input: ES:BX -> CONTROL block
569 ; psdata_seg:SI -> $P_STRING_BUF
571 ; Output: CY = 1 : not match
573 ; Use: $P_Fill_Result, $P_Search_KEYorSW, $P_Check_Match_Flags
575 ; Vars: $P_RC(W), $P_SaveSI_Cmpx(W), $P_KEYorSW_Ptr(R), $P_Flags(W)
576 ;***********************************************************************
577 $P_Chk_Key_Control proc
;AN000;
578 IF KeySW
;AN000;(Check if keyword is supported)
579 or psdata_seg
:$P_Flags2
,$P_Key_Cmp
;AC034; Indicate keyword for later string comparison
580 call $P_Search_KEYorSW
;AN000; Search the keyword in the CONTROL block
581 jc $P_Chk_Key_Err0
;AN000; not found, then try next CONTROL
583 and psdata_seg
:$P_Flags2
,0ffh-$P_Key_Cmp
;AC034; reset the indicator previously set
585 push ax ;AN000; keyword=
586 mov ax,psdata_seg
:$P_KEYorSW_Ptr
;AC034; ^ ^
587 sub ax,si ;AN000; SI KEYorSW
588 add psdata_seg
:$P_SaveSI_Cmpx
,ax ;AC034; update for complex, quoted or file spec.
591 mov si,psdata_seg
:$P_KEYorSW_Ptr
;AC034; set si just after equal char
592 cmp byte ptr psdata_seg
:[si],$P_NULL
;AN000; any data after equal ?
593 je $P_Chk_Key_Err1
;AN000; if no, syntax error
595 call $P_Check_Match_Flags
;AN000; else, process match flags
597 jmp short $P_Chk_Key_Exit
;AN000;
599 $P_Chk_Key_Err0
: ;AN000;
600 stc ;AN000; not found in keyword synonym list
601 jmp short $P_Chk_Key_Exit
;AN000;
603 $P_Chk_Key_Err1
: ;AN000;
604 mov psdata_seg
:$P_RC
,$P_Syntax
;AC034; no parameter is not specified after "="
605 $P_Chk_Key_ErrExit
: ;AN000;
607 mov al,$P_String
;AN000; set
608 mov ah,$P_No_Tag
;AN000; result
609 call $P_Fill_Result
;AN000; buffer
612 $P_Chk_Key_Exit
: ;AN000;
614 ELSE ;AN000;(of IF KeySW)
615 stc ;AN000;this logic works when the KeySW
617 ENDIF
;AN000;(of KeySW)
618 $P_Chk_Key_Control endp
;AN000;
620 ;***********************************************************************
621 IF KeySW
+SwSW
;AN000;(Check if keyword or switch is supported)
624 ; Function: Seach specified keyword or switch from CONTROL
626 ; Input: ES:BX -> CONTROL block
627 ; psdata_seg:SI -> $P_STRING_BUF
629 ; Output: CY = 1 : not match
631 ; Use: $P_String_Comp, $P_MoveBP_NUL, $P_Found_SYNONYM
632 ;***********************************************************************
633 $P_Search_KEYorSW proc
;AN000;
636 mov cl,es:[bx].$P_nid
;AN000; Get synonym count
637 xor ch,ch ;AN000; and set it to cx
638 or cx,cx ;AN000; No synonyms specified ?
639 je $P_KEYorSW_Not_Found
;AN000; then indicate not found by CY
641 lea bp,es:[bx].$P_KEYorSW
;AN000; BP points to the 1st synonym
642 $P_KEYorSW_Loop
: ;AN000;
643 call $P_String_Comp
;AN000; compare string in buffer w/ the synonym
644 jnc $P_KEYorSW_Found
;AN000; If match, set it to synonym pointer
646 call $P_MoveBP_NUL
;AN000; else, bp points to the next string
647 loop $P_KEYorSW_Loop
;AN000; loop nid times
648 $P_KEYorSW_Not_Found
: ;AN000;
649 stc ;AN000; indicate not found in synonym list
650 jmp short $P_KEYorSW_Exit
;AN000; and exit
652 $P_KEYorSW_Found
: ;AN000;
653 mov psdata_seg
:$P_Found_SYNONYM
,bp ;AC034; set synonym pointer
654 clc ;AN000; indicate found
655 $P_KEYorSW_Exit
: ;AN000;
659 $P_Search_KEYorSW endp
;AN000;
660 ;***********************************************************************
662 ;***********************************************************************
663 $P_MoveBP_NUL proc
;AN000;
665 cmp byte ptr es:[bp],$P_NULL
;AN000; Increment BP that points
666 je $P_MBP_Exit
;AN000; to the synomym list
669 jmp short $P_MBP_Loop
;AN000; NULL encountered.
672 inc bp ;AN000; bp points to next to NULL
674 $P_MoveBP_NUL endp
;AN000;
675 ENDIF
;AN000;(of KeySW+SwSW)
677 ;***********************************************************************
680 ; Function: Parse CONTROL block for a switch
682 ; Input: ES:BX -> CONTROL block
683 ; psdata_seg:SI -> $P_STRING_BUF
685 ; Output: CY = 1 : not match
687 ; Use: $P_Fill_Result, $P_Search_KEYorSW, $P_Check_Match_Flags
689 ; Vars: $P_SaveSI_Cmpx(W), $P_KEYorSW_Ptr(R), $P_Flags(W)
690 ;***********************************************************************
691 $P_Chk_SW_Control proc
;AN000;
694 IF SwSW
;AN000;(Check if switch is supported)
695 or psdata_seg
:$P_Flags2
,$P_Sw_Cmp
;AC034; Indicate switch for later string comparison
696 call $P_Search_KEYorSW
;AN000; Search the switch in the CONTROL block
697 jc $P_Chk_SW_Err0
;AN000; not found, then try next CONTROL
699 and psdata_seg
:$P_Flags2
,0ffh-$P_Sw_Cmp
;AC034; reset the indicator previously set
701 push ax ;AN000; /switch:
702 mov ax,psdata_seg
:$P_KEYorSW_Ptr
;AC034; ^ ^
703 sub ax,si ;AN000; SI KEYorSW
704 add psdata_seg
:$P_SaveSI_Cmpx
,ax ;AC034; update for complex list
707 mov si,psdata_seg
:$P_KEYorSW_Ptr
;AC034; set si at the end or colon
708 cmp byte ptr psdata_seg
:[si],$P_NULL
;AN000; any data after colon
709 jne $P_CSW00
;AN000; if yes, process match flags
711 cmp byte ptr psdata_seg
:[si-1],$P_Colon
;AN000; if no, the switch terminated by colon ?
712 jne $P_Chk_if_data_required
;AN000; if yes,
714 mov psdata_seg
:$P_RC
,$P_Syntax
;AC034; return syntax error
715 jmp short $P_Chk_SW_Exit
;AN000;
717 $P_Chk_if_data_required
: ;AN018; no data, no colon
718 cmp es:[bx].$P_Match_Flag
,0 ;AN018; should have data? zero match flag means switch followed by nothing is OK
719 je $P_Chk_SW_Exit
;AN018; match flags not zero so should have something if optional bit is not on
721 test es:[bx].$P_Match_Flag
,$P_Optional
;AN019; see if no value is valid
722 jnz $P_Chk_SW_Exit
;AN019; if so, then leave, else yell
724 mov psdata_seg
:$P_RC
,$P_Op_Missing
;AC034; return required operand missing
725 jmp short $P_Chk_SW_Exit
;AN018;
728 call $P_Check_Match_Flags
;AN000; process match flag
729 clc ;AN000; indicate match
730 jmp short $P_Chk_SW_Single_Exit
;AN000;
732 $P_Chk_SW_Err0
: ;AN000;
733 stc ;AN000; not found in switch synonym list
734 jmp short $P_Chk_SW_Single_Exit
;AN000;
736 $P_Chk_SW_Exit
: ;AN000;
738 mov al,$P_String
;AN000; set
739 mov ah,$P_No_Tag
;AN000; result
740 call $P_Fill_Result
;AN000; buffer
743 $P_Chk_SW_Single_Exit
: ;AN000;
745 ELSE ;AN000;(of IF SwSW)
746 stc ;AN000; this logic works when the SwSW
747 ret ;AN000; is reset.
748 ENDIF
;AN000;(of SwSW)
749 $P_Chk_SW_Control endp
;AN000;
751 ;***********************************************************************
754 ; Function: Fill the result buffer
756 ; Input: AH = Item tag
758 ; AL = 1: CX,DX has 32bit number (CX = high)
759 ; AL = 2: DX has index(offset) into value list
760 ; AL = 6: DL has driver # (1-A, 2-B, ... , 26 - Z)
761 ; AL = 7: DX has year, CL has month and CH has date
762 ; AL = 8: DL has hours, DH has minutes, CL has secondsn,
763 ; amd CH has hundredths
764 ; AL = else: psdata_seg:SI points to returned string buffer
765 ; ES:BX -> CONTROL block
769 ; Use: $P_Do_CAPS_String, $P_Remove_Colon, $P_Found_SYNONYM
772 ;***********************************************************************
773 $P_Fill_Result proc
;AN000;
775 mov di,es:[bx].$P_Result_Buf
;AN000; di points to result buffer
776 mov psdata_seg
:$P_DX
,di ;AC034; set returned result address
777 mov es:[di].$P_Type
,al ;AN000; store type
778 mov es:[di].$P_Item_Tag
,ah ;AN000; store item tag
780 mov ax,psdata_seg
:$P_Found_SYNONYM
;AC034; if yes,
781 mov es:[di].$P_SYNONYM_Ptr
,ax ;AN000; then set it to the result
784 cmp al,$P_Number
;AN000; if number
788 mov word ptr es:[di].$P_Picked_Val
,dx ;AN000; then store 32bit
789 mov word ptr es:[di+2].$P_Picked_Val
,cx ;AN000; number
790 jmp short $P_RLT_Exit
;AN000;
793 cmp al,$P_List_Idx
;AN000; if list index
796 mov word ptr es:[di].$P_Picked_Val
,dx ;AN000; then store list index
797 jmp short $P_RLT_Exit
;AN000;
800 cmp al,$P_Date_F
;AN000; Date format ?
803 cmp al,$P_Time_F
;AN000; Time format ?
806 cmp al,$P_Drive
;AN000; drive format ?
809 mov byte ptr es:[di].$P_Picked_Val
,dl ;AN000; store drive number
810 jmp short $P_RLT_Exit
;AN000;
813 cmp al,$P_Complex
;AN000; complex format ?
816 mov ax,psdata_seg
:$P_SaveSI_Cmpx
;AC034; then get pointer in command buffer
817 inc ax ;AN000; skip left Parentheses
818 mov word ptr es:[di].$P_Picked_Val
,ax ;AN000; store offset
819 mov word ptr es:[di+2].$P_Picked_Val
,ds ;AN000; store segment
820 jmp short $P_RLT_Exit
;AN000;
823 ;------------------------ AL = 3, 5, or 9
824 mov word ptr es:[di].$P_Picked_Val
,si ;AN000; store offset of STRING_BUF
825 ;(replaced ;AN031;) mov word ptr es:[di+word].$P_Picked_Val,cs ;AN000; store segment of STRING_BUF
826 mov word ptr es:[di+2].$P_Picked_Val
,Psdata_Seg
;AN031; store segment of STRING_BUF
829 test byte ptr es:[bx].$P_Function_Flag
,$P_CAP_File
;AN000; need CAPS by file table?
830 je $P_RLT_CAP00
;AN000;
832 mov al,$P_DOSTBL_File
;AN000; use file upper case table
833 jmp short $P_RLT_CAP02
;AN000;
835 $P_RLT_CAP00
: ;AN000;
836 test byte ptr es:[bx].$P_Function_Flag
,$P_CAP_Char
;AN000; need CAPS by char table ?
837 je $P_RLT_CAP01
;AN000;
839 mov al,$P_DOSTBL_Char
;AN000; use character upper case table
840 $P_RLT_CAP02
: ;AN000;
841 call $P_Do_CAPS_String
;AN000; process CAPS along the table
842 $P_RLT_CAP01
: ;AN000;
844 test byte ptr es:[bx].$P_Function_Flag
,$P_Rm_Colon
;AN000; removing colon at end ?
845 je $P_RLT_Exit
;AN000;
847 call $P_Remove_Colon
;AN000; then process it.
851 $P_Fill_Result endp
;AN000;
853 ;***********************************************************************
854 ; $P_Check_Match_Flags
856 ; Function: Check the mutch_flags and make the exit code and set the
859 ; Check for types in this order:
868 ; Input: psdata_seg:SI -> $P_STRING_BUF
869 ; ES:BX -> CONTROL block
873 ; Use: $P_Value, P$_SValue, $P_Simple_String, $P_Date_Format
874 ; $P_Time_Format, $P_Complex_Format, $P_File_Foemat
876 ;***********************************************************************
877 $P_Check_Match_Flags proc
;AN000;
878 mov psdata_seg
:$P_err_flag
,$P_NULL
;AN033;AC034;; clear filespec error flag.
880 mov ax,es:[bx].$P_Match_Flag
;AN000; load match flag(16bit) to ax
882 or ax,ax ;AC035; test ax for zero
883 ;(changed ;AC035;) cmp ax,0 ;AN000; (tm12)
884 jne $P_Mat
;AN000; (tm12)
886 push ax ;AN000; (tm12)
887 push bx ;AN000; (tm12)
888 push dx ;AN000; (tm12)
889 push di ;AN000; (tm12)
890 mov psdata_seg
:$P_RC
,$P_Syntax
;AC034; (tm12)
891 mov ah,$P_No_Tag
;AN000; (tm12)
892 mov al,$P_String
;AN000; (tm12)
893 call $P_Fill_Result
;AN000; (tm12)
894 pop di ;AN000; (tm12)
895 pop dx ;AN000; (tm12)
896 pop bx ;AN000; (tm12)
897 pop ax ;AN000; (tm12)
898 jmp short $P_Bridge
;AC035; (tm12)
900 $P_Mat
: ;AN000; (tm12)
902 IF CmpxSW
;AN000;(Check if complex item is supported)
903 test ax,$P_Cmpx_S
;AN000; Complex string
904 je $P_Match01
;AN000;
906 mov psdata_seg
:$P_RC
,$P_No_Error
;AC034; assume no error
907 call $P_Complex_Format
;AN000; do process
908 cmp psdata_seg
:$P_RC
,$P_Syntax
;AC034; if error, examine the next type
909 jne $P_Bridge
;AN000;
912 ENDIF
;AN000;(of CmpxSW)
913 IF DateSW
;AN000;(Check if date format is supported)
914 test ax,$P_Date_S
;AN000; Date string
915 je $P_Match02
;AN000;
917 mov psdata_seg
:$P_RC
,$P_No_Error
;AC034; assume no error
918 call $P_Date_Format
;AN000; do process
919 cmp psdata_seg
:$P_RC
,$P_Syntax
;AC034; if error, examine the next type
920 jne $P_Bridge
;AN000;
923 ENDIF
;AN000;(of DateSW)
924 IF TimeSW
;AN000;(Check if time format is supported)
925 test ax,$P_Time_S
;AN000; Time string
926 je $P_Match03
;AN000;
928 mov psdata_seg
:$P_RC
,$P_No_Error
;AC034; assume no error
929 call $P_Time_Format
;AN000; do process
930 cmp psdata_seg
:$P_RC
,$P_Syntax
;AC034; if error, examine the next type
931 ; je $P_Match03 ;AN000:
933 jne $P_Bridge
;AN000; (tm09)
935 ENDIF
;AN000;(of TimeSW) (tm04)
936 jmp short $P_Match03
;AN025; (tm09)
939 ; jmp short $P_Match_Exit (tm02)
941 jmp $P_Match_Exit
;AN000; (tm02)
944 ; ENDIF ;AN000;(of TimeSW) (tm04)
945 IF NumSW
;AN000;(Check if numeric value is supported)
946 test ax,$P_Num_Val
;AN000; Numeric value
947 je $P_Match04
;AN000;
949 mov psdata_seg
:$P_RC
,$P_No_Error
;AC034; assume no error
950 call $P_Value
;AN000; do process
951 cmp psdata_seg
:$P_RC
,$P_Syntax
;AC034; if error, examine the next type
952 jne $P_Match_Exit
;AN000;
955 test ax,$P_SNUM_Val
;AN000; Signed numeric value
956 je $P_Match05
;AN000;
958 mov psdata_seg
:$P_RC
,$P_No_Error
;AC034; assume no error
959 call $P_SValue
;AN000; do process
960 cmp psdata_seg
:$P_RC
,$P_Syntax
;AC034; if error, examine the next type
961 jne $P_Match_Exit
;AN000;
964 ENDIF
;AN000;(of NumSW)
965 IF DrvSW
;AN000;(Check if drive only is supported)
966 test ax,$P_Drv_Only
;AN000; Drive only
967 je $P_Match06
;AN000;
969 mov psdata_seg
:$P_RC
,$P_No_Error
;AC034; assume no error
970 call $P_File_Format
;AN000; 1st, call file format
971 call $P_Drive_Format
;AN000; check drive format, next
972 cmp psdata_seg
:$P_RC
,$P_Syntax
;AC034; if error, examinee the next type
973 jne $P_Match_Exit
;AN000;
976 ENDIF
;AN000;(of DrvSW)
977 IF FileSW
;AN000;(Check if file spec is supported)
978 test ax,$P_File_Spc
;AN000; File spec
979 je $P_Match07
;AN000;
981 mov psdata_seg
:$P_RC
,$P_No_Error
;AC034; assume no error
982 call $P_File_Format
;AN000; do process
983 cmp psdata_seg
:$P_RC
,$P_Syntax
;AC034; if error, examine the next type
984 jne $P_Match_Exit
;AN000;
987 ENDIF
;AN000;(of FileSW)
988 IF QusSW
;AN000;(Check if quoted string is supported)
989 test ax,$P_Qu_String
;AN000; Quoted string
990 je $P_Match08
;AN000;
992 mov psdata_seg
:$P_RC
,$P_No_Error
;AC034; assume no error
993 call $P_Quoted_Format
;AN000; do process
994 cmp psdata_seg
:$P_RC
,$P_Syntax
;AC034; if error, examine the next type
995 jne $P_Match_Exit
;AN000;
998 ENDIF
;AN000;(of QusSW)
999 test ax,$P_Simple_S
;AN000; Simple string
1000 je $P_Match09
;AN000;
1002 mov psdata_seg
:$P_RC
,$P_No_Error
;AC034; assume no error
1003 call $P_Simple_String
;AN000; do process
1004 ;;;; cmp psdata_seg:$P_RC,$P_Syntax ;AC034; These two lines will be alive
1005 ;;;; jne $P_Match_Exit ;when extending the match_flags.
1007 $P_Match_Exit
: ;AN000;
1008 cmp psdata_seg
:$P_err_flag
,$P_error_filespec
;AC034; bad filespec ?
1009 jne $P_Match2_Exit
;AN033; no, continue
1010 cmp psdata_seg
:$P_RC
,$P_No_Error
;AN033;AC034;; check for other errors ?
1011 jne $P_Match2_Exit
;AN033; no, continue
1012 mov psdata_seg
:$P_RC
,$P_Syntax
;AN033;AC034;; set error flag
1013 $P_Match2_Exit
: ;AN033;
1016 $P_Check_Match_Flags endp
;AN000;
1018 ;***********************************************************************
1021 ; Function: Remove colon at end
1023 ; Input: psdata_seg:SI points to string buffer to be examineed
1028 ;***********************************************************************
1029 $P_Remove_Colon proc
;AN000;
1032 $P_RCOL_Loop
: ;AN000;
1033 mov al,psdata_seg
:[si] ;AN000; get character
1034 or al,al ;AN000; end of string ?
1035 je $P_RCOL_Exit
;AN000; if yes, just exit
1037 cmp al,$P_Colon
;AN000; is it colon ?
1038 jne $P_RCOL00
;AN000;
1040 cmp byte ptr psdata_seg
:[si+byte],$P_NULL
;AN000; if so, next is NULL ?
1041 jne $P_RCOL00
;AN000; no, then next char
1043 mov byte ptr psdata_seg
:[si],$P_NULL
;AN000; yes, remove colon
1044 jmp short $P_RCOL_Exit
;AN000; and exit.
1047 call $P_Chk_DBCS
;AN000; if not colon, then check if
1048 jnc $P_RCOL01
;AN000; DBCS leading byte.
1050 inc si ;AN000; if yes, skip trailing byte
1052 inc si ;AN000; si points to next byte
1053 jmp short $P_RCOL_Loop
;AN000; loop until NULL encountered
1055 $P_RCOL_Exit
: ;AN000;
1059 $P_Remove_Colon endp
;AN000;
1061 ;***********************************************************************
1062 ; $P_Do_CAPS_String;
1064 ; Function: Perform capitalization along with the file case map table
1065 ; or character case map table.
1067 ; Input: AL = 2 : Use character table
1068 ; AL = 4 : Use file table
1069 ; psdata_seg:SI points to string buffer to be capitalized
1073 ; Use: $P_Do_CAPS_Char, $P_Chk_DBCS
1074 ;***********************************************************************
1075 $P_Do_CAPS_String proc
;AN000;
1078 mov dl,al ;AN000; save info id
1080 $P_DCS_Loop
: ;AN000;
1081 mov al,psdata_seg
:[si] ;AN000; load charater and
1082 call $P_Chk_DBCS
;AN000; check if DBCS leading byte
1083 jc $P_DCS00
;AN000; if yes, do not need CAPS
1085 or al,al ;AN000; end of string ?
1086 je $P_DCS_Exit
;AN000; then exit.
1088 call $P_Do_CAPS_Char
;AN000; Here a SBCS char need to be CAPS
1089 mov psdata_seg
:[si],al ;AN000; stored upper case char to buffer
1090 jmp short $P_DCS01
;AN000; process nexit
1092 inc si ;AN000; skip DBCS leading and trailing byte
1094 inc si ;AN000; si point to next byte
1095 jmp short $P_DCS_Loop
;AN000; loop until NULL encountered
1096 $P_DCS_Exit
: ;AN000;
1100 $P_Do_CAPS_String endp
;AN000;
1102 ;***********************************************************************
1105 ; Function: Perform capitalization along with the file case map table
1106 ; or character case map table.
1108 ; Input: DL = 2 : Use character table
1109 ; DL = 4 : Use file table
1110 ; AL = character to be capitalized
1114 ; Use: INT 21h /w AH=65h
1115 ;***********************************************************************
1116 $P_Do_CAPS_Char proc
;AN000;
1117 cmp al,$P_ASCII80
;AN000; need upper case table ?
1118 jae $P_DCC_Go
;AN000;
1120 cmp al,"a" ;AN000; if no,
1121 jb $P_CAPS_Ret
;AN000; check if "a" <= AL <= "z"
1124 ja $P_CAPS_Ret
;AN000; if yes, make CAPS
1126 and al,$P_Make_Upper
;AN000; else do nothing.
1127 jmp short $P_CAPS_Ret
;AN000;
1133 IF CAPSW
;AN000;(Check if uppercase conversion is supported)
1134 lea di,psdata_seg
:$P_File_CAP_Ptr
;AC034;
1135 cmp dl,$P_DOSTBL_File
;AN000; Use file CAPS table ?
1138 ENDIF
;AN000;(of CAPSW)
1139 lea di,psdata_seg
:$P_Char_CAP_Ptr
;AC034; or use char CAPS table ?
1141 cmp psdata_seg
:[di],dl ;AN000; already got table address ?
1142 je $P_DCC01
;AN000; if no,
1144 ;In this next section, ES will be used to pass a 5 byte workarea to INT 21h,
1145 ; the GET COUNTYRY INFO call. This usage of ES is required by the function
1146 ; call, regardless of what base register is currently be defined as PSDATA_SEG.
1147 ;BASESW EQU 0 means that ES is the psdata_seg reg.
1149 IFDEF BASESW
;AN037; If BASESW has been defined, and
1150 IFE BASESW
;AN037; If ES is psdata base
1151 push PSDATA_SEG
;AN037; save current base reg
1155 push ax ;AN000; get CAPS table thru DOS call
1160 push PSDATA_SEG
;AC036; pass current base seg into
1161 ;(Note: this used to push CS. BUG...
1162 pop es ;AN000; ES reg, required for
1163 ;get extended country information
1164 mov ah,$P_DOS_Get_TBL
;AN000; get extended CDI
1165 mov al,dl ;AN000; upper case table
1166 mov bx,$P_DOSTBL_Def
;AN000; get active CON
1167 mov cx,$P_DOSTBL_BL
;AN000; buffer length
1168 mov dx,$P_DOSTBL_Def
;AN000; get for default code page
1169 ;DI already set to point to buffer
1170 int 21h
;AN000; es:di point to buffer that
1171 ;now has been filled in with info
1175 IFDEF BASESW
;AN037; If BASESW has been defined, and
1176 IFE BASESW
;AN037; If ES is psdata base
1177 pop PSDATA_SEG
;AN037; restore current base reg
1182 ;In this next section, ES will be used as the base of the XLAT table, provided
1183 ; by the previous GET COUNTRY INFO DOS call. This usage of ES is made
1184 ; regardless of which base reg is currently the PSDATA_SEG reg.
1186 IFDEF BASESW
;AN037; If BASESW has been defined, and
1187 IFE BASESW
;AN037; If ES is psdata base
1188 push PSDATA_SEG
;AN037; save current base reg
1191 mov bx,psdata_seg
:[di+$P_DOS_TBL_Off
] ;AN000; get offset of table
1192 mov es,psdata_seg
:[di+$P_DOS_TBL_Seg
] ;AN000; get segment of table
1193 inc bx ;AC035; add '2' to
1194 inc bx ;AC035; BX reg
1195 ;AN000; skip length field
1196 ;(changed ;AN035;) add bx,word ;AN000; skip length field
1197 sub al,$P_ASCII80
;AN000; make char to index
1198 xlat es:[bx] ;AN000; perform case map
1200 IFDEF BASESW
;AN037; If BASESW has been defined, and
1201 IFE BASESW
;AN037; If ES is psdata base
1202 pop PSDATA_SEG
;AN037; restore current base reg
1208 $P_CAPS_Ret
: ;AN000;
1210 $P_Do_CAPS_Char endp
;AN000;
1212 ;***********************************************************************
1213 IF NumSW
;AN000;(Check if numeric value is supported)
1214 ; $P_Value / $P_SValue
1216 ; Function: Make 32bit value from psdata_seg:SI and see value list
1217 ; and make result buffer.
1218 ; $P_SValue is an entry point for the signed value
1219 ; and this will simply call $P_Value after the handling
1220 ; of the sign character, "+" or "-"
1222 ; Input: psdata_seg:SI -> $P_STRING_BUF
1223 ; ES:BX -> CONTROL block
1227 ; Use: $P_Fill_Result, $P_Check_OVF
1229 ; Vars: $P_RC(W), $P_Flags(RW)
1230 ;***********************************************************************
1231 $P_SValue proc
;AN000; when signed value here
1233 or psdata_seg
:$P_Flags2
,$P_Signed
;AC034; indicate a signed numeric
1234 and psdata_seg
:$P_Flags2
,0ffh-$P_Neg
;AC034; assume positive value
1235 mov al,psdata_seg
:[si] ;AN000; get sign
1236 cmp al,$P_Plus
;AN000; "+" ?
1237 je $P_SVal00
;AN000;
1239 cmp al,$P_Minus
;AN000; "-" ?
1240 jne $P_Sval01
;AN000; else
1242 or psdata_seg
:$P_Flags2
,$P_Neg
;AC034; set this is negative value
1244 inc si ;AN000; skip sign char
1246 call $P_Value
;AN000; and process value
1249 $P_SValue endp
;AN000;
1250 ;***********************************************************************
1251 $P_Value proc
;AN000;
1256 xor cx,cx ;AN000; cx = higher 16 bits
1257 xor dx,dx ;AN000; dx = lower 16 bits
1258 push bx ;AN000; save control pointer
1259 $P_Value_Loop
: ;AN000;
1260 mov al,psdata_seg
:[si] ;AN000; get character
1261 or al,al ;AN000; end of line ?
1262 je $P_Value00
;AN000;
1264 call $P_0099
;AN000; make asc(0..9) to bin(0..9)
1265 jc $P_Value_Err0
;AN000;
1268 mov bp,ax ;AN000; save binary number
1269 shl dx,1 ;AN000; to have 2*x
1270 rcl cx,1 ;AN000; shift left w/ carry
1271 call $P_Check_OVF
;AN000; Overflow occurred ?
1272 jc $P_Value_Err0
;AN000; then error, exit
1274 mov bx,dx ;AN000; save low(2*x)
1275 mov ax,cx ;AN000; save high(2*x)
1276 shl dx,1 ;AN000; to have 4*x
1277 rcl cx,1 ;AN000; shift left w/ carry
1278 call $P_Check_OVF
;AN000; Overflow occurred ?
1279 jc $P_Value_Err0
;AN000; then error, exit
1281 shl dx,1 ;AN000; to have 8*x
1282 rcl cx,1 ;AN000; shift left w/ carry
1283 call $P_Check_OVF
;AN000; Overflow occurred ?
1284 jc $P_Value_Err0
;AN000; then error, exit
1286 add dx,bx ;AN000; now have 10*x
1287 adc cx,ax ;AN000; 32bit ADD
1288 call $P_Check_OVF
;AN000; Overflow occurred ?
1289 jc $P_Value_Err0
;AN000; then error, exit
1291 add dx,bp ;AN000; Add the current one degree decimal
1292 adc cx,0 ;AN000; if carry, add 1 to high 16bit
1293 call $P_Check_OVF
;AN000; Overflow occurred ?
1294 jc $P_Value_Err0
;AN000; then error, exit
1296 inc si ;AN000; update pointer
1297 jmp short $P_Value_Loop
;AN000; loop until NULL encountered
1299 $P_Value_Err0
: ;AN000;
1301 jmp $P_Value_Err
;AN000; Bridge
1304 pop bx ;AN000; restore control pointer
1305 test psdata_seg
:$P_Flags2
,$P_Neg
;AC034; here cx,dx = 32bit value
1306 je $P_Value01
;AN000; was it negative ?
1309 not dx ;AN000; |- Make 2's complement
1312 $P_Value01
: ;AN000; / nval =0
1313 mov si,es:[bx].$P_Value_List
;AN000; si points to value list
1314 mov al,es:[si] ;AN000; get nval
1315 cmp al,$P_nval_None
;AN000; no value list ?
1316 jne $P_Value02
;AN000;
1318 mov al,$P_Number
;AN000; Set type
1319 mov ah,$P_No_Tag
;AN000; No ITEM_TAG set
1320 jmp $P_Value_Exit
;AN000;
1322 $P_Value02
: ;AN000; / nval = 1
1323 IF Val1SW
;AN000;(Check if value list id #1 is supported)
1324 ;(tm07) cmp al,$P_nval_Range ;AN000; have range list ?
1325 ;(tm07) jne $P_Value03 ;AN000;
1328 mov al,es:[si] ;AN000; al = number of range
1329 cmp al,$P_No_nrng
;AN000; (tm07)
1330 je $P_Value03
;AN000; (tm07)
1332 inc si ;AN000; si points to 1st item_tag
1333 $P_Val02_Loop
: ;AN000;
1334 test psdata_seg
:$P_Flags2
,$P_Signed
;AC034;
1335 jne $P_Val02_Sign
;AN000;
1337 cmp cx,es:[si+$P_Val_XH
] ;AN000; comp cx with XH
1338 jb $P_Val02_Next
;AN000;
1340 ja $P_Val_In
;AN000;
1342 cmp dx,es:[si+$P_Val_XL
] ;AN000; comp dx with XL
1343 jb $P_Val02_Next
;AN000;
1346 ;;;;;; cmp cx,es:$P_Val_YH] ; comp cx with YH (tm01)
1347 cmp cx,es:[si+$P_Val_YH
] ;AN000; comp cx with YH (tm01)
1348 ja $P_Val02_Next
;AN000;
1350 jb $P_Val_Found
;AN000;
1352 cmp dx,es:[si+$P_Val_YL
] ;AN000; comp dx with YL
1353 ja $P_Val02_Next
;AN000;
1355 jmp short $P_Val_Found
;AN000;
1357 $P_Val02_Sign
: ;AN000;
1358 cmp cx,es:[si+$P_Val_XH
] ;AN000; comp cx with XH
1359 jl $P_Val02_Next
;AN000;
1361 jg $P_SVal_In
;AN000;
1363 cmp dx,es:[si+$P_Val_XL
] ;AN000; comp dx with XL
1364 jl $P_Val02_Next
;AN000;
1367 cmp cx,es:[si+$P_Val_YH
] ;AN000; comp cx with YH
1368 jg $P_Val02_Next
;AN000;
1370 jl $P_Val_Found
;AN000;
1372 cmp dx,es:[si+$P_Val_YL
] ;AN000; comp dx with YL
1373 jg $P_Val02_Next
;AN000;
1375 jmp short $P_Val_Found
;AN000;
1377 $P_Val02_Next
: ;AN000;
1378 add si,$P_Len_Range
;AN000;
1379 dec al ;AN000; loop nrng times in AL
1380 jne $P_Val02_Loop
;AN000;
1382 mov psdata_seg
:$P_RC
,$P_Out_of_Range
;AC034;
1383 mov al,$P_Number
;AN000;
1384 mov ah,$P_No_Tag
;AN000; No ITEM_TAG set
1385 jmp short $P_Value_Exit
;AN000;
1387 ENDIF
;AN000;(of Val1SW)
1388 IF Val1SW
+Val2SW
;AN000;(Check if value list id #1 or #2 is supported)
1389 $P_Val_Found
: ;AN000;
1390 mov al,$P_Number
;AN000;
1391 mov ah,es:[si] ;AN000; found ITEM_TAG set
1392 jmp short $P_Value_Exit
;AN000;
1394 ENDIF
;AN000;(of Val1SW+Val2SW)
1395 $P_Value03
: ;AN000; / nval = 2
1396 IF Val2SW
;AN000;(Check if value list id #2 is supported)
1397 ;;;; cmp al,$P_nval_Value ; have match list ? ASSUME nval=2,
1398 ;;;; jne $P_Value04 ; even if it is 3 or more.
1399 ;(tm07) inc si ;AN000;
1400 ;(tm07) mov al,es:[si] ;AN000; al = nrng
1401 mov ah,$P_Len_Range
;AN000;
1402 mul ah ;AN000; Skip nrng field
1404 add si,ax ;AN000; si points to nnval
1405 mov al,es:[si] ;AN000; get nnval
1406 inc si ;AN000; si points to 1st item_tag
1407 $P_Val03_Loop
: ;AN000;
1408 cmp cx,es:[si+$P_Val_XH
] ;AN000; comp cx with XH
1409 jne $P_Val03_Next
;AN000;
1411 cmp dx,es:[si+$P_Val_XL
] ;AN000; comp dx with XL
1412 je $P_Val_Found
;AN000;
1414 $P_Val03_Next
: ;AN000;
1415 add si,$P_Len_Value
;AN000; points to next value choice
1416 dec al ;AN000; loop nval times in AL
1417 jne $P_Val03_Loop
;AN000;
1419 mov psdata_seg
:$P_RC
,$P_Not_in_Val
;AC034;
1420 mov al,$P_Number
;AN000;
1421 mov ah,$P_No_Tag
;AN000; No ITEM_TAG set
1422 jmp short $P_Value_Exit
;AN000;
1424 ENDIF
;AN000;(of Val2SW)
1425 $P_Value04
: ;AN000; / nval = 3 or else
1426 $P_Value_Err
: ;AN000;
1427 mov psdata_seg
:$P_RC
,$P_Syntax
;AC034;
1428 mov al,$P_String
;AN000; Set type
1429 mov ah,$P_No_Tag
;AN000; No ITEM_TAG set
1430 $P_Value_Exit
: ;AN000;
1431 call $P_Fill_Result
;AN000;
1437 $P_Value endp
;AN000;
1439 ;***********************************************************************
1442 ; Function: Check if overflow is occurred with consideration of
1443 ; signed or un-signed numeric value
1445 ; Input: Flag register
1447 ; Output: CY = 1 : Overflow
1450 ;***********************************************************************
1451 $P_Check_OVF proc
;AN000;
1453 test psdata_seg
:$P_Flags2
,$P_Neg
;AC034; is it negative value ?
1454 jne $P_COVF
;AN000; if no, check overflow
1456 popf ;AN000; by the CY bit
1461 jo $P_COVF00
;AN000; check overflow by the OF
1463 clc ;AN000; indicate it with CY bit
1464 ret ;AN000; CY=0 means no overflow
1467 stc ;AN000; and CY=1 means overflow
1469 $P_Check_OVF endp
;AN000;
1470 ENDIF
;AN000;(of FarSW)
1471 ;***********************************************************************
1474 ; Function: Make ASCII 0-9 to Binary 0-9
1476 ; Input: AL = character code
1478 ; Output: CY = 1 : AL is not number
1479 ; CY = 0 : AL contains binary value
1480 ;***********************************************************************
1481 $P_0099 proc
;AN000;
1483 jb $P_0099Err
;AN000; must be 0 =< al =< 9
1486 ja $P_0099Err
;AN000; must be 0 =< al =< 9
1488 sub al,"0" ;AN000; make char -> bin
1489 clc ;AN000; indicate no error
1493 stc ;AN000; indicate error
1495 $P_0099 endp
;AN000;
1497 ;***********************************************************************
1500 ; Function: See value list for the simple string
1501 ; and make result buffer.
1503 ; Input: psdata_seg:SI -> $P_STRING_BUF
1504 ; ES:BX -> CONTROL block
1508 ; Use: $P_Fill_Result, $P_String_Comp
1511 ;***********************************************************************
1512 $P_Simple_String proc
;AN000;
1517 mov di,es:[bx].$P_Value_List
;AN000; di points to value list
1518 mov al,es:[di] ;AN000; get nval
1519 or al,al ;AN000; no value list ?
1520 jne $P_Sim00
;AN000; then
1522 mov ah,$P_No_Tag
;AN000; No ITEM_TAG set
1523 jmp short $P_Sim_Exit
;AN000; and set result buffer
1526 IF Val3SW
+KeySW
;AN000;(Check if keyword or value list id #3 is supported)
1527 cmp al,$P_nval_String
;AN000; String choice list provided ?
1528 jne $P_Sim01
;AN000; if no, syntax error
1531 mov al,es:[di] ;AN000; al = nrng
1532 mov ah,$P_Len_Range
;AN000;
1533 mul ah ;AN000; Skip nrng field
1534 inc ax ;AN000; ax = (nrng*9)+1
1535 add di,ax ;AN000; di points to nnval
1536 mov al,es:[di] ;AN000; get nnval
1537 mov ah,$P_Len_Value
;AN000;
1538 mul ah ;AN000; Skip nnval field
1539 inc ax ;AN000; ax = (nnval*5)+1
1540 add di,ax ;AN000; di points to nstrval
1541 mov al,es:[di] ;AN000; get nstrval
1542 inc di ;AC035; add '2' to
1543 inc di ;AC035; DI reg
1544 ;AN000; di points to 1st string in list
1545 ;(replaced ;AC035;) add di,2 ;AN000; di points to 1st string in list
1546 $P_Sim_Loop
: ;AN000;
1547 mov bp,es:[di] ;AN000; get string pointer
1548 call $P_String_Comp
;AN000; compare it with operand
1549 jnc $P_Sim_Found
;AN000; found on list ?
1551 add di,$P_Len_String
;AN000; if no, point to next choice
1552 dec al ;AN000; loop nstval times in AL
1553 jne $P_Sim_Loop
;AN000;
1555 mov psdata_seg
:$P_RC
,$P_Not_In_Str
;AC034;
1556 mov ah,$P_No_Tag
;AN000; No ITEM_TAG set
1557 jmp short $P_Sim_Exit
;AN000;
1559 $P_Sim_Found
: ;AN000;
1560 mov ah,es:[di-1] ;AN000; set item_tag
1561 mov al,$P_List_Idx
;AN000;
1562 mov dx,es:[di] ;AN000; get address of STRING
1563 jmp short $P_Sim_Exit0
;AN000;
1564 ENDIF
;AN000;(of Val3SW+KeySW)
1566 mov psdata_seg
:$P_RC
,$P_Syntax
;AC034;
1567 mov ah,$P_No_Tag
;AN000; No ITEM_TAG set
1568 $P_Sim_Exit
: ;AN000;
1569 mov al,$P_String
;AN000; Set type
1570 $P_Sim_Exit0
: ;AN000;
1571 call $P_Fill_Result
;AN000;
1577 $P_Simple_String endp
;AN000;
1579 ;***********************************************************************
1582 ; Function: Compare two string
1584 ; Input: psdata_seg:SI -> 1st string
1585 ; ES:BP -> 2nd string (Must be upper case)
1586 ; ES:BX -> CONTROL block
1588 ; Output: CY = 1 if not match
1590 ; Use: $P_Chk_DBCS, $P_Do_CAPS_Char
1592 ; Vars: $P_KEYor_SW_Ptr(W), $P_Flags(R). $P_KEYorSW_Ptr
1593 ;***********************************************************************
1594 $P_String_Comp proc
;AN000;
1599 mov dl,$P_DOSTBL_Char
;AN000; use character case map table
1600 $P_SCOM_Loop
: ;AN000;
1601 mov al,psdata_seg
:[si] ;AN000; get command character
1602 call $P_Chk_DBCS
;AN000; DBCS ?
1603 jc $P_SCOM00
;AN000; yes,DBCS
1605 call $P_Do_CAPS_Char
;AN000; else, upper case map before comparison
1606 IF KeySW
+SwSW
;AN000;(Check if keyword or switch is supported)
1607 test psdata_seg
:$P_Flags2
,$P_Key_Cmp
;AC034; keyword search ?
1608 je $P_SCOM04
;AN000;
1610 cmp al,$P_Keyword
;AN000; "=" is delimiter
1611 jne $P_SCOM03
;AN000;IF "=" on command line AND (bp+1=> char after the "=" in synonym list)
1613 cmp byte ptr es:[bp+1],$P_NULL
;AN021; at end of keyword string in the control block THEN
1614 jne $P_SCOM_DIFFER
;AN021;
1616 jmp short $P_SCOM05
;AN000; keyword found in synonym list
1619 test psdata_seg
:$P_Flags2
,$P_SW_Cmp
;AC034; switch search ?
1620 je $P_SCOM03
;AN000;
1622 cmp al,$P_Colon
;AN000; ":" is delimiter, at end of switch on command line
1623 jne $P_SCOM03
;AN000; continue compares
1625 cmp byte ptr es:[bp],$P_NULL
;AN021; IF at end of switch on command AND
1626 jne $P_SCOM_DIFFER
;AN021; at end of switch string in the control block THEN
1628 $P_SCOM05
: ;AN000; found a match
1629 inc si ;AN000; si points to just after "=" or ":"
1630 jmp short $P_SCOM_Same
;AN000; exit
1633 ENDIF
;AN000;(of KeySW+SwSW)
1634 cmp al,es:[bp] ;AN000; compare operand w/ a synonym
1635 jne $P_SCOM_Differ0
;AN000; if different, check ignore colon option
1637 or al,al ;AN000; end of line
1638 je $P_SCOM_Same
;AN000; if so, exit
1640 inc si ;AN000; update operand pointer
1641 inc bp ;AN000; and synonym pointer
1642 jmp short $P_SCOM01
;AN000; loop until NULL or "=" or ":" found in case
1644 $P_SCOM00
: ;AN000; Here al is DBCS leading byte
1645 cmp al,es:[bp] ;AN000; compare leading byte
1646 jne $P_SCOM_Differ
;AN000; if not match, say different
1648 inc si ;AN000; else, load next byte
1649 mov al,psdata_seg
:[si] ;AN000; and
1651 cmp al,es:[bp] ;AN000; compare 2nd byte
1652 jne $P_SCOM_Differ
;AN000; if not match, say different, too
1654 inc si ;AN000; else update operand pointer
1655 inc bp ;AN000; and synonym pointer
1657 jmp short $P_SCOM_Loop
;AN000; loop until NULL or "=" or "/" found in case
1659 $P_SCOM_Differ0
: ;AN000;
1661 IF SwSW
;AN000;(tm10)
1662 test psdata_seg
:$P_Flags2
,$P_SW
;AC034;(tm10)
1663 je $P_not_applicable
;AN000;(tm10)
1665 test es:[bx].$P_Function_Flag
,$P_colon_is_not_necessary
;AN000;(tm10)
1666 je $P_not_applicable
;AN000;(tm10)
1668 cmp byte ptr es:[bp],$P_NULL
;AN000;(tm10)
1669 ;(deleted ;AN025;) jne $P_not_applicable ;AN000;(tm10)
1670 je $P_SCOM_Same
;AN025;(tm10)
1672 $P_not_applicable
: ;AN000;(tm10)
1675 test es:[bx].$P_Match_Flag
,$P_Ig_Colon
;AN000; ignore colon option specified ?
1676 je $P_SCOM_Differ
;AN000; if no, say different.
1678 cmp al,$P_Colon
;AN000; End up with ":" and
1679 jne $P_SCOM02
;AN000; subseqently
1681 cmp byte ptr es:[bp],$P_NULL
;AN000; NULL ?
1682 jne $P_SCOM_Differ
;AN000; if no, say different
1684 jmp short $p_SCOM_Same
;AN000; else, say same
1687 cmp al,$P_NULL
;AN000; end up NULL and :
1688 jne $P_SCOM_Differ
;AN000;
1690 cmp byte ptr es:[bp],$P_Colon
;AN000; if no, say different
1691 je $p_SCOM_Same
;AN000; else, say same
1693 $P_SCOM_Differ
: ;AN000;
1694 stc ;AN000; indicate not found
1695 jmp short $P_SCOM_Exit
;AN000;
1697 $P_SCOM_Same
: ;AN000;
1698 mov psdata_seg
:$P_KEYorSW_Ptr
,si ;AC034; for later use by keyword or switch
1699 clc ;AN000; indicate found
1700 $P_SCOM_Exit
: ;AN000;
1706 $P_String_Comp endp
;AN000;
1708 ;***********************************************************************
1709 IF DateSW
;AN000;(Check if date format is supported)
1712 ; Function: Convert a date string to DOS date format for int 21h
1713 ; with format validation.
1715 ; Input: psdata_seg:SI -> $P_STRING_BUF
1716 ; ES:BX -> CONTROL block
1720 ; Use: $P_Fill_Result, $P_Set_CDI, $P_Get_DecNum
1722 ; Vars: $P_RC(W), $P_1st_Val(RW), $P_2nd_Val(RW), $P_3rd_Val(RW)
1723 ;***********************************************************************
1724 $P_Date_Format proc
;AN000;
1731 call $P_Set_CDI
;AN000; set country dependent information before process
1732 ; mov bl,psdata_seg:[si].$P_CDI_DateS ;load date separator ;AN020; (deleted)
1733 ; note: the country info is still needed
1734 ; to determine the order of the fields,
1735 ; but the separator char is no longer used.
1737 mov psdata_seg
:$P_1st_Val
,0 ;AC034; set initial value
1738 mov psdata_seg
:$P_2nd_Val
,0 ;AC034; set initial value
1739 mov psdata_seg
:$P_3rd_Val
,0 ;AC034; set initial value
1740 call $P_Get_DecNum
;AN000; get 1st number
1741 jc $P_DateF_Err0
;AN000;-----------------------+
1743 mov psdata_seg
:$P_1st_Val
,ax ;AC034; |
1744 or bl,bl ;AN000; end of line ? |
1745 je $P_DateF_YMD
;AN000; |
1747 call $P_Get_DecNum
;AN000; get 2nd number |
1748 jc $P_DateF_Error
;AN000; |
1750 mov psdata_seg
:$P_2nd_Val
,ax ;AC034; |
1751 or bl,bl ;AN000; end of line ? |
1752 je $P_DateF_YMD
;AN000; |
1754 call $P_Get_DecNum
;AN000; get 3rd number |
1755 $P_DateF_Err0
: ;AN000; Bridge <-----------+
1756 jc $P_DateF_Error
;AN000;
1758 mov psdata_seg
:$P_3rd_Val
,ax ;AC034;
1759 or bl,bl ;AN000; end of line ?
1760 jne $P_DateF_Error
;AN000;
1762 $P_DateF_YMD
: ;AN000;
1763 mov bx,psdata_seg
:$P_Country_Info
.$P_CDI_DateF
;AC034; get date format
1764 cmp bx,$P_Date_YMD
;AN000;
1765 je $P_DateF00
;AN000;
1767 mov ax,psdata_seg
:$P_1st_Val
;AC034;
1769 jne $P_DateF_Error
;AN000;
1771 mov cl,al ;AN000; set month
1772 mov ax,psdata_seg
:$P_2nd_Val
;AC034;
1773 or ah,ah ;AN000; if overflow, error.
1774 jne $P_DateF_Error
;AN000;
1776 mov ch,al ;AN000; set date
1777 mov dx,psdata_seg
:$P_3rd_Val
;AC034; set year
1778 cmp bx,$P_Date_DMY
;AN000; from here format = MDY
1779 jne $P_DateF01
;AN000; if it is DMY
1781 xchg ch,cl ;AN000; then swap M <-> D
1783 jmp short $P_DateF02
;AN000;
1785 $P_DateF00
: ;AN000; / here format = YMD
1786 mov dx,psdata_seg
:$P_1st_Val
;AC034; set year
1787 mov ax,psdata_seg
:$P_2nd_Val
;AC034;
1788 or ah,ah ;AN000; if overflow, error
1789 jne $P_DateF_Error
;AN000;
1791 mov cl,al ;AN000; set month
1792 mov ax,psdata_seg
:$P_3rd_Val
;AC034;
1793 or ah,ah ;AN000; if overflow, error
1794 jne $P_DateF_Error
;AN000;
1796 mov ch,al ;AN000; set date
1798 cmp dx,100 ;AN000; year is less that 100 ?
1799 jae $P_DateF03
;AN000;
1801 add dx,1900 ;AN000; set year 19xx
1803 pop bx ;AN000; recover CONTROL block
1804 pop si ;AN000; recover string pointer
1805 mov ah,$P_No_Tag
;AN000; set
1806 mov al,$P_Date_F
;AN000; result
1807 call $P_Fill_Result
;AN000; buffer
1808 jmp short $P_Date_Format_Exit
;AN000; to Date
1810 $P_DateF_Error
: ;AN000;
1811 pop bx ;AN000; recover CONTROL block
1812 pop si ;AN000; recover string pointer
1813 mov ah,$P_No_Tag
;AN000; set
1814 mov al,$P_String
;AN000; result
1815 call $P_Fill_Result
;AN000; buffer to string
1816 mov psdata_seg
:$P_RC
,$P_Syntax
;AC034; indicate syntax error
1817 $P_Date_Format_Exit
: ;AN000;
1822 $P_Date_Format endp
;AN000;
1823 ENDIF
;AN000;(of DateSW)
1825 ;***********************************************************************
1826 IF TimeSW
+DateSW
;AN000;(Check if time or date format is supported)
1829 ; Function: Read CDI from DOS if it has not been read yet
1833 ; Output: psdata_seg:SI -> CDI
1835 ; Use: INT 21h w/ AH = 38h
1836 ;***********************************************************************
1837 $P_Set_CDI proc
;AN000;
1838 lea si,psdata_seg
:$P_Country_Info
;AC034;
1839 cmp psdata_seg
:[si].$P_CDI_DateF
,$P_NeedToBeRead
;AN000; already read ?
1840 je $P_Read_CDI
;AN000;
1842 jmp short $P_Set_CDI_Exit
;AN000; then do nothing
1844 $P_Read_CDI
: ;AN000; else read CDI thru DOS
1848 push PSDATA_SEG
;AC023;
1849 pop ds ;AN000; set segment register
1850 mov ax,$P_DOS_Get_CDI
;AN000; get country information
1851 mov dx,si ;AN000; set offset of CDI in local data area
1856 $P_Set_CDI_Exit
: ;AN000;
1858 $P_Set_CDI endp
;AN000;
1860 ;***********************************************************************
1863 ; Function: Read a chcrater code from psdata_seg:SI until specified delimiter
1864 ; or NULL encountered. And make a decimal number.
1866 ; Input: psdata_seg:SI -> $P_STRING_BUF
1868 ; Output: BL = delimiter code or NULL
1869 ; AX = Decimal number
1870 ; SI advanced to the next number
1871 ; CY = 1 : Syntax error, AL = Latest examineed number
1874 ;***********************************************************************
1875 $P_Get_DecNum proc
;AN000;
1878 xor cx,cx ;AN000; cx will have final value
1879 $P_GetNum_Loop
: ;AN000;
1880 mov al,psdata_seg
:[si] ;AN000; load character
1881 or al,al ;AN000; end of line ?
1882 je $P_GetNum00
;AN000; if yes, exit
1884 cmp psdata_seg
:$P_Got_Time
,0 ;AC034; ;is this numeric in a time field? ;AC023
1885 je $P_Do_Date_Delims
;AN000;no, go check out Date delimiters ;AC023
1887 ; Determine which delimiter(s) to check for. Colon & period or period only
1888 cmp bl,$P_colon_period
;AN032; ;Time
1889 jne $P_Do_Time_Delim1
;AN032; ;only check for period
1891 cmp al,$P_Colon
;AN032; ;Is this a valid delimiter ?
1892 je $P_GetNum01
;AN032; ;yes, exit
1894 $P_Do_Time_Delim1
: ;AN000;
1895 cmp al,$P_Period
;;AC032;;AC023;Is this a valid delimiter ?
1896 je $P_GetNum01
;AC023; yes, exit
1898 jmp short $P_Neither_Delims
;AN023;
1900 $P_Do_Date_Delims
: ;AN000;
1901 ;Regardless of the date delimiter character specified in the country
1902 ;dependent information, check for the presence of any one of these
1903 ;three field delimiters: "-", "/", or ".".
1904 cmp al,$P_Minus
;AN020;is this a date delimiter character?
1905 je $P_GetNum01
;AN020;if yes, exit
1907 cmp al,$P_Slash
;AN020;is this a date delimiter character?
1908 je $P_GetNum01
;AN020;if yes, exit
1910 cmp al,$P_Period
;AN020;is this a date delimiter character?
1911 je $P_GetNum01
;AN000; if yes, exit
1913 $P_Neither_Delims
: ;AN023;
1915 call $P_0099
;AN000; convert it to binary
1916 jc $P_GetNum_Exit
;AN000; if error exit
1921 mul dx ;AN000; ax = ax * 10
1922 or dx,dx ;AN000; overflow
1923 jne $P_GetNum02
;AN000; then exit
1926 jc $P_GetNum_Exit
;AN000;
1930 jmp short $P_GetNum_Loop
;AN000;
1932 $P_GetNum00
: ;AN000;
1933 mov bl,al ;AN000; set bl to NULL
1934 clc ;AN000; indicate no error
1935 jmp short $P_GetNum_Exit
;AN000;
1937 $P_GetNum01
: ;AN000;
1938 inc si ;AN000; si points to next number
1939 clc ;AN000; indicate no error
1940 jmp short $P_GetNum_Exit
;AN000;
1942 $P_GetNum02
: ;AN000;
1943 stc ;AN000; indicate error
1944 $P_GetNum_Exit
: ;AN000;
1945 mov ax,cx ;AN000;return value
1949 $P_Get_DecNum endp
;AN000;
1950 ENDIF
;AN000;(of TimeSW+DateSW)
1952 ;***********************************************************************
1953 IF TimeSW
;AN000;(Check if time format is supported)
1956 ; Function: Convert a time string to DOS time format for int 21h
1957 ; with format validation.
1959 ; Input: psdata_seg:SI -> $P_STRING_BUF
1960 ; ES:BX -> CONTROL block
1964 ; Use: $P_Fill_Result, $P_Set_CDI, $P_Get_DecNum, $P_Time_2412
1966 ; Vars: $P_RC(W), $P_Flags(R), $P_1st_Val(RW), $P_2nd_Val(RW)
1967 ; $P_3rd_Val(RW), $P_4th_Val(RW)
1968 ;***********************************************************************
1969 $P_Time_Format proc
;AN000;
1976 call $P_Set_CDI
;AN000; Set country independent
1977 ; information before process
1978 ;(AN032; deleted) mov bl,psdata_seg:[si].$P_CDI_TimeS ;load time separator
1979 ;(AN032; deleted) mov bh,psdata_seg:[si].$P_CDI_Dec ;load decimal separator
1980 test byte ptr psdata_seg
:[si].$P_CDI_TimeF
,1 ;AN000; 24 hour system
1982 jne $P_TimeF00
;AN000; if no, means 12 hour system
1984 call $P_Time_2412
;AN000; this routine handle "am" "pm"
1986 mov psdata_seg
:$P_1st_Val
,0 ;AC034; set initial value
1987 mov psdata_seg
:$P_2nd_Val
,0 ;AC034; set initial value
1988 mov psdata_seg
:$P_3rd_Val
,0 ;AC034; set initial value
1989 mov psdata_seg
:$P_4th_Val
,0 ;AC034; set initial value
1990 mov psdata_seg
:$P_Got_Time
,1 ;AN023;AC034;; use time delimiter
1991 mov bl,$P_colon_period
;AN032; flag, indicates use of
1992 ; delimiters between hours,
1994 call $P_Get_DecNum
;AN000; get 1st number
1995 jc $P_TimeF_Err0
;AN000;
1997 mov psdata_seg
:$P_1st_Val
,ax ;AC034;
1998 or bl,bl ;AN000; end of line ?
1999 je $P_TimeF_Rlt
;AN000;
2001 call $P_Get_DecNum
;AN000; get 2nd number
2002 jc $P_TimeF_Err0
;AC038; if OK
2004 mov psdata_seg
:$P_2nd_Val
,ax ;AC034;
2005 or bl,bl ;AN000; end of line ?
2006 je $P_TimeF_Rlt
;AN000;
2008 ;(;AN032; deleted) mov bl,bh ;set decimal separator
2009 mov bl,$P_period_only
;AN032; flag, which to decimal separator
2010 call $P_Get_DecNum
;AN000; get 3rd number
2011 jc $P_TimeF_Err0
;AC039; if problem, bridge to error
2013 mov psdata_seg
:$P_3rd_Val
,ax ;AC034;
2014 or bl,bl ;AN000; end of line ?
2015 ;(DELETED ;AN039;) je $P_TimeF_Rlt ;AN000;
2016 jne $P_Time_4
;AN039; NOT END OF LINE,
2017 ;AN039; GO TO 4TH NUMBER
2018 test psdata_seg
:$P_Flags1
,$P_Time_Again
;AN039; HAS TIME PARSE
2019 ;AN039; BEEN REPEATED?
2020 jnz $P_TimeF_Rlt
;AN039; yes, this is really
2021 ;AN039; the end of line
2022 ;AN039; no, time has not been repeated
2023 mov si,psdata_seg
:$P_SI_Save
;AN039; get where parser quit
2024 ;AN039; in command line
2025 cmp byte ptr [si-1],$P_Comma
;AN039; look at delimiter
2026 ;AN039; from command line
2027 jne $P_TimeF_Rlt
;AN039; was not a comma, this is
2028 ;AN039; really end of line
2029 ;AN039; is comma before hundredths,
2031 mov byte ptr [si-1],$P_Period
;AN039; change that ambiguous
2032 ;AN039; comma to a decimal point
2033 ;AN039; parse can understand
2034 mov psdata_seg
:$P_Flags
,0 ;AN039; Clear all internal flags
2035 or psdata_seg
:$P_Flags1
,$P_Time_Again
;AN039; indicate TIME
2036 ;AN039; is being repeated
2037 mov cx,psdata_seg
:$P_ORIG_ORD
;AN039; ORIGINAL ORDINAL FROM CX
2038 mov sp,psdata_seg
:$P_ORIG_STACK
;AN039; ORIGINAL VALUE
2039 ;AN039; OF STACK FROM SP
2040 mov si,psdata_seg
:$P_ORIG_SI
;AN039; ORIGINAL START
2041 ;AN039; PARSE POINTER FROM SI
2042 jmp $P_Redo_Time
;AN039; go try TIME again
2043 ; ===============================================================
2044 $P_Time_4
: ;AN039; READY FOR 4TH (HUNDREDTHS) NUMBER
2045 call $P_Get_DecNum
;AN000; get 4th number
2046 $P_TimeF_Err0
: ;AN000; Bridge
2047 jc $P_TimeF_Error
;AN000;
2049 mov psdata_seg
:$P_4th_Val
,ax ;AC034;
2050 or bl,bl ;AN000; After hundredth, no data allowed
2051 jne $P_TimeF_Error
;AN000; if some, then error
2053 $P_TimeF_RLT
: ;AN000;
2054 mov ax,psdata_seg
:$P_1st_Val
;AC034;
2055 or ah,ah ;AN000; if overflow then error
2056 jne $P_TimeF_Err
;AN000;
2058 test psdata_seg
:$P_Flags1
,$P_Time12am
;AN038;if "am" specified
2059 jz $P_Time_notAM
;AN038;skip if no "AM" specified
2060 ;since "AM" was specified,
2061 cmp al,12 ;AN038: if hour specified as later than noon
2062 ja $P_TimeF_Err
;AN038; error if "AM" on more than noon
2063 jne $P_Time_notAM
;AN038; for noon exactly,
2065 xor al,al ;AN038; set hour = zero
2066 $P_Time_notAM
: ;AN038;
2067 test psdata_seg
:$P_Flags2
,$P_Time12
;AC034; if 12 hour system and pm is specified
2068 je $P_TimeSkip00
;AN000; then
2070 cmp al,12 ;AN038; if 12:00 o'clock already
2071 je $P_TimeSkip00
;AN038; it is PM already
2073 add al,12 ;AN000; add 12 hours to make it afternoon
2074 jc $P_TimeF_Err
;AN000; if overflow then error
2076 cmp al,24 ;AN038; after adding 12, now cannot be >24
2077 ja $P_TimeF_Err
;AN038; if too big, error
2079 $P_TimeSkip00
: ;AN000;
2080 mov dl,al ;AN000; set hour
2081 mov ax,psdata_seg
:$P_2nd_Val
;AC034;
2082 or ah,ah ;AN000; if overflow then error
2083 jne $P_TimeF_Err
;AN000;
2085 mov dh,al ;AN000; set minute
2086 mov ax,psdata_seg
:$P_3rd_Val
;AC034;
2087 or ah,ah ;AN000; if overflow then error
2088 jne $P_TimeF_Err
;AN000;
2090 mov cl,al ;AN000; set second
2091 mov ax,psdata_seg
:$P_4th_Val
;AC034;
2092 or ah,ah ;AN000; if overflow then error
2093 jne $P_TimeF_Err
;AN000;
2095 mov ch,al ;AN000; set hundredth
2096 pop bx ;AN000; recover CONTROL block
2097 pop si ;AN000; recover string pointer
2098 mov ah,$P_No_Tag
;AN000; set
2099 mov al,$P_Time_F
;AN000; result
2100 call $P_Fill_Result
;AN000; buffer
2101 jmp short $P_Time_Format_Exit
;AN000; to time
2103 $P_TimeF_Error
: ;AN000;
2104 $P_TimeF_Err
: ;AN000;
2105 pop bx ;AN000; recover CONTROL block
2106 pop si ;AN000; recover string pointer
2107 mov ah,$P_No_Tag
;AN000; set
2108 mov al,$P_String
;AN000; result
2109 call $P_Fill_Result
;AN000; buffer to string
2110 mov psdata_seg
:$P_RC
,$P_Syntax
;AC034; return syntax error
2111 $P_Time_Format_Exit
: ;AN000;
2112 mov psdata_seg
:$P_Got_Time
,0 ;AN023;AC034;; finished with this time field
2117 $P_Time_Format endp
;AN000;
2119 ;***********************************************************************
2122 ; Function: Remove "a", "p", "am", or "pm" from the end of stinrg
2124 ; Input: psdata_seg:SI -> $P_STRING_BUF
2126 ; Output: Set $P_Time12 flag when the string is terminated by "p"
2130 ;***********************************************************************
2131 $P_Time_2412 proc
;AN000;
2134 $P_T12_Loop
: ;AN000;
2135 mov al,psdata_seg
:[si] ;AN000; Move
2138 jne $P_T12_Loop
;AN000; end of string
2140 mov al,psdata_seg
:[si-word] ;AN000; get char just before NULL
2141 or al,$P_Make_Lower
;AN000; lower case map
2142 cmp al,"p" ;AN000; only "p" of "pm" ?
2145 cmp al,"a" ;AN000; only "a" of "am" ?
2148 cmp al,"m" ;AN000; "m" of "am" or "pm"
2149 jne $P_T12_Exit
;AN000;
2152 mov al,psdata_seg
:[si-word] ;AN000;
2153 or al,$P_Make_lower
;AN000; lower case map
2154 cmp al,"p" ;AN000; "p" of "pm" ?
2157 cmp al,"a" ;AN000; "a" of "am" ?
2158 je $P_T1201
;AN000; go process "a"
2160 jmp short $P_T12_Exit
;AN000; no special chars found
2162 $P_T1200
: ;AN000; "P" found
2163 or psdata_seg
:$P_Flags2
,$P_Time12
;AC034; flag "PM" found
2164 jmp short $P_Tclr_chr
;AN038; go clear the special char
2166 $P_T1201
: ;AN000; "A" found
2167 or psdata_seg
:$P_Flags1
,$P_Time12AM
;AN038; flag "AM" found
2168 $P_Tclr_chr
: ;AN038;
2169 mov byte ptr psdata_seg
:[si-2],$P_NULL
;AN000; null out special char
2170 $P_T12_Exit
: ;AN000;
2174 $P_Time_2412 endp
;AN000;
2175 ENDIF
;AN000;(of TimeSW)
2177 ;***********************************************************************
2178 IF CmpxSW
;AN000;(Check if complex item is supported)
2179 ; $P_Complex_Format:
2181 ; Function: Check if the input string is valid complex format.
2182 ; And set the result buffer.
2184 ; Input: psdata_seg:SI -> $P_STRING_BUF
2185 ; ES:BX -> CONTROL block
2189 ; Use: $P_Fill_Result, $P_Chk_DBCS, $P_Chk_EOL, $P_Skip_Delim
2190 ; $P_Quoted_str, $P_Chk_DSQuote
2192 ; Vars: $P_RC(W), $P_SI_Save(W), $P_SaveSI_Cmpx(R), $P_Save_EOB(R)
2193 ;***********************************************************************
2194 $P_Complex_Format proc
;AN000;
2198 mov bx,psdata_seg
:$P_SaveSI_Cmpx
;AC034; bx points to user buffer
2199 cmp byte ptr [bx],$P_Lparen
;AN000; 1st char = left parentheses
2200 jne $P_Cmpx_Err
;AN000;
2202 xor ah,ah ;AN000; ah = parentheses counter
2203 $P_Cmpx_Loop
: ;AN000;
2204 mov al,[bx] ;AN000; load character from command buffer
2205 call $P_Chk_EOL
;AN000; if it is one of EOL
2206 je $P_CmpxErr0
;AN000; then error exit.
2208 cmp al,$P_Lparen
;AN000; left parentheses ?
2209 jne $P_Cmpx00
;AN000; then
2211 inc ah ;AC035; add '1' to AH reg
2212 ;AN000; increment parentheses counter
2213 ;(replaced ;AC035;) add ah,1 ;AN000; increment parentheses counter
2214 jc $P_CmpxErr0
;AN000; if overflow, error
2216 cmp al,$P_Rparen
;AN000; right parentheses ?
2217 jne $P_Cmpx01
;AN000; then
2219 dec ah ;AC035; subtract '1' from AH reg
2220 ;AN000; decrement parentheses counter
2221 ;(changed ;AC035;) sub ah,1 ;AN000; decrement parentheses counter
2222 jc $P_CmpxErr0
;AN000; if overflow error
2224 je $P_Cmpx03
;AN000; ok, valid complex
2227 ;(deleted ;AN025;) call $P_Chk_DSQuote ;AN000; double or single quotation mark ? 3/17/KK
2228 cmp al,$P_DQuote
;AN025; double quotation mark?
2229 jne $P_Cmpx04
;AN000; 3/17/KK
2231 mov psdata_seg
:[si],al ;AN000; here quoted string is found in the complex list.
2233 inc bx ;AN000; bx points to 2nd character
2234 call $P_Quoted_Str
;AN000; skip pointers until closing of quoted string
2235 jc $P_CmpxErr0
;AN000; if error in quoted string syntax then exit
2237 jmp short $P_Cmpx05
;AN000;
2240 call $P_Chk_DBCS
;AN000; was it a lead byte of DBCS ?
2241 jnc $P_Cmpx02
;AN000;
2243 mov psdata_seg
:[si],al ;AN000; then store 1st byte
2246 mov al,[bx] ;AN000; load 2nd byte
2248 mov psdata_seg
:[si],al ;AN000; store SBCS or 2nd byte of DBCS
2252 jmp short $P_Cmpx_Loop
;AN000; loop
2255 mov byte ptr psdata_seg
:[si],al ;AN000;
2256 mov byte ptr psdata_seg
:[si+byte],$P_NULL
;AN000;
2257 mov byte ptr [bx],$P_NULL
;AN000; replace right parentheses with NULL
2258 mov si,bx ;AN000; skip whitespaces
2259 inc si ;AN000; after
2260 call $P_Skip_Delim
;AN000; right parentheses
2261 mov psdata_seg
:$P_SI_Save
,si ;AC034; save next pointer, SI
2262 jmp short $P_Cmpx_Exit
;AN000;
2264 $P_CmpxErr0
: ;AN000;
2265 mov si,psdata_seg
:$P_Save_EOB
;AC034; if EOF encountered, restore
2266 mov byte ptr psdata_seg
:[si],$P_NULL
;AN000; EOB mark
2267 $P_Cmpx_Err
: ;AN000;
2268 mov psdata_seg
:$P_RC
,$P_Syntax
;AC034;
2269 $P_Cmpx_Exit
: ;AN000;
2270 mov ah,$P_No_Tag
;AN000;
2271 mov al,$P_Complex
;AN000;
2274 call $P_Fill_Result
;AN000;
2277 $P_Complex_Format endp
;AN000;
2278 ENDIF
;AN000;(of CpmxSW)
2280 ;***********************************************************************
2281 IF QusSW
;AN000;(Check if quoted string is supported)
2284 ; Function: Check if the input string is valid quoted string format.
2285 ; And set the result buffer.
2287 ; Input: psdata_seg:SI -> $P_STRING_BUF
2288 ; ES:BX -> CONTROL block
2292 ; Use: $P_Fill_Result, $P_Chk_DBCS, $P_Chk_EOL, $P_Skip_Delim
2293 ; $P_Chk_DSQuote, $P_Quoted_Str
2295 ; Vars: $P_RC(W), $P_SI_Save(W), $P_SaveSI_Cmpx(R),$P_Save_EOB(R)
2296 ;***********************************************************************
2297 $P_Quoted_Format proc
;AN000;
2301 mov bx,psdata_seg
:$P_SaveSI_Cmpx
;AC034; bx points to user buffer
2302 mov al,byte ptr [bx] ;AN000; get 1st character
2303 ;(deleted ;AN025;) call $P_Chk_DSQuote ;AN000; is it single or double quote ?
2304 cmp al,$P_DQuote
;AN025; double quotation mark?
2305 jne $P_Qus_Err
;AN000; if no, error
2307 ; mov psdata_seg:[si],al ;AN000; move it to internal buffer
2309 inc bx ;AN000; bx points to 2nd character
2310 call $P_Quoted_Str
;AN000; skip pointers to the closing of quoted string
2311 jc $P_Qus_Err0
;AN000; if invali quoted string syntax, exit
2313 mov byte ptr psdata_seg
:[si+byte],$P_NULL
;AN000; end up with NULL
2316 call $P_Skip_Delim
;AN000; skip whitespaces after closing quote
2317 mov psdata_seg
:$P_SI_Save
,si ;AC034; save next pointer, SI
2318 jmp short $P_Qus_Exit
;AN000;
2320 $P_Qus_Err0
: ;AN000;
2321 mov si,psdata_seg
:$P_Save_EOB
;AC034; if EOF encountered, restore
2322 mov byte ptr psdata_seg
:[si],$P_NULL
;AN000; EOB mark
2323 $P_Qus_Err
: ;AN000;AN000
2324 mov psdata_seg
:$P_RC
,$P_Syntax
;AC034; indicate syntax error
2325 $P_Qus_Exit
: ;AN000;
2326 mov ah,$P_No_Tag
;AN000; set
2327 mov al,$P_Quoted_String
;AN000; result
2328 pop si ;AN000; buffer
2330 call $P_Fill_Result
;AN000; quoted string
2333 $P_Quoted_Format endp
;AN000;
2334 ENDIF
;AN000;(of QusSW)
2336 ;***********************************************************************
2339 ; Function: Check if AL is double quotation or single quotation
2341 ; Input: AL = byte to be examineed
2343 ; Output: ZF on if AL is single or double quotetaion
2345 ; Vars: $P_SorD_Quote(W)
2346 ;***********************************************************************
2347 IF QusSW
+CmpxSW
;AN000;(Check if quoted string or complex item is supported)
2348 ;(deleted ;AN025;) $P_Chk_DSQuote proc ;
2349 ;(deleted ;AN025;) mov $P_SorD_Quote,$P_SQuote ; 3/17/87 assume single quote
2350 ;(deleted ;AN025;) cmp al,$P_DQuote ; 1st char = double quotation ?
2351 ;(deleted ;AN025;) jne $P_CDSQ00 ; 3/17/87
2352 ;(deleted ;AN025;) mov $P_SorD_Quote,al ; 3/17/87 set bigning w/ double quote
2353 ;(deleted ;AN025;) ret ; 3/17/87
2354 ;(deleted ;AN025;) $P_CDSQ00: ; 3/17/87
2355 ;(deleted ;AN025;) cmp al,$P_SQuote ; 1st char = single quotation ?
2356 ;(deleted ;AN025;) ret ;
2357 ;(deleted ;AN025;) $P_Chk_DSQuote endp ;
2359 ;***********************************************************************
2362 ; Function: Copy chracacter from ES:BX to psdata_seg:SI until closing single
2363 ; (double) quotation found.
2365 ; Input: psdata_seg:SI -> $P_STRING_BUF
2366 ; ES:BX -> Operand in command buffer
2368 ; Output: CY on indicates EOF encounterd before closing quotation
2372 ; Vars: $P_SorD_Quote(R)
2373 ;***********************************************************************
2374 $P_Quoted_Str proc
;AN000;
2376 $P_Qus_Loop
: ;AN000;
2377 mov ax,[bx] ;AN000; 3/17/87
2378 call $P_Chk_EOL
;AN000;
2379 je $P_Qustr_Err0
;AN000;
2381 ;(deleted ;AN025;) cmp al,$P_SorD_Quote ;AN000; quotation ? 3/17/87
2382 cmp al,$P_DQuote
;AN025; double quote?
2383 jne $P_Qus00
;AN000;
2385 ;(deleted ;AN025;) cmp ah,$P_SorD_Quote ;AN000; contiguous quotation 3/17/87
2386 cmp ah,$P_DQuote
;AN025; double quote?
2387 jne $P_Qus02
;AN000;
2389 ;(deleted ;AN025:) mov word ptr psdata_seg:[si],ax ;AN000; 3/17/87
2390 mov byte ptr psdata_seg
:[si],al ;AN025; save one of the quotes
2391 ;(deleted ;AN025:) add si,2 ;AN000;
2393 inc si ;AC035; add '1' to SI reg
2394 ;AN025; adjust target index
2395 ;(changed ;AC035;) add si,1 ;AN025; adjust target index
2396 inc bx ;AC035; add '2' to
2397 inc bx ;AC035; BX reg
2398 ;AN000; adjust source index by 2 to skip extra quote
2399 ;(changed ;AC035;) add bx,2 ;AN000; adjust source index by 2 to skip extra quote
2400 jmp short $P_Qus_Loop
;AN000;
2403 call $P_Chk_DBCS
;AN000; was it a lead byte of DBCS ?
2404 jnc $P_Qus01
;AN000;
2406 mov psdata_seg
:[si],al ;AN000; store 1st byte
2409 mov al,[bx] ;AN000; load 2nd byte
2411 mov psdata_seg
:[si],al ;AN000; store SBCS or 2nd byte of DBCS
2414 jmp short $P_Qus_Loop
;AN000;
2416 $P_Qustr_Err0
: ;AN000;
2417 stc ;AN000; indicate error
2418 jmp short $P_Quoted_Str_Exit
;AN000;
2421 mov byte ptr psdata_seg
:[si],0 ;AN000;
2422 clc ;AN000; indicate no error
2423 $P_Quoted_Str_Exit
: ;AN000;
2426 $P_Quoted_Str endp
;AN000;
2427 ENDIF
;AN000;(of QusSW+CmpxSW)
2429 ;***********************************************************************
2430 IF FileSW
+DrvSW
;AN000;(Check if file spec or drive only is supported)
2433 ; Function: Check if the input string is valid file spec format.
2434 ; And set the result buffer.
2436 ; Input: psdata_seg:SI -> $P_STRING_BUF
2437 ; ES:BX -> CONTROL block
2441 ; Use: $P_Fill_Result, $P_Chk_DBCS, $P_FileSp_Chk
2443 ; Vars: $P_RC(W), $P_SI_Save(W), $P_Terminator(W), $P_SaveSI_Cmpx(R)
2445 ;***********************************************************************
2446 $P_File_Format proc
;AN000;
2450 mov di,psdata_seg
:$P_SaveSI_cmpx
;AC034; get user buffer address
2451 $P_FileF_Loop0
: ;AN000; / skip special characters
2452 mov al,psdata_seg
:[si] ;AN000; load character
2453 or al,al ;AN000; end of line ?
2454 je $P_FileF_Err
;AN000; if yes, error exit
2456 call $P_FileSp_Chk
;AN000; else, check if file special character
2457 jne $P_FileF03
;AN000; if yes,
2459 ;AN033; deleted inc di ;skip
2460 ;AN033; deleted inc si ; the
2461 ;AN033; deleted jmp short $P_FileF_Loop0 ; character
2462 mov psdata_seg
:$P_err_flag
,$P_error_filespec
;AN033;AC034;; set error flag- bad char.
2464 mov byte ptr psdata_seg
:[si],$P_NULL
;AN033;
2466 jmp short $P_FileF02
;AN033;
2469 $P_FileF_Err
: ;AN000;
2471 mov byte ptr psdata_seg
:[si],$P_NULL
;AN000;
2472 ;(deleted ;AN030;) mov di,$P_SaveSI_cmpx ;AN000; get user buffer address
2473 ;(deleted ;AN030;) mov $P_SI_Save,di ;AN000; update pointer to user buffer
2475 test es:[bx].$P_Match_Flag
,$P_Optional
;AN000; is it optional ?
2476 jne $P_FileF02
;AN000;
2478 mov psdata_seg
:$P_RC
,$P_Op_Missing
;AC034; 3/17/87
2479 jmp short $P_FileF02
;AN000;
2482 pop ax ;AN000; discard save si
2483 push si ;AN000; save new si
2484 $P_FileF_Loop1
: ;AN000;
2485 mov al,psdata_seg
:[si] ;AN000; load character (not special char)
2486 or al,al ;AN000; end of line ?
2487 je $P_FileF_RLT
;AN000;
2489 call $P_FileSp_Chk
;AN000; File special character ?
2490 je $P_FileF00
;AN000;
2492 call $P_Chk_DBCS
;AN000; no, then DBCS ?
2493 jnc $P_FileF01
;AN000;
2494 inc di ;AN000; if yes, skip next byte
2499 jmp short $P_FileF_Loop1
;AN000;
2502 mov psdata_seg
:$P_Terminator
,al ;AC034;
2503 mov byte ptr psdata_seg
:[si],$P_NULL
;AN000; update end of string
2505 mov psdata_seg
:$P_SI_Save
,di ;AC034; update next pointer in command line
2506 $P_FileF_RLT
: ;AN000;
2511 pop ax ;AN000; (tm14)
2512 test ax,$P_File_Spc
;AN000; (tm14)
2513 je $P_Drv_Only_Exit
;AN000; (tm14)
2515 push ax ;AN000; (tm14)
2517 mov ah,$P_No_Tag
;AN000; set
2518 mov al,$P_File_Spec
;AN000; result
2519 call $P_Fill_Result
;AN000; buffer to file spec
2522 $P_Drv_Only_Exit
: ;AN000; (tm14)
2525 $P_File_Format endp
;AN000;
2527 ;***********************************************************************
2530 ; Function: Check if the input byte is one of file special characters
2532 ; Input: psdata_seg:SI -> $P_STRING_BUF
2533 ; AL = character code to be examineed
2535 ; Output: ZF = 1 , AL is one of special characters
2536 ;***********************************************************************
2537 $P_FileSp_Chk proc
;AN000;
2540 lea bx,psdata_seg
:$P_FileSp_Char
;AC034; special character table
2541 mov cx,$P_FileSp_Len
;AN000; load length of it
2542 $P_FileSp_Loop
: ;AN000;
2543 cmp al,psdata_seg
:[bx] ;AN000; is it one of special character ?
2544 je $P_FileSp_Exit
;AN000;
2547 loop $P_FileSp_Loop
;AN000;
2549 inc cx ;AN000; reset ZF
2550 $P_FileSp_Exit
: ;AN000;
2554 $P_FileSp_Chk endp
;AN000;
2555 ENDIF
;AN000;(of FileSW+DrvSW)
2557 ;***********************************************************************
2558 IF DrvSW
;AN000;(Check if drive only is supported)
2561 ; Function: Check if the input string is valid drive only format.
2562 ; And set the result buffer.
2564 ; Input: psdata_seg:SI -> $P_STRING_BUF
2565 ; ES:BX -> CONTROL block
2569 ; Use: $P_Fill_Result, $P_Chk_DBCS
2572 ;***********************************************************************
2573 $P_Drive_Format proc
;AN000;
2576 mov al,psdata_seg
:[si] ;AN000;
2577 or al,al ;AN000; if null string
2578 je $P_Drv_Exit
;AN000; do nothing
2580 call $P_Chk_DBCS
;AN000; is it leading byte ?
2581 jc $P_Drv_Err
;AN000;
2583 cmp word ptr psdata_seg
:[si+byte],$P_Colon
;AN000; "d", ":", 0 ?
2584 je $P_DrvF00
;AN000;
2586 test es:[bx].$P_Match_Flag
,$P_Ig_Colon
;AN000; colon can be ignored?
2587 je $P_Drv_Err
;AN000;
2589 cmp byte ptr psdata_seg
:[si+byte],$P_NULL
;AN000; "d", 0 ?
2590 jne $P_Drv_Err
;AN000;
2593 or al,$P_Make_Lower
;AN000; lower case
2594 cmp al,"a" ;AN000; drive letter must
2595 jb $P_Drv_Err
;AN000; in range of
2597 cmp al,"z" ;AN000; "a" - "z"
2598 ja $P_Drv_Err
;AN000; if no, error
2600 sub al,"a"-1 ;AN000; make text drive to binary drive
2601 mov dl,al ;AN000; set
2602 mov ah,$P_No_Tag
;AN000; result
2603 mov al,$P_Drive
;AN000; buffer
2604 call $P_Fill_Result
;AN000; to drive
2605 jmp short $P_Drv_Exit
;AN000;
2608 mov psdata_seg
:$P_RC
,$P_Syntax
;AC034;
2609 $P_Drv_Exit
: ;AN000;
2613 $P_Drive_Format endp
;AN000;
2614 ENDIF
;AN000;(of DrvSW)
2616 ;***********************************************************************
2619 ; Function: Skip delimiters specified in the PARMS list, white space
2622 ; Input: DS:SI -> Command String
2623 ; ES:DI -> Parameter List
2625 ; Output: CY = 1 if the end of line encounterd
2626 ; CY = 0 then SI move to 1st non-delimiter character
2627 ; AL = Last examineed character
2629 ; Use: $P_Chk_EOL, $P_Chk_Delim,
2632 ;***********************************************************************
2633 $P_Skip_Delim proc
;AN000;
2634 $P_Skip_Delim_Loop
: ;AN000;
2636 call $P_Chk_EOL
;AN000; is it EOL character ?
2637 je $P_Skip_Delim_CY
;AN000; if yes, exit w/ CY on
2639 call $P_Chk_Delim
;AN000; is it one of delimiters ?
2640 jne $P_Skip_Delim_NCY
;AN000; if no, exit w/ CY off
2642 test psdata_seg
:$P_Flags2
,$P_Extra
;AC034; extra delim or comma found ?
2643 je $P_Skip_Delim_Loop
;AN000; if no, loop
2645 test psdata_seg
:$P_Flags2
,$P_SW
+$P_equ
;AC034; /x , or xxx=zzz , (tm08)
2646 je short $P_Exit_At_Extra
;AN000; no switch, no keyword (tm08)
2648 dec si ;AN000; backup si for next call (tm08)
2649 jmp short $P_Exit_At_Extra
;AN000; else exit w/ CY off
2651 $P_Skip_Delim_CY
: ;AN000;
2652 stc ;AN000; indicate EOL
2653 jmp short $P_Skip_Delim_Exit
;AN000;
2655 $P_Skip_Delim_NCY
: ;AN000;
2656 clc ;AN000; indicate non delim
2657 $P_Skip_Delim_Exit
: ;AN000; in this case, need
2658 dec si ;AN000; backup index pointer
2661 $P_Exit_At_Extra
: ;AN000;
2662 clc ;AN000; indicate extra delim
2664 $P_Skip_Delim endp
;AN000;
2666 ;***********************************************************************
2669 ; Function: Check if AL is one of End of Line characters.
2671 ; Input: AL = character code
2672 ; ES:DI -> Parameter List
2674 ; Output: ZF = 1 if one of End of Line characters
2675 ;**********************************************************************
2676 $P_Chk_EOL proc
;AN000;
2679 cmp al,$P_CR
;AN000; Carriage return ?
2680 je $P_Chk_EOL_Exit
;AN000;
2682 cmp al,$P_NULL
;AN000; zero ?
2683 je $P_Chk_EOL_Exit
;AN000;
2685 IF LFEOLSW
;AN028; IF LF TO BE ACCEPTED AS EOL
2686 cmp al,$P_LF
;AN000; Line feed ?
2687 je $P_Chk_EOL_Exit
;AN000;
2690 cmp byte ptr es:[di].$P_Num_Extra
,$P_I_Have_EOL
;AN000; EOL character specified ?
2691 jb $P_Chk_EOL_Exit
;AN000;
2694 mov bl,es:[di].$P_Len_Extra_Delim
;AN000; get length of delimiter list
2695 add bx,$P_Len_PARMS
;AN000; skip it
2696 cmp byte ptr es:[bx+di],$P_I_Use_Default
;AN000; No extra EOL character ?
2697 je $P_Chk_EOL_NZ
;AN000;
2699 xor cx,cx ;AN000; Get number of extra chcracter
2700 mov cl,es:[bx+di] ;AN000;
2701 $P_Chk_EOL_Loop
: ;AN000;
2703 cmp al,es:[bx+di] ;AN000; Check extra EOL character
2704 je $P_Chk_EOL_Exit
;AN000;
2706 loop $P_Chk_EOL_Loop
;AN000;
2708 $P_Chk_EOL_NZ
: ;AN000;
2709 cmp al,$P_CR
;AN000; reset ZF
2710 $P_Chk_EOL_Exit
: ;AN000;
2714 $P_Chk_EOL endp
;AN000;
2716 ;***********************************************************************
2719 ; Function: Check if AL is one of delimiter characters.
2720 ; if AL+[si] is DBCS blank, it is replaced with two SBCS
2723 ; Input: AL = character code
2724 ; DS:SI -> Next Character
2725 ; ES:DI -> Parameter List
2727 ; Output: ZF = 1 if one of delimiter characters
2728 ; SI points to the next character
2729 ; Vars: $P_Terminator(W), $P_Flags(W)
2730 ;***********************************************************************
2731 $P_Chk_Delim proc
;AN000;
2734 mov psdata_seg
:$P_Terminator
,$P_Space
;AC034; Assume terminated by space
2735 and psdata_seg
:$P_Flags2
,0ffh-$P_Extra
;AC034;
2736 cmp al,$P_Space
;AN000; Space ?
2737 je $P_Chk_Delim_Exit
;AN000;
2739 cmp al,$P_TAB
;AN000; TAB ?
2740 je $P_Chk_Delim_Exit
;AN000;
2742 cmp al,$P_Comma
;AN000; Comma ?
2743 je $P_Chk_Delim_Exit0
;AN000;
2745 $P_Chk_Delim00
: ;AN000;
2746 cmp al,$P_DBSP1
;AN000; 1st byte of DBCS Space ?
2747 jne $P_Chk_Delim01
;AN000;
2749 cmp byte ptr [si],$P_DBSP2
;AN000; 2nd byte of DBCS Space ?
2750 jne $P_Chk_Delim01
;AN000;
2752 mov al,$P_Space
;AN000;
2753 inc si ;AN000; make si point to next character
2754 cmp al,al ;AN000; Set ZF
2755 jmp short $P_Chk_Delim_Exit
;AN000;
2757 $P_Chk_Delim01
: ;AN000;
2758 cmp byte ptr es:[di].$P_Num_Extra
,$P_I_Have_Delim
;AN000; delimiter character specified ?
2759 jb $P_Chk_Delim_Exit
;AN000;
2762 mov cl,es:[di].$P_Len_Extra_Delim
;AN000; get length of delimiter list
2763 or cx,cx ;AN000; No extra Delim character ?
2764 je $P_Chk_Delim_NZ
;AN000;
2766 mov bx,$P_Len_PARMS
-1 ;AN000; set bx to 1st extra delimiter
2767 $P_Chk_Delim_Loop
: ;AN000;
2769 cmp al,es:[bx+di] ;AN000; Check extra Delim character
2770 je $P_Chk_Delim_Exit0
;AN000;
2772 loop $P_Chk_Delim_Loop
;AN000; examine all extra delimiter
2774 $P_Chk_Delim_NZ
: ;AN000;
2775 cmp al,$P_Space
;AN000; reset ZF
2776 $P_Chk_Delim_Exit
: ;AN000;
2778 ;;;; mov psdata_seg:$P_Terminator,al ;AN034;
2784 $P_Chk_Delim_Exit0
: ;AN000;
2785 mov psdata_seg
:$P_Terminator
,al ;AC034; keep terminated delimiter
2786 test psdata_seg
:$P_Flags2
,$P_Equ
;AN027;AC034;; if terminating a key=
2787 jnz $P_No_Set_Extra
;AN027; then do not set the EXTRA bit
2789 or psdata_seg
:$P_Flags2
,$P_Extra
;AC034; flag terminated extra delimiter or comma
2790 $P_No_Set_Extra
: ;AN027;
2791 cmp al,al ;AN000; set ZF
2792 jmp short $P_Chk_Delim_Exit
;AN000;
2794 $P_Chk_Delim endp
;AN000;
2796 ;***********************************************************************
2799 ; Function: Check if AL is the switch character not in first position of
2802 ; Input: AL = character code
2803 ; BX = current pointer within $P_String_Buf
2804 ; SI =>next char on command line (following the one in AL)
2806 ; Output: CF = 1 (set)if AL is switch character, and not in first
2807 ; position, and has no chance of being part of a date string,
2808 ; i.e. should be treated as a delimiter.
2810 ; CF = 0 (reset, cleared) if AL is not a switch char, is in the first
2811 ; position, or is a slash but may be part of a date string, i.e.
2812 ; should not be treated as a delimiter.
2814 ; Vars: $P_Terminator(W)
2817 ;***********************************************************************
2818 $P_Chk_Switch proc
;AN000;
2820 ;AN020;; Function: Check if AL is the switch character from 2nd position of $P_STRING_BUF
2821 ;AN020;; Output: ZF = 1 if switch character
2822 ;AN020;; lea bp,$P_STRING_BUF ;AN000;
2823 ;AN020;; cmp bx,bp ;AN000; 1st position ?
2824 ;AN020;; je $P_Chk_S_Exit_1 ;AN000;
2825 ;AN020;; cmp al,$P_Switch ;AN000;
2826 ;AN020;; jmp short $P_Chk_S_Exit_0 ;AN000;
2827 ;AN020;;$P_Chk_S_Exit_1: ;AN000;
2828 ;AN020;; cmp al,$P_Switch ;AN000; (tm08)
2829 ;AN020;; jne $P_Nop ;AN000; (tm08)
2830 ;AN020;; or $P_Flags2,$P_SW ;AN000; (tm08) It could be valid switch
2831 ;AN020;;$P_Nop: ;AN000; (tm08)
2832 ;AN020;; inc bp ;AN000;
2833 ;AN020;; cmp bx,bp ;AN000; reset ZF
2834 ;AN020;;$P_Chk_S_Exit_0: ;AN000;
2835 ;AN020;; jne $P_Chk_S_Exit ;AN000;
2836 ;AN020;; mov $P_Terminator,al ;AN000; store switch character
2837 ;AN020;;$P_Chk_S_Exit: ;AN000;
2839 LEA BP,psdata_seg
:$P_String_Buf
;AN020;AC034; BP=OFFSET of $P_String_Buf even in group addressing
2840 ; .IF <BX NE BP> THEN ;AN020;IF not first char THEN
2842 je $P_STRUC_L2
;AN000;
2844 ; .IF <AL EQ $P_Switch> THEN ;AN020;otherwise see if a slash
2845 cmp AL,$P_Switch
;AN000;
2846 jne $P_STRUC_L5
;AN000;
2848 STC ;AN020;not in first position and is slash, now see if might be in date string
2849 IF DateSw
;AN020;caller looking for date, see if this may be part of one
2850 PUSH AX ;AN020;save input char
2851 MOV AL,PSDATA_SEG
:[BX-1] ;AN026;AL=char before the current char
2852 CALL $P_0099
;AN020;return carry set if not numeric
2853 ; .IF NC ;AND ;AN020;IF previous char numeric AND
2854 jc $P_STRUC_L7
;AN000;
2856 MOV AL,[SI] ;AN020;AL=char after the current char
2857 CALL $P_0099
;AN020;return carry set if not numeric
2858 ;(deleted) .IF NC THEN ;AN020;IF next char numeric THEN could be a date
2859 ;(deleted) CLC ;AN020;reset CF so "/" not treated as a delimiter
2860 ;(deleted) .ENDIF ;AN026;
2861 ; .ENDIF ;AN020;ENDIF looks like date (number/number)
2862 $P_STRUC_L7
: ;AN000;
2863 POP AX ;AN020;restore AL to input char
2866 jmp short $P_STRUC_L1
;AN000;
2868 $P_STRUC_L5
: ;AN000;
2869 CLC ;AN020;not a slash
2871 ; .ELSE ;AN020;is first char in the buffer, ZF=0
2872 jmp short $P_STRUC_L1
;AN000;
2874 $P_STRUC_L2
: ;AN000;
2875 ; .IF <AL EQ $P_Switch> THEN ;AN020;
2876 cmp AL,$P_Switch
;AN000;
2877 jne $P_STRUC_L12
;AN000;
2879 OR psdata_seg
:$P_Flags2
,$P_SW
;AN020;AC034;;could be valid switch, first char and is slash
2881 $P_STRUC_L12
: ;AN000;
2882 CLC ;AN020;CF=0 indicating first char
2884 $P_STRUC_L1
: ;AN000;
2887 $P_Chk_Switch endp
;AN000;
2889 ;**************************************************************************
2892 ; Function: Check if a specified byte is in ranges of the DBCS lead bytes
2895 ; AL = Code to be examineed
2898 ; If CF is on then a lead byte of DBCS
2900 ; Use: INT 21h w/AH=63
2902 ; Vars: $P_DBCSEV_Seg(RW), $P_DBCSEV_Off(RW)
2903 ;***************************************************************************
2904 $P_Chk_DBCS PROC
;AN000;
2908 PUSH bx ;AN000; (tm11)
2909 CMP psdata_seg
:$P_DBCSEV_SEG
,0 ;AC034; ALREADY SET ?
2910 JNE $P_DBCS00
;AN000;
2913 ; PUSH BX ;AN000; (tm11)
2914 PUSH ds ;AN000; (tm11)
2922 MOV AX,$P_DOS_GetEV
;AN000; GET DBCS EV CALL
2925 ; MOV AX,DS ;AN000; (tm11)
2926 ; OR AX,AX ;AN000; (tm11)
2927 MOV bx,DS ;AN000; (tm11)
2928 OR bx,bx ;AN000; (tm11)
2934 ; POP BX ;AN000; (tm11)
2935 POP ds ;AN000; (tm11)
2937 JE $P_NON_DBCS
;AN000;
2940 MOV psdata_seg
:$P_DBCSEV_OFF
,SI ;AC034; save EV offset
2941 ; MOV psdata_seg:$P_DBCSEV_SEG,DS ;AC034; save EV segment
2942 MOV psdata_seg
:$P_DBCSEV_SEG
,bx ;AC034; save EV segment (tm11)
2944 MOV SI,psdata_seg
:$P_DBCSEV_OFF
;AC034; load EV offset
2945 MOV DS,psdata_seg
:$P_DBCSEV_SEG
;AC034; and segment
2947 $P_DBCS_LOOP
: ;AN000;
2948 CMP WORD PTR [SI],0 ;AN000; zero vector ?
2949 JE $P_NON_DBCS
;AN000; then exit
2952 JB $P_DBCS01
;AN000; Check if AL is in
2954 CMP AL,[SI+BYTE] ;AN000; range of
2955 JA $P_DBCS01
;AN000; the vector
2957 STC ;AN000; if yes, indicate DBCS and exit
2958 JMP short $P_DBCS_EXIT
;AN000;
2961 INC SI ;AC035; add '2' to
2962 INC SI ;AC035; SI reg
2963 ;AN000; get next vector
2964 ;(changed ;AC035;) ADD SI,2 ;AN000; get next vector
2965 JMP short $P_DBCS_LOOP
;AN000; loop until zero vector found
2967 $P_NON_DBCS
: ;AN000;
2968 CLC ;AN000; indicate SBCS
2969 $P_DBCS_EXIT
: ;AN000;
2970 POP bx ;AN000; (tm11)
2974 $P_Chk_DBCS ENDP
;AN000;