summaryrefslogtreecommitdiff
path: root/v4.0/src/INC/PARSE.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/INC/PARSE.ASM')
-rw-r--r--v4.0/src/INC/PARSE.ASM2974
1 files changed, 2974 insertions, 0 deletions
diff --git a/v4.0/src/INC/PARSE.ASM b/v4.0/src/INC/PARSE.ASM
new file mode 100644
index 0000000..80dc9d7
--- /dev/null
+++ b/v4.0/src/INC/PARSE.ASM
@@ -0,0 +1,2974 @@
1 PAGE ;AN000;
2; $SALUT (4,4,8,41)
3;(deleted).XLIST
4;(deleted)INCLUDE STRUC.INC ;AN020;structured macro definitions for .IF,.ELSE etc.
5;(deleted).LIST
6;
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.
13;
14;
15IFNDEF basesw ;AN022;
16 psdata_seg EQU CS ;AN022;
17ELSE ;AN022;
18 IF basesw ;AN022;IF "basesw EQU 1" specified by caller THEN
19 psdata_seg EQU DS ;AN022;
20 ELSE ;AN022;
21 psdata_seg EQU ES ;AN022;ELSE only other choice is ES (basesw EQU 0)
22 ENDIF ;AN022;
23ENDIF ;AN022;
24
25ifndef incsw ;AN000; (tm03) Someone doesn't want to include psdata
26 incsw equ 1 ;AN000; include psdata.inc (tm03)
27endif ;AN000; (tm03)
28if incsw ;AN000; If incsw = 1 then (tm03)
29 include psdata.inc ;AN000; include psdata.inc (tm03)
30endif ;AN000; endif (tm03)
31 PAGE ;AN000;
32IF1 ;AN000;
33 %OUT INCLUDING COMP=COMMON DSN=PARSE.ASM...;AN000;
34ENDIF ;AN000;
35;***********************************************************************
36; SysParse;
37;
38; Function : Parser Entry
39;
40; Input: DS:SI -> command line
41; ES:DI -> parameter block
42; psdata_seg -> psdata.inc
43; CX = operand ordinal
44;
45; Note: ES is the segment containing all the control blocks defined
46; by the caller, except for the DOS COMMAND line parms, which
47; is in DS.
48;
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.
52;
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
58;
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
62;
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)
65;
66;-------- Modification History -----------------------------------------
67;
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
82; (tm08)
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
90; (tm12)
91; 7/10/87 : Invalid switch/keyword does not work correctly
92; (tm13)
93; 7/10/87 : Drive_only breaks 3 bytes after the result buffer
94; (tm14)
95; 7/12/87 : Too_Many_Operands sets DX=0 as the PARSE result
96; (tm15)
97; 7/24/87 : Negative lower bound on numeric ranges cause trouble
98
99; 7/24/87 : Quoted strings being returned with quotes.
100
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.
105
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.
110;
111
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.
118
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.
128
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
133; segment.
134
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.
141
142; 9/24/87 : Ed K
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.
146
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.
150
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.
157
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.
162
163; Also fixed are several JMP that caused a NOP, these changed to
164; have the SHORT operator to avoid the unneeded NOP.
165
166; The code and PSDATA.INC have been aligned for ease of reading.
167
168; 10/26/87 : Ed K (;AN026;) PTM2041, DATE within SWITCH, BX reference to
169; psdata buffer should have psdata_seg.
170
171; 10/27/87 : Ed K (;AN027;) PTM2042 comma between keywords implies
172; positional missing.
173
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.
177
178; 11/11/87 : Ed K (;AN029;) PTM 1651 GET RID OF WHITESPACE AROUND "=".
179
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
182; of that parm.
183
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
187; but wrong place.
188
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.
192
193; 12/14/87 : Bill L (;AN033;) PTM 2722 if illegal delimiter characters
194; in a filespec, then flag an error.
195
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 ?????
201
202; 02/02/88 : Ed K (;AC035;) INSPECT utility, suggests optimizations.
203
204; 02/05/88 : Ed K (;AN036;) P3372-UPPERCASE TRANSLATION, PSDATA_SEG HOSED.
205;
206; 02/08/88 : Ed K (;AN037;) P3410-AVOID POP OF CS, CHECK BASESW FIRST.
207
208; 02/19/88 : Ed K (;AN038;) p3524 above noon and "am" should be error
209
210; 02/23/88 : Ed K (;AN039;) p3518 accept "comma" and "period" as decimal
211; separator in TIME before hundredths field.
212;
213;***********************************************************************
214IF FarSW ;AN000;(Check if need far return)
215SysParse proc far ;AN000;
216ELSE ;AN000;
217SysParse proc near ;AN000;
218ENDIF ;AN000;(of FarSW)
219; $SALUT (4,9,17,41)
220 mov psdata_seg:$P_Flags,0 ;AC034; Clear all internal flags
221IF 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
226ENDIF ;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
231
232 mov word ptr psdata_seg:$P_DX,0 ;AC034; (tm15)
233IF KeySW ;AN029;
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.
237 push cx ;AN029;
238 push dx ;AN029;
239 push di ;AN029;
240
241 push si ;AN029; remember where command line starts
242 mov cx,-1 ;AN029; init counter
243; $do
244$P_loc_eol: ;AN029;
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
248
249; enddo z
250 jnz $P_loc_EOL ;AN029; not found that EOL char
251
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
254
255;scan command string for combinations including "=",
256; and replace each with just the simple "="
257
258;REPEAT UNTIL ONE PASS IS MADE WHEREIN NO CHANGES WERE MADE
259; $do
260$P_DO1: ;AN029;
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
267; $do ;AN029;
268$P_DO2: ;AN029;
269 cmp BYTE PTR [SI],$P_double_quote ;AN029;
270; $if e ;AN029;if a double quote was found
271 JNE $P_IF3 ;AN029;
272 NOT $P_REG_BL_DQ_SW ;AN029;TOGGLE THE DOUBLE QUOTE STATE SWITCH
273; $endif ;AN029;
274$P_IF3: ;AN029;
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
277 JNZ $P_IF5 ;AN029;
278 mov ax,word ptr [si] ;AN029; get pair to be checked out
279 cmp ax,$P_BL_EQ ;AN029;" ="
280; $if e,or ;AN029;
281 JE $P_LL6 ;AN029;
282 cmp ax,$P_EQ_BL ;AN029;"= "
283; $if e,or ;AN029;
284 JE $P_LL6 ;AN029;
285 cmp ax,$P_EQ_TB ;AN029; "=<tab>"
286; $if e,or ;AN029;
287 JE $P_LL6 ;AN029;
288 cmp ax,$P_TB_EQ ;AN029;"<tab>="
289; $if e ;AN029;if this pair to be replaced with a single "="
290 JNE $P_IF6 ;AN029;
291$P_LL6: ;AN029;
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 "="
295
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
306
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
310 dec CX ;AN029;DITTO
311; $endif ;AN029;comparand pair found?
312$P_IF6: ;AN029;
313; $endif ;AN029;double quote switch?
314$P_IF5: ;AN029;
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
319 JNLE $P_DO2 ;AN029;
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
323 JNZ $P_DO1 ;AN029;
324 pop di ;AN029;
325 pop dx ;AN029;
326 pop cx ;AN029;
327
328;NOW THAT ALL WHITESPACE SURROUNDING "=" HAVE BEEN COMPRESSED OUT,
329;RESUME NORMAL PARSING...
330ENDIF ;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
333
334;--------------------------- End of Line
335 mov ax,$P_RC_EOL ;AN000; set exit code to -1
336 push bx ;AN000;
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.
340
341 mov ax,$P_Op_Missing ;AN000; If no, set exit code to missing operand
342$P_Fin: ;AN000;
343 pop bx ;AN000;
344 jmp $P_Single_Exit ;AN000; return to the caller
345
346;---------------------------
347$P_Start: ;AN000;
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.
350 push di ;AN000;
351 push bp ;AN000;
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
355
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
360
361 call $P_Chk_EOL ;AN000; Check EOL character
362 je $P_Pack_End_BY_EOL ;AN000; need backup si
363
364 call $P_Chk_Delim ;AN000; Check delimiter
365 jne $P_PL01 ;AN000; If no, process next byte
366
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)
370
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
373
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)
377
378 dec si ;AN000; (tm08)
379 jmp short $P_Pack_End ;AN025; (tm08)
380
381$P_PL01: ;AN000;
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
385
386 or psdata_seg:$P_Flags2,$P_equ ;AC034; remember it in flag
387$P_PL00: ;AN000;
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
391
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
396
397$P_Pack_End_BY_EOL: ;AN000;
398 dec si ;AN000; backup si pointer
399$P_Pack_End: ;AN000;
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
407
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
410
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
416
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
427
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
431;
432$P_SW_Manager: ;AN000;
433 mov al,es:[bx].$P_MaxP ;AN000; get maxp
434 xor ah,ah ;AN000; ax = maxp
435 inc ax ;AN000;
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;
442
443 inc bx ;AN000; now bx points to 1st CONTROL address
444
445$P_SW_Mgr_Loop: ;AN000;
446 push bx ;AN000;
447 mov bx,es:[bx] ;AN000; bx points to Switch CONTROL itself
448 call $P_Chk_SW_Control ;AN000; do process for switch
449 pop bx ;AN000;
450 jnc $P_Return_to_Caller ;AN000; if the CONTROL is for the switch, exit
451
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
457
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.
461;
462$P_Key_Manager: ;AN000;
463 mov al,es:[bx].$P_MaxP ;AN000; get maxp
464 xor ah,ah ;AN000; ax = maxp
465 inc ax ;AN000;
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
470 shl ax,1 ;AN000;
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;
477
478 inc bx ;AN000; now bx points to 1st CONTROL
479
480$P_Key_Mgr_Loop: ;AN000;
481 push bx ;AN000;
482 mov bx,es:[bx] ;AN000; bx points to keyword CONTROL itself
483 call $P_Chk_Key_Control ;AN000; do process for keyword
484 pop bx ;AN000;
485 jnc $P_Return_to_Caller ;AN000; if the CONTROL is for the keyword, exit
486
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
492
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.
496
497;(deleted ;AN024;) mov bx,es:[bx-2] ;AN000; (tm13) backup bx
498
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
502
503$P_Return_to_Caller: ;AN000;
504 pop bp ;AN000;
505 pop di ;AN000;
506 pop bx ;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;
513 clc ;AN000;
514 ret ;AN000;
515SysParse endp ;AN000;
516PAGE ;AN000;
517;***********************************************************************
518; $P_Chk_Pos_Control
519;
520; Function: Parse CONTROL block for a positional
521;
522; Input: ES:BX -> CONTROL block
523; psdata_seg:SI -> $P_STRING_BUF
524;
525; Output: None
526;
527; Use: $P_Fill_Result, $P_Check_Match_Flags
528;
529; Vars: $P_Ordinal(W), $P_RC(W)
530;***********************************************************************
531$P_Chk_Pos_Control proc ;AN000;
532 push ax ;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
536
537 inc psdata_seg:$P_ORDINAL ;AC034; update the ordinal
538$P_CPC00: ;AN000;
539 cmp byte ptr psdata_seg:[si],$P_NULL ;AN000; no data ?
540 jne $P_CPC01 ;AN000;
541
542 test ax,$P_Optional ;AN000; yes, then is it optional ?
543 jne $P_CPC02 ;AN000;
544
545 mov psdata_seg:$P_RC,$P_Op_Missing ;AC034; no, then error 3/17/87
546 jmp short $P_CPC_Exit ;AN000;
547
548$P_CPC02: ;AN000;
549 push ax ;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;
553 pop ax ;AN000;
554 jmp short $P_CPC_Exit ;AN000;
555
556$P_CPC01: ;AN000;
557 call $P_Check_Match_Flags ;AN000;
558$P_CPC_Exit: ;AN000;
559 pop ax ;AN000;
560 ret ;AN000;
561$P_Chk_Pos_Control endp ;AN000;
562PAGE ;AN000;
563;***********************************************************************
564; $P_Chk_Key_Control
565;
566; Function: Parse CONTROL block for a keyword
567;
568; Input: ES:BX -> CONTROL block
569; psdata_seg:SI -> $P_STRING_BUF
570;
571; Output: CY = 1 : not match
572;
573; Use: $P_Fill_Result, $P_Search_KEYorSW, $P_Check_Match_Flags
574;
575; Vars: $P_RC(W), $P_SaveSI_Cmpx(W), $P_KEYorSW_Ptr(R), $P_Flags(W)
576;***********************************************************************
577$P_Chk_Key_Control proc ;AN000;
578IF 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
582
583 and psdata_seg:$P_Flags2,0ffh-$P_Key_Cmp ;AC034; reset the indicator previously set
584;
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.
589 pop ax ;AN000;
590;
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
594
595 call $P_Check_Match_Flags ;AN000; else, process match flags
596 clc ;AN000;
597 jmp short $P_Chk_Key_Exit ;AN000;
598
599$P_Chk_Key_Err0: ;AN000;
600 stc ;AN000; not found in keyword synonym list
601 jmp short $P_Chk_Key_Exit ;AN000;
602
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;
606 push ax ;AN000;
607 mov al,$P_String ;AN000; set
608 mov ah,$P_No_Tag ;AN000; result
609 call $P_Fill_Result ;AN000; buffer
610 pop ax ;AN000;
611 clc ;AN000;
612$P_Chk_Key_Exit: ;AN000;
613 ret ;AN000;
614ELSE ;AN000;(of IF KeySW)
615 stc ;AN000;this logic works when the KeySW
616 ret ;AN000;is reset.
617ENDIF ;AN000;(of KeySW)
618$P_Chk_Key_Control endp ;AN000;
619PAGE ;AN000;
620;***********************************************************************
621IF KeySW+SwSW ;AN000;(Check if keyword or switch is supported)
622; $P_Search_KEYorSW:
623;
624; Function: Seach specified keyword or switch from CONTROL
625;
626; Input: ES:BX -> CONTROL block
627; psdata_seg:SI -> $P_STRING_BUF
628;
629; Output: CY = 1 : not match
630;
631; Use: $P_String_Comp, $P_MoveBP_NUL, $P_Found_SYNONYM
632;***********************************************************************
633$P_Search_KEYorSW proc ;AN000;
634 push bp ;AN000;
635 push cx ;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
640
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
645
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
651
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;
656 pop cx ;AN000;
657 pop bp ;AN000;
658 ret ;AN000;
659$P_Search_KEYorSW endp ;AN000;
660;***********************************************************************
661; $P_MoveBP_NUL
662;***********************************************************************
663$P_MoveBP_NUL proc ;AN000;
664$P_MBP_Loop: ;AN000;
665 cmp byte ptr es:[bp],$P_NULL ;AN000; Increment BP that points
666 je $P_MBP_Exit ;AN000; to the synomym list
667
668 inc bp ;AN000; until
669 jmp short $P_MBP_Loop ;AN000; NULL encountered.
670
671$P_MBP_Exit: ;AN000;
672 inc bp ;AN000; bp points to next to NULL
673 ret ;AN000;
674$P_MoveBP_NUL endp ;AN000;
675ENDIF ;AN000;(of KeySW+SwSW)
676PAGE ;AN000;
677;***********************************************************************
678; $P_Chk_SW_Control
679;
680; Function: Parse CONTROL block for a switch
681;
682; Input: ES:BX -> CONTROL block
683; psdata_seg:SI -> $P_STRING_BUF
684;
685; Output: CY = 1 : not match
686;
687; Use: $P_Fill_Result, $P_Search_KEYorSW, $P_Check_Match_Flags
688;
689; Vars: $P_SaveSI_Cmpx(W), $P_KEYorSW_Ptr(R), $P_Flags(W)
690;***********************************************************************
691$P_Chk_SW_Control proc ;AN000;
692
693
694IF 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
698
699 and psdata_seg:$P_Flags2,0ffh-$P_Sw_Cmp ;AC034; reset the indicator previously set
700;
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
705 pop ax ;AN000;
706;
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
710
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,
713
714 mov psdata_seg:$P_RC,$P_Syntax ;AC034; return syntax error
715 jmp short $P_Chk_SW_Exit ;AN000;
716
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
720
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
723
724 mov psdata_seg:$P_RC,$P_Op_Missing ;AC034; return required operand missing
725 jmp short $P_Chk_SW_Exit ;AN018;
726
727$P_CSW00: ;AN000;
728 call $P_Check_Match_Flags ;AN000; process match flag
729 clc ;AN000; indicate match
730 jmp short $P_Chk_SW_Single_Exit ;AN000;
731
732$P_Chk_SW_Err0: ;AN000;
733 stc ;AN000; not found in switch synonym list
734 jmp short $P_Chk_SW_Single_Exit ;AN000;
735
736$P_Chk_SW_Exit: ;AN000;
737 push ax ;AN000;
738 mov al,$P_String ;AN000; set
739 mov ah,$P_No_Tag ;AN000; result
740 call $P_Fill_Result ;AN000; buffer
741 pop ax ;AN000;
742 clc ;AN000;
743$P_Chk_SW_Single_Exit: ;AN000;
744 ret ;AN000;
745ELSE ;AN000;(of IF SwSW)
746 stc ;AN000; this logic works when the SwSW
747 ret ;AN000; is reset.
748ENDIF ;AN000;(of SwSW)
749$P_Chk_SW_Control endp ;AN000;
750PAGE ;AN000;
751;***********************************************************************
752; $P_Fill_Result
753;
754; Function: Fill the result buffer
755;
756; Input: AH = Item tag
757; AL = type
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
766;
767; Output: None
768;
769; Use: $P_Do_CAPS_String, $P_Remove_Colon, $P_Found_SYNONYM
770;
771; Vars: $P_DX(W)
772;***********************************************************************
773$P_Fill_Result proc ;AN000;
774 push di ;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
779 push ax ;AN000;
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
782 pop ax ;AN000;
783$P_RLT04: ;AN000;
784 cmp al,$P_Number ;AN000; if number
785 jne $P_RLT00 ;AN000;
786
787$P_RLT02: ;AN000;
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;
791
792$P_RLT00: ;AN000;
793 cmp al,$P_List_Idx ;AN000; if list index
794 jne $P_RLT01 ;AN000;
795
796 mov word ptr es:[di].$P_Picked_Val,dx ;AN000; then store list index
797 jmp short $P_RLT_Exit ;AN000;
798
799$P_RLT01: ;AN000;
800 cmp al,$P_Date_F ;AN000; Date format ?
801 je $P_RLT02 ;AN000;
802
803 cmp al,$P_Time_F ;AN000; Time format ?
804 je $P_RLT02 ;AN000;
805;
806 cmp al,$P_Drive ;AN000; drive format ?
807 jne $P_RLT03 ;AN000;
808
809 mov byte ptr es:[di].$P_Picked_Val,dl ;AN000; store drive number
810 jmp short $P_RLT_Exit ;AN000;
811
812$P_RLT03: ;AN000;
813 cmp al,$P_Complex ;AN000; complex format ?
814 jne $P_RLT05 ;AN000;
815
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;
821
822$P_RLT05: ;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
827;
828 push ax ;AN000;
829 test byte ptr es:[bx].$P_Function_Flag,$P_CAP_File ;AN000; need CAPS by file table?
830 je $P_RLT_CAP00 ;AN000;
831
832 mov al,$P_DOSTBL_File ;AN000; use file upper case table
833 jmp short $P_RLT_CAP02 ;AN000;
834
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;
838
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;
843 pop ax ;AN000;
844 test byte ptr es:[bx].$P_Function_Flag,$P_Rm_Colon ;AN000; removing colon at end ?
845 je $P_RLT_Exit ;AN000;
846
847 call $P_Remove_Colon ;AN000; then process it.
848$P_RLT_Exit: ;AN000;
849 pop di ;AN000;
850 ret ;AN000;
851$P_Fill_Result endp ;AN000;
852PAGE ;AN000;
853;***********************************************************************
854; $P_Check_Match_Flags
855;
856; Function: Check the mutch_flags and make the exit code and set the
857; result buffer
858;
859; Check for types in this order:
860; Complex
861; Date
862; Time
863; Drive
864; Filespec
865; Quoted String
866; Simple String
867;
868; Input: psdata_seg:SI -> $P_STRING_BUF
869; ES:BX -> CONTROL block
870;
871; Output: None
872;
873; Use: $P_Value, P$_SValue, $P_Simple_String, $P_Date_Format
874; $P_Time_Format, $P_Complex_Format, $P_File_Foemat
875; $P_Drive_Format
876;***********************************************************************
877$P_Check_Match_Flags proc ;AN000;
878 mov psdata_seg:$P_err_flag,$P_NULL ;AN033;AC034;; clear filespec error flag.
879 push ax ;AN000;
880 mov ax,es:[bx].$P_Match_Flag ;AN000; load match flag(16bit) to ax
881
882 or ax,ax ;AC035; test ax for zero
883;(changed ;AC035;) cmp ax,0 ;AN000; (tm12)
884 jne $P_Mat ;AN000; (tm12)
885
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)
899
900$P_Mat: ;AN000; (tm12)
901
902IF CmpxSW ;AN000;(Check if complex item is supported)
903 test ax,$P_Cmpx_S ;AN000; Complex string
904 je $P_Match01 ;AN000;
905
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;
910
911$P_Match01: ;AN000;
912ENDIF ;AN000;(of CmpxSW)
913IF DateSW ;AN000;(Check if date format is supported)
914 test ax,$P_Date_S ;AN000; Date string
915 je $P_Match02 ;AN000;
916
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;
921
922$P_Match02: ;AN000;
923ENDIF ;AN000;(of DateSW)
924IF TimeSW ;AN000;(Check if time format is supported)
925 test ax,$P_Time_S ;AN000; Time string
926 je $P_Match03 ;AN000;
927
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:
932
933 jne $P_Bridge ;AN000; (tm09)
934
935ENDIF ;AN000;(of TimeSW) (tm04)
936 jmp short $P_Match03 ;AN025; (tm09)
937
938$P_Bridge: ;AN000;
939; jmp short $P_Match_Exit (tm02)
940
941 jmp $P_Match_Exit ;AN000; (tm02)
942
943$P_Match03: ;AN000;
944; ENDIF ;AN000;(of TimeSW) (tm04)
945IF NumSW ;AN000;(Check if numeric value is supported)
946 test ax,$P_Num_Val ;AN000; Numeric value
947 je $P_Match04 ;AN000;
948
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;
953
954$P_Match04: ;AN000;
955 test ax,$P_SNUM_Val ;AN000; Signed numeric value
956 je $P_Match05 ;AN000;
957
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;
962
963$P_Match05: ;AN000;
964ENDIF ;AN000;(of NumSW)
965IF DrvSW ;AN000;(Check if drive only is supported)
966 test ax,$P_Drv_Only ;AN000; Drive only
967 je $P_Match06 ;AN000;
968
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;
974
975$P_Match06: ;AN000;
976ENDIF ;AN000;(of DrvSW)
977IF FileSW ;AN000;(Check if file spec is supported)
978 test ax,$P_File_Spc ;AN000; File spec
979 je $P_Match07 ;AN000;
980
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;
985
986$P_Match07: ;AN000;
987ENDIF ;AN000;(of FileSW)
988IF QusSW ;AN000;(Check if quoted string is supported)
989 test ax,$P_Qu_String ;AN000; Quoted string
990 je $P_Match08 ;AN000;
991
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;
996
997$P_Match08: ;AN000;
998ENDIF ;AN000;(of QusSW)
999 test ax,$P_Simple_S ;AN000; Simple string
1000 je $P_Match09 ;AN000;
1001
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.
1006$P_Match09: ;AN000;
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;
1014 pop ax ;AN000;
1015 ret ;AN000;
1016$P_Check_Match_Flags endp ;AN000;
1017PAGE ;AN000;
1018;***********************************************************************
1019; $P_Remove_Colon;
1020;
1021; Function: Remove colon at end
1022;
1023; Input: psdata_seg:SI points to string buffer to be examineed
1024;
1025; Output: None
1026;
1027; Use: $P_Chk_DBCS
1028;***********************************************************************
1029$P_Remove_Colon proc ;AN000;
1030 push ax ;AN000;
1031 push si ;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
1036
1037 cmp al,$P_Colon ;AN000; is it colon ?
1038 jne $P_RCOL00 ;AN000;
1039
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
1042
1043 mov byte ptr psdata_seg:[si],$P_NULL ;AN000; yes, remove colon
1044 jmp short $P_RCOL_Exit ;AN000; and exit.
1045
1046$P_RCOL00: ;AN000;
1047 call $P_Chk_DBCS ;AN000; if not colon, then check if
1048 jnc $P_RCOL01 ;AN000; DBCS leading byte.
1049
1050 inc si ;AN000; if yes, skip trailing byte
1051$P_RCOL01: ;AN000;
1052 inc si ;AN000; si points to next byte
1053 jmp short $P_RCOL_Loop ;AN000; loop until NULL encountered
1054
1055$P_RCOL_Exit: ;AN000;
1056 pop si ;AN000;
1057 pop ax ;AN000;
1058 ret ;AN000;
1059$P_Remove_Colon endp ;AN000;
1060PAGE ;AN000;
1061;***********************************************************************
1062; $P_Do_CAPS_String;
1063;
1064; Function: Perform capitalization along with the file case map table
1065; or character case map table.
1066;
1067; Input: AL = 2 : Use character table
1068; AL = 4 : Use file table
1069; psdata_seg:SI points to string buffer to be capitalized
1070;
1071; Output: None
1072;
1073; Use: $P_Do_CAPS_Char, $P_Chk_DBCS
1074;***********************************************************************
1075$P_Do_CAPS_String proc ;AN000;
1076 push si ;AN000;
1077 push dx ;AN000;
1078 mov dl,al ;AN000; save info id
1079
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
1084
1085 or al,al ;AN000; end of string ?
1086 je $P_DCS_Exit ;AN000; then exit.
1087
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
1091$P_DCS00: ;AN000;
1092 inc si ;AN000; skip DBCS leading and trailing byte
1093$P_DCS01: ;AN000;
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;
1097 pop dx ;AN000;
1098 pop si ;AN000;
1099 ret ;AN000;
1100$P_Do_CAPS_String endp ;AN000;
1101PAGE ;AN000;
1102;***********************************************************************
1103; $P_Do_CAPS_Char;
1104;
1105; Function: Perform capitalization along with the file case map table
1106; or character case map table.
1107;
1108; Input: DL = 2 : Use character table
1109; DL = 4 : Use file table
1110; AL = character to be capitalized
1111;
1112; Output: None
1113;
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;
1119
1120 cmp al,"a" ;AN000; if no,
1121 jb $P_CAPS_Ret ;AN000; check if "a" <= AL <= "z"
1122
1123 cmp al,"z" ;AN000;
1124 ja $P_CAPS_Ret ;AN000; if yes, make CAPS
1125
1126 and al,$P_Make_Upper ;AN000; else do nothing.
1127 jmp short $P_CAPS_Ret ;AN000;
1128
1129$P_DCC_Go: ;AN000;
1130 push bx ;AN000;
1131 push es ;AN000;
1132 push di ;AN000;
1133IF 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 ?
1136 je $P_DCC00 ;AN000;
1137
1138ENDIF ;AN000;(of CAPSW)
1139 lea di,psdata_seg:$P_Char_CAP_Ptr ;AC034; or use char CAPS table ?
1140$P_DCC00: ;AN000;
1141 cmp psdata_seg:[di],dl ;AN000; already got table address ?
1142 je $P_DCC01 ;AN000; if no,
1143
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.
1148
1149IFDEF 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
1152 ENDIF ;AN037;
1153ENDIF ;AN037;
1154
1155 push ax ;AN000; get CAPS table thru DOS call
1156 push cx ;AN000;
1157 push dx ;AN000;
1158
1159
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
1172 pop dx ;AN000;
1173 pop cx ;AN000;
1174 pop ax ;AN000;
1175IFDEF 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
1178 ENDIF ;AN037;
1179ENDIF ;AN037;
1180$P_DCC01: ;AN000;
1181
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.
1185
1186IFDEF 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
1189 ENDIF ;AN037;
1190ENDIF ;AN037;
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
1199
1200IFDEF 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
1203 ENDIF ;AN037;
1204ENDIF ;AN037;
1205 pop di ;AN000;
1206 pop es ;AN000;
1207 pop bx ;AN000;
1208$P_CAPS_Ret: ;AN000;
1209 ret ;AN000;
1210$P_Do_CAPS_Char endp ;AN000;
1211PAGE ;AN000;
1212;***********************************************************************
1213IF NumSW ;AN000;(Check if numeric value is supported)
1214; $P_Value / $P_SValue
1215;
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 "-"
1221;
1222; Input: psdata_seg:SI -> $P_STRING_BUF
1223; ES:BX -> CONTROL block
1224;
1225; Output: None
1226;
1227; Use: $P_Fill_Result, $P_Check_OVF
1228;
1229; Vars: $P_RC(W), $P_Flags(RW)
1230;***********************************************************************
1231$P_SValue proc ;AN000; when signed value here
1232 push ax ;AN000;
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;
1238
1239 cmp al,$P_Minus ;AN000; "-" ?
1240 jne $P_Sval01 ;AN000; else
1241
1242 or psdata_seg:$P_Flags2,$P_Neg ;AC034; set this is negative value
1243$P_SVal00: ;AN000;
1244 inc si ;AN000; skip sign char
1245$P_Sval01: ;AN000;
1246 call $P_Value ;AN000; and process value
1247 pop ax ;AN000;
1248 ret ;AN000;
1249$P_SValue endp ;AN000;
1250;***********************************************************************
1251$P_Value proc ;AN000;
1252 push ax ;AN000;
1253 push cx ;AN000;
1254 push dx ;AN000;
1255 push si ;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;
1263
1264 call $P_0099 ;AN000; make asc(0..9) to bin(0..9)
1265 jc $P_Value_Err0 ;AN000;
1266
1267 xor ah,ah ;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
1273
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
1280
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
1285
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
1290
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
1295
1296 inc si ;AN000; update pointer
1297 jmp short $P_Value_Loop ;AN000; loop until NULL encountered
1298;
1299$P_Value_Err0: ;AN000;
1300 pop bx ;AN000;
1301 jmp $P_Value_Err ;AN000; Bridge
1302;
1303$P_Value00: ;AN000;
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 ?
1307
1308 not cx ;AN000; +
1309 not dx ;AN000; |- Make 2's complement
1310 add dx,1 ;AN000; |
1311 adc cx,0 ;AN000; +
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;
1317
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;
1321
1322$P_Value02: ;AN000; / nval = 1
1323IF 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;
1326
1327 inc si ;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)
1331
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;
1336
1337 cmp cx,es:[si+$P_Val_XH] ;AN000; comp cx with XH
1338 jb $P_Val02_Next ;AN000;
1339
1340 ja $P_Val_In ;AN000;
1341
1342 cmp dx,es:[si+$P_Val_XL] ;AN000; comp dx with XL
1343 jb $P_Val02_Next ;AN000;
1344
1345$P_Val_In: ;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;
1349
1350 jb $P_Val_Found ;AN000;
1351
1352 cmp dx,es:[si+$P_Val_YL] ;AN000; comp dx with YL
1353 ja $P_Val02_Next ;AN000;
1354
1355 jmp short $P_Val_Found ;AN000;
1356
1357$P_Val02_Sign: ;AN000;
1358 cmp cx,es:[si+$P_Val_XH] ;AN000; comp cx with XH
1359 jl $P_Val02_Next ;AN000;
1360
1361 jg $P_SVal_In ;AN000;
1362
1363 cmp dx,es:[si+$P_Val_XL] ;AN000; comp dx with XL
1364 jl $P_Val02_Next ;AN000;
1365
1366$P_SVal_In: ;AN000;
1367 cmp cx,es:[si+$P_Val_YH] ;AN000; comp cx with YH
1368 jg $P_Val02_Next ;AN000;
1369
1370 jl $P_Val_Found ;AN000;
1371
1372 cmp dx,es:[si+$P_Val_YL] ;AN000; comp dx with YL
1373 jg $P_Val02_Next ;AN000;
1374
1375 jmp short $P_Val_Found ;AN000;
1376
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;
1381 ; / Not found
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;
1386
1387ENDIF ;AN000;(of Val1SW)
1388IF 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;
1393
1394ENDIF ;AN000;(of Val1SW+Val2SW)
1395$P_Value03: ;AN000; / nval = 2
1396IF 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
1403 inc ax ;AN000;
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;
1410
1411 cmp dx,es:[si+$P_Val_XL] ;AN000; comp dx with XL
1412 je $P_Val_Found ;AN000;
1413
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;
1418 ;AN000; / Not found
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;
1423
1424ENDIF ;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;
1432 pop si ;AN000;
1433 pop dx ;AN000;
1434 pop cx ;AN000;
1435 pop ax ;AN000;
1436 ret ;AN000;
1437$P_Value endp ;AN000;
1438PAGE ;AN000;
1439;***********************************************************************
1440; $P_Check_OVF
1441;
1442; Function: Check if overflow is occurred with consideration of
1443; signed or un-signed numeric value
1444;
1445; Input: Flag register
1446;
1447; Output: CY = 1 : Overflow
1448;
1449; Vars: $P_Flags(R)
1450;***********************************************************************
1451$P_Check_OVF proc ;AN000;
1452 pushf ;AN000;
1453 test psdata_seg:$P_Flags2,$P_Neg ;AC034; is it negative value ?
1454 jne $P_COVF ;AN000; if no, check overflow
1455
1456 popf ;AN000; by the CY bit
1457 ret ;AN000;
1458
1459$P_COVF: ;AN000;
1460 popf ;AN000; else,
1461 jo $P_COVF00 ;AN000; check overflow by the OF
1462
1463 clc ;AN000; indicate it with CY bit
1464 ret ;AN000; CY=0 means no overflow
1465
1466$P_COVF00: ;AN000;
1467 stc ;AN000; and CY=1 means overflow
1468 ret ;AN000;
1469$P_Check_OVF endp ;AN000;
1470ENDIF ;AN000;(of FarSW)
1471;***********************************************************************
1472; $P_0099;
1473;
1474; Function: Make ASCII 0-9 to Binary 0-9
1475;
1476; Input: AL = character code
1477;
1478; Output: CY = 1 : AL is not number
1479; CY = 0 : AL contains binary value
1480;***********************************************************************
1481$P_0099 proc ;AN000;
1482 cmp al,"0" ;AN000;
1483 jb $P_0099Err ;AN000; must be 0 =< al =< 9
1484
1485 cmp al,"9" ;AN000;
1486 ja $P_0099Err ;AN000; must be 0 =< al =< 9
1487
1488 sub al,"0" ;AN000; make char -> bin
1489 clc ;AN000; indicate no error
1490 ret ;AN000;
1491
1492$P_0099Err: ;AN000;
1493 stc ;AN000; indicate error
1494 ret ;AN000;
1495$P_0099 endp ;AN000;
1496PAGE ;AN000;
1497;***********************************************************************
1498; $P_Simple_String
1499;
1500; Function: See value list for the simple string
1501; and make result buffer.
1502;
1503; Input: psdata_seg:SI -> $P_STRING_BUF
1504; ES:BX -> CONTROL block
1505;
1506; Output: None
1507;
1508; Use: $P_Fill_Result, $P_String_Comp
1509;
1510; Vars: $P_RC(W)
1511;***********************************************************************
1512$P_Simple_String proc ;AN000;
1513 push ax ;AN000;
1514 push bx ;AN000;
1515 push dx ;AN000;
1516 push di ;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
1521
1522 mov ah,$P_No_Tag ;AN000; No ITEM_TAG set
1523 jmp short $P_Sim_Exit ;AN000; and set result buffer
1524
1525$P_Sim00: ;AN000;
1526IF 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
1529
1530 inc di ;AN000;
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 ?
1550
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;
1554 ;AN000; / Not found
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;
1558
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;
1564ENDIF ;AN000;(of Val3SW+KeySW)
1565$P_Sim01: ;AN000;
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;
1572 pop di ;AN000;
1573 pop dx ;AN000;
1574 pop bx ;AN000;
1575 pop ax ;AN000;
1576 ret ;AN000;
1577$P_Simple_String endp ;AN000;
1578PAGE ;AN000;
1579;***********************************************************************
1580; $P_String_Comp:
1581;
1582; Function: Compare two string
1583;
1584; Input: psdata_seg:SI -> 1st string
1585; ES:BP -> 2nd string (Must be upper case)
1586; ES:BX -> CONTROL block
1587;
1588; Output: CY = 1 if not match
1589;
1590; Use: $P_Chk_DBCS, $P_Do_CAPS_Char
1591;
1592; Vars: $P_KEYor_SW_Ptr(W), $P_Flags(R). $P_KEYorSW_Ptr
1593;***********************************************************************
1594$P_String_Comp proc ;AN000;
1595 push ax ;AN000;
1596 push bp ;AN000;
1597 push dx ;AN000;
1598 push si ;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
1604
1605 call $P_Do_CAPS_Char ;AN000; else, upper case map before comparison
1606IF 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;
1609
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)
1612
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;
1615
1616 jmp short $P_SCOM05 ;AN000; keyword found in synonym list
1617
1618$P_SCOM04: ;AN000;
1619 test psdata_seg:$P_Flags2,$P_SW_Cmp ;AC034; switch search ?
1620 je $P_SCOM03 ;AN000;
1621
1622 cmp al,$P_Colon ;AN000; ":" is delimiter, at end of switch on command line
1623 jne $P_SCOM03 ;AN000; continue compares
1624
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
1627
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
1631
1632$P_SCOM03: ;AN000;
1633ENDIF ;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
1636
1637 or al,al ;AN000; end of line
1638 je $P_SCOM_Same ;AN000; if so, exit
1639
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
1643
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
1647
1648 inc si ;AN000; else, load next byte
1649 mov al,psdata_seg:[si] ;AN000; and
1650 inc bp ;AN000;
1651 cmp al,es:[bp] ;AN000; compare 2nd byte
1652 jne $P_SCOM_Differ ;AN000; if not match, say different, too
1653
1654 inc si ;AN000; else update operand pointer
1655 inc bp ;AN000; and synonym pointer
1656$P_SCOM01: ;AN000;
1657 jmp short $P_SCOM_Loop ;AN000; loop until NULL or "=" or "/" found in case
1658
1659$P_SCOM_Differ0: ;AN000;
1660
1661IF SwSW ;AN000;(tm10)
1662 test psdata_seg:$P_Flags2,$P_SW ;AC034;(tm10)
1663 je $P_not_applicable ;AN000;(tm10)
1664
1665 test es:[bx].$P_Function_Flag,$P_colon_is_not_necessary ;AN000;(tm10)
1666 je $P_not_applicable ;AN000;(tm10)
1667
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)
1671
1672$P_not_applicable: ;AN000;(tm10)
1673ENDIF ;AN000;(tm10)
1674
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.
1677
1678 cmp al,$P_Colon ;AN000; End up with ":" and
1679 jne $P_SCOM02 ;AN000; subseqently
1680
1681 cmp byte ptr es:[bp],$P_NULL ;AN000; NULL ?
1682 jne $P_SCOM_Differ ;AN000; if no, say different
1683
1684 jmp short $p_SCOM_Same ;AN000; else, say same
1685
1686$P_SCOM02: ;AN000;
1687 cmp al,$P_NULL ;AN000; end up NULL and :
1688 jne $P_SCOM_Differ ;AN000;
1689
1690 cmp byte ptr es:[bp],$P_Colon ;AN000; if no, say different
1691 je $p_SCOM_Same ;AN000; else, say same
1692
1693$P_SCOM_Differ: ;AN000;
1694 stc ;AN000; indicate not found
1695 jmp short $P_SCOM_Exit ;AN000;
1696
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;
1701 pop si ;AN000;
1702 pop dx ;AN000;
1703 pop bp ;AN000;
1704 pop ax ;AN000;
1705 ret ;AN000;
1706$P_String_Comp endp ;AN000;
1707PAGE ;AN000;
1708;***********************************************************************
1709IF DateSW ;AN000;(Check if date format is supported)
1710; $P_Date_Format
1711;
1712; Function: Convert a date string to DOS date format for int 21h
1713; with format validation.
1714;
1715; Input: psdata_seg:SI -> $P_STRING_BUF
1716; ES:BX -> CONTROL block
1717;
1718; Output: None
1719;
1720; Use: $P_Fill_Result, $P_Set_CDI, $P_Get_DecNum
1721;
1722; Vars: $P_RC(W), $P_1st_Val(RW), $P_2nd_Val(RW), $P_3rd_Val(RW)
1723;***********************************************************************
1724$P_Date_Format proc ;AN000;
1725 push ax ;AN000;
1726 push cx ;AN000;
1727 push dx ;AN000;
1728 push si ;AN000;
1729 push bx ;AN000;
1730 push si ;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.
1736 pop si ;AN000;
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;-----------------------+
1742
1743 mov psdata_seg:$P_1st_Val,ax ;AC034; |
1744 or bl,bl ;AN000; end of line ? |
1745 je $P_DateF_YMD ;AN000; |
1746
1747 call $P_Get_DecNum ;AN000; get 2nd number |
1748 jc $P_DateF_Error ;AN000; |
1749
1750 mov psdata_seg:$P_2nd_Val,ax ;AC034; |
1751 or bl,bl ;AN000; end of line ? |
1752 je $P_DateF_YMD ;AN000; |
1753
1754 call $P_Get_DecNum ;AN000; get 3rd number |
1755$P_DateF_Err0: ;AN000; Bridge <-----------+
1756 jc $P_DateF_Error ;AN000;
1757
1758 mov psdata_seg:$P_3rd_Val,ax ;AC034;
1759 or bl,bl ;AN000; end of line ?
1760 jne $P_DateF_Error ;AN000;
1761
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;
1766
1767 mov ax,psdata_seg:$P_1st_Val ;AC034;
1768 or ah,ah ;AN000;
1769 jne $P_DateF_Error ;AN000;
1770
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;
1775
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
1780
1781 xchg ch,cl ;AN000; then swap M <-> D
1782$P_DateF01: ;AN000;
1783 jmp short $P_DateF02 ;AN000;
1784
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;
1790
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;
1795
1796 mov ch,al ;AN000; set date
1797$P_DateF02: ;AN000;
1798 cmp dx,100 ;AN000; year is less that 100 ?
1799 jae $P_DateF03 ;AN000;
1800
1801 add dx,1900 ;AN000; set year 19xx
1802$P_DateF03: ;AN000;
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
1809
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;
1818 pop dx ;AN000;
1819 pop cx ;AN000;
1820 pop ax ;AN000;
1821 ret ;AN000;
1822$P_Date_Format endp ;AN000;
1823ENDIF ;AN000;(of DateSW)
1824PAGE ;AN000;
1825;***********************************************************************
1826IF TimeSW+DateSW ;AN000;(Check if time or date format is supported)
1827; $P_Set_CDI:
1828;
1829; Function: Read CDI from DOS if it has not been read yet
1830;
1831; Input: None
1832;
1833; Output: psdata_seg:SI -> CDI
1834;
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;
1841
1842 jmp short $P_Set_CDI_Exit ;AN000; then do nothing
1843
1844$P_Read_CDI: ;AN000; else read CDI thru DOS
1845 push ds ;AN000;
1846 push dx ;AN000;
1847 push ax ;AN000;
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
1852 int 21h ;AN000;
1853 pop ax ;AN000;
1854 pop dx ;AN000;
1855 pop ds ;AN000;
1856$P_Set_CDI_Exit: ;AN000;
1857 ret ;AN000;
1858$P_Set_CDI endp ;AN000;
1859PAGE ;AN000;
1860;***********************************************************************
1861; $P_Get_DecNum:
1862;
1863; Function: Read a chcrater code from psdata_seg:SI until specified delimiter
1864; or NULL encountered. And make a decimal number.
1865;
1866; Input: psdata_seg:SI -> $P_STRING_BUF
1867;
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
1872;
1873; Use: $P_0099
1874;***********************************************************************
1875$P_Get_DecNum proc ;AN000;
1876 push cx ;AN000;
1877 push dx ;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
1883
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
1886
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
1890
1891 cmp al,$P_Colon ;AN032; ;Is this a valid delimiter ?
1892 je $P_GetNum01 ;AN032; ;yes, exit
1893
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
1897
1898 jmp short $P_Neither_Delims ;AN023;
1899
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
1906
1907 cmp al,$P_Slash ;AN020;is this a date delimiter character?
1908 je $P_GetNum01 ;AN020;if yes, exit
1909
1910 cmp al,$P_Period ;AN020;is this a date delimiter character?
1911 je $P_GetNum01 ;AN000; if yes, exit
1912
1913$P_Neither_Delims: ;AN023;
1914
1915 call $P_0099 ;AN000; convert it to binary
1916 jc $P_GetNum_Exit ;AN000; if error exit
1917
1918 mov ah,0 ;AN000;
1919 xchg ax,cx ;AN000;
1920 mov dx,10 ;AN000;
1921 mul dx ;AN000; ax = ax * 10
1922 or dx,dx ;AN000; overflow
1923 jne $P_GetNum02 ;AN000; then exit
1924
1925 add ax,cx ;AN000;
1926 jc $P_GetNum_Exit ;AN000;
1927
1928 xchg ax,cx ;AN000;
1929 inc si ;AN000;
1930 jmp short $P_GetNum_Loop ;AN000;
1931
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;
1936
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;
1941
1942$P_GetNum02: ;AN000;
1943 stc ;AN000; indicate error
1944$P_GetNum_Exit: ;AN000;
1945 mov ax,cx ;AN000;return value
1946 pop dx ;AN000;
1947 pop cx ;AN000;
1948 ret ;AN000;
1949$P_Get_DecNum endp ;AN000;
1950ENDIF ;AN000;(of TimeSW+DateSW)
1951PAGE ;AN000;
1952;***********************************************************************
1953IF TimeSW ;AN000;(Check if time format is supported)
1954; $P_Time_Format
1955;
1956; Function: Convert a time string to DOS time format for int 21h
1957; with format validation.
1958;
1959; Input: psdata_seg:SI -> $P_STRING_BUF
1960; ES:BX -> CONTROL block
1961;
1962; Output: None
1963;
1964; Use: $P_Fill_Result, $P_Set_CDI, $P_Get_DecNum, $P_Time_2412
1965;
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;
1970 push ax ;AN000;
1971 push cx ;AN000;
1972 push dx ;AN000;
1973 push si ;AN000;
1974 push bx ;AN000;
1975 push si ;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
1981 pop si ;AN000;
1982 jne $P_TimeF00 ;AN000; if no, means 12 hour system
1983
1984 call $P_Time_2412 ;AN000; this routine handle "am" "pm"
1985$P_TimeF00: ;AN000;
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,
1993 ; minutes,seconds
1994 call $P_Get_DecNum ;AN000; get 1st number
1995 jc $P_TimeF_Err0 ;AN000;
1996
1997 mov psdata_seg:$P_1st_Val,ax ;AC034;
1998 or bl,bl ;AN000; end of line ?
1999 je $P_TimeF_Rlt ;AN000;
2000
2001 call $P_Get_DecNum ;AN000; get 2nd number
2002 jc $P_TimeF_Err0 ;AC038; if OK
2003
2004 mov psdata_seg:$P_2nd_Val,ax ;AC034;
2005 or bl,bl ;AN000; end of line ?
2006 je $P_TimeF_Rlt ;AN000;
2007
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
2012
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,
2030 ;AN039; redo TIME
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;
2048
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
2052
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;
2057
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,
2064
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
2069
2070 cmp al,12 ;AN038; if 12:00 o'clock already
2071 je $P_TimeSkip00 ;AN038; it is PM already
2072
2073 add al,12 ;AN000; add 12 hours to make it afternoon
2074 jc $P_TimeF_Err ;AN000; if overflow then error
2075
2076 cmp al,24 ;AN038; after adding 12, now cannot be >24
2077 ja $P_TimeF_Err ;AN038; if too big, error
2078
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;
2084
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;
2089
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;
2094
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
2102
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
2113 pop dx ;AN000;
2114 pop cx ;AN000;
2115 pop ax ;AN000;
2116 ret ;AN000;
2117$P_Time_Format endp ;AN000;
2118PAGE ;AN000;
2119;***********************************************************************
2120; $P_Time_2412:
2121;
2122; Function: Remove "a", "p", "am", or "pm" from the end of stinrg
2123;
2124; Input: psdata_seg:SI -> $P_STRING_BUF
2125;
2126; Output: Set $P_Time12 flag when the string is terminated by "p"
2127; or "pm"
2128;
2129; Vars: $P_Flags(W)
2130;***********************************************************************
2131$P_Time_2412 proc ;AN000;
2132 push ax ;AN000;
2133 push si ;AN000;
2134$P_T12_Loop: ;AN000;
2135 mov al,psdata_seg:[si] ;AN000; Move
2136 inc si ;AN000; si
2137 or al,al ;AN000; to
2138 jne $P_T12_Loop ;AN000; end of string
2139
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" ?
2143 je $P_T1200 ;AN000;
2144
2145 cmp al,"a" ;AN000; only "a" of "am" ?
2146 je $P_T1201 ;AN000;
2147
2148 cmp al,"m" ;AN000; "m" of "am" or "pm"
2149 jne $P_T12_Exit ;AN000;
2150
2151 dec si ;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" ?
2155 je $P_T1200 ;AN000;
2156
2157 cmp al,"a" ;AN000; "a" of "am" ?
2158 je $P_T1201 ;AN000; go process "a"
2159
2160 jmp short $P_T12_Exit ;AN000; no special chars found
2161
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
2165
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;
2171 pop si ;AN000;
2172 pop ax ;AN000;
2173 ret ;AN000;
2174$P_Time_2412 endp ;AN000;
2175ENDIF ;AN000;(of TimeSW)
2176PAGE ;AN000;
2177;***********************************************************************
2178IF CmpxSW ;AN000;(Check if complex item is supported)
2179; $P_Complex_Format:
2180;
2181; Function: Check if the input string is valid complex format.
2182; And set the result buffer.
2183;
2184; Input: psdata_seg:SI -> $P_STRING_BUF
2185; ES:BX -> CONTROL block
2186;
2187; Output: None
2188;
2189; Use: $P_Fill_Result, $P_Chk_DBCS, $P_Chk_EOL, $P_Skip_Delim
2190; $P_Quoted_str, $P_Chk_DSQuote
2191;
2192; Vars: $P_RC(W), $P_SI_Save(W), $P_SaveSI_Cmpx(R), $P_Save_EOB(R)
2193;***********************************************************************
2194$P_Complex_Format proc ;AN000;
2195 push ax ;AN000;
2196 push bx ;AN000;
2197 push si ;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;
2201
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.
2207
2208 cmp al,$P_Lparen ;AN000; left parentheses ?
2209 jne $P_Cmpx00 ;AN000; then
2210
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
2215$P_Cmpx00: ;AN000;
2216 cmp al,$P_Rparen ;AN000; right parentheses ?
2217 jne $P_Cmpx01 ;AN000; then
2218
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
2223
2224 je $P_Cmpx03 ;AN000; ok, valid complex
2225
2226$P_Cmpx01: ;AN000;
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
2230
2231 mov psdata_seg:[si],al ;AN000; here quoted string is found in the complex list.
2232 inc si ;AN000;
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
2236
2237 jmp short $P_Cmpx05 ;AN000;
2238
2239$P_Cmpx04: ;AN000;
2240 call $P_Chk_DBCS ;AN000; was it a lead byte of DBCS ?
2241 jnc $P_Cmpx02 ;AN000;
2242
2243 mov psdata_seg:[si],al ;AN000; then store 1st byte
2244 inc si ;AN000;
2245 inc bx ;AN000;
2246 mov al,[bx] ;AN000; load 2nd byte
2247$P_Cmpx02: ;AN000;
2248 mov psdata_seg:[si],al ;AN000; store SBCS or 2nd byte of DBCS
2249$P_Cmpx05: ;AN000;
2250 inc si ;AN000;
2251 inc bx ;AN000;
2252 jmp short $P_Cmpx_Loop ;AN000; loop
2253;---- ;AN000;
2254$P_Cmpx03: ;AN000;
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;
2263
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;
2272 pop si ;AN000;
2273 pop bx ;AN000;
2274 call $P_Fill_Result ;AN000;
2275 pop ax ;AN000;
2276 ret ;AN000;
2277$P_Complex_Format endp ;AN000;
2278ENDIF ;AN000;(of CpmxSW)
2279PAGE ;AN000;
2280;***********************************************************************
2281IF QusSW ;AN000;(Check if quoted string is supported)
2282; $P_Quoted_Format:
2283;
2284; Function: Check if the input string is valid quoted string format.
2285; And set the result buffer.
2286;
2287; Input: psdata_seg:SI -> $P_STRING_BUF
2288; ES:BX -> CONTROL block
2289;
2290; Output: None
2291;
2292; Use: $P_Fill_Result, $P_Chk_DBCS, $P_Chk_EOL, $P_Skip_Delim
2293; $P_Chk_DSQuote, $P_Quoted_Str
2294;
2295; Vars: $P_RC(W), $P_SI_Save(W), $P_SaveSI_Cmpx(R),$P_Save_EOB(R)
2296;***********************************************************************
2297$P_Quoted_Format proc ;AN000;
2298 push ax ;AN000;
2299 push bx ;AN000;
2300 push si ;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
2306
2307; mov psdata_seg:[si],al ;AN000; move it to internal buffer
2308; inc si ;AN000;
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
2312
2313 mov byte ptr psdata_seg:[si+byte],$P_NULL ;AN000; end up with NULL
2314 mov si,bx ;AN000;
2315 inc si ;AN000;
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;
2319
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
2329 pop bx ;AN000; to
2330 call $P_Fill_Result ;AN000; quoted string
2331 pop ax ;AN000;
2332 ret ;AN000;
2333$P_Quoted_Format endp ;AN000;
2334ENDIF ;AN000;(of QusSW)
2335PAGE ;AN000;
2336;***********************************************************************
2337; $P_Chk_DSQuote;
2338;
2339; Function: Check if AL is double quotation or single quotation
2340;
2341; Input: AL = byte to be examineed
2342;
2343; Output: ZF on if AL is single or double quotetaion
2344;
2345; Vars: $P_SorD_Quote(W)
2346;***********************************************************************
2347IF 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 ;
2358 PAGE ;AN000;
2359;***********************************************************************
2360; $P_Quoted_Str:
2361;
2362; Function: Copy chracacter from ES:BX to psdata_seg:SI until closing single
2363; (double) quotation found.
2364;
2365; Input: psdata_seg:SI -> $P_STRING_BUF
2366; ES:BX -> Operand in command buffer
2367;
2368; Output: CY on indicates EOF encounterd before closing quotation
2369; BX and SI
2370;
2371;
2372; Vars: $P_SorD_Quote(R)
2373;***********************************************************************
2374$P_Quoted_Str proc ;AN000;
2375 push ax ;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;
2380
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;
2384
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;
2388
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;
2392
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;
2401
2402$P_Qus00: ;AN000;
2403 call $P_Chk_DBCS ;AN000; was it a lead byte of DBCS ?
2404 jnc $P_Qus01 ;AN000;
2405
2406 mov psdata_seg:[si],al ;AN000; store 1st byte
2407 inc si ;AN000;
2408 inc bx ;AN000;
2409 mov al,[bx] ;AN000; load 2nd byte
2410$P_Qus01: ;AN000;
2411 mov psdata_seg:[si],al ;AN000; store SBCS or 2nd byte of DBCS
2412 inc si ;AN000;
2413 inc bx ;AN000;
2414 jmp short $P_Qus_Loop ;AN000;
2415
2416$P_Qustr_Err0: ;AN000;
2417 stc ;AN000; indicate error
2418 jmp short $P_Quoted_Str_Exit ;AN000;
2419
2420$P_Qus02: ;AN000;
2421 mov byte ptr psdata_seg:[si],0 ;AN000;
2422 clc ;AN000; indicate no error
2423$P_Quoted_Str_Exit: ;AN000;
2424 pop ax ;AN000;
2425 ret ;AN000;
2426$P_Quoted_Str endp ;AN000;
2427ENDIF ;AN000;(of QusSW+CmpxSW)
2428PAGE ;AN000;
2429;***********************************************************************
2430IF FileSW+DrvSW ;AN000;(Check if file spec or drive only is supported)
2431; $P_File_Format;
2432;
2433; Function: Check if the input string is valid file spec format.
2434; And set the result buffer.
2435;
2436; Input: psdata_seg:SI -> $P_STRING_BUF
2437; ES:BX -> CONTROL block
2438;
2439; Output: None
2440;
2441; Use: $P_Fill_Result, $P_Chk_DBCS, $P_FileSp_Chk
2442;
2443; Vars: $P_RC(W), $P_SI_Save(W), $P_Terminator(W), $P_SaveSI_Cmpx(R)
2444; $P_SaveSI_Cmpx(R)
2445;***********************************************************************
2446$P_File_Format proc ;AN000;
2447 push ax ;AN000;
2448 push di ;AN000;
2449 push si ;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
2455
2456 call $P_FileSp_Chk ;AN000; else, check if file special character
2457 jne $P_FileF03 ;AN000; if yes,
2458
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.
2463 pop si ;AN033;
2464 mov byte ptr psdata_seg:[si],$P_NULL ;AN033;
2465 pop di ;AN033;
2466 jmp short $P_FileF02 ;AN033;
2467
2468
2469$P_FileF_Err: ;AN000;
2470 pop si ;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
2474 pop di ;AN000;
2475 test es:[bx].$P_Match_Flag,$P_Optional ;AN000; is it optional ?
2476 jne $P_FileF02 ;AN000;
2477
2478 mov psdata_seg:$P_RC,$P_Op_Missing ;AC034; 3/17/87
2479 jmp short $P_FileF02 ;AN000;
2480
2481$P_FileF03: ;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;
2488
2489 call $P_FileSp_Chk ;AN000; File special character ?
2490 je $P_FileF00 ;AN000;
2491
2492 call $P_Chk_DBCS ;AN000; no, then DBCS ?
2493 jnc $P_FileF01 ;AN000;
2494 inc di ;AN000; if yes, skip next byte
2495 inc si ;AN000;
2496$P_FileF01: ;AN000;
2497 inc di ;AN000;
2498 inc si ;AN000;
2499 jmp short $P_FileF_Loop1 ;AN000;
2500;
2501$P_FileF00: ;AN000;
2502 mov psdata_seg:$P_Terminator,al ;AC034;
2503 mov byte ptr psdata_seg:[si],$P_NULL ;AN000; update end of string
2504 inc di ;AN000;
2505 mov psdata_seg:$P_SI_Save,di ;AC034; update next pointer in command line
2506$P_FileF_RLT: ;AN000;
2507 pop si ;AN000;
2508 pop di ;AN000;
2509$P_FileF02: ;AN000;
2510
2511 pop ax ;AN000; (tm14)
2512 test ax,$P_File_Spc ;AN000; (tm14)
2513 je $P_Drv_Only_Exit ;AN000; (tm14)
2514
2515 push ax ;AN000; (tm14)
2516
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
2520 pop ax ;AN000;
2521
2522$P_Drv_Only_Exit: ;AN000; (tm14)
2523
2524 ret ;AN000;
2525$P_File_Format endp ;AN000;
2526PAGE ;AN000;
2527;***********************************************************************
2528; $P_FileSp_Chk
2529;
2530; Function: Check if the input byte is one of file special characters
2531;
2532; Input: psdata_seg:SI -> $P_STRING_BUF
2533; AL = character code to be examineed
2534;
2535; Output: ZF = 1 , AL is one of special characters
2536;***********************************************************************
2537$P_FileSp_Chk proc ;AN000;
2538 push bx ;AN000;
2539 push cx ;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;
2545
2546 inc bx ;AN000;
2547 loop $P_FileSp_Loop ;AN000;
2548
2549 inc cx ;AN000; reset ZF
2550$P_FileSp_Exit: ;AN000;
2551 pop cx ;AN000;
2552 pop bx ;AN000;
2553 ret ;AN000;
2554$P_FileSp_Chk endp ;AN000;
2555ENDIF ;AN000;(of FileSW+DrvSW)
2556PAGE ;AN000;
2557;***********************************************************************
2558IF DrvSW ;AN000;(Check if drive only is supported)
2559; $P_Drive_Format;
2560;
2561; Function: Check if the input string is valid drive only format.
2562; And set the result buffer.
2563;
2564; Input: psdata_seg:SI -> $P_STRING_BUF
2565; ES:BX -> CONTROL block
2566;
2567; Output: None
2568;
2569; Use: $P_Fill_Result, $P_Chk_DBCS
2570;
2571; Vars: $P_RC(W)
2572;***********************************************************************
2573$P_Drive_Format proc ;AN000;
2574 push ax ;AN000;
2575 push dx ;AN000;
2576 mov al,psdata_seg:[si] ;AN000;
2577 or al,al ;AN000; if null string
2578 je $P_Drv_Exit ;AN000; do nothing
2579
2580 call $P_Chk_DBCS ;AN000; is it leading byte ?
2581 jc $P_Drv_Err ;AN000;
2582
2583 cmp word ptr psdata_seg:[si+byte],$P_Colon ;AN000; "d", ":", 0 ?
2584 je $P_DrvF00 ;AN000;
2585
2586 test es:[bx].$P_Match_Flag,$P_Ig_Colon ;AN000; colon can be ignored?
2587 je $P_Drv_Err ;AN000;
2588
2589 cmp byte ptr psdata_seg:[si+byte],$P_NULL ;AN000; "d", 0 ?
2590 jne $P_Drv_Err ;AN000;
2591
2592$P_DrvF00: ;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
2596
2597 cmp al,"z" ;AN000; "a" - "z"
2598 ja $P_Drv_Err ;AN000; if no, error
2599
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;
2606
2607$P_Drv_Err: ;AN000;
2608 mov psdata_seg:$P_RC,$P_Syntax ;AC034;
2609$P_Drv_Exit: ;AN000;
2610 pop dx ;AN000;
2611 pop ax ;AN000;
2612 ret ;AN000;
2613$P_Drive_Format endp ;AN000;
2614ENDIF ;AN000;(of DrvSW)
2615PAGE ;AN000;
2616;***********************************************************************
2617; $P_Skip_Delim;
2618;
2619; Function: Skip delimiters specified in the PARMS list, white space
2620; and comma.
2621;
2622; Input: DS:SI -> Command String
2623; ES:DI -> Parameter List
2624;
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
2628;
2629; Use: $P_Chk_EOL, $P_Chk_Delim,
2630;
2631; Vars: $P_Flags(R)
2632;***********************************************************************
2633$P_Skip_Delim proc ;AN000;
2634$P_Skip_Delim_Loop: ;AN000;
2635 LODSB ;AN000;
2636 call $P_Chk_EOL ;AN000; is it EOL character ?
2637 je $P_Skip_Delim_CY ;AN000; if yes, exit w/ CY on
2638
2639 call $P_Chk_Delim ;AN000; is it one of delimiters ?
2640 jne $P_Skip_Delim_NCY ;AN000; if no, exit w/ CY off
2641
2642 test psdata_seg:$P_Flags2,$P_Extra ;AC034; extra delim or comma found ?
2643 je $P_Skip_Delim_Loop ;AN000; if no, loop
2644
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)
2647
2648 dec si ;AN000; backup si for next call (tm08)
2649 jmp short $P_Exit_At_Extra ;AN000; else exit w/ CY off
2650
2651$P_Skip_Delim_CY: ;AN000;
2652 stc ;AN000; indicate EOL
2653 jmp short $P_Skip_Delim_Exit ;AN000;
2654
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
2659 ret ;AN000;
2660
2661$P_Exit_At_Extra: ;AN000;
2662 clc ;AN000; indicate extra delim
2663 ret ;AN000;
2664$P_Skip_Delim endp ;AN000;
2665PAGE ;AN000;
2666;***********************************************************************
2667; $P_Chk_EOL;
2668;
2669; Function: Check if AL is one of End of Line characters.
2670;
2671; Input: AL = character code
2672; ES:DI -> Parameter List
2673;
2674; Output: ZF = 1 if one of End of Line characters
2675;**********************************************************************
2676$P_Chk_EOL proc ;AN000;
2677 push bx ;AN000;
2678 push cx ;AN000;
2679 cmp al,$P_CR ;AN000; Carriage return ?
2680 je $P_Chk_EOL_Exit ;AN000;
2681
2682 cmp al,$P_NULL ;AN000; zero ?
2683 je $P_Chk_EOL_Exit ;AN000;
2684
2685IF LFEOLSW ;AN028; IF LF TO BE ACCEPTED AS EOL
2686 cmp al,$P_LF ;AN000; Line feed ?
2687 je $P_Chk_EOL_Exit ;AN000;
2688ENDIF ;AN028;
2689
2690 cmp byte ptr es:[di].$P_Num_Extra,$P_I_Have_EOL ;AN000; EOL character specified ?
2691 jb $P_Chk_EOL_Exit ;AN000;
2692
2693 xor bx,bx ;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;
2698
2699 xor cx,cx ;AN000; Get number of extra chcracter
2700 mov cl,es:[bx+di] ;AN000;
2701$P_Chk_EOL_Loop: ;AN000;
2702 inc bx ;AN000;
2703 cmp al,es:[bx+di] ;AN000; Check extra EOL character
2704 je $P_Chk_EOL_Exit ;AN000;
2705
2706 loop $P_Chk_EOL_Loop ;AN000;
2707
2708$P_Chk_EOL_NZ: ;AN000;
2709 cmp al,$P_CR ;AN000; reset ZF
2710$P_Chk_EOL_Exit: ;AN000;
2711 pop cx ;AN000;
2712 pop bx ;AN000;
2713 ret ;AN000;
2714$P_Chk_EOL endp ;AN000;
2715PAGE ;AN000;
2716;***********************************************************************
2717; $P_Chk_Delim;
2718;
2719; Function: Check if AL is one of delimiter characters.
2720; if AL+[si] is DBCS blank, it is replaced with two SBCS
2721; blanks.
2722;
2723; Input: AL = character code
2724; DS:SI -> Next Character
2725; ES:DI -> Parameter List
2726;
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;
2732 push bx ;AN000;
2733 push cx ;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;
2738
2739 cmp al,$P_TAB ;AN000; TAB ?
2740 je $P_Chk_Delim_Exit ;AN000;
2741
2742 cmp al,$P_Comma ;AN000; Comma ?
2743 je $P_Chk_Delim_Exit0 ;AN000;
2744
2745$P_Chk_Delim00: ;AN000;
2746 cmp al,$P_DBSP1 ;AN000; 1st byte of DBCS Space ?
2747 jne $P_Chk_Delim01 ;AN000;
2748
2749 cmp byte ptr [si],$P_DBSP2 ;AN000; 2nd byte of DBCS Space ?
2750 jne $P_Chk_Delim01 ;AN000;
2751
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;
2756
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;
2760
2761 xor cx,cx ;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;
2765
2766 mov bx,$P_Len_PARMS-1 ;AN000; set bx to 1st extra delimiter
2767$P_Chk_Delim_Loop: ;AN000;
2768 inc bx ;AN000;
2769 cmp al,es:[bx+di] ;AN000; Check extra Delim character
2770 je $P_Chk_Delim_Exit0 ;AN000;
2771
2772 loop $P_Chk_Delim_Loop ;AN000; examine all extra delimiter
2773
2774$P_Chk_Delim_NZ: ;AN000;
2775 cmp al,$P_Space ;AN000; reset ZF
2776$P_Chk_Delim_Exit: ;AN000;
2777;;;; jne $P_ChkDfin
2778;;;; mov psdata_seg:$P_Terminator,al ;AN034;
2779$P_ChkDfin: ;AN000;
2780 pop cx ;AN000;
2781 pop bx ;AN000;
2782 ret ;AN000;
2783
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
2788
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;
2793
2794$P_Chk_Delim endp ;AN000;
2795PAGE ;AN000;
2796;***********************************************************************
2797; $P_Chk_Switch;
2798;
2799; Function: Check if AL is the switch character not in first position of
2800; $P_STRING_BUF
2801;
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)
2805;
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.
2809
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.
2813;
2814; Vars: $P_Terminator(W)
2815
2816; Use: $P_0099
2817;***********************************************************************
2818$P_Chk_Switch proc ;AN000;
2819
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;
2838
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
2841 cmp BX,BP ;AN000;
2842 je $P_STRUC_L2 ;AN000;
2843
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;
2847
2848 STC ;AN020;not in first position and is slash, now see if might be in date string
2849IF 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;
2855
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
2864ENDIF ;AN020;DateSw
2865; .ELSE ;AN020;
2866 jmp short $P_STRUC_L1 ;AN000;
2867
2868$P_STRUC_L5: ;AN000;
2869 CLC ;AN020;not a slash
2870; .ENDIF ;AN020;
2871; .ELSE ;AN020;is first char in the buffer, ZF=0
2872 jmp short $P_STRUC_L1 ;AN000;
2873
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;
2878
2879 OR psdata_seg:$P_Flags2,$P_SW ;AN020;AC034;;could be valid switch, first char and is slash
2880; .ENDIF ;AN020;
2881$P_STRUC_L12: ;AN000;
2882 CLC ;AN020;CF=0 indicating first char
2883; .ENDIF ;AN020;
2884$P_STRUC_L1: ;AN000;
2885
2886 ret ;AN000;
2887$P_Chk_Switch endp ;AN000;
2888 PAGE ;AN000;
2889;**************************************************************************
2890; $P_Chk_DBCS:
2891;
2892; Function: Check if a specified byte is in ranges of the DBCS lead bytes
2893;
2894; Input:
2895; AL = Code to be examineed
2896;
2897; Output:
2898; If CF is on then a lead byte of DBCS
2899;
2900; Use: INT 21h w/AH=63
2901;
2902; Vars: $P_DBCSEV_Seg(RW), $P_DBCSEV_Off(RW)
2903;***************************************************************************
2904$P_Chk_DBCS PROC ;AN000;
2905;
2906 PUSH DS ;AN000;
2907 PUSH SI ;AN000;
2908 PUSH bx ;AN000; (tm11)
2909 CMP psdata_seg:$P_DBCSEV_SEG,0 ;AC034; ALREADY SET ?
2910 JNE $P_DBCS00 ;AN000;
2911
2912 PUSH AX ;AN000;
2913; PUSH BX ;AN000; (tm11)
2914 PUSH ds ;AN000; (tm11)
2915 PUSH CX ;AN000;
2916 PUSH DX ;AN000;
2917 PUSH DI ;AN000;
2918 PUSH BP ;AN000;
2919 PUSH ES ;AN000;
2920 XOR SI,SI ;AN000;
2921 MOV DS,SI ;AN000;
2922 MOV AX,$P_DOS_GetEV ;AN000; GET DBCS EV CALL
2923 INT 21H ;AN000;
2924
2925; MOV AX,DS ;AN000; (tm11)
2926; OR AX,AX ;AN000; (tm11)
2927 MOV bx,DS ;AN000; (tm11)
2928 OR bx,bx ;AN000; (tm11)
2929 POP ES ;AN000;
2930 POP BP ;AN000;
2931 POP DI ;AN000;
2932 POP DX ;AN000;
2933 POP CX ;AN000;
2934; POP BX ;AN000; (tm11)
2935 POP ds ;AN000; (tm11)
2936 POP AX ;AN000;
2937 JE $P_NON_DBCS ;AN000;
2938
2939$P_DBCS02: ;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)
2943$P_DBCS00: ;AN000;
2944 MOV SI,psdata_seg:$P_DBCSEV_OFF ;AC034; load EV offset
2945 MOV DS,psdata_seg:$P_DBCSEV_SEG ;AC034; and segment
2946
2947$P_DBCS_LOOP: ;AN000;
2948 CMP WORD PTR [SI],0 ;AN000; zero vector ?
2949 JE $P_NON_DBCS ;AN000; then exit
2950
2951 CMP AL,[SI] ;AN000;
2952 JB $P_DBCS01 ;AN000; Check if AL is in
2953
2954 CMP AL,[SI+BYTE] ;AN000; range of
2955 JA $P_DBCS01 ;AN000; the vector
2956
2957 STC ;AN000; if yes, indicate DBCS and exit
2958 JMP short $P_DBCS_EXIT ;AN000;
2959
2960$P_DBCS01: ;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
2966
2967$P_NON_DBCS: ;AN000;
2968 CLC ;AN000; indicate SBCS
2969$P_DBCS_EXIT: ;AN000;
2970 POP bx ;AN000; (tm11)
2971 POP SI ;AN000;
2972 POP DS ;AN000;
2973 RET ;AN000;
2974$P_Chk_DBCS ENDP ;AN000;