Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3015 lines
99 KiB

  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. ;Revision History
  8. ;================
  9. ;
  10. ; M029 02/15/91 SR Bug #5699. In SysParse, reinitialize $P_FileSp_Char
  11. ; everytime because this is in the non-checksum region
  12. ; and can get corrupted without the checksum region
  13. ; getting corrupted. Yet another data structure that
  14. ; should have been in the checksum region but isnt.
  15. ;
  16. ;
  17. ; NOTE: basesw must be set properly to allow the PARSER to access psdata.
  18. ; - basesw undefined means CS seg. override for psdata access.
  19. ; - basesw = 1 means DS seg. override for psdata access &
  20. ; DS must point to psdata.
  21. ; - basesw = 0 means ES seg. override for psdata access &
  22. ; ES must point to psdata.
  23. ;
  24. ;
  25. IFNDEF basesw ;AN022;
  26. psdata_seg EQU CS ;AN022;
  27. ELSE ;AN022;
  28. IF basesw ;AN022;IF "basesw EQU 1" specified by caller THEN
  29. psdata_seg EQU DS ;AN022;
  30. ELSE ;AN022;
  31. psdata_seg EQU ES ;AN022;ELSE only other choice is ES (basesw EQU 0)
  32. ENDIF ;AN022;
  33. ENDIF ;AN022;
  34. ifndef incsw ;AN000; (tm03) Someone doesn't want to include psdata
  35. incsw equ 1 ;AN000; include psdata.inc (tm03)
  36. endif ;AN000; (tm03)
  37. if incsw ;AN000; If incsw = 1 then (tm03)
  38. include psdata.inc ;AN000; include psdata.inc (tm03)
  39. endif ;AN000; endif (tm03)
  40. PAGE ;AN000;
  41. IF1 ;AN000;
  42. ; %OUT INCLUDING COMP=COMMON DSN=PARSE.ASM...;AN000;
  43. ENDIF ;AN000;
  44. ;***********************************************************************
  45. ; SysParse;
  46. ;
  47. ; Function : Parser Entry
  48. ;
  49. ; Input: DS:SI -> command line
  50. ; ES:DI -> parameter block
  51. ; psdata_seg -> psdata.inc
  52. ; CX = operand ordinal
  53. ;
  54. ; Note: ES is the segment containing all the control blocks defined
  55. ; by the caller, except for the DOS COMMAND line parms, which
  56. ; is in DS.
  57. ;
  58. ; Output: CY = 1 error of caller, means invalid parameter block or
  59. ; invalid value list. But this parser does NOT implement
  60. ; this feature. Therefore CY always zero.
  61. ;
  62. ; CY = 0 AX = return code
  63. ; BL = terminated delimiter code
  64. ; CX = new operand ordinal
  65. ; SI = set past scaned operand
  66. ; DX = selected result buffer
  67. ;
  68. ; Use: $P_Skip_Delim, $P_Chk_EOL, $P_Chk_Delim, $P_Chk_DBCS
  69. ; $P_Chk_Swtch, $P_Chk_Pos_Control, $P_Chk_Key_Control
  70. ; $P_Chk_Sw_Control, $P_Fill_Result
  71. ;
  72. ; Vars: $P_Ordinal(RW), $P_RC(RW), $P_SI_Save(RW), $P_DX(R), $P_Terminator(R)
  73. ; $P_SaveSI_Cmpx(W), $P_Flags(RW), $P_Found_SYNONYM(R), $P_Save_EOB(W)
  74. ;
  75. ;-------- Modification History -----------------------------------------
  76. ;
  77. ; 4/04/87 : Created by K. K,
  78. ; 4/28/87 : $P_Val_YH assemble error (tm01)
  79. ; : JMP SHORT assemble error (tm02)
  80. ; 5/14/87 : Someone doesn't want to include psdata (tm03)
  81. ; 6/12/87 : $P_Bridge is missing when TimeSw equ 0 and (CmpxSw equ 1 or
  82. ; DateSW equ 1) (tm04)
  83. ; 6/12/87 : $P_SorD_Quote is missing when QusSw equ 0 and CmpxSW equ 1
  84. ; (tm05) in PSDATA.INC
  85. ; 6/12/87 : $P_FileSp_Char and $P_FileSP_Len are missing
  86. ; when FileSW equ 0 and DrvSW equ 1 (tm06) in PSDATA.INC
  87. ; 6/18/87 : $VAL1 and $VAL3, $VAL2 and $VAL3 can be used in the same
  88. ; value-list block (tm07)
  89. ; 6/20/87 : Add $P_SW to check if there's an omiting parameter after
  90. ; switch (keyword) or not. If there is, backup si for next call
  91. ; (tm08)
  92. ; 6/24/87 : Complex Item checking does not work correctly when CmpSW equ 1
  93. ; and DateSW equ 0 and TimeSW equ 0 (tm09)
  94. ; 6/24/87 : New function flag $P_colon_is_not_necessary for switch
  95. ; /+15 and /+:15 are allowed for user (tm10)
  96. ; 6/29/87 : ECS call changes DS register but it causes the address problem
  97. ; in user's routines. $P_Chk_DBCS (tm11)
  98. ; 7/10/87 : Switch with no_match flag (0x0000H) does not work correctly
  99. ; (tm12)
  100. ; 7/10/87 : Invalid switch/keyword does not work correctly
  101. ; (tm13)
  102. ; 7/10/87 : Drive_only breaks 3 bytes after the result buffer
  103. ; (tm14)
  104. ; 7/12/87 : Too_Many_Operands sets DX=0 as the PARSE result
  105. ; (tm15)
  106. ; 7/24/87 : Negative lower bound on numeric ranges cause trouble
  107. ; 7/24/87 : Quoted strings being returned with quotes.
  108. ; 7/28/87 : Kerry S (;AN018;)
  109. ; Non optional value on switch (match flags<>0 and <>1) not flagged
  110. ; as an error when missing. Solution: return error 2. Modules
  111. ; affected: $P_Chk_SW_Control.
  112. ; 7/29/87 : Kerry S (;AN019;)
  113. ; Now allow the optional bit in match flags for switches. This
  114. ; allows the switch to be encountered with a value or without a
  115. ; value and no error is returned.
  116. ;
  117. ; 8/28/87 : Ed K, Kerry S (;AN020;)
  118. ; 9/14/87 In PROC $P_Get_DecNum, when checking for field separators
  119. ; within a date response, instead of checking just for the one
  120. ; character defined by the COUNTRY DEPENDENT INFO, check for
  121. ; all three chars, "-", "/", and ".". Change $P_Chk_Switch to allow
  122. ; slashes in date strings when DateSw (assembler switch) is set.
  123. ; 9/1/87 : Kerry S (;AN021)
  124. ; In PROC $P_String_Comp, when comparing the switch or keyword on
  125. ; the command line with the string in the control block the
  126. ; comparing was stopping at a colon (switch) or equal (keyword)
  127. ; on the command line and assuming a match. This allowed a shorter
  128. ; string on the command line than in the synonym list in the control
  129. ; block. I put in a test for a null in the control block so the
  130. ; string in the control block must be the same length as the string
  131. ; preceeding the colon or equal on the command line.
  132. ; 8/28/87 : Kerry S (;AN022;)
  133. ; All references to data in PSDATA.INC had CS overrides. This caused
  134. ; problems for people who included it themselves in a segment other
  135. ; than CS. Added switch to allow including PSDATA.INC in any
  136. ; segment.
  137. ; 9/16/87 : Ed K (;AN023;) PTM1040
  138. ; in $p_set_cdi PROC, it assumes CS points to psdata. Change Push CS
  139. ; into PUSH PSDATA_SEG. In $P_Get_DecNum PROC, fix AN020
  140. ; forced both TIME and DATE to use the delims, "-","/",".".
  141. ; Created FLag, in $P_time_Format PROC, to request the delim in
  142. ; BL be used if TIME is being parsed.
  143. ; 9/24/87 : Ed K
  144. ; Removed the include to STRUC.INC. Replaced the STRUC macro
  145. ; invocations with their normally expanded code; made comments
  146. ; out of the STRUC macro invocation statements to maintain readability.
  147. ; 9/24/87 : Ed K (;AN024;) PTM1222
  148. ; When no CONTROL for a keyword found, tried to fill in RESULT
  149. ; pointed to by non-existant CONTROL.
  150. ; 10/15/87 : Ed K (;AN025;) PTM1672
  151. ; A quoted text string can be framed only by double quote. Remove
  152. ; support to frame quoted text string with single quote.
  153. ; (apostrophe) $P_SorD_Quote is removed from PSDATA.INC.
  154. ; $P_SQuote EQU also removed from PSDATA.INC. Any references to
  155. ; single quote in PROC prologues are left as is for history reasons.
  156. ; This fixes another bug, not mentioned in p1672, in that two
  157. ; quote chars within a quoted string is supposed to be reported as
  158. ; one quote character, but is reported as two quotes. This changed
  159. ; two instructions in PROC $P_Quoted_Str.
  160. ; Also fixed are several JMP that caused a NOP, these changed to
  161. ; have the SHORT operator to avoid the unneeded NOP.
  162. ; The code and PSDATA.INC have been aligned for ease of reading.
  163. ; 10/26/87 : Ed K (;AN026;) PTM2041, DATE within SWITCH, BX reference to
  164. ; psdata buffer should have psdata_seg.
  165. ; 10/27/87 : Ed K (;AN027;) PTM2042 comma between keywords implies
  166. ; positional missing.
  167. ; 11/06/87 : Ed K (;AN028;) PTM 2315 Parser should not use line feed
  168. ; as a line delimiter, should use carriage return.
  169. ; Define switch: LFEOLSW, if on, accept LF as end of line char.
  170. ; 11/11/87 : Ed K (;AN029;) PTM 1651 GET RID OF WHITESPACE AROUND "=".
  171. ; 11/18/87 : Ed K (;AN030;) PTM 2551 If filename is just "", then
  172. ; endless loop since SI is returned still pointing to start
  173. ; of that parm.
  174. ; 11/19/87 : Ed K (;AN031;) PTM 2585 date & time getting bad values.
  175. ; Vector to returned string has CS instead of Psdata_Seg, but
  176. ; when tried to fix it on previous version, changed similar
  177. ; but wrong place.
  178. ; 12/09/87 : Bill L (;AN032;) PTM 2772 colon and period are now valid
  179. ; delimiters between hours, minutes, seconds for time. And period
  180. ; and comma are valid delimiters between seconds and 100th second.
  181. ; 12/14/87 : Bill L (;AN033;) PTM 2722 if illegal delimiter characters
  182. ; in a filespec, then flag an error.
  183. ; 12/22/87 : Bill L (;AN034;) All local data to parser is now
  184. ; indexed off of the psdata_seg equate instead of the DS register.
  185. ; Using this method, DS can point to the segment of PSP or to psdata
  186. ; --> local parser data. Why were some references to local data changed
  187. ; to do this before, but not all ?????
  188. ; 02/02/88 : Ed K (;AC035;) INSPECT utility, suggests optimizations.
  189. ; 02/05/88 : Ed K (;AN036;) P3372-UPPERCASE TRANSLATION, PSDATA_SEG HOSED.
  190. ;
  191. ; 02/08/88 : Ed K (;AN037;) P3410-AVOID POP OF CS, CHECK BASESW FIRST.
  192. ; 02/19/88 : Ed K (;AN038;) p3524 above noon and "am" should be error
  193. ; 02/23/88 : Ed K (;AN039;) p3518 accept "comma" and "period" as decimal
  194. ; separator in TIME before hundredths field.
  195. ;
  196. ; 08/09/90 : SA M005 Prevented parser from recognizing '=' signs within
  197. ; strings as keywords.
  198. ;
  199. ;***********************************************************************
  200. IF FarSW ;AN000;(Check if need far return)
  201. SysParse proc far ;AN000;
  202. ELSE ;AN000;
  203. SysParse proc near ;AN000;
  204. ENDIF ;AN000;(of FarSW)
  205. ; $SALUT (4,9,17,41)
  206. mov psdata_seg:$P_Flags,0 ;AC034; Clear all internal flags
  207. IF TimeSw ;AN039; FOR TIME ONLY
  208. MOV PSDATA_SEG:$P_ORIG_ORD,CX ;AN039; ORIGINAL ORDINAL FROM CX
  209. MOV PSDATA_SEG:$P_ORIG_STACK,SP ;AN039; ORIGINAL VALUE OF STACK FROM SP
  210. MOV PSDATA_SEG:$P_ORIG_SI,SI ;AN039; ORIGINAL START PARSE POINTER FROM SI
  211. $P_REDO_TIME: ;AN039; try to parse time again
  212. ENDIF ;AN039; FOR TIME ONLY
  213. cld ;AN000; confirm forward direction
  214. mov psdata_seg:$P_ordinal,cx ;AC034; save operand ordinal
  215. mov psdata_seg:$P_RC,$P_No_Error ;AC034; Assume no error
  216. mov psdata_seg:$P_Found_SYNONYM,0 ;AC034; initalize synonym pointer
  217. mov word ptr psdata_seg:$P_DX,0 ;AC034; (tm15)
  218. ;M029 -- Begin changes
  219. ; The table of special chars $P_FileSp_Char should be initialized on every
  220. ;entry to SysParse. This is in the non-checksum region and any program that
  221. ;corrupts this table but does not corrupt the checksum region will leave
  222. ;command.com parsing in an inconsistent state.
  223. ; NB: The special characters string has been hardcoded here. If any change
  224. ;is made to it in psdata.inc, a corresponding change needs to be made here.
  225. ;
  226. IF FileSW + DrvSW
  227. mov word ptr psdata_seg:$P_FileSp_Char, ']['
  228. mov word ptr psdata_seg:$P_FileSp_Char+2, '<|'
  229. mov word ptr psdata_seg:$P_FileSp_Char+4, '+>'
  230. mov word ptr psdata_seg:$P_FileSp_Char+6, ';='
  231. ENDIF
  232. ;
  233. ;M029 -- End of changes
  234. ;
  235. IF KeySW ;AN029;
  236. ;IN CASE THE USER PUT OPTIONAL WHITESPACE CHARS AROUND THE "=" USED IN
  237. ;KEYWORD DEFINITIONS, SCAN THE COMMAND LINE AND COMPRESS OUT ANY WHITESPACES
  238. ;NEXT TO "=" BEFORE STARTING THE USUAL PARSING.
  239. push cx ;AN029;
  240. push dx ;AN029;
  241. push di ;AN029;
  242. push si ;AN029; remember where command line starts
  243. mov cx,-1 ;AN029; init counter
  244. ; $do
  245. $P_loc_eol: ;AN029;
  246. inc cx ;AN029; bump counter of chars up to EOL
  247. lodsb ;AN029; get a char from command line
  248. CALL $P_Chk_EOL ;AN029; see if AL is EOL char
  249. ; enddo z
  250. jnz $P_loc_EOL ;AN029; not found that EOL char
  251. mov psdata_seg:$P_count_to_EOL,cx ;AN029;AC034;; save count of chars up to EOL
  252. pop si ;AN029; restore start of command line
  253. ;scan command string for combinations including "=",
  254. ; and replace each with just the simple "="
  255. ;REPEAT UNTIL ONE PASS IS MADE WHEREIN NO CHANGES WERE MADE
  256. ; $do
  257. $P_DO1: ;AN029;
  258. push si ;AN029; remember where string started
  259. MOV CX,psdata_seg:$P_COUNT_TO_EOL ;AN029;AC034;; set count to no. chars in string,
  260. ;AN029; not counting the EOL char
  261. XOR BX,BX ;AN029;SET $P_REG_BL_DQ_SW TO "NOT IN QUOTES", AND...
  262. ;AN029;SET $P_REG_BH_CG_SW TO "NO CHANGES MADE"
  263. ;MAKE ONE PASS THRU THE STRING, LOOKING AT EACH CHARACTER
  264. ; $do ;AN029;
  265. $P_DO2: ;AN029;
  266. cmp BYTE PTR [SI],$P_double_quote ;AN029;
  267. ; $if e ;AN029;if a double quote was found
  268. JNE $P_IF3 ;AN029;
  269. NOT $P_REG_BL_DQ_SW ;AN029;TOGGLE THE DOUBLE QUOTE STATE SWITCH
  270. ; $endif ;AN029;
  271. $P_IF3: ;AN029;
  272. OR $P_REG_BL_DQ_SW,$P_REG_BL_DQ_SW ;AN029;IS THE DOUBLE QUOTE SWITCH SET?
  273. ; $if Z ;AN029;IF NOT IN DOUBLE QUOTES
  274. JNZ $P_IF5 ;AN029;
  275. mov ax,word ptr [si] ;AN029; get pair to be checked out
  276. cmp ax,$P_BL_EQ ;AN029;" ="
  277. ; $if e,or ;AN029;
  278. JE $P_LL6 ;AN029;
  279. cmp ax,$P_EQ_BL ;AN029;"= "
  280. ; $if e,or ;AN029;
  281. JE $P_LL6 ;AN029;
  282. cmp ax,$P_EQ_TB ;AN029; "=<tab>"
  283. ; $if e,or ;AN029;
  284. JE $P_LL6 ;AN029;
  285. cmp ax,$P_TB_EQ ;AN029;"<tab>="
  286. ; $if e ;AN029;if this pair to be replaced with a single "="
  287. JNE $P_IF6 ;AN029;
  288. $P_LL6: ;AN029;
  289. mov BYTE PTR [SI],$P_Keyword ;AN029; "="
  290. inc si ;AN029;point to next char after the new "="
  291. mov di,si ;AN029;move target right after new "="
  292. push si ;AN029;remember where i am, right after new "="
  293. PUSH CX ;AN029;SAVE CURRENT COUNT
  294. inc si ;AN029;source is one beyond that
  295. push es ;AN029;remember the extra segment
  296. push ds ;AN029;temporarily, set source seg and
  297. pop es ;AN029; target seg to the command line seg
  298. rep movsb ;AN029;move chars left one position
  299. pop es ;AN029;restore the extra segment
  300. POP CX ;AN029;RESTORE CURRENT COUNT
  301. pop si ;AN029;back to where I was
  302. DEC SI ;AN029;LOOK AT FIRST CHAR JUST MOVED
  303. MOV $P_REG_BH_CG_SW,-1 ;AN029;set switch to say "a change was made"
  304. DEC psdata_seg:$P_COUNT_TO_EOL ;AN029;AC034;;because just threw away a char
  305. dec CX ;AN029;DITTO
  306. ; $endif ;AN029;comparand pair found?
  307. $P_IF6: ;AN029;
  308. ; $endif ;AN029;double quote switch?
  309. $P_IF5: ;AN029;
  310. inc si ;AN029;bump index to look at next char in command string
  311. dec CX ;AN029;one less char to look at
  312. ;(deleted ;AC035;) CMP CX,0 ;AN029;is char count all gone yet?
  313. ; $enddo LE ;AN029;quit if no more chars
  314. JNLE $P_DO2 ;AN029;
  315. pop si ;AN029;remember where string started
  316. OR $P_REG_BH_CG_SW,$P_REG_BH_CG_SW ;AN029;WAS "A CHANGE MADE"?
  317. ; $enddo Z ;AN029;QUIT when no changes were made
  318. JNZ $P_DO1 ;AN029;
  319. pop di ;AN029;
  320. pop dx ;AN029;
  321. pop cx ;AN029;
  322. ;NOW THAT ALL WHITESPACE SURROUNDING "=" HAVE BEEN COMPRESSED OUT,
  323. ;RESUME NORMAL PARSING...
  324. ENDIF ;AN029; KEYWORDS SUPPORTED?
  325. call $P_Skip_Delim ;AN000; Move si to 1st non white space
  326. jnc $P_Start ;AN000; If EOL is not encountered, do parse
  327. ;--------------------------- End of Line
  328. mov ax,$P_RC_EOL ;AN000; set exit code to -1
  329. push bx ;AN000;
  330. mov bx,es:[di].$P_PARMSX_Address ;AN000; Get the PARMSX address to
  331. cmp cl,es:[bx].$P_MinP ;AN000; check ORDINAL to see if the minimum
  332. jae $P_Fin ;AN000; positional found.
  333. mov ax,$P_Op_Missing ;AN000; If no, set exit code to missing operand
  334. $P_Fin: ;AN000;
  335. pop bx ;AN000;
  336. jmp $P_Single_Exit ;AN000; return to the caller
  337. ;---------------------------
  338. $P_Start: ;AN000;
  339. mov psdata_seg:$P_SaveSI_Cmpx,si ;AN000;AC034; save ptr to command line for later use by complex,
  340. push bx ;AN000; quoted string or file spec.
  341. push di ;AN000;
  342. push bp ;AN000;
  343. lea bx,psdata_seg:$P_STRING_BUF ;AC034; set buffer to copy from command string
  344. test psdata_seg:$P_Flags2,$P_Extra ;AC034; 3/9 extra delimiter encountered ?
  345. jne $P_Pack_End ;AN000; 3/9 if yes, no need to copy
  346. $P_Pack_Loop: ;AN000;
  347. lodsb ;AN000; Pick a operand from buffer
  348. call $P_Chk_Switch ;AN000; Check switch character
  349. jc $P_Pack_End_BY_EOL ;AN020; if carry set found delimiter type slash, need backup si, else continue
  350. call $P_Chk_EOL ;AN000; Check EOL character
  351. je $P_Pack_End_BY_EOL ;AN000; need backup si
  352. call $P_Chk_Delim ;AN000; Check delimiter
  353. jne $P_PL01 ;AN000; If no, process next byte
  354. test psdata_seg:$P_Flags2,$P_Extra ;AC034; 3/9 If yes and white spec,
  355. ; (tm08)jne $P_Pack_End ;AN000; 3/9 then
  356. jne $P_Pack_End_backup_si ;AN000; (tm08)
  357. call $P_Skip_Delim ;AN000; skip subsequent white space,too
  358. jmp short $P_Pack_End ;AN000; finish copy by placing NUL at end
  359. $P_PAck_End_backup_si: ;AN000; (tm08)
  360. test psdata_seg:$P_Flags2,$P_SW+$P_equ ;AN000;AC034; (tm08)
  361. je $P_Pack_End ;AN000; (tm08)
  362. dec si ;AN000; (tm08)
  363. jmp short $P_Pack_End ;AN025; (tm08)
  364. $P_PL01: ;AN000;
  365. mov psdata_seg:[bx],al ;AN000; move byte to STRING_BUF
  366. cmp al,$P_Keyword ;AN000; if it is equal character,
  367. jne $P_PL00 ;AN000; then
  368. or psdata_seg:$P_Flags2,$P_equ ;AC034; remember it in flag
  369. $P_PL00: ;AN000;
  370. inc bx ;AN000; ready to see next byte
  371. call $P_Chk_DBCS ;AN000; was it 1st byte of DBCS ?
  372. jnc $P_Pack_Loop ;AN000; if no, process to next byte
  373. lodsb ;AN000; if yes, store
  374. mov psdata_seg:[bx],al ;AN000; 2nd byte of DBCS
  375. inc bx ;AN000; update pointer
  376. jmp short $P_Pack_Loop ;AN000; process to next byte
  377. $P_Pack_End_BY_EOL: ;AN000;
  378. dec si ;AN000; backup si pointer
  379. $P_Pack_End: ;AN000;
  380. mov psdata_seg:$P_SI_Save,si ;AC034; save next pointer, SI
  381. mov byte ptr psdata_seg:[bx],$P_NULL ;AN000; put NULL at the end
  382. mov psdata_seg:$P_Save_EOB,bx ;AC034; 3/17/87 keep the address for later use of complex
  383. mov bx,es:[di].$P_PARMSX_Address ;AN000; get PARMSX address
  384. lea si,psdata_seg:$P_STRING_BUF ;AC034;
  385. cmp byte ptr psdata_seg:[si],$P_Switch ;AN000; the operand begins w/ switch char ?
  386. je $P_SW_Manager ;AN000; if yes, process as switch
  387. cmp byte ptr psdata_seg:[si],$P_DQuote ;M005;is it a string?
  388. je $P_Positional_Manager ;M005;if so, process as one!
  389. test psdata_seg:$P_Flags2,$P_equ ;AC034; the operand includes equal char ?
  390. jne $P_Key_manager ;AN000; if yes, process as keyword
  391. $P_Positional_Manager: ;AN000; else process as positional
  392. mov al,es:[bx].$P_MaxP ;AN000; get maxp
  393. xor ah,ah ;AN000; ax = maxp
  394. cmp psdata_seg:$P_ORDINAL,ax ;AC034; too many positional ?
  395. jae $P_Too_Many_Error ;AN000; if yes, set exit code to too many
  396. mov ax,psdata_seg:$P_ORDINAL ;AC034; see what the current ordinal
  397. shl ax,1 ;AN000; ax = ax*2
  398. inc bx ;AC035; add '2' to
  399. inc bx ;AC035; BX reg
  400. ;AN000; now bx points to 1st CONTROL
  401. ;(changed ;AC035;) add bx,2 ;AN000; now bx points to 1st CONTROL
  402. add bx,ax ;AN000; now bx points to specified CONTROL address
  403. mov bx,es:[bx] ;AN000; now bx points to specified CONTROL itself
  404. call $P_Chk_Pos_Control ;AN000; Do process for positional
  405. jmp short $P_Return_to_Caller ;AN000; and return to the caller
  406. $P_Too_Many_Error: ;AN000;
  407. mov psdata_seg:$P_RC,$P_Too_Many ;AC034; set exit code
  408. jmp short $P_Return_to_Caller ;AN000; and return to the caller
  409. ;
  410. $P_SW_Manager: ;AN000;
  411. mov al,es:[bx].$P_MaxP ;AN000; get maxp
  412. xor ah,ah ;AN000; ax = maxp
  413. inc ax ;AN000;
  414. shl ax,1 ;AN000; ax = (ax+1)*2
  415. add bx,ax ;AN000; now bx points to maxs
  416. mov cl,es:[bx] ;AN000;
  417. xor ch,ch ;AN000; cx = maxs
  418. or cx,cx ;AN000; at least one switch ?
  419. je $P_SW_Not_Found ;AN000;
  420. inc bx ;AN000; now bx points to 1st CONTROL address
  421. $P_SW_Mgr_Loop: ;AN000;
  422. push bx ;AN000;
  423. mov bx,es:[bx] ;AN000; bx points to Switch CONTROL itself
  424. call $P_Chk_SW_Control ;AN000; do process for switch
  425. pop bx ;AN000;
  426. jnc $P_Return_to_Caller ;AN000; if the CONTROL is for the switch, exit
  427. inc bx ;AC035; add '2' to
  428. inc bx ;AC035; BX reg
  429. ;AN000; else bx points to the next CONTROL
  430. ;(changed ;AC035;) add bx,2 ;AN000; else bx points to the next CONTROL
  431. loop $P_SW_Mgr_Loop ;AN000; and loop
  432. $P_SW_Not_Found: ;AN000;
  433. mov psdata_seg:$P_RC,$P_Not_In_SW ;AC034; here no CONTROL for the switch has
  434. jmp short $P_Return_to_Caller0 ;AN000; not been found, means error.
  435. ;
  436. $P_Key_Manager: ;AN000;
  437. mov al,es:[bx].$P_MaxP ;AN000; get maxp
  438. xor ah,ah ;AN000; ax = maxp
  439. inc ax ;AN000;
  440. shl ax,1 ;AN000; ax = (ax+1)*2
  441. add bx,ax ;AN000; now bx points to maxs
  442. mov al,es:[bx] ;AN000;
  443. xor ah,ah ;AN000; ax = maxs
  444. shl ax,1 ;AN000;
  445. inc ax ;AN000; ax = ax*2+1
  446. add bx,ax ;AN000; now bx points to maxk
  447. mov cl,es:[bx] ;AN000;
  448. xor ch,ch ;AN000; cx = maxk
  449. or cx,cx ;AN000; at least one keyword ?
  450. je $P_Key_Not_Found ;AN000;
  451. inc bx ;AN000; now bx points to 1st CONTROL
  452. $P_Key_Mgr_Loop: ;AN000;
  453. push bx ;AN000;
  454. mov bx,es:[bx] ;AN000; bx points to keyword CONTROL itself
  455. call $P_Chk_Key_Control ;AN000; do process for keyword
  456. pop bx ;AN000;
  457. jnc $P_Return_to_Caller ;AN000; if the CONTROL is for the keyword, exit
  458. inc bx ;AC035; add '2' to
  459. inc bx ;AC035; BX reg
  460. ;AN000; else bx points to the next CONTROL
  461. ;(changed ;AC035;) add bx,2 ;AN000; else bx points to the next CONTROL
  462. loop $P_Key_Mgr_Loop ;AN000; and loop
  463. $P_Key_Not_Found: ;AN000;
  464. mov psdata_seg:$P_RC,$P_Not_In_Key ;AC034; here no CONTROL for the keyword has
  465. $P_Return_to_Caller0: ;AN000; not been found, means error.
  466. ;(deleted ;AN024;) mov bx,es:[bx-2] ;AN000; (tm13) backup bx
  467. ;(deleted ;AN024;) mov al,$P_String ;AN000; Set
  468. ;(deleted ;AN024;) mov ah,$P_No_Tag ;AN000; result
  469. ;(deleted ;AN024;) call $P_Fill_Result ;AN000; buffer
  470. $P_Return_to_Caller: ;AN000;
  471. pop bp ;AN000;
  472. pop di ;AN000;
  473. pop bx ;AN000;
  474. mov cx,psdata_seg:$P_Ordinal ;AC034; return next ordinal
  475. mov ax,psdata_seg:$P_RC ;AC034; return exit code
  476. mov si,psdata_seg:$P_SI_Save ;AC034; return next operand pointer
  477. mov dx,psdata_seg:$P_DX ;AC034; return result buffer address
  478. mov bl,psdata_seg:$P_Terminator ;AC034; return delimiter code found
  479. $P_Single_Exit: ;AN000;
  480. clc ;AN000;
  481. ret ;AN000;
  482. SysParse endp ;AN000;
  483. PAGE ;AN000;
  484. ;***********************************************************************
  485. ; $P_Chk_Pos_Control
  486. ;
  487. ; Function: Parse CONTROL block for a positional
  488. ;
  489. ; Input: ES:BX -> CONTROL block
  490. ; psdata_seg:SI -> $P_STRING_BUF
  491. ;
  492. ; Output: None
  493. ;
  494. ; Use: $P_Fill_Result, $P_Check_Match_Flags
  495. ;
  496. ; Vars: $P_Ordinal(W), $P_RC(W)
  497. ;***********************************************************************
  498. $P_Chk_Pos_Control proc ;AN000;
  499. push ax ;AN000;
  500. mov ax,es:[bx].$P_Match_Flag ;AN000;
  501. test ax,$P_Repeat ;AN000; repeat allowed ?
  502. jne $P_CPC00 ;AN000; then do not increment ORDINAL
  503. inc psdata_seg:$P_ORDINAL ;AC034; update the ordinal
  504. $P_CPC00: ;AN000;
  505. cmp byte ptr psdata_seg:[si],$P_NULL ;AN000; no data ?
  506. jne $P_CPC01 ;AN000;
  507. test ax,$P_Optional ;AN000; yes, then is it optional ?
  508. jne $P_CPC02 ;AN000;
  509. mov psdata_seg:$P_RC,$P_Op_Missing ;AC034; no, then error 3/17/87
  510. jmp short $P_CPC_Exit ;AN000;
  511. $P_CPC02: ;AN000;
  512. push ax ;AN000;
  513. mov al,$P_String ;AN000; if it is optional return NULL
  514. mov ah,$P_No_Tag ;AN000; no item tag indication
  515. call $P_Fill_Result ;AN000;
  516. pop ax ;AN000;
  517. jmp short $P_CPC_Exit ;AN000;
  518. $P_CPC01: ;AN000;
  519. call $P_Check_Match_Flags ;AN000;
  520. $P_CPC_Exit: ;AN000;
  521. pop ax ;AN000;
  522. ret ;AN000;
  523. $P_Chk_Pos_Control endp ;AN000;
  524. PAGE ;AN000;
  525. ;***********************************************************************
  526. ; $P_Chk_Key_Control
  527. ;
  528. ; Function: Parse CONTROL block for a keyword
  529. ;
  530. ; Input: ES:BX -> CONTROL block
  531. ; psdata_seg:SI -> $P_STRING_BUF
  532. ;
  533. ; Output: CY = 1 : not match
  534. ;
  535. ; Use: $P_Fill_Result, $P_Search_KEYorSW, $P_Check_Match_Flags
  536. ;
  537. ; Vars: $P_RC(W), $P_SaveSI_Cmpx(W), $P_KEYorSW_Ptr(R), $P_Flags(W)
  538. ;***********************************************************************
  539. $P_Chk_Key_Control proc ;AN000;
  540. IF KeySW ;AN000;(Check if keyword is supported)
  541. or psdata_seg:$P_Flags2,$P_Key_Cmp ;AC034; Indicate keyword for later string comparison
  542. call $P_Search_KEYorSW ;AN000; Search the keyword in the CONTROL block
  543. jc $P_Chk_Key_Err0 ;AN000; not found, then try next CONTROL
  544. and psdata_seg:$P_Flags2,0ffh-$P_Key_Cmp ;AC034; reset the indicator previously set
  545. ;
  546. push ax ;AN000; keyword=
  547. mov ax,psdata_seg:$P_KEYorSW_Ptr ;AC034; ^ ^
  548. sub ax,si ;AN000; SI KEYorSW
  549. add psdata_seg:$P_SaveSI_Cmpx,ax ;AC034; update for complex, quoted or file spec.
  550. pop ax ;AN000;
  551. ;
  552. mov si,psdata_seg:$P_KEYorSW_Ptr ;AC034; set si just after equal char
  553. cmp byte ptr psdata_seg:[si],$P_NULL ;AN000; any data after equal ?
  554. je $P_Chk_Key_Err1 ;AN000; if no, syntax error
  555. call $P_Check_Match_Flags ;AN000; else, process match flags
  556. clc ;AN000;
  557. jmp short $P_Chk_Key_Exit ;AN000;
  558. $P_Chk_Key_Err0: ;AN000;
  559. stc ;AN000; not found in keyword synonym list
  560. jmp short $P_Chk_Key_Exit ;AN000;
  561. $P_Chk_Key_Err1: ;AN000;
  562. mov psdata_seg:$P_RC,$P_Syntax ;AC034; no parameter is not specified after "="
  563. $P_Chk_Key_ErrExit: ;AN000;
  564. push ax ;AN000;
  565. mov al,$P_String ;AN000; set
  566. mov ah,$P_No_Tag ;AN000; result
  567. call $P_Fill_Result ;AN000; buffer
  568. pop ax ;AN000;
  569. clc ;AN000;
  570. $P_Chk_Key_Exit: ;AN000;
  571. ret ;AN000;
  572. ELSE ;AN000;(of IF KeySW)
  573. stc ;AN000;this logic works when the KeySW
  574. ret ;AN000;is reset.
  575. ENDIF ;AN000;(of KeySW)
  576. $P_Chk_Key_Control endp ;AN000;
  577. PAGE ;AN000;
  578. ;***********************************************************************
  579. IF KeySW+SwSW ;AN000;(Check if keyword or switch is supported)
  580. ; $P_Search_KEYorSW:
  581. ;
  582. ; Function: Seach specified keyword or switch from CONTROL
  583. ;
  584. ; Input: ES:BX -> CONTROL block
  585. ; psdata_seg:SI -> $P_STRING_BUF
  586. ;
  587. ; Output: CY = 1 : not match
  588. ;
  589. ; Use: $P_String_Comp, $P_MoveBP_NUL, $P_Found_SYNONYM
  590. ;***********************************************************************
  591. $P_Search_KEYorSW proc ;AN000;
  592. push bp ;AN000;
  593. push cx ;AN000;
  594. mov cl,es:[bx].$P_nid ;AN000; Get synonym count
  595. xor ch,ch ;AN000; and set it to cx
  596. or cx,cx ;AN000; No synonyms specified ?
  597. je $P_KEYorSW_Not_Found ;AN000; then indicate not found by CY
  598. lea bp,es:[bx].$P_KEYorSW ;AN000; BP points to the 1st synonym
  599. $P_KEYorSW_Loop: ;AN000;
  600. call $P_String_Comp ;AN000; compare string in buffer w/ the synonym
  601. jnc $P_KEYorSW_Found ;AN000; If match, set it to synonym pointer
  602. call $P_MoveBP_NUL ;AN000; else, bp points to the next string
  603. loop $P_KEYorSW_Loop ;AN000; loop nid times
  604. $P_KEYorSW_Not_Found: ;AN000;
  605. stc ;AN000; indicate not found in synonym list
  606. jmp short $P_KEYorSW_Exit ;AN000; and exit
  607. $P_KEYorSW_Found: ;AN000;
  608. mov psdata_seg:$P_Found_SYNONYM,bp ;AC034; set synonym pointer
  609. clc ;AN000; indicate found
  610. $P_KEYorSW_Exit: ;AN000;
  611. pop cx ;AN000;
  612. pop bp ;AN000;
  613. ret ;AN000;
  614. $P_Search_KEYorSW endp ;AN000;
  615. ;***********************************************************************
  616. ; $P_MoveBP_NUL
  617. ;***********************************************************************
  618. $P_MoveBP_NUL proc ;AN000;
  619. $P_MBP_Loop: ;AN000;
  620. cmp byte ptr es:[bp],$P_NULL ;AN000; Increment BP that points
  621. je $P_MBP_Exit ;AN000; to the synomym list
  622. inc bp ;AN000; until
  623. jmp short $P_MBP_Loop ;AN000; NULL encountered.
  624. $P_MBP_Exit: ;AN000;
  625. inc bp ;AN000; bp points to next to NULL
  626. ret ;AN000;
  627. $P_MoveBP_NUL endp ;AN000;
  628. ENDIF ;AN000;(of KeySW+SwSW)
  629. PAGE ;AN000;
  630. ;***********************************************************************
  631. ; $P_Chk_SW_Control
  632. ;
  633. ; Function: Parse CONTROL block for a switch
  634. ;
  635. ; Input: ES:BX -> CONTROL block
  636. ; psdata_seg:SI -> $P_STRING_BUF
  637. ;
  638. ; Output: CY = 1 : not match
  639. ;
  640. ; Use: $P_Fill_Result, $P_Search_KEYorSW, $P_Check_Match_Flags
  641. ;
  642. ; Vars: $P_SaveSI_Cmpx(W), $P_KEYorSW_Ptr(R), $P_Flags(W)
  643. ;***********************************************************************
  644. $P_Chk_SW_Control proc ;AN000;
  645. IF SwSW ;AN000;(Check if switch is supported)
  646. or psdata_seg:$P_Flags2,$P_Sw_Cmp ;AC034; Indicate switch for later string comparison
  647. call $P_Search_KEYorSW ;AN000; Search the switch in the CONTROL block
  648. jc $P_Chk_SW_Err0 ;AN000; not found, then try next CONTROL
  649. and psdata_seg:$P_Flags2,0ffh-$P_Sw_Cmp ;AC034; reset the indicator previously set
  650. ;
  651. push ax ;AN000; /switch:
  652. mov ax,psdata_seg:$P_KEYorSW_Ptr ;AC034; ^ ^
  653. sub ax,si ;AN000; SI KEYorSW
  654. add psdata_seg:$P_SaveSI_Cmpx,ax ;AC034; update for complex list
  655. pop ax ;AN000;
  656. ;
  657. mov si,psdata_seg:$P_KEYorSW_Ptr ;AC034; set si at the end or colon
  658. cmp byte ptr psdata_seg:[si],$P_NULL ;AN000; any data after colon
  659. jne $P_CSW00 ;AN000; if yes, process match flags
  660. cmp byte ptr psdata_seg:[si-1],$P_Colon ;AN000; if no, the switch terminated by colon ?
  661. jne $P_Chk_if_data_required ;AN000; if yes,
  662. mov psdata_seg:$P_RC,$P_Syntax ;AC034; return syntax error
  663. jmp short $P_Chk_SW_Exit ;AN000;
  664. $P_Chk_if_data_required: ;AN018; no data, no colon
  665. cmp es:[bx].$P_Match_Flag,0 ;AN018; should have data? zero match flag means switch followed by nothing is OK
  666. je $P_Chk_SW_Exit ;AN018; match flags not zero so should have something if optional bit is not on
  667. test es:[bx].$P_Match_Flag,$P_Optional ;AN019; see if no value is valid
  668. jnz $P_Chk_SW_Exit ;AN019; if so, then leave, else yell
  669. mov psdata_seg:$P_RC,$P_Op_Missing ;AC034; return required operand missing
  670. jmp short $P_Chk_SW_Exit ;AN018;
  671. $P_CSW00: ;AN000;
  672. call $P_Check_Match_Flags ;AN000; process match flag
  673. clc ;AN000; indicate match
  674. jmp short $P_Chk_SW_Single_Exit ;AN000;
  675. $P_Chk_SW_Err0: ;AN000;
  676. stc ;AN000; not found in switch synonym list
  677. jmp short $P_Chk_SW_Single_Exit ;AN000;
  678. $P_Chk_SW_Exit: ;AN000;
  679. push ax ;AN000;
  680. mov al,$P_String ;AN000; set
  681. mov ah,$P_No_Tag ;AN000; result
  682. call $P_Fill_Result ;AN000; buffer
  683. pop ax ;AN000;
  684. clc ;AN000;
  685. $P_Chk_SW_Single_Exit: ;AN000;
  686. ret ;AN000;
  687. ELSE ;AN000;(of IF SwSW)
  688. stc ;AN000; this logic works when the SwSW
  689. ret ;AN000; is reset.
  690. ENDIF ;AN000;(of SwSW)
  691. $P_Chk_SW_Control endp ;AN000;
  692. PAGE ;AN000;
  693. ;***********************************************************************
  694. ; $P_Fill_Result
  695. ;
  696. ; Function: Fill the result buffer
  697. ;
  698. ; Input: AH = Item tag
  699. ; AL = type
  700. ; AL = 1: CX,DX has 32bit number (CX = high)
  701. ; AL = 2: DX has index(offset) into value list
  702. ; AL = 6: DL has driver # (1-A, 2-B, ... , 26 - Z)
  703. ; AL = 7: DX has year, CL has month and CH has date
  704. ; AL = 8: DL has hours, DH has minutes, CL has secondsn,
  705. ; amd CH has hundredths
  706. ; AL = else: psdata_seg:SI points to returned string buffer
  707. ; ES:BX -> CONTROL block
  708. ;
  709. ; Output: None
  710. ;
  711. ; Use: $P_Do_CAPS_String, $P_Remove_Colon, $P_Found_SYNONYM
  712. ;
  713. ; Vars: $P_DX(W)
  714. ;***********************************************************************
  715. $P_Fill_Result proc ;AN000;
  716. push di ;AN000;
  717. mov di,es:[bx].$P_Result_Buf ;AN000; di points to result buffer
  718. mov psdata_seg:$P_DX,di ;AC034; set returned result address
  719. mov es:[di].$P_Type,al ;AN000; store type
  720. mov es:[di].$P_Item_Tag,ah ;AN000; store item tag
  721. push ax ;AN000;
  722. mov ax,psdata_seg:$P_Found_SYNONYM ;AC034; if yes,
  723. mov es:[di].$P_SYNONYM_Ptr,ax ;AN000; then set it to the result
  724. pop ax ;AN000;
  725. $P_RLT04: ;AN000;
  726. cmp al,$P_Number ;AN000; if number
  727. jne $P_RLT00 ;AN000;
  728. $P_RLT02: ;AN000;
  729. mov word ptr es:[di].$P_Picked_Val,dx ;AN000; then store 32bit
  730. mov word ptr es:[di+2].$P_Picked_Val,cx ;AN000; number
  731. jmp short $P_RLT_Exit ;AN000;
  732. $P_RLT00: ;AN000;
  733. cmp al,$P_List_Idx ;AN000; if list index
  734. jne $P_RLT01 ;AN000;
  735. mov word ptr es:[di].$P_Picked_Val,dx ;AN000; then store list index
  736. jmp short $P_RLT_Exit ;AN000;
  737. $P_RLT01: ;AN000;
  738. cmp al,$P_Date_F ;AN000; Date format ?
  739. je $P_RLT02 ;AN000;
  740. cmp al,$P_Time_F ;AN000; Time format ?
  741. je $P_RLT02 ;AN000;
  742. ;
  743. cmp al,$P_Drive ;AN000; drive format ?
  744. jne $P_RLT03 ;AN000;
  745. mov byte ptr es:[di].$P_Picked_Val,dl ;AN000; store drive number
  746. jmp short $P_RLT_Exit ;AN000;
  747. $P_RLT03: ;AN000;
  748. cmp al,$P_Complex ;AN000; complex format ?
  749. jne $P_RLT05 ;AN000;
  750. mov ax,psdata_seg:$P_SaveSI_Cmpx ;AC034; then get pointer in command buffer
  751. inc ax ;AN000; skip left Parentheses
  752. mov word ptr es:[di].$P_Picked_Val,ax ;AN000; store offset
  753. mov word ptr es:[di+2].$P_Picked_Val,ds ;AN000; store segment
  754. jmp short $P_RLT_Exit ;AN000;
  755. $P_RLT05: ;AN000;
  756. ;------------------------ AL = 3, 5, or 9
  757. mov word ptr es:[di].$P_Picked_Val,si ;AN000; store offset of STRING_BUF
  758. ;(replaced ;AN031;) mov word ptr es:[di+word].$P_Picked_Val,cs ;AN000; store segment of STRING_BUF
  759. mov word ptr es:[di+2].$P_Picked_Val,Psdata_Seg ;AN031; store segment of STRING_BUF
  760. ;
  761. push ax ;AN000;
  762. test byte ptr es:[bx].$P_Function_Flag,$P_CAP_File ;AN000; need CAPS by file table?
  763. je $P_RLT_CAP00 ;AN000;
  764. mov al,$P_DOSTBL_File ;AN000; use file upper case table
  765. jmp short $P_RLT_CAP02 ;AN000;
  766. $P_RLT_CAP00: ;AN000;
  767. test byte ptr es:[bx].$P_Function_Flag,$P_CAP_Char ;AN000; need CAPS by char table ?
  768. je $P_RLT_CAP01 ;AN000;
  769. mov al,$P_DOSTBL_Char ;AN000; use character upper case table
  770. $P_RLT_CAP02: ;AN000;
  771. call $P_Do_CAPS_String ;AN000; process CAPS along the table
  772. $P_RLT_CAP01: ;AN000;
  773. pop ax ;AN000;
  774. test byte ptr es:[bx].$P_Function_Flag,$P_Rm_Colon ;AN000; removing colon at end ?
  775. je $P_RLT_Exit ;AN000;
  776. call $P_Remove_Colon ;AN000; then process it.
  777. $P_RLT_Exit: ;AN000;
  778. pop di ;AN000;
  779. ret ;AN000;
  780. $P_Fill_Result endp ;AN000;
  781. PAGE ;AN000;
  782. ;***********************************************************************
  783. ; $P_Check_Match_Flags
  784. ;
  785. ; Function: Check the mutch_flags and make the exit code and set the
  786. ; result buffer
  787. ;
  788. ; Check for types in this order:
  789. ; Complex
  790. ; Date
  791. ; Time
  792. ; Drive
  793. ; Filespec
  794. ; Quoted String
  795. ; Simple String
  796. ;
  797. ; Input: psdata_seg:SI -> $P_STRING_BUF
  798. ; ES:BX -> CONTROL block
  799. ;
  800. ; Output: None
  801. ;
  802. ; Use: $P_Value, P$_SValue, $P_Simple_String, $P_Date_Format
  803. ; $P_Time_Format, $P_Complex_Format, $P_File_Foemat
  804. ; $P_Drive_Format
  805. ;***********************************************************************
  806. $P_Check_Match_Flags proc ;AN000;
  807. mov psdata_seg:$P_err_flag,$P_NULL ;AN033;AC034;; clear filespec error flag.
  808. push ax ;AN000;
  809. mov ax,es:[bx].$P_Match_Flag ;AN000; load match flag(16bit) to ax
  810. or ax,ax ;AC035; test ax for zero
  811. ;(changed ;AC035;) cmp ax,0 ;AN000; (tm12)
  812. jne $P_Mat ;AN000; (tm12)
  813. push ax ;AN000; (tm12)
  814. push bx ;AN000; (tm12)
  815. push dx ;AN000; (tm12)
  816. push di ;AN000; (tm12)
  817. mov psdata_seg:$P_RC,$P_Syntax ;AC034; (tm12)
  818. mov ah,$P_No_Tag ;AN000; (tm12)
  819. mov al,$P_String ;AN000; (tm12)
  820. call $P_Fill_Result ;AN000; (tm12)
  821. pop di ;AN000; (tm12)
  822. pop dx ;AN000; (tm12)
  823. pop bx ;AN000; (tm12)
  824. pop ax ;AN000; (tm12)
  825. jmp short $P_Bridge ;AC035; (tm12)
  826. $P_Mat: ;AN000; (tm12)
  827. IF CmpxSW ;AN000;(Check if complex item is supported)
  828. test ax,$P_Cmpx_S ;AN000; Complex string
  829. je $P_Match01 ;AN000;
  830. mov psdata_seg:$P_RC,$P_No_Error ;AC034; assume no error
  831. call $P_Complex_Format ;AN000; do process
  832. cmp psdata_seg:$P_RC,$P_Syntax ;AC034; if error, examine the next type
  833. jne $P_Bridge ;AN000;
  834. $P_Match01: ;AN000;
  835. ENDIF ;AN000;(of CmpxSW)
  836. IF DateSW ;AN000;(Check if date format is supported)
  837. test ax,$P_Date_S ;AN000; Date string
  838. je $P_Match02 ;AN000;
  839. mov psdata_seg:$P_RC,$P_No_Error ;AC034; assume no error
  840. call $P_Date_Format ;AN000; do process
  841. cmp psdata_seg:$P_RC,$P_Syntax ;AC034; if error, examine the next type
  842. jne $P_Bridge ;AN000;
  843. $P_Match02: ;AN000;
  844. ENDIF ;AN000;(of DateSW)
  845. IF TimeSW ;AN000;(Check if time format is supported)
  846. test ax,$P_Time_S ;AN000; Time string
  847. je $P_Match03 ;AN000;
  848. mov psdata_seg:$P_RC,$P_No_Error ;AC034; assume no error
  849. call $P_Time_Format ;AN000; do process
  850. cmp psdata_seg:$P_RC,$P_Syntax ;AC034; if error, examine the next type
  851. ; je $P_Match03 ;AN000:
  852. jne $P_Bridge ;AN000; (tm09)
  853. ENDIF ;AN000;(of TimeSW) (tm04)
  854. jmp short $P_Match03 ;AN025; (tm09)
  855. $P_Bridge: ;AN000;
  856. ; jmp short $P_Match_Exit (tm02)
  857. jmp $P_Match_Exit ;AN000; (tm02)
  858. $P_Match03: ;AN000;
  859. ; ENDIF ;AN000;(of TimeSW) (tm04)
  860. IF NumSW ;AN000;(Check if numeric value is supported)
  861. test ax,$P_Num_Val ;AN000; Numeric value
  862. je $P_Match04 ;AN000;
  863. mov psdata_seg:$P_RC,$P_No_Error ;AC034; assume no error
  864. call $P_Value ;AN000; do process
  865. cmp psdata_seg:$P_RC,$P_Syntax ;AC034; if error, examine the next type
  866. jne $P_Match_Exit ;AN000;
  867. $P_Match04: ;AN000;
  868. test ax,$P_SNUM_Val ;AN000; Signed numeric value
  869. je $P_Match05 ;AN000;
  870. mov psdata_seg:$P_RC,$P_No_Error ;AC034; assume no error
  871. call $P_SValue ;AN000; do process
  872. cmp psdata_seg:$P_RC,$P_Syntax ;AC034; if error, examine the next type
  873. jne $P_Match_Exit ;AN000;
  874. $P_Match05: ;AN000;
  875. ENDIF ;AN000;(of NumSW)
  876. IF DrvSW ;AN000;(Check if drive only is supported)
  877. test ax,$P_Drv_Only ;AN000; Drive only
  878. je $P_Match06 ;AN000;
  879. mov psdata_seg:$P_RC,$P_No_Error ;AC034; assume no error
  880. call $P_File_Format ;AN000; 1st, call file format
  881. call $P_Drive_Format ;AN000; check drive format, next
  882. cmp psdata_seg:$P_RC,$P_Syntax ;AC034; if error, examinee the next type
  883. jne $P_Match_Exit ;AN000;
  884. $P_Match06: ;AN000;
  885. ENDIF ;AN000;(of DrvSW)
  886. IF FileSW ;AN000;(Check if file spec is supported)
  887. test ax,$P_File_Spc ;AN000; File spec
  888. je $P_Match07 ;AN000;
  889. mov psdata_seg:$P_RC,$P_No_Error ;AC034; assume no error
  890. call $P_File_Format ;AN000; do process
  891. cmp psdata_seg:$P_RC,$P_Syntax ;AC034; if error, examine the next type
  892. jne $P_Match_Exit ;AN000;
  893. $P_Match07: ;AN000;
  894. ENDIF ;AN000;(of FileSW)
  895. IF QusSW ;AN000;(Check if quoted string is supported)
  896. test ax,$P_Qu_String ;AN000; Quoted string
  897. je $P_Match08 ;AN000;
  898. mov psdata_seg:$P_RC,$P_No_Error ;AC034; assume no error
  899. call $P_Quoted_Format ;AN000; do process
  900. cmp psdata_seg:$P_RC,$P_Syntax ;AC034; if error, examine the next type
  901. jne $P_Match_Exit ;AN000;
  902. $P_Match08: ;AN000;
  903. ENDIF ;AN000;(of QusSW)
  904. test ax,$P_Simple_S ;AN000; Simple string
  905. je $P_Match09 ;AN000;
  906. mov psdata_seg:$P_RC,$P_No_Error ;AC034; assume no error
  907. call $P_Simple_String ;AN000; do process
  908. ;;;; cmp psdata_seg:$P_RC,$P_Syntax ;AC034; These two lines will be alive
  909. ;;;; jne $P_Match_Exit ;when extending the match_flags.
  910. $P_Match09: ;AN000;
  911. $P_Match_Exit: ;AN000;
  912. cmp psdata_seg:$P_err_flag,$P_error_filespec ;AC034; bad filespec ?
  913. jne $P_Match2_Exit ;AN033; no, continue
  914. cmp psdata_seg:$P_RC,$P_No_Error ;AN033;AC034;; check for other errors ?
  915. jne $P_Match2_Exit ;AN033; no, continue
  916. mov psdata_seg:$P_RC,$P_Syntax ;AN033;AC034;; set error flag
  917. $P_Match2_Exit: ;AN033;
  918. pop ax ;AN000;
  919. ret ;AN000;
  920. $P_Check_Match_Flags endp ;AN000;
  921. PAGE ;AN000;
  922. ;***********************************************************************
  923. ; $P_Remove_Colon;
  924. ;
  925. ; Function: Remove colon at end
  926. ;
  927. ; Input: psdata_seg:SI points to string buffer to be examineed
  928. ;
  929. ; Output: None
  930. ;
  931. ; Use: $P_Chk_DBCS
  932. ;***********************************************************************
  933. $P_Remove_Colon proc ;AN000;
  934. push ax ;AN000;
  935. push si ;AN000;
  936. $P_RCOL_Loop: ;AN000;
  937. mov al,psdata_seg:[si] ;AN000; get character
  938. or al,al ;AN000; end of string ?
  939. je $P_RCOL_Exit ;AN000; if yes, just exit
  940. cmp al,$P_Colon ;AN000; is it colon ?
  941. jne $P_RCOL00 ;AN000;
  942. cmp byte ptr psdata_seg:[si+byte],$P_NULL ;AN000; if so, next is NULL ?
  943. jne $P_RCOL00 ;AN000; no, then next char
  944. mov byte ptr psdata_seg:[si],$P_NULL ;AN000; yes, remove colon
  945. jmp short $P_RCOL_Exit ;AN000; and exit.
  946. $P_RCOL00: ;AN000;
  947. call $P_Chk_DBCS ;AN000; if not colon, then check if
  948. jnc $P_RCOL01 ;AN000; DBCS leading byte.
  949. inc si ;AN000; if yes, skip trailing byte
  950. $P_RCOL01: ;AN000;
  951. inc si ;AN000; si points to next byte
  952. jmp short $P_RCOL_Loop ;AN000; loop until NULL encountered
  953. $P_RCOL_Exit: ;AN000;
  954. pop si ;AN000;
  955. pop ax ;AN000;
  956. ret ;AN000;
  957. $P_Remove_Colon endp ;AN000;
  958. PAGE ;AN000;
  959. ;***********************************************************************
  960. ; $P_Do_CAPS_String;
  961. ;
  962. ; Function: Perform capitalization along with the file case map table
  963. ; or character case map table.
  964. ;
  965. ; Input: AL = 2 : Use character table
  966. ; AL = 4 : Use file table
  967. ; psdata_seg:SI points to string buffer to be capitalized
  968. ;
  969. ; Output: None
  970. ;
  971. ; Use: $P_Do_CAPS_Char, $P_Chk_DBCS
  972. ;***********************************************************************
  973. $P_Do_CAPS_String proc ;AN000;
  974. push si ;AN000;
  975. push dx ;AN000;
  976. mov dl,al ;AN000; save info id
  977. $P_DCS_Loop: ;AN000;
  978. mov al,psdata_seg:[si] ;AN000; load charater and
  979. call $P_Chk_DBCS ;AN000; check if DBCS leading byte
  980. jc $P_DCS00 ;AN000; if yes, do not need CAPS
  981. or al,al ;AN000; end of string ?
  982. je $P_DCS_Exit ;AN000; then exit.
  983. call $P_Do_CAPS_Char ;AN000; Here a SBCS char need to be CAPS
  984. mov psdata_seg:[si],al ;AN000; stored upper case char to buffer
  985. jmp short $P_DCS01 ;AN000; process nexit
  986. $P_DCS00: ;AN000;
  987. inc si ;AN000; skip DBCS leading and trailing byte
  988. $P_DCS01: ;AN000;
  989. inc si ;AN000; si point to next byte
  990. jmp short $P_DCS_Loop ;AN000; loop until NULL encountered
  991. $P_DCS_Exit: ;AN000;
  992. pop dx ;AN000;
  993. pop si ;AN000;
  994. ret ;AN000;
  995. $P_Do_CAPS_String endp ;AN000;
  996. PAGE ;AN000;
  997. ;***********************************************************************
  998. ; $P_Do_CAPS_Char;
  999. ;
  1000. ; Function: Perform capitalization along with the file case map table
  1001. ; or character case map table.
  1002. ;
  1003. ; Input: DL = 2 : Use character table
  1004. ; DL = 4 : Use file table
  1005. ; AL = character to be capitalized
  1006. ;
  1007. ; Output: None
  1008. ;
  1009. ; Use: INT 21h /w AH=65h
  1010. ;***********************************************************************
  1011. $P_Do_CAPS_Char proc ;AN000;
  1012. cmp al,$P_ASCII80 ;AN000; need upper case table ?
  1013. jae $P_DCC_Go ;AN000;
  1014. cmp al,"a" ;AN000; if no,
  1015. jb $P_CAPS_Ret ;AN000; check if "a" <= AL <= "z"
  1016. cmp al,"z" ;AN000;
  1017. ja $P_CAPS_Ret ;AN000; if yes, make CAPS
  1018. and al,$P_Make_Upper ;AN000; else do nothing.
  1019. jmp short $P_CAPS_Ret ;AN000;
  1020. $P_DCC_Go: ;AN000;
  1021. push bx ;AN000;
  1022. push es ;AN000;
  1023. push di ;AN000;
  1024. IF CAPSW ;AN000;(Check if uppercase conversion is supported)
  1025. lea di,psdata_seg:$P_File_CAP_Ptr ;AC034;
  1026. cmp dl,$P_DOSTBL_File ;AN000; Use file CAPS table ?
  1027. je $P_DCC00 ;AN000;
  1028. ENDIF ;AN000;(of CAPSW)
  1029. lea di,psdata_seg:$P_Char_CAP_Ptr ;AC034; or use char CAPS table ?
  1030. $P_DCC00: ;AN000;
  1031. cmp psdata_seg:[di],dl ;AN000; already got table address ?
  1032. je $P_DCC01 ;AN000; if no,
  1033. ;In this next section, ES will be used to pass a 5 byte workarea to INT 21h,
  1034. ; the GET COUNTYRY INFO call. This usage of ES is required by the function
  1035. ; call, regardless of what base register is currently be defined as PSDATA_SEG.
  1036. ;BASESW EQU 0 means that ES is the psdata_seg reg.
  1037. IFDEF BASESW ;AN037; If BASESW has been defined, and
  1038. IFE BASESW ;AN037; If ES is psdata base
  1039. push PSDATA_SEG ;AN037; save current base reg
  1040. ENDIF ;AN037;
  1041. ENDIF ;AN037;
  1042. push ax ;AN000; get CAPS table thru DOS call
  1043. push cx ;AN000;
  1044. push dx ;AN000;
  1045. push PSDATA_SEG ;AC036; pass current base seg into
  1046. ;(Note: this used to push CS. BUG...
  1047. pop es ;AN000; ES reg, required for
  1048. ;get extended country information
  1049. mov ah,$P_DOS_Get_TBL ;AN000; get extended CDI
  1050. mov al,dl ;AN000; upper case table
  1051. mov bx,$P_DOSTBL_Def ;AN000; get active CON
  1052. mov cx,$P_DOSTBL_BL ;AN000; buffer length
  1053. mov dx,$P_DOSTBL_Def ;AN000; get for default code page
  1054. ;DI already set to point to buffer
  1055. int 21h ;AN000; es:di point to buffer that
  1056. ;now has been filled in with info
  1057. pop dx ;AN000;
  1058. pop cx ;AN000;
  1059. pop ax ;AN000;
  1060. IFDEF BASESW ;AN037; If BASESW has been defined, and
  1061. IFE BASESW ;AN037; If ES is psdata base
  1062. pop PSDATA_SEG ;AN037; restore current base reg
  1063. ENDIF ;AN037;
  1064. ENDIF ;AN037;
  1065. $P_DCC01: ;AN000;
  1066. ;In this next section, ES will be used as the base of the XLAT table, provided
  1067. ; by the previous GET COUNTRY INFO DOS call. This usage of ES is made
  1068. ; regardless of which base reg is currently the PSDATA_SEG reg.
  1069. IFDEF BASESW ;AN037; If BASESW has been defined, and
  1070. IFE BASESW ;AN037; If ES is psdata base
  1071. push PSDATA_SEG ;AN037; save current base reg
  1072. ENDIF ;AN037;
  1073. ENDIF ;AN037;
  1074. mov bx,psdata_seg:[di+$P_DOS_TBL_Off] ;AN000; get offset of table
  1075. mov es,psdata_seg:[di+$P_DOS_TBL_Seg] ;AN000; get segment of table
  1076. inc bx ;AC035; add '2' to
  1077. inc bx ;AC035; BX reg
  1078. ;AN000; skip length field
  1079. ;(changed ;AN035;) add bx,word ;AN000; skip length field
  1080. sub al,$P_ASCII80 ;AN000; make char to index
  1081. xlat es:[bx] ;AN000; perform case map
  1082. IFDEF BASESW ;AN037; If BASESW has been defined, and
  1083. IFE BASESW ;AN037; If ES is psdata base
  1084. pop PSDATA_SEG ;AN037; restore current base reg
  1085. ENDIF ;AN037;
  1086. ENDIF ;AN037;
  1087. pop di ;AN000;
  1088. pop es ;AN000;
  1089. pop bx ;AN000;
  1090. $P_CAPS_Ret: ;AN000;
  1091. ret ;AN000;
  1092. $P_Do_CAPS_Char endp ;AN000;
  1093. PAGE ;AN000;
  1094. ;***********************************************************************
  1095. IF NumSW ;AN000;(Check if numeric value is supported)
  1096. ; $P_Value / $P_SValue
  1097. ;
  1098. ; Function: Make 32bit value from psdata_seg:SI and see value list
  1099. ; and make result buffer.
  1100. ; $P_SValue is an entry point for the signed value
  1101. ; and this will simply call $P_Value after the handling
  1102. ; of the sign character, "+" or "-"
  1103. ;
  1104. ; Input: psdata_seg:SI -> $P_STRING_BUF
  1105. ; ES:BX -> CONTROL block
  1106. ;
  1107. ; Output: None
  1108. ;
  1109. ; Use: $P_Fill_Result, $P_Check_OVF
  1110. ;
  1111. ; Vars: $P_RC(W), $P_Flags(RW)
  1112. ;***********************************************************************
  1113. $P_SValue proc ;AN000; when signed value here
  1114. push ax ;AN000;
  1115. or psdata_seg:$P_Flags2,$P_Signed ;AC034; indicate a signed numeric
  1116. and psdata_seg:$P_Flags2,0ffh-$P_Neg ;AC034; assume positive value
  1117. mov al,psdata_seg:[si] ;AN000; get sign
  1118. cmp al,$P_Plus ;AN000; "+" ?
  1119. je $P_SVal00 ;AN000;
  1120. cmp al,$P_Minus ;AN000; "-" ?
  1121. jne $P_Sval01 ;AN000; else
  1122. or psdata_seg:$P_Flags2,$P_Neg ;AC034; set this is negative value
  1123. $P_SVal00: ;AN000;
  1124. inc si ;AN000; skip sign char
  1125. $P_Sval01: ;AN000;
  1126. call $P_Value ;AN000; and process value
  1127. pop ax ;AN000;
  1128. ret ;AN000;
  1129. $P_SValue endp ;AN000;
  1130. ;***********************************************************************
  1131. $P_Value proc ;AN000;
  1132. push ax ;AN000;
  1133. push cx ;AN000;
  1134. push dx ;AN000;
  1135. push si ;AN000;
  1136. xor cx,cx ;AN000; cx = higher 16 bits
  1137. xor dx,dx ;AN000; dx = lower 16 bits
  1138. push bx ;AN000; save control pointer
  1139. $P_Value_Loop: ;AN000;
  1140. mov al,psdata_seg:[si] ;AN000; get character
  1141. or al,al ;AN000; end of line ?
  1142. je $P_Value00 ;AN000;
  1143. call $P_0099 ;AN000; make asc(0..9) to bin(0..9)
  1144. jc $P_Value_Err0 ;AN000;
  1145. xor ah,ah ;AN000;
  1146. mov bp,ax ;AN000; save binary number
  1147. shl dx,1 ;AN000; to have 2*x
  1148. rcl cx,1 ;AN000; shift left w/ carry
  1149. call $P_Check_OVF ;AN000; Overflow occurred ?
  1150. jc $P_Value_Err0 ;AN000; then error, exit
  1151. mov bx,dx ;AN000; save low(2*x)
  1152. mov ax,cx ;AN000; save high(2*x)
  1153. shl dx,1 ;AN000; to have 4*x
  1154. rcl cx,1 ;AN000; shift left w/ carry
  1155. call $P_Check_OVF ;AN000; Overflow occurred ?
  1156. jc $P_Value_Err0 ;AN000; then error, exit
  1157. shl dx,1 ;AN000; to have 8*x
  1158. rcl cx,1 ;AN000; shift left w/ carry
  1159. call $P_Check_OVF ;AN000; Overflow occurred ?
  1160. jc $P_Value_Err0 ;AN000; then error, exit
  1161. add dx,bx ;AN000; now have 10*x
  1162. adc cx,ax ;AN000; 32bit ADD
  1163. call $P_Check_OVF ;AN000; Overflow occurred ?
  1164. jc $P_Value_Err0 ;AN000; then error, exit
  1165. add dx,bp ;AN000; Add the current one degree decimal
  1166. adc cx,0 ;AN000; if carry, add 1 to high 16bit
  1167. call $P_Check_OVF ;AN000; Overflow occurred ?
  1168. jc $P_Value_Err0 ;AN000; then error, exit
  1169. inc si ;AN000; update pointer
  1170. jmp short $P_Value_Loop ;AN000; loop until NULL encountered
  1171. ;
  1172. $P_Value_Err0: ;AN000;
  1173. pop bx ;AN000;
  1174. jmp $P_Value_Err ;AN000; Bridge
  1175. ;
  1176. $P_Value00: ;AN000;
  1177. pop bx ;AN000; restore control pointer
  1178. test psdata_seg:$P_Flags2,$P_Neg ;AC034; here cx,dx = 32bit value
  1179. je $P_Value01 ;AN000; was it negative ?
  1180. not cx ;AN000; +
  1181. not dx ;AN000; |- Make 2's complement
  1182. add dx,1 ;AN000; |
  1183. adc cx,0 ;AN000; +
  1184. $P_Value01: ;AN000; / nval =0
  1185. mov si,es:[bx].$P_Value_List ;AN000; si points to value list
  1186. mov al,es:[si] ;AN000; get nval
  1187. cmp al,$P_nval_None ;AN000; no value list ?
  1188. jne $P_Value02 ;AN000;
  1189. mov al,$P_Number ;AN000; Set type
  1190. mov ah,$P_No_Tag ;AN000; No ITEM_TAG set
  1191. jmp $P_Value_Exit ;AN000;
  1192. $P_Value02: ;AN000; / nval = 1
  1193. IF Val1SW ;AN000;(Check if value list id #1 is supported)
  1194. ;(tm07) cmp al,$P_nval_Range ;AN000; have range list ?
  1195. ;(tm07) jne $P_Value03 ;AN000;
  1196. inc si ;AN000;
  1197. mov al,es:[si] ;AN000; al = number of range
  1198. cmp al,$P_No_nrng ;AN000; (tm07)
  1199. je $P_Value03 ;AN000; (tm07)
  1200. inc si ;AN000; si points to 1st item_tag
  1201. $P_Val02_Loop: ;AN000;
  1202. test psdata_seg:$P_Flags2,$P_Signed ;AC034;
  1203. jne $P_Val02_Sign ;AN000;
  1204. cmp cx,es:[si+$P_Val_XH] ;AN000; comp cx with XH
  1205. jb $P_Val02_Next ;AN000;
  1206. ja $P_Val_In ;AN000;
  1207. cmp dx,es:[si+$P_Val_XL] ;AN000; comp dx with XL
  1208. jb $P_Val02_Next ;AN000;
  1209. $P_Val_In: ;AN000;
  1210. ;;;;;; cmp cx,es:$P_Val_YH] ; comp cx with YH (tm01)
  1211. cmp cx,es:[si+$P_Val_YH] ;AN000; comp cx with YH (tm01)
  1212. ja $P_Val02_Next ;AN000;
  1213. jb $P_Val_Found ;AN000;
  1214. cmp dx,es:[si+$P_Val_YL] ;AN000; comp dx with YL
  1215. ja $P_Val02_Next ;AN000;
  1216. jmp short $P_Val_Found ;AN000;
  1217. $P_Val02_Sign: ;AN000;
  1218. cmp cx,es:[si+$P_Val_XH] ;AN000; comp cx with XH
  1219. jl $P_Val02_Next ;AN000;
  1220. jg $P_SVal_In ;AN000;
  1221. cmp dx,es:[si+$P_Val_XL] ;AN000; comp dx with XL
  1222. jl $P_Val02_Next ;AN000;
  1223. $P_SVal_In: ;AN000;
  1224. cmp cx,es:[si+$P_Val_YH] ;AN000; comp cx with YH
  1225. jg $P_Val02_Next ;AN000;
  1226. jl $P_Val_Found ;AN000;
  1227. cmp dx,es:[si+$P_Val_YL] ;AN000; comp dx with YL
  1228. jg $P_Val02_Next ;AN000;
  1229. jmp short $P_Val_Found ;AN000;
  1230. $P_Val02_Next: ;AN000;
  1231. add si,$P_Len_Range ;AN000;
  1232. dec al ;AN000; loop nrng times in AL
  1233. jne $P_Val02_Loop ;AN000;
  1234. ; / Not found
  1235. mov psdata_seg:$P_RC,$P_Out_of_Range ;AC034;
  1236. mov al,$P_Number ;AN000;
  1237. mov ah,$P_No_Tag ;AN000; No ITEM_TAG set
  1238. jmp short $P_Value_Exit ;AN000;
  1239. ENDIF ;AN000;(of Val1SW)
  1240. IF Val1SW+Val2SW ;AN000;(Check if value list id #1 or #2 is supported)
  1241. $P_Val_Found: ;AN000;
  1242. mov al,$P_Number ;AN000;
  1243. mov ah,es:[si] ;AN000; found ITEM_TAG set
  1244. jmp short $P_Value_Exit ;AN000;
  1245. ENDIF ;AN000;(of Val1SW+Val2SW)
  1246. $P_Value03: ;AN000; / nval = 2
  1247. IF Val2SW ;AN000;(Check if value list id #2 is supported)
  1248. ;;;; cmp al,$P_nval_Value ; have match list ? ASSUME nval=2,
  1249. ;;;; jne $P_Value04 ; even if it is 3 or more.
  1250. ;(tm07) inc si ;AN000;
  1251. ;(tm07) mov al,es:[si] ;AN000; al = nrng
  1252. mov ah,$P_Len_Range ;AN000;
  1253. mul ah ;AN000; Skip nrng field
  1254. inc ax ;AN000;
  1255. add si,ax ;AN000; si points to nnval
  1256. mov al,es:[si] ;AN000; get nnval
  1257. inc si ;AN000; si points to 1st item_tag
  1258. $P_Val03_Loop: ;AN000;
  1259. cmp cx,es:[si+$P_Val_XH] ;AN000; comp cx with XH
  1260. jne $P_Val03_Next ;AN000;
  1261. cmp dx,es:[si+$P_Val_XL] ;AN000; comp dx with XL
  1262. je $P_Val_Found ;AN000;
  1263. $P_Val03_Next: ;AN000;
  1264. add si,$P_Len_Value ;AN000; points to next value choice
  1265. dec al ;AN000; loop nval times in AL
  1266. jne $P_Val03_Loop ;AN000;
  1267. ;AN000; / Not found
  1268. mov psdata_seg:$P_RC,$P_Not_in_Val ;AC034;
  1269. mov al,$P_Number ;AN000;
  1270. mov ah,$P_No_Tag ;AN000; No ITEM_TAG set
  1271. jmp short $P_Value_Exit ;AN000;
  1272. ENDIF ;AN000;(of Val2SW)
  1273. $P_Value04: ;AN000; / nval = 3 or else
  1274. $P_Value_Err: ;AN000;
  1275. mov psdata_seg:$P_RC,$P_Syntax ;AC034;
  1276. mov al,$P_String ;AN000; Set type
  1277. mov ah,$P_No_Tag ;AN000; No ITEM_TAG set
  1278. $P_Value_Exit: ;AN000;
  1279. call $P_Fill_Result ;AN000;
  1280. pop si ;AN000;
  1281. pop dx ;AN000;
  1282. pop cx ;AN000;
  1283. pop ax ;AN000;
  1284. ret ;AN000;
  1285. $P_Value endp ;AN000;
  1286. PAGE ;AN000;
  1287. ;***********************************************************************
  1288. ; $P_Check_OVF
  1289. ;
  1290. ; Function: Check if overflow is occurred with consideration of
  1291. ; signed or un-signed numeric value
  1292. ;
  1293. ; Input: Flag register
  1294. ;
  1295. ; Output: CY = 1 : Overflow
  1296. ;
  1297. ; Vars: $P_Flags(R)
  1298. ;***********************************************************************
  1299. $P_Check_OVF proc ;AN000;
  1300. pushf ;AN000;
  1301. test psdata_seg:$P_Flags2,$P_Neg ;AC034; is it negative value ?
  1302. jne $P_COVF ;AN000; if no, check overflow
  1303. popf ;AN000; by the CY bit
  1304. ret ;AN000;
  1305. $P_COVF: ;AN000;
  1306. popf ;AN000; else,
  1307. jo $P_COVF00 ;AN000; check overflow by the OF
  1308. clc ;AN000; indicate it with CY bit
  1309. ret ;AN000; CY=0 means no overflow
  1310. $P_COVF00: ;AN000;
  1311. stc ;AN000; and CY=1 means overflow
  1312. ret ;AN000;
  1313. $P_Check_OVF endp ;AN000;
  1314. ENDIF ;AN000;(of FarSW)
  1315. ;***********************************************************************
  1316. ; $P_0099;
  1317. ;
  1318. ; Function: Make ASCII 0-9 to Binary 0-9
  1319. ;
  1320. ; Input: AL = character code
  1321. ;
  1322. ; Output: CY = 1 : AL is not number
  1323. ; CY = 0 : AL contains binary value
  1324. ;***********************************************************************
  1325. $P_0099 proc ;AN000;
  1326. cmp al,"0" ;AN000;
  1327. jb $P_0099Err ;AN000; must be 0 =< al =< 9
  1328. cmp al,"9" ;AN000;
  1329. ja $P_0099Err ;AN000; must be 0 =< al =< 9
  1330. sub al,"0" ;AN000; make char -> bin
  1331. clc ;AN000; indicate no error
  1332. ret ;AN000;
  1333. $P_0099Err: ;AN000;
  1334. stc ;AN000; indicate error
  1335. ret ;AN000;
  1336. $P_0099 endp ;AN000;
  1337. PAGE ;AN000;
  1338. ;***********************************************************************
  1339. ; $P_Simple_String
  1340. ;
  1341. ; Function: See value list for the simple string
  1342. ; and make result buffer.
  1343. ;
  1344. ; Input: psdata_seg:SI -> $P_STRING_BUF
  1345. ; ES:BX -> CONTROL block
  1346. ;
  1347. ; Output: None
  1348. ;
  1349. ; Use: $P_Fill_Result, $P_String_Comp
  1350. ;
  1351. ; Vars: $P_RC(W)
  1352. ;***********************************************************************
  1353. $P_Simple_String proc ;AN000;
  1354. push ax ;AN000;
  1355. push bx ;AN000;
  1356. push dx ;AN000;
  1357. push di ;AN000;
  1358. mov di,es:[bx].$P_Value_List ;AN000; di points to value list
  1359. mov al,es:[di] ;AN000; get nval
  1360. or al,al ;AN000; no value list ?
  1361. jne $P_Sim00 ;AN000; then
  1362. mov ah,$P_No_Tag ;AN000; No ITEM_TAG set
  1363. jmp short $P_Sim_Exit ;AN000; and set result buffer
  1364. $P_Sim00: ;AN000;
  1365. IF Val3SW+KeySW ;AN000;(Check if keyword or value list id #3 is supported)
  1366. cmp al,$P_nval_String ;AN000; String choice list provided ?
  1367. jne $P_Sim01 ;AN000; if no, syntax error
  1368. inc di ;AN000;
  1369. mov al,es:[di] ;AN000; al = nrng
  1370. mov ah,$P_Len_Range ;AN000;
  1371. mul ah ;AN000; Skip nrng field
  1372. inc ax ;AN000; ax = (nrng*9)+1
  1373. add di,ax ;AN000; di points to nnval
  1374. mov al,es:[di] ;AN000; get nnval
  1375. mov ah,$P_Len_Value ;AN000;
  1376. mul ah ;AN000; Skip nnval field
  1377. inc ax ;AN000; ax = (nnval*5)+1
  1378. add di,ax ;AN000; di points to nstrval
  1379. mov al,es:[di] ;AN000; get nstrval
  1380. inc di ;AC035; add '2' to
  1381. inc di ;AC035; DI reg
  1382. ;AN000; di points to 1st string in list
  1383. ;(replaced ;AC035;) add di,2 ;AN000; di points to 1st string in list
  1384. $P_Sim_Loop: ;AN000;
  1385. mov bp,es:[di] ;AN000; get string pointer
  1386. call $P_String_Comp ;AN000; compare it with operand
  1387. jnc $P_Sim_Found ;AN000; found on list ?
  1388. add di,$P_Len_String ;AN000; if no, point to next choice
  1389. dec al ;AN000; loop nstval times in AL
  1390. jne $P_Sim_Loop ;AN000;
  1391. ;AN000; / Not found
  1392. mov psdata_seg:$P_RC,$P_Not_In_Str ;AC034;
  1393. mov ah,$P_No_Tag ;AN000; No ITEM_TAG set
  1394. jmp short $P_Sim_Exit ;AN000;
  1395. $P_Sim_Found: ;AN000;
  1396. mov ah,es:[di-1] ;AN000; set item_tag
  1397. mov al,$P_List_Idx ;AN000;
  1398. mov dx,es:[di] ;AN000; get address of STRING
  1399. jmp short $P_Sim_Exit0 ;AN000;
  1400. ENDIF ;AN000;(of Val3SW+KeySW)
  1401. $P_Sim01: ;AN000;
  1402. mov psdata_seg:$P_RC,$P_Syntax ;AC034;
  1403. mov ah,$P_No_Tag ;AN000; No ITEM_TAG set
  1404. $P_Sim_Exit: ;AN000;
  1405. mov al,$P_String ;AN000; Set type
  1406. $P_Sim_Exit0: ;AN000;
  1407. call $P_Fill_Result ;AN000;
  1408. pop di ;AN000;
  1409. pop dx ;AN000;
  1410. pop bx ;AN000;
  1411. pop ax ;AN000;
  1412. ret ;AN000;
  1413. $P_Simple_String endp ;AN000;
  1414. PAGE ;AN000;
  1415. ;***********************************************************************
  1416. ; $P_String_Comp:
  1417. ;
  1418. ; Function: Compare two string
  1419. ;
  1420. ; Input: psdata_seg:SI -> 1st string
  1421. ; ES:BP -> 2nd string (Must be upper case)
  1422. ; ES:BX -> CONTROL block
  1423. ;
  1424. ; Output: CY = 1 if not match
  1425. ;
  1426. ; Use: $P_Chk_DBCS, $P_Do_CAPS_Char
  1427. ;
  1428. ; Vars: $P_KEYor_SW_Ptr(W), $P_Flags(R). $P_KEYorSW_Ptr
  1429. ;***********************************************************************
  1430. $P_String_Comp proc ;AN000;
  1431. push ax ;AN000;
  1432. push bp ;AN000;
  1433. push dx ;AN000;
  1434. push si ;AN000;
  1435. mov dl,$P_DOSTBL_Char ;AN000; use character case map table
  1436. $P_SCOM_Loop: ;AN000;
  1437. mov al,psdata_seg:[si] ;AN000; get command character
  1438. call $P_Chk_DBCS ;AN000; DBCS ?
  1439. jc $P_SCOM00 ;AN000; yes,DBCS
  1440. call $P_Do_CAPS_Char ;AN000; else, upper case map before comparison
  1441. IF KeySW+SwSW ;AN000;(Check if keyword or switch is supported)
  1442. test psdata_seg:$P_Flags2,$P_Key_Cmp ;AC034; keyword search ?
  1443. je $P_SCOM04 ;AN000;
  1444. cmp al,$P_Keyword ;AN000; "=" is delimiter
  1445. jne $P_SCOM03 ;AN000;IF "=" on command line AND (bp+1=> char after the "=" in synonym list)
  1446. cmp byte ptr es:[bp+1],$P_NULL ;AN021; at end of keyword string in the control block THEN
  1447. jne $P_SCOM_DIFFER ;AN021;
  1448. jmp short $P_SCOM05 ;AN000; keyword found in synonym list
  1449. $P_SCOM04: ;AN000;
  1450. test psdata_seg:$P_Flags2,$P_SW_Cmp ;AC034; switch search ?
  1451. je $P_SCOM03 ;AN000;
  1452. cmp al,$P_Colon ;AN000; ":" is delimiter, at end of switch on command line
  1453. jne $P_SCOM03 ;AN000; continue compares
  1454. cmp byte ptr es:[bp],$P_NULL ;AN021; IF at end of switch on command AND
  1455. jne $P_SCOM_DIFFER ;AN021; at end of switch string in the control block THEN
  1456. $P_SCOM05: ;AN000; found a match
  1457. inc si ;AN000; si points to just after "=" or ":"
  1458. jmp short $P_SCOM_Same ;AN000; exit
  1459. $P_SCOM03: ;AN000;
  1460. ENDIF ;AN000;(of KeySW+SwSW)
  1461. cmp al,es:[bp] ;AN000; compare operand w/ a synonym
  1462. jne $P_SCOM_Differ0 ;AN000; if different, check ignore colon option
  1463. or al,al ;AN000; end of line
  1464. je $P_SCOM_Same ;AN000; if so, exit
  1465. inc si ;AN000; update operand pointer
  1466. inc bp ;AN000; and synonym pointer
  1467. jmp short $P_SCOM01 ;AN000; loop until NULL or "=" or ":" found in case
  1468. $P_SCOM00: ;AN000; Here al is DBCS leading byte
  1469. cmp al,es:[bp] ;AN000; compare leading byte
  1470. jne $P_SCOM_Differ ;AN000; if not match, say different
  1471. inc si ;AN000; else, load next byte
  1472. mov al,psdata_seg:[si] ;AN000; and
  1473. inc bp ;AN000;
  1474. cmp al,es:[bp] ;AN000; compare 2nd byte
  1475. jne $P_SCOM_Differ ;AN000; if not match, say different, too
  1476. inc si ;AN000; else update operand pointer
  1477. inc bp ;AN000; and synonym pointer
  1478. $P_SCOM01: ;AN000;
  1479. jmp short $P_SCOM_Loop ;AN000; loop until NULL or "=" or "/" found in case
  1480. $P_SCOM_Differ0: ;AN000;
  1481. IF SwSW ;AN000;(tm10)
  1482. test psdata_seg:$P_Flags2,$P_SW ;AC034;(tm10)
  1483. je $P_not_applicable ;AN000;(tm10)
  1484. test es:[bx].$P_Function_Flag,$P_colon_is_not_necessary ;AN000;(tm10)
  1485. je $P_not_applicable ;AN000;(tm10)
  1486. cmp byte ptr es:[bp],$P_NULL ;AN000;(tm10)
  1487. ;(deleted ;AN025;) jne $P_not_applicable ;AN000;(tm10)
  1488. je $P_SCOM_Same ;AN025;(tm10)
  1489. $P_not_applicable: ;AN000;(tm10)
  1490. ENDIF ;AN000;(tm10)
  1491. test es:[bx].$P_Match_Flag,$P_Ig_Colon ;AN000; ignore colon option specified ?
  1492. je $P_SCOM_Differ ;AN000; if no, say different.
  1493. cmp al,$P_Colon ;AN000; End up with ":" and
  1494. jne $P_SCOM02 ;AN000; subseqently
  1495. cmp byte ptr es:[bp],$P_NULL ;AN000; NULL ?
  1496. jne $P_SCOM_Differ ;AN000; if no, say different
  1497. jmp short $p_SCOM_Same ;AN000; else, say same
  1498. $P_SCOM02: ;AN000;
  1499. cmp al,$P_NULL ;AN000; end up NULL and :
  1500. jne $P_SCOM_Differ ;AN000;
  1501. cmp byte ptr es:[bp],$P_Colon ;AN000; if no, say different
  1502. je $p_SCOM_Same ;AN000; else, say same
  1503. $P_SCOM_Differ: ;AN000;
  1504. stc ;AN000; indicate not found
  1505. jmp short $P_SCOM_Exit ;AN000;
  1506. $P_SCOM_Same: ;AN000;
  1507. mov psdata_seg:$P_KEYorSW_Ptr,si ;AC034; for later use by keyword or switch
  1508. clc ;AN000; indicate found
  1509. $P_SCOM_Exit: ;AN000;
  1510. pop si ;AN000;
  1511. pop dx ;AN000;
  1512. pop bp ;AN000;
  1513. pop ax ;AN000;
  1514. ret ;AN000;
  1515. $P_String_Comp endp ;AN000;
  1516. PAGE ;AN000;
  1517. ;***********************************************************************
  1518. IF DateSW ;AN000;(Check if date format is supported)
  1519. ; $P_Date_Format
  1520. ;
  1521. ; Function: Convert a date string to DOS date format for int 21h
  1522. ; with format validation.
  1523. ;
  1524. ; Input: psdata_seg:SI -> $P_STRING_BUF
  1525. ; ES:BX -> CONTROL block
  1526. ;
  1527. ; Output: None
  1528. ;
  1529. ; Use: $P_Fill_Result, $P_Set_CDI, $P_Get_DecNum
  1530. ;
  1531. ; Vars: $P_RC(W), $P_1st_Val(RW), $P_2nd_Val(RW), $P_3rd_Val(RW)
  1532. ;***********************************************************************
  1533. $P_Date_Format proc ;AN000;
  1534. push ax ;AN000;
  1535. push cx ;AN000;
  1536. push dx ;AN000;
  1537. push si ;AN000;
  1538. push bx ;AN000;
  1539. push si ;AN000;
  1540. call $P_Set_CDI ;AN000; set country dependent information before process
  1541. ; mov bl,psdata_seg:[si].$P_CDI_DateS ;load date separator ;AN020; (deleted)
  1542. ; note: the country info is still needed
  1543. ; to determine the order of the fields,
  1544. ; but the separator char is no longer used.
  1545. pop si ;AN000;
  1546. mov psdata_seg:$P_1st_Val,0 ;AC034; set initial value
  1547. mov psdata_seg:$P_2nd_Val,0 ;AC034; set initial value
  1548. mov psdata_seg:$P_3rd_Val,0 ;AC034; set initial value
  1549. call $P_Get_DecNum ;AN000; get 1st number
  1550. jc $P_DateF_Err0 ;AN000;-----------------------+
  1551. mov psdata_seg:$P_1st_Val,ax ;AC034; |
  1552. or bl,bl ;AN000; end of line ? |
  1553. je $P_DateF_YMD ;AN000; |
  1554. call $P_Get_DecNum ;AN000; get 2nd number |
  1555. jc $P_DateF_Error ;AN000; |
  1556. mov psdata_seg:$P_2nd_Val,ax ;AC034; |
  1557. or bl,bl ;AN000; end of line ? |
  1558. je $P_DateF_YMD ;AN000; |
  1559. call $P_Get_DecNum ;AN000; get 3rd number |
  1560. $P_DateF_Err0: ;AN000; Bridge <-----------+
  1561. jc $P_DateF_Error ;AN000;
  1562. mov psdata_seg:$P_3rd_Val,ax ;AC034;
  1563. or bl,bl ;AN000; end of line ?
  1564. jne $P_DateF_Error ;AN000;
  1565. $P_DateF_YMD: ;AN000;
  1566. mov bx,psdata_seg:$P_Country_Info.$P_CDI_DateF ;AC034; get date format
  1567. cmp bx,$P_Date_YMD ;AN000;
  1568. je $P_DateF00 ;AN000;
  1569. mov ax,psdata_seg:$P_1st_Val ;AC034;
  1570. or ah,ah ;AN000;
  1571. jne $P_DateF_Error ;AN000;
  1572. mov cl,al ;AN000; set month
  1573. mov ax,psdata_seg:$P_2nd_Val ;AC034;
  1574. or ah,ah ;AN000; if overflow, error.
  1575. jne $P_DateF_Error ;AN000;
  1576. mov ch,al ;AN000; set date
  1577. mov dx,psdata_seg:$P_3rd_Val ;AC034; set year
  1578. cmp bx,$P_Date_DMY ;AN000; from here format = MDY
  1579. jne $P_DateF01 ;AN000; if it is DMY
  1580. xchg ch,cl ;AN000; then swap M <-> D
  1581. $P_DateF01: ;AN000;
  1582. jmp short $P_DateF02 ;AN000;
  1583. $P_DateF00: ;AN000; / here format = YMD
  1584. mov dx,psdata_seg:$P_1st_Val ;AC034; set year
  1585. mov ax,psdata_seg:$P_2nd_Val ;AC034;
  1586. or ah,ah ;AN000; if overflow, error
  1587. jne $P_DateF_Error ;AN000;
  1588. mov cl,al ;AN000; set month
  1589. mov ax,psdata_seg:$P_3rd_Val ;AC034;
  1590. or ah,ah ;AN000; if overflow, error
  1591. jne $P_DateF_Error ;AN000;
  1592. mov ch,al ;AN000; set date
  1593. $P_DateF02: ;AN000;
  1594. cmp dx,100 ;AN000; year is less that 100 ?
  1595. jae $P_DateF03 ;AN000;
  1596. add dx,1900 ;AN000; set year 19xx
  1597. $P_DateF03: ;AN000;
  1598. pop bx ;AN000; recover CONTROL block
  1599. pop si ;AN000; recover string pointer
  1600. mov ah,$P_No_Tag ;AN000; set
  1601. mov al,$P_Date_F ;AN000; result
  1602. call $P_Fill_Result ;AN000; buffer
  1603. jmp short $P_Date_Format_Exit ;AN000; to Date
  1604. $P_DateF_Error: ;AN000;
  1605. pop bx ;AN000; recover CONTROL block
  1606. pop si ;AN000; recover string pointer
  1607. mov ah,$P_No_Tag ;AN000; set
  1608. mov al,$P_String ;AN000; result
  1609. call $P_Fill_Result ;AN000; buffer to string
  1610. mov psdata_seg:$P_RC,$P_Syntax ;AC034; indicate syntax error
  1611. $P_Date_Format_Exit: ;AN000;
  1612. pop dx ;AN000;
  1613. pop cx ;AN000;
  1614. pop ax ;AN000;
  1615. ret ;AN000;
  1616. $P_Date_Format endp ;AN000;
  1617. ENDIF ;AN000;(of DateSW)
  1618. PAGE ;AN000;
  1619. ;***********************************************************************
  1620. IF TimeSW+DateSW ;AN000;(Check if time or date format is supported)
  1621. ; $P_Set_CDI:
  1622. ;
  1623. ; Function: Read CDI from DOS if it has not been read yet
  1624. ;
  1625. ; Input: None
  1626. ;
  1627. ; Output: psdata_seg:SI -> CDI
  1628. ;
  1629. ; Use: INT 21h w/ AH = 38h
  1630. ;***********************************************************************
  1631. $P_Set_CDI proc ;AN000;
  1632. lea si,psdata_seg:$P_Country_Info ;AC034;
  1633. ifndef BILINGUAL
  1634. cmp psdata_seg:[si].$P_CDI_DateF,$P_NeedToBeRead ;AN000; already read ?
  1635. je $P_Read_CDI ;AN000;
  1636. jmp short $P_Set_CDI_Exit ;AN000; then do nothing
  1637. endif
  1638. $P_Read_CDI: ;AN000; else read CDI thru DOS
  1639. push ds ;AN000;
  1640. push dx ;AN000;
  1641. push ax ;AN000;
  1642. push PSDATA_SEG ;AC023;
  1643. pop ds ;AN000; set segment register
  1644. mov ax,$P_DOS_Get_CDI ;AN000; get country information
  1645. mov dx,si ;AN000; set offset of CDI in local data area
  1646. int 21h ;AN000;
  1647. pop ax ;AN000;
  1648. pop dx ;AN000;
  1649. pop ds ;AN000;
  1650. $P_Set_CDI_Exit: ;AN000;
  1651. ret ;AN000;
  1652. $P_Set_CDI endp ;AN000;
  1653. PAGE ;AN000;
  1654. ;***********************************************************************
  1655. ; $P_Get_DecNum:
  1656. ;
  1657. ; Function: Read a chcrater code from psdata_seg:SI until specified delimiter
  1658. ; or NULL encountered. And make a decimal number.
  1659. ;
  1660. ; Input: psdata_seg:SI -> $P_STRING_BUF
  1661. ;
  1662. ; Output: BL = delimiter code or NULL
  1663. ; AX = Decimal number
  1664. ; SI advanced to the next number
  1665. ; CY = 1 : Syntax error, AL = Latest examineed number
  1666. ;
  1667. ; Use: $P_0099
  1668. ;***********************************************************************
  1669. $P_Get_DecNum proc ;AN000;
  1670. push cx ;AN000;
  1671. push dx ;AN000;
  1672. xor cx,cx ;AN000; cx will have final value
  1673. $P_GetNum_Loop: ;AN000;
  1674. mov al,psdata_seg:[si] ;AN000; load character
  1675. or al,al ;AN000; end of line ?
  1676. je $P_GetNum00 ;AN000; if yes, exit
  1677. cmp psdata_seg:$P_Got_Time,0 ;AC034; ;is this numeric in a time field? ;AC023
  1678. je $P_Do_Date_Delims ;AN000;no, go check out Date delimiters ;AC023
  1679. ; Determine which delimiter(s) to check for. Colon & period or period only
  1680. cmp bl,$P_colon_period ;AN032; ;Time
  1681. jne $P_Do_Time_Delim1 ;AN032; ;only check for period
  1682. cmp al,$P_Colon ;AN032; ;Is this a valid delimiter ?
  1683. je $P_GetNum01 ;AN032; ;yes, exit
  1684. $P_Do_Time_Delim1: ;AN000;
  1685. cmp al,$P_Period ;;AC032;;AC023;Is this a valid delimiter ?
  1686. je $P_GetNum01 ;AC023; yes, exit
  1687. jmp short $P_Neither_Delims ;AN023;
  1688. $P_Do_Date_Delims: ;AN000;
  1689. ;Regardless of the date delimiter character specified in the country
  1690. ;dependent information, check for the presence of any one of these
  1691. ;three field delimiters: "-", "/", or ".".
  1692. cmp al,$P_Minus ;AN020;is this a date delimiter character?
  1693. je $P_GetNum01 ;AN020;if yes, exit
  1694. cmp al,$P_Slash ;AN020;is this a date delimiter character?
  1695. je $P_GetNum01 ;AN020;if yes, exit
  1696. cmp al,$P_Period ;AN020;is this a date delimiter character?
  1697. je $P_GetNum01 ;AN000; if yes, exit
  1698. $P_Neither_Delims: ;AN023;
  1699. call $P_0099 ;AN000; convert it to binary
  1700. jc $P_GetNum_Exit ;AN000; if error exit
  1701. mov ah,0 ;AN000;
  1702. xchg ax,cx ;AN000;
  1703. mov dx,10 ;AN000;
  1704. mul dx ;AN000; ax = ax * 10
  1705. or dx,dx ;AN000; overflow
  1706. jne $P_GetNum02 ;AN000; then exit
  1707. add ax,cx ;AN000;
  1708. jc $P_GetNum_Exit ;AN000;
  1709. xchg ax,cx ;AN000;
  1710. inc si ;AN000;
  1711. jmp short $P_GetNum_Loop ;AN000;
  1712. $P_GetNum00: ;AN000;
  1713. mov bl,al ;AN000; set bl to NULL
  1714. clc ;AN000; indicate no error
  1715. jmp short $P_GetNum_Exit ;AN000;
  1716. $P_GetNum01: ;AN000;
  1717. inc si ;AN000; si points to next number
  1718. clc ;AN000; indicate no error
  1719. jmp short $P_GetNum_Exit ;AN000;
  1720. $P_GetNum02: ;AN000;
  1721. stc ;AN000; indicate error
  1722. $P_GetNum_Exit: ;AN000;
  1723. mov ax,cx ;AN000;return value
  1724. pop dx ;AN000;
  1725. pop cx ;AN000;
  1726. ret ;AN000;
  1727. $P_Get_DecNum endp ;AN000;
  1728. ENDIF ;AN000;(of TimeSW+DateSW)
  1729. PAGE ;AN000;
  1730. ;***********************************************************************
  1731. IF TimeSW ;AN000;(Check if time format is supported)
  1732. ; $P_Time_Format
  1733. ;
  1734. ; Function: Convert a time string to DOS time format for int 21h
  1735. ; with format validation.
  1736. ;
  1737. ; Input: psdata_seg:SI -> $P_STRING_BUF
  1738. ; ES:BX -> CONTROL block
  1739. ;
  1740. ; Output: None
  1741. ;
  1742. ; Use: $P_Fill_Result, $P_Set_CDI, $P_Get_DecNum, $P_Time_2412
  1743. ;
  1744. ; Vars: $P_RC(W), $P_Flags(R), $P_1st_Val(RW), $P_2nd_Val(RW)
  1745. ; $P_3rd_Val(RW), $P_4th_Val(RW)
  1746. ;***********************************************************************
  1747. $P_Time_Format proc ;AN000;
  1748. push ax ;AN000;
  1749. push cx ;AN000;
  1750. push dx ;AN000;
  1751. push si ;AN000;
  1752. push bx ;AN000;
  1753. push si ;AN000;
  1754. call $P_Set_CDI ;AN000; Set country independent
  1755. ; information before process
  1756. ;(AN032; deleted) mov bl,psdata_seg:[si].$P_CDI_TimeS ;load time separator
  1757. ;(AN032; deleted) mov bh,psdata_seg:[si].$P_CDI_Dec ;load decimal separator
  1758. test byte ptr psdata_seg:[si].$P_CDI_TimeF,1 ;AN000; 24 hour system
  1759. pop si ;AN000;
  1760. jne $P_TimeF00 ;AN000; if no, means 12 hour system
  1761. call $P_Time_2412 ;AN000; this routine handle "am" "pm"
  1762. $P_TimeF00: ;AN000;
  1763. mov psdata_seg:$P_1st_Val,0 ;AC034; set initial value
  1764. mov psdata_seg:$P_2nd_Val,0 ;AC034; set initial value
  1765. mov psdata_seg:$P_3rd_Val,0 ;AC034; set initial value
  1766. mov psdata_seg:$P_4th_Val,0 ;AC034; set initial value
  1767. mov psdata_seg:$P_Got_Time,1 ;AN023;AC034;; use time delimiter
  1768. mov bl,$P_colon_period ;AN032; flag, indicates use of
  1769. ; delimiters between hours,
  1770. ; minutes,seconds
  1771. call $P_Get_DecNum ;AN000; get 1st number
  1772. jc $P_TimeF_Err0 ;AN000;
  1773. mov psdata_seg:$P_1st_Val,ax ;AC034;
  1774. or bl,bl ;AN000; end of line ?
  1775. je $P_TimeF_Rlt ;AN000;
  1776. call $P_Get_DecNum ;AN000; get 2nd number
  1777. jc $P_TimeF_Err0 ;AC038; if OK
  1778. mov psdata_seg:$P_2nd_Val,ax ;AC034;
  1779. or bl,bl ;AN000; end of line ?
  1780. je $P_TimeF_Rlt ;AN000;
  1781. ;(;AN032; deleted) mov bl,bh ;set decimal separator
  1782. mov bl,$P_period_only ;AN032; flag, which to decimal separator
  1783. call $P_Get_DecNum ;AN000; get 3rd number
  1784. jc $P_TimeF_Err0 ;AC039; if problem, bridge to error
  1785. mov psdata_seg:$P_3rd_Val,ax ;AC034;
  1786. or bl,bl ;AN000; end of line ?
  1787. ;(DELETED ;AN039;) je $P_TimeF_Rlt ;AN000;
  1788. jne $P_Time_4 ;AN039; NOT END OF LINE,
  1789. ;AN039; GO TO 4TH NUMBER
  1790. test psdata_seg:$P_Flags1,$P_Time_Again ;AN039; HAS TIME PARSE
  1791. ;AN039; BEEN REPEATED?
  1792. jnz $P_TimeF_Rlt ;AN039; yes, this is really
  1793. ;AN039; the end of line
  1794. ;AN039; no, time has not been repeated
  1795. mov si,psdata_seg:$P_SI_Save ;AN039; get where parser quit
  1796. ;AN039; in command line
  1797. cmp byte ptr [si-1],$P_Comma ;AN039; look at delimiter
  1798. ;AN039; from command line
  1799. jne $P_TimeF_Rlt ;AN039; was not a comma, this is
  1800. ;AN039; really end of line
  1801. ;AN039; is comma before hundredths,
  1802. ;AN039; redo TIME
  1803. mov byte ptr [si-1],$P_Period ;AN039; change that ambiguous
  1804. ;AN039; comma to a decimal point
  1805. ;AN039; parse can understand
  1806. mov psdata_seg:$P_Flags,0 ;AN039; Clear all internal flags
  1807. or psdata_seg:$P_Flags1,$P_Time_Again ;AN039; indicate TIME
  1808. ;AN039; is being repeated
  1809. mov cx,psdata_seg:$P_ORIG_ORD ;AN039; ORIGINAL ORDINAL FROM CX
  1810. mov sp,psdata_seg:$P_ORIG_STACK ;AN039; ORIGINAL VALUE
  1811. ;AN039; OF STACK FROM SP
  1812. mov si,psdata_seg:$P_ORIG_SI ;AN039; ORIGINAL START
  1813. ;AN039; PARSE POINTER FROM SI
  1814. jmp $P_Redo_Time ;AN039; go try TIME again
  1815. ; ===============================================================
  1816. $P_Time_4: ;AN039; READY FOR 4TH (HUNDREDTHS) NUMBER
  1817. call $P_Get_DecNum ;AN000; get 4th number
  1818. $P_TimeF_Err0: ;AN000; Bridge
  1819. jc $P_TimeF_Error ;AN000;
  1820. mov psdata_seg:$P_4th_Val,ax ;AC034;
  1821. or bl,bl ;AN000; After hundredth, no data allowed
  1822. jne $P_TimeF_Error ;AN000; if some, then error
  1823. $P_TimeF_RLT: ;AN000;
  1824. mov ax,psdata_seg:$P_1st_Val ;AC034;
  1825. or ah,ah ;AN000; if overflow then error
  1826. jne $P_TimeF_Err ;AN000;
  1827. test psdata_seg:$P_Flags1,$P_Time12am ;AN038;if "am" specified
  1828. jz $P_Time_notAM ;AN038;skip if no "AM" specified
  1829. ;since "AM" was specified,
  1830. cmp al,12 ;AN038: if hour specified as later than noon
  1831. ja $P_TimeF_Err ;AN038; error if "AM" on more than noon
  1832. jne $P_Time_notAM ;AN038; for noon exactly,
  1833. xor al,al ;AN038; set hour = zero
  1834. $P_Time_notAM: ;AN038;
  1835. test psdata_seg:$P_Flags2,$P_Time12 ;AC034; if 12 hour system and pm is specified
  1836. je $P_TimeSkip00 ;AN000; then
  1837. cmp al,12 ;AN038; if 12:00 o'clock already
  1838. je $P_TimeSkip00 ;AN038; it is PM already
  1839. add al,12 ;AN000; add 12 hours to make it afternoon
  1840. jc $P_TimeF_Err ;AN000; if overflow then error
  1841. cmp al,24 ;AN038; after adding 12, now cannot be >24
  1842. ja $P_TimeF_Err ;AN038; if too big, error
  1843. $P_TimeSkip00: ;AN000;
  1844. mov dl,al ;AN000; set hour
  1845. mov ax,psdata_seg:$P_2nd_Val ;AC034;
  1846. or ah,ah ;AN000; if overflow then error
  1847. jne $P_TimeF_Err ;AN000;
  1848. mov dh,al ;AN000; set minute
  1849. mov ax,psdata_seg:$P_3rd_Val ;AC034;
  1850. or ah,ah ;AN000; if overflow then error
  1851. jne $P_TimeF_Err ;AN000;
  1852. mov cl,al ;AN000; set second
  1853. mov ax,psdata_seg:$P_4th_Val ;AC034;
  1854. or ah,ah ;AN000; if overflow then error
  1855. jne $P_TimeF_Err ;AN000;
  1856. mov ch,al ;AN000; set hundredth
  1857. pop bx ;AN000; recover CONTROL block
  1858. pop si ;AN000; recover string pointer
  1859. mov ah,$P_No_Tag ;AN000; set
  1860. mov al,$P_Time_F ;AN000; result
  1861. call $P_Fill_Result ;AN000; buffer
  1862. jmp short $P_Time_Format_Exit ;AN000; to time
  1863. $P_TimeF_Error: ;AN000;
  1864. $P_TimeF_Err: ;AN000;
  1865. pop bx ;AN000; recover CONTROL block
  1866. pop si ;AN000; recover string pointer
  1867. mov ah,$P_No_Tag ;AN000; set
  1868. mov al,$P_String ;AN000; result
  1869. call $P_Fill_Result ;AN000; buffer to string
  1870. mov psdata_seg:$P_RC,$P_Syntax ;AC034; return syntax error
  1871. $P_Time_Format_Exit: ;AN000;
  1872. mov psdata_seg:$P_Got_Time,0 ;AN023;AC034;; finished with this time field
  1873. pop dx ;AN000;
  1874. pop cx ;AN000;
  1875. pop ax ;AN000;
  1876. ret ;AN000;
  1877. $P_Time_Format endp ;AN000;
  1878. PAGE ;AN000;
  1879. ;***********************************************************************
  1880. ; $P_Time_2412:
  1881. ;
  1882. ; Function: Remove "a", "p", "am", or "pm" from the end of stinrg
  1883. ;
  1884. ; Input: psdata_seg:SI -> $P_STRING_BUF
  1885. ;
  1886. ; Output: Set $P_Time12 flag when the string is terminated by "p"
  1887. ; or "pm"
  1888. ;
  1889. ; Vars: $P_Flags(W)
  1890. ;***********************************************************************
  1891. $P_Time_2412 proc ;AN000;
  1892. push ax ;AN000;
  1893. push si ;AN000;
  1894. $P_T12_Loop: ;AN000;
  1895. mov al,psdata_seg:[si] ;AN000; Move
  1896. inc si ;AN000; si
  1897. or al,al ;AN000; to
  1898. jne $P_T12_Loop ;AN000; end of string
  1899. mov al,psdata_seg:[si-word] ;AN000; get char just before NULL
  1900. or al,$P_Make_Lower ;AN000; lower case map
  1901. cmp al,"p" ;AN000; only "p" of "pm" ?
  1902. je $P_T1200 ;AN000;
  1903. cmp al,"a" ;AN000; only "a" of "am" ?
  1904. je $P_T1201 ;AN000;
  1905. cmp al,"m" ;AN000; "m" of "am" or "pm"
  1906. jne $P_T12_Exit ;AN000;
  1907. dec si ;AN000;
  1908. mov al,psdata_seg:[si-word] ;AN000;
  1909. or al,$P_Make_lower ;AN000; lower case map
  1910. cmp al,"p" ;AN000; "p" of "pm" ?
  1911. je $P_T1200 ;AN000;
  1912. cmp al,"a" ;AN000; "a" of "am" ?
  1913. je $P_T1201 ;AN000; go process "a"
  1914. jmp short $P_T12_Exit ;AN000; no special chars found
  1915. $P_T1200: ;AN000; "P" found
  1916. or psdata_seg:$P_Flags2,$P_Time12 ;AC034; flag "PM" found
  1917. jmp short $P_Tclr_chr ;AN038; go clear the special char
  1918. $P_T1201: ;AN000; "A" found
  1919. or psdata_seg:$P_Flags1,$P_Time12AM ;AN038; flag "AM" found
  1920. $P_Tclr_chr: ;AN038;
  1921. mov byte ptr psdata_seg:[si-2],$P_NULL ;AN000; null out special char
  1922. $P_T12_Exit: ;AN000;
  1923. pop si ;AN000;
  1924. pop ax ;AN000;
  1925. ret ;AN000;
  1926. $P_Time_2412 endp ;AN000;
  1927. ENDIF ;AN000;(of TimeSW)
  1928. PAGE ;AN000;
  1929. ;***********************************************************************
  1930. IF CmpxSW ;AN000;(Check if complex item is supported)
  1931. ; $P_Complex_Format:
  1932. ;
  1933. ; Function: Check if the input string is valid complex format.
  1934. ; And set the result buffer.
  1935. ;
  1936. ; Input: psdata_seg:SI -> $P_STRING_BUF
  1937. ; ES:BX -> CONTROL block
  1938. ;
  1939. ; Output: None
  1940. ;
  1941. ; Use: $P_Fill_Result, $P_Chk_DBCS, $P_Chk_EOL, $P_Skip_Delim
  1942. ; $P_Quoted_str, $P_Chk_DSQuote
  1943. ;
  1944. ; Vars: $P_RC(W), $P_SI_Save(W), $P_SaveSI_Cmpx(R), $P_Save_EOB(R)
  1945. ;***********************************************************************
  1946. $P_Complex_Format proc ;AN000;
  1947. push ax ;AN000;
  1948. push bx ;AN000;
  1949. push si ;AN000;
  1950. mov bx,psdata_seg:$P_SaveSI_Cmpx ;AC034; bx points to user buffer
  1951. cmp byte ptr [bx],$P_Lparen ;AN000; 1st char = left parentheses
  1952. jne $P_Cmpx_Err ;AN000;
  1953. xor ah,ah ;AN000; ah = parentheses counter
  1954. $P_Cmpx_Loop: ;AN000;
  1955. mov al,[bx] ;AN000; load character from command buffer
  1956. call $P_Chk_EOL ;AN000; if it is one of EOL
  1957. je $P_CmpxErr0 ;AN000; then error exit.
  1958. cmp al,$P_Lparen ;AN000; left parentheses ?
  1959. jne $P_Cmpx00 ;AN000; then
  1960. inc ah ;AC035; add '1' to AH reg
  1961. ;AN000; increment parentheses counter
  1962. ;(replaced ;AC035;) add ah,1 ;AN000; increment parentheses counter
  1963. jc $P_CmpxErr0 ;AN000; if overflow, error
  1964. $P_Cmpx00: ;AN000;
  1965. cmp al,$P_Rparen ;AN000; right parentheses ?
  1966. jne $P_Cmpx01 ;AN000; then
  1967. dec ah ;AC035; subtract '1' from AH reg
  1968. ;AN000; decrement parentheses counter
  1969. ;(changed ;AC035;) sub ah,1 ;AN000; decrement parentheses counter
  1970. jc $P_CmpxErr0 ;AN000; if overflow error
  1971. je $P_Cmpx03 ;AN000; ok, valid complex
  1972. $P_Cmpx01: ;AN000;
  1973. ;(deleted ;AN025;) call $P_Chk_DSQuote ;AN000; double or single quotation mark ? 3/17/KK
  1974. cmp al,$P_DQuote ;AN025; double quotation mark?
  1975. jne $P_Cmpx04 ;AN000; 3/17/KK
  1976. mov psdata_seg:[si],al ;AN000; here quoted string is found in the complex list.
  1977. inc si ;AN000;
  1978. inc bx ;AN000; bx points to 2nd character
  1979. call $P_Quoted_Str ;AN000; skip pointers until closing of quoted string
  1980. jc $P_CmpxErr0 ;AN000; if error in quoted string syntax then exit
  1981. jmp short $P_Cmpx05 ;AN000;
  1982. $P_Cmpx04: ;AN000;
  1983. call $P_Chk_DBCS ;AN000; was it a lead byte of DBCS ?
  1984. jnc $P_Cmpx02 ;AN000;
  1985. mov psdata_seg:[si],al ;AN000; then store 1st byte
  1986. inc si ;AN000;
  1987. inc bx ;AN000;
  1988. mov al,[bx] ;AN000; load 2nd byte
  1989. $P_Cmpx02: ;AN000;
  1990. mov psdata_seg:[si],al ;AN000; store SBCS or 2nd byte of DBCS
  1991. $P_Cmpx05: ;AN000;
  1992. inc si ;AN000;
  1993. inc bx ;AN000;
  1994. jmp short $P_Cmpx_Loop ;AN000; loop
  1995. ;---- ;AN000;
  1996. $P_Cmpx03: ;AN000;
  1997. mov byte ptr psdata_seg:[si],al ;AN000;
  1998. mov byte ptr psdata_seg:[si+byte],$P_NULL ;AN000;
  1999. mov byte ptr [bx],$P_NULL ;AN000; replace right parentheses with NULL
  2000. mov si,bx ;AN000; skip whitespaces
  2001. inc si ;AN000; after
  2002. call $P_Skip_Delim ;AN000; right parentheses
  2003. mov psdata_seg:$P_SI_Save,si ;AC034; save next pointer, SI
  2004. jmp short $P_Cmpx_Exit ;AN000;
  2005. $P_CmpxErr0: ;AN000;
  2006. mov si,psdata_seg:$P_Save_EOB ;AC034; if EOF encountered, restore
  2007. mov byte ptr psdata_seg:[si],$P_NULL ;AN000; EOB mark
  2008. $P_Cmpx_Err: ;AN000;
  2009. mov psdata_seg:$P_RC,$P_Syntax ;AC034;
  2010. $P_Cmpx_Exit: ;AN000;
  2011. mov ah,$P_No_Tag ;AN000;
  2012. mov al,$P_Complex ;AN000;
  2013. pop si ;AN000;
  2014. pop bx ;AN000;
  2015. call $P_Fill_Result ;AN000;
  2016. pop ax ;AN000;
  2017. ret ;AN000;
  2018. $P_Complex_Format endp ;AN000;
  2019. ENDIF ;AN000;(of CpmxSW)
  2020. PAGE ;AN000;
  2021. ;***********************************************************************
  2022. IF QusSW ;AN000;(Check if quoted string is supported)
  2023. ; $P_Quoted_Format:
  2024. ;
  2025. ; Function: Check if the input string is valid quoted string format.
  2026. ; And set the result buffer.
  2027. ;
  2028. ; Input: psdata_seg:SI -> $P_STRING_BUF
  2029. ; ES:BX -> CONTROL block
  2030. ;
  2031. ; Output: None
  2032. ;
  2033. ; Use: $P_Fill_Result, $P_Chk_DBCS, $P_Chk_EOL, $P_Skip_Delim
  2034. ; $P_Chk_DSQuote, $P_Quoted_Str
  2035. ;
  2036. ; Vars: $P_RC(W), $P_SI_Save(W), $P_SaveSI_Cmpx(R),$P_Save_EOB(R)
  2037. ;***********************************************************************
  2038. $P_Quoted_Format proc ;AN000;
  2039. push ax ;AN000;
  2040. push bx ;AN000;
  2041. push si ;AN000;
  2042. mov bx,psdata_seg:$P_SaveSI_Cmpx ;AC034; bx points to user buffer
  2043. mov al,byte ptr [bx] ;AN000; get 1st character
  2044. ;(deleted ;AN025;) call $P_Chk_DSQuote ;AN000; is it single or double quote ?
  2045. cmp al,$P_DQuote ;AN025; double quotation mark?
  2046. jne $P_Qus_Err ;AN000; if no, error
  2047. ; mov psdata_seg:[si],al ;AN000; move it to internal buffer
  2048. ; inc si ;AN000;
  2049. inc bx ;AN000; bx points to 2nd character
  2050. call $P_Quoted_Str ;AN000; skip pointers to the closing of quoted string
  2051. jc $P_Qus_Err0 ;AN000; if invali quoted string syntax, exit
  2052. mov byte ptr psdata_seg:[si+byte],$P_NULL ;AN000; end up with NULL
  2053. mov si,bx ;AN000;
  2054. inc si ;AN000;
  2055. call $P_Skip_Delim ;AN000; skip whitespaces after closing quote
  2056. mov psdata_seg:$P_SI_Save,si ;AC034; save next pointer, SI
  2057. jmp short $P_Qus_Exit ;AN000;
  2058. $P_Qus_Err0: ;AN000;
  2059. mov si,psdata_seg:$P_Save_EOB ;AC034; if EOF encountered, restore
  2060. mov byte ptr psdata_seg:[si],$P_NULL ;AN000; EOB mark
  2061. $P_Qus_Err: ;AN000;AN000
  2062. mov psdata_seg:$P_RC,$P_Syntax ;AC034; indicate syntax error
  2063. $P_Qus_Exit: ;AN000;
  2064. mov ah,$P_No_Tag ;AN000; set
  2065. mov al,$P_Quoted_String ;AN000; result
  2066. pop si ;AN000; buffer
  2067. pop bx ;AN000; to
  2068. call $P_Fill_Result ;AN000; quoted string
  2069. pop ax ;AN000;
  2070. ret ;AN000;
  2071. $P_Quoted_Format endp ;AN000;
  2072. ENDIF ;AN000;(of QusSW)
  2073. PAGE ;AN000;
  2074. ;***********************************************************************
  2075. ; $P_Chk_DSQuote;
  2076. ;
  2077. ; Function: Check if AL is double quotation or single quotation
  2078. ;
  2079. ; Input: AL = byte to be examineed
  2080. ;
  2081. ; Output: ZF on if AL is single or double quotetaion
  2082. ;
  2083. ; Vars: $P_SorD_Quote(W)
  2084. ;***********************************************************************
  2085. IF QusSW+CmpxSW ;AN000;(Check if quoted string or complex item is supported)
  2086. ;(deleted ;AN025;) $P_Chk_DSQuote proc ;
  2087. ;(deleted ;AN025;) mov $P_SorD_Quote,$P_SQuote ; 3/17/87 assume single quote
  2088. ;(deleted ;AN025;) cmp al,$P_DQuote ; 1st char = double quotation ?
  2089. ;(deleted ;AN025;) jne $P_CDSQ00 ; 3/17/87
  2090. ;(deleted ;AN025;) mov $P_SorD_Quote,al ; 3/17/87 set bigning w/ double quote
  2091. ;(deleted ;AN025;) ret ; 3/17/87
  2092. ;(deleted ;AN025;) $P_CDSQ00: ; 3/17/87
  2093. ;(deleted ;AN025;) cmp al,$P_SQuote ; 1st char = single quotation ?
  2094. ;(deleted ;AN025;) ret ;
  2095. ;(deleted ;AN025;) $P_Chk_DSQuote endp ;
  2096. PAGE ;AN000;
  2097. ;***********************************************************************
  2098. ; $P_Quoted_Str:
  2099. ;
  2100. ; Function: Copy chracacter from ES:BX to psdata_seg:SI until closing single
  2101. ; (double) quotation found.
  2102. ;
  2103. ; Input: psdata_seg:SI -> $P_STRING_BUF
  2104. ; ES:BX -> Operand in command buffer
  2105. ;
  2106. ; Output: CY on indicates EOF encounterd before closing quotation
  2107. ; BX and SI
  2108. ;
  2109. ;
  2110. ; Vars: $P_SorD_Quote(R)
  2111. ;***********************************************************************
  2112. $P_Quoted_Str proc ;AN000;
  2113. push ax ;AN000;
  2114. $P_Qus_Loop: ;AN000;
  2115. mov ax,[bx] ;AN000; 3/17/87
  2116. call $P_Chk_EOL ;AN000;
  2117. je $P_Qustr_Err0 ;AN000;
  2118. ;(deleted ;AN025;) cmp al,$P_SorD_Quote ;AN000; quotation ? 3/17/87
  2119. cmp al,$P_DQuote ;AN025; double quote?
  2120. jne $P_Qus00 ;AN000;
  2121. ;(deleted ;AN025;) cmp ah,$P_SorD_Quote ;AN000; contiguous quotation 3/17/87
  2122. cmp ah,$P_DQuote ;AN025; double quote?
  2123. jne $P_Qus02 ;AN000;
  2124. ;(deleted ;AN025:) mov word ptr psdata_seg:[si],ax ;AN000; 3/17/87
  2125. mov byte ptr psdata_seg:[si],al ;AN025; save one of the quotes
  2126. ;(deleted ;AN025:) add si,2 ;AN000;
  2127. inc si ;AC035; add '1' to SI reg
  2128. ;AN025; adjust target index
  2129. ;(changed ;AC035;) add si,1 ;AN025; adjust target index
  2130. inc bx ;AC035; add '2' to
  2131. inc bx ;AC035; BX reg
  2132. ;AN000; adjust source index by 2 to skip extra quote
  2133. ;(changed ;AC035;) add bx,2 ;AN000; adjust source index by 2 to skip extra quote
  2134. jmp short $P_Qus_Loop ;AN000;
  2135. $P_Qus00: ;AN000;
  2136. call $P_Chk_DBCS ;AN000; was it a lead byte of DBCS ?
  2137. jnc $P_Qus01 ;AN000;
  2138. mov psdata_seg:[si],al ;AN000; store 1st byte
  2139. inc si ;AN000;
  2140. inc bx ;AN000;
  2141. mov al,[bx] ;AN000; load 2nd byte
  2142. $P_Qus01: ;AN000;
  2143. mov psdata_seg:[si],al ;AN000; store SBCS or 2nd byte of DBCS
  2144. inc si ;AN000;
  2145. inc bx ;AN000;
  2146. jmp short $P_Qus_Loop ;AN000;
  2147. $P_Qustr_Err0: ;AN000;
  2148. stc ;AN000; indicate error
  2149. jmp short $P_Quoted_Str_Exit ;AN000;
  2150. $P_Qus02: ;AN000;
  2151. mov byte ptr psdata_seg:[si],0 ;AN000;
  2152. clc ;AN000; indicate no error
  2153. $P_Quoted_Str_Exit: ;AN000;
  2154. pop ax ;AN000;
  2155. ret ;AN000;
  2156. $P_Quoted_Str endp ;AN000;
  2157. ENDIF ;AN000;(of QusSW+CmpxSW)
  2158. PAGE ;AN000;
  2159. ;***********************************************************************
  2160. IF FileSW+DrvSW ;AN000;(Check if file spec or drive only is supported)
  2161. ; $P_File_Format;
  2162. ;
  2163. ; Function: Check if the input string is valid file spec format.
  2164. ; And set the result buffer.
  2165. ;
  2166. ; Input: psdata_seg:SI -> $P_STRING_BUF
  2167. ; ES:BX -> CONTROL block
  2168. ;
  2169. ; Output: None
  2170. ;
  2171. ; Use: $P_Fill_Result, $P_Chk_DBCS, $P_FileSp_Chk
  2172. ;
  2173. ; Vars: $P_RC(W), $P_SI_Save(W), $P_Terminator(W), $P_SaveSI_Cmpx(R)
  2174. ; $P_SaveSI_Cmpx(R)
  2175. ;***********************************************************************
  2176. $P_File_Format proc ;AN000;
  2177. push ax ;AN000;
  2178. push di ;AN000;
  2179. push si ;AN000;
  2180. mov di,psdata_seg:$P_SaveSI_cmpx ;AC034; get user buffer address
  2181. $P_FileF_Loop0: ;AN000; / skip special characters
  2182. mov al,psdata_seg:[si] ;AN000; load character
  2183. or al,al ;AN000; end of line ?
  2184. je $P_FileF_Err ;AN000; if yes, error exit
  2185. call $P_FileSp_Chk ;AN000; else, check if file special character
  2186. jne $P_FileF03 ;AN000; if yes,
  2187. ;AN033; deleted inc di ;skip
  2188. ;AN033; deleted inc si ; the
  2189. ;AN033; deleted jmp short $P_FileF_Loop0 ; character
  2190. mov psdata_seg:$P_err_flag,$P_error_filespec ;AN033;AC034;; set error flag- bad char.
  2191. pop si ;AN033;
  2192. mov byte ptr psdata_seg:[si],$P_NULL ;AN033;
  2193. pop di ;AN033;
  2194. jmp short $P_FileF02 ;AN033;
  2195. $P_FileF_Err: ;AN000;
  2196. pop si ;AN000;
  2197. mov byte ptr psdata_seg:[si],$P_NULL ;AN000;
  2198. ;(deleted ;AN030;) mov di,$P_SaveSI_cmpx ;AN000; get user buffer address
  2199. ;(deleted ;AN030;) mov $P_SI_Save,di ;AN000; update pointer to user buffer
  2200. pop di ;AN000;
  2201. test es:[bx].$P_Match_Flag,$P_Optional ;AN000; is it optional ?
  2202. jne $P_FileF02 ;AN000;
  2203. mov psdata_seg:$P_RC,$P_Op_Missing ;AC034; 3/17/87
  2204. jmp short $P_FileF02 ;AN000;
  2205. $P_FileF03: ;AN000;
  2206. pop ax ;AN000; discard save si
  2207. push si ;AN000; save new si
  2208. $P_FileF_Loop1: ;AN000;
  2209. mov al,psdata_seg:[si] ;AN000; load character (not special char)
  2210. or al,al ;AN000; end of line ?
  2211. je $P_FileF_RLT ;AN000;
  2212. call $P_FileSp_Chk ;AN000; File special character ?
  2213. je $P_FileF00 ;AN000;
  2214. call $P_Chk_DBCS ;AN000; no, then DBCS ?
  2215. jnc $P_FileF01 ;AN000;
  2216. inc di ;AN000; if yes, skip next byte
  2217. inc si ;AN000;
  2218. $P_FileF01: ;AN000;
  2219. inc di ;AN000;
  2220. inc si ;AN000;
  2221. jmp short $P_FileF_Loop1 ;AN000;
  2222. ;
  2223. $P_FileF00: ;AN000;
  2224. mov psdata_seg:$P_Terminator,al ;AC034;
  2225. mov byte ptr psdata_seg:[si],$P_NULL ;AN000; update end of string
  2226. inc di ;AN000;
  2227. mov psdata_seg:$P_SI_Save,di ;AC034; update next pointer in command line
  2228. $P_FileF_RLT: ;AN000;
  2229. pop si ;AN000;
  2230. pop di ;AN000;
  2231. $P_FileF02: ;AN000;
  2232. pop ax ;AN000; (tm14)
  2233. test ax,$P_File_Spc ;AN000; (tm14)
  2234. je $P_Drv_Only_Exit ;AN000; (tm14)
  2235. push ax ;AN000; (tm14)
  2236. mov ah,$P_No_Tag ;AN000; set
  2237. mov al,$P_File_Spec ;AN000; result
  2238. call $P_Fill_Result ;AN000; buffer to file spec
  2239. pop ax ;AN000;
  2240. $P_Drv_Only_Exit: ;AN000; (tm14)
  2241. ret ;AN000;
  2242. $P_File_Format endp ;AN000;
  2243. PAGE ;AN000;
  2244. ;***********************************************************************
  2245. ; $P_FileSp_Chk
  2246. ;
  2247. ; Function: Check if the input byte is one of file special characters
  2248. ;
  2249. ; Input: psdata_seg:SI -> $P_STRING_BUF
  2250. ; AL = character code to be examineed
  2251. ;
  2252. ; Output: ZF = 1 , AL is one of special characters
  2253. ;***********************************************************************
  2254. $P_FileSp_Chk proc ;AN000;
  2255. push bx ;AN000;
  2256. push cx ;AN000;
  2257. lea bx,psdata_seg:$P_FileSp_Char ;AC034; special character table
  2258. mov cx,$P_FileSp_Len ;AN000; load length of it
  2259. $P_FileSp_Loop: ;AN000;
  2260. cmp al,psdata_seg:[bx] ;AN000; is it one of special character ?
  2261. je $P_FileSp_Exit ;AN000;
  2262. inc bx ;AN000;
  2263. loop $P_FileSp_Loop ;AN000;
  2264. inc cx ;AN000; reset ZF
  2265. $P_FileSp_Exit: ;AN000;
  2266. pop cx ;AN000;
  2267. pop bx ;AN000;
  2268. ret ;AN000;
  2269. $P_FileSp_Chk endp ;AN000;
  2270. ENDIF ;AN000;(of FileSW+DrvSW)
  2271. PAGE ;AN000;
  2272. ;***********************************************************************
  2273. IF DrvSW ;AN000;(Check if drive only is supported)
  2274. ; $P_Drive_Format;
  2275. ;
  2276. ; Function: Check if the input string is valid drive only format.
  2277. ; And set the result buffer.
  2278. ;
  2279. ; Input: psdata_seg:SI -> $P_STRING_BUF
  2280. ; ES:BX -> CONTROL block
  2281. ;
  2282. ; Output: None
  2283. ;
  2284. ; Use: $P_Fill_Result, $P_Chk_DBCS
  2285. ;
  2286. ; Vars: $P_RC(W)
  2287. ;***********************************************************************
  2288. $P_Drive_Format proc ;AN000;
  2289. push ax ;AN000;
  2290. push dx ;AN000;
  2291. mov al,psdata_seg:[si] ;AN000;
  2292. or al,al ;AN000; if null string
  2293. je $P_Drv_Exit ;AN000; do nothing
  2294. call $P_Chk_DBCS ;AN000; is it leading byte ?
  2295. jc $P_Drv_Err ;AN000;
  2296. cmp word ptr psdata_seg:[si+byte],$P_Colon ;AN000; "d", ":", 0 ?
  2297. je $P_DrvF00 ;AN000;
  2298. test es:[bx].$P_Match_Flag,$P_Ig_Colon ;AN000; colon can be ignored?
  2299. je $P_Drv_Err ;AN000;
  2300. cmp byte ptr psdata_seg:[si+byte],$P_NULL ;AN000; "d", 0 ?
  2301. jne $P_Drv_Err ;AN000;
  2302. $P_DrvF00: ;AN000;
  2303. or al,$P_Make_Lower ;AN000; lower case
  2304. cmp al,"a" ;AN000; drive letter must
  2305. jb $P_Drv_Err ;AN000; in range of
  2306. cmp al,"z" ;AN000; "a" - "z"
  2307. ja $P_Drv_Err ;AN000; if no, error
  2308. sub al,"a"-1 ;AN000; make text drive to binary drive
  2309. mov dl,al ;AN000; set
  2310. mov ah,$P_No_Tag ;AN000; result
  2311. mov al,$P_Drive ;AN000; buffer
  2312. call $P_Fill_Result ;AN000; to drive
  2313. jmp short $P_Drv_Exit ;AN000;
  2314. $P_Drv_Err: ;AN000;
  2315. mov psdata_seg:$P_RC,$P_Syntax ;AC034;
  2316. $P_Drv_Exit: ;AN000;
  2317. pop dx ;AN000;
  2318. pop ax ;AN000;
  2319. ret ;AN000;
  2320. $P_Drive_Format endp ;AN000;
  2321. ENDIF ;AN000;(of DrvSW)
  2322. PAGE ;AN000;
  2323. ;***********************************************************************
  2324. ; $P_Skip_Delim;
  2325. ;
  2326. ; Function: Skip delimiters specified in the PARMS list, white space
  2327. ; and comma.
  2328. ;
  2329. ; Input: DS:SI -> Command String
  2330. ; ES:DI -> Parameter List
  2331. ;
  2332. ; Output: CY = 1 if the end of line encounterd
  2333. ; CY = 0 then SI move to 1st non-delimiter character
  2334. ; AL = Last examineed character
  2335. ;
  2336. ; Use: $P_Chk_EOL, $P_Chk_Delim,
  2337. ;
  2338. ; Vars: $P_Flags(R)
  2339. ;***********************************************************************
  2340. $P_Skip_Delim proc ;AN000;
  2341. $P_Skip_Delim_Loop: ;AN000;
  2342. LODSB ;AN000;
  2343. call $P_Chk_EOL ;AN000; is it EOL character ?
  2344. je $P_Skip_Delim_CY ;AN000; if yes, exit w/ CY on
  2345. call $P_Chk_Delim ;AN000; is it one of delimiters ?
  2346. jne $P_Skip_Delim_NCY ;AN000; if no, exit w/ CY off
  2347. test psdata_seg:$P_Flags2,$P_Extra ;AC034; extra delim or comma found ?
  2348. je $P_Skip_Delim_Loop ;AN000; if no, loop
  2349. test psdata_seg:$P_Flags2,$P_SW+$P_equ ;AC034; /x , or xxx=zzz , (tm08)
  2350. je short $P_Exit_At_Extra ;AN000; no switch, no keyword (tm08)
  2351. dec si ;AN000; backup si for next call (tm08)
  2352. jmp short $P_Exit_At_Extra ;AN000; else exit w/ CY off
  2353. $P_Skip_Delim_CY: ;AN000;
  2354. stc ;AN000; indicate EOL
  2355. jmp short $P_Skip_Delim_Exit ;AN000;
  2356. $P_Skip_Delim_NCY: ;AN000;
  2357. clc ;AN000; indicate non delim
  2358. $P_Skip_Delim_Exit: ;AN000; in this case, need
  2359. dec si ;AN000; backup index pointer
  2360. ret ;AN000;
  2361. $P_Exit_At_Extra: ;AN000;
  2362. clc ;AN000; indicate extra delim
  2363. ret ;AN000;
  2364. $P_Skip_Delim endp ;AN000;
  2365. PAGE ;AN000;
  2366. ;***********************************************************************
  2367. ; $P_Chk_EOL;
  2368. ;
  2369. ; Function: Check if AL is one of End of Line characters.
  2370. ;
  2371. ; Input: AL = character code
  2372. ; ES:DI -> Parameter List
  2373. ;
  2374. ; Output: ZF = 1 if one of End of Line characters
  2375. ;**********************************************************************
  2376. $P_Chk_EOL proc ;AN000;
  2377. push bx ;AN000;
  2378. push cx ;AN000;
  2379. cmp al,$P_CR ;AN000; Carriage return ?
  2380. je $P_Chk_EOL_Exit ;AN000;
  2381. cmp al,$P_NULL ;AN000; zero ?
  2382. je $P_Chk_EOL_Exit ;AN000;
  2383. IF LFEOLSW ;AN028; IF LF TO BE ACCEPTED AS EOL
  2384. cmp al,$P_LF ;AN000; Line feed ?
  2385. je $P_Chk_EOL_Exit ;AN000;
  2386. ENDIF ;AN028;
  2387. cmp byte ptr es:[di].$P_Num_Extra,$P_I_Have_EOL ;AN000; EOL character specified ?
  2388. jb $P_Chk_EOL_Exit ;AN000;
  2389. xor bx,bx ;AN000;
  2390. mov bl,es:[di].$P_Len_Extra_Delim ;AN000; get length of delimiter list
  2391. add bx,$P_Len_PARMS ;AN000; skip it
  2392. cmp byte ptr es:[bx+di],$P_I_Use_Default ;AN000; No extra EOL character ?
  2393. je $P_Chk_EOL_NZ ;AN000;
  2394. xor cx,cx ;AN000; Get number of extra chcracter
  2395. mov cl,es:[bx+di] ;AN000;
  2396. $P_Chk_EOL_Loop: ;AN000;
  2397. inc bx ;AN000;
  2398. cmp al,es:[bx+di] ;AN000; Check extra EOL character
  2399. je $P_Chk_EOL_Exit ;AN000;
  2400. loop $P_Chk_EOL_Loop ;AN000;
  2401. $P_Chk_EOL_NZ: ;AN000;
  2402. cmp al,$P_CR ;AN000; reset ZF
  2403. $P_Chk_EOL_Exit: ;AN000;
  2404. pop cx ;AN000;
  2405. pop bx ;AN000;
  2406. ret ;AN000;
  2407. $P_Chk_EOL endp ;AN000;
  2408. PAGE ;AN000;
  2409. ;***********************************************************************
  2410. ; $P_Chk_Delim;
  2411. ;
  2412. ; Function: Check if AL is one of delimiter characters.
  2413. ; if AL+[si] is DBCS blank, it is replaced with two SBCS
  2414. ; blanks.
  2415. ;
  2416. ; Input: AL = character code
  2417. ; DS:SI -> Next Character
  2418. ; ES:DI -> Parameter List
  2419. ;
  2420. ; Output: ZF = 1 if one of delimiter characters
  2421. ; SI points to the next character
  2422. ; Vars: $P_Terminator(W), $P_Flags(W)
  2423. ;***********************************************************************
  2424. $P_Chk_Delim proc ;AN000;
  2425. push bx ;AN000;
  2426. push cx ;AN000;
  2427. mov psdata_seg:$P_Terminator,$P_Space ;AC034; Assume terminated by space
  2428. and psdata_seg:$P_Flags2,0ffh-$P_Extra ;AC034;
  2429. cmp al,$P_Space ;AN000; Space ?
  2430. je $P_Chk_Delim_Exit ;AN000;
  2431. cmp al,$P_TAB ;AN000; TAB ?
  2432. je $P_Chk_Delim_Exit ;AN000;
  2433. cmp al,$P_Comma ;AN000; Comma ?
  2434. je $P_Chk_Delim_Exit0 ;AN000;
  2435. $P_Chk_Delim00: ;AN000;
  2436. cmp al,$P_DBSP1 ;AN000; 1st byte of DBCS Space ?
  2437. jne $P_Chk_Delim01 ;AN000;
  2438. cmp byte ptr [si],$P_DBSP2 ;AN000; 2nd byte of DBCS Space ?
  2439. jne $P_Chk_Delim01 ;AN000;
  2440. mov al,$P_Space ;AN000;
  2441. inc si ;AN000; make si point to next character
  2442. cmp al,al ;AN000; Set ZF
  2443. jmp short $P_Chk_Delim_Exit ;AN000;
  2444. $P_Chk_Delim01: ;AN000;
  2445. cmp byte ptr es:[di].$P_Num_Extra,$P_I_Have_Delim ;AN000; delimiter character specified ?
  2446. jb $P_Chk_Delim_Exit ;AN000;
  2447. xor cx,cx ;AN000;
  2448. mov cl,es:[di].$P_Len_Extra_Delim ;AN000; get length of delimiter list
  2449. or cx,cx ;AN000; No extra Delim character ?
  2450. je $P_Chk_Delim_NZ ;AN000;
  2451. mov bx,$P_Len_PARMS-1 ;AN000; set bx to 1st extra delimiter
  2452. $P_Chk_Delim_Loop: ;AN000;
  2453. inc bx ;AN000;
  2454. cmp al,es:[bx+di] ;AN000; Check extra Delim character
  2455. je $P_Chk_Delim_Exit0 ;AN000;
  2456. loop $P_Chk_Delim_Loop ;AN000; examine all extra delimiter
  2457. $P_Chk_Delim_NZ: ;AN000;
  2458. cmp al,$P_Space ;AN000; reset ZF
  2459. $P_Chk_Delim_Exit: ;AN000;
  2460. ;;;; jne $P_ChkDfin
  2461. ;;;; mov psdata_seg:$P_Terminator,al ;AN034;
  2462. $P_ChkDfin: ;AN000;
  2463. pop cx ;AN000;
  2464. pop bx ;AN000;
  2465. ret ;AN000;
  2466. $P_Chk_Delim_Exit0: ;AN000;
  2467. mov psdata_seg:$P_Terminator,al ;AC034; keep terminated delimiter
  2468. test psdata_seg:$P_Flags2,$P_Equ ;AN027;AC034;; if terminating a key=
  2469. jnz $P_No_Set_Extra ;AN027; then do not set the EXTRA bit
  2470. or psdata_seg:$P_Flags2,$P_Extra ;AC034; flag terminated extra delimiter or comma
  2471. $P_No_Set_Extra: ;AN027;
  2472. cmp al,al ;AN000; set ZF
  2473. jmp short $P_Chk_Delim_Exit ;AN000;
  2474. $P_Chk_Delim endp ;AN000;
  2475. PAGE ;AN000;
  2476. ;***********************************************************************
  2477. ; $P_Chk_Switch;
  2478. ;
  2479. ; Function: Check if AL is the switch character not in first position of
  2480. ; $P_STRING_BUF
  2481. ;
  2482. ; Input: AL = character code
  2483. ; BX = current pointer within $P_String_Buf
  2484. ; SI =>next char on command line (following the one in AL)
  2485. ;
  2486. ; Output: CF = 1 (set)if AL is switch character, and not in first
  2487. ; position, and has no chance of being part of a date string,
  2488. ; i.e. should be treated as a delimiter.
  2489. ; CF = 0 (reset, cleared) if AL is not a switch char, is in the first
  2490. ; position, or is a slash but may be part of a date string, i.e.
  2491. ; should not be treated as a delimiter.
  2492. ;
  2493. ; Vars: $P_Terminator(W)
  2494. ; Use: $P_0099
  2495. ;***********************************************************************
  2496. $P_Chk_Switch proc ;AN000;
  2497. ;AN020;; Function: Check if AL is the switch character from 2nd position of $P_STRING_BUF
  2498. ;AN020;; Output: ZF = 1 if switch character
  2499. ;AN020;; lea bp,$P_STRING_BUF ;AN000;
  2500. ;AN020;; cmp bx,bp ;AN000; 1st position ?
  2501. ;AN020;; je $P_Chk_S_Exit_1 ;AN000;
  2502. ;AN020;; cmp al,$P_Switch ;AN000;
  2503. ;AN020;; jmp short $P_Chk_S_Exit_0 ;AN000;
  2504. ;AN020;;$P_Chk_S_Exit_1: ;AN000;
  2505. ;AN020;; cmp al,$P_Switch ;AN000; (tm08)
  2506. ;AN020;; jne $P_Nop ;AN000; (tm08)
  2507. ;AN020;; or $P_Flags2,$P_SW ;AN000; (tm08) It could be valid switch
  2508. ;AN020;;$P_Nop: ;AN000; (tm08)
  2509. ;AN020;; inc bp ;AN000;
  2510. ;AN020;; cmp bx,bp ;AN000; reset ZF
  2511. ;AN020;;$P_Chk_S_Exit_0: ;AN000;
  2512. ;AN020;; jne $P_Chk_S_Exit ;AN000;
  2513. ;AN020;; mov $P_Terminator,al ;AN000; store switch character
  2514. ;AN020;;$P_Chk_S_Exit: ;AN000;
  2515. LEA BP,psdata_seg:$P_String_Buf ;AN020;AC034; BP=OFFSET of $P_String_Buf even in group addressing
  2516. ; .IF <BX NE BP> THEN ;AN020;IF not first char THEN
  2517. cmp BX,BP ;AN000;
  2518. je $P_STRUC_L2 ;AN000;
  2519. ; .IF <AL EQ $P_Switch> THEN ;AN020;otherwise see if a slash
  2520. cmp AL,$P_Switch ;AN000;
  2521. jne $P_STRUC_L5 ;AN000;
  2522. STC ;AN020;not in first position and is slash, now see if might be in date string
  2523. IF DateSw ;AN020;caller looking for date, see if this may be part of one
  2524. PUSH AX ;AN020;save input char
  2525. MOV AL,PSDATA_SEG:[BX-1] ;AN026;AL=char before the current char
  2526. CALL $P_0099 ;AN020;return carry set if not numeric
  2527. ; .IF NC ;AND ;AN020;IF previous char numeric AND
  2528. jc $P_STRUC_L7 ;AN000;
  2529. MOV AL,[SI] ;AN020;AL=char after the current char
  2530. CALL $P_0099 ;AN020;return carry set if not numeric
  2531. ;(deleted) .IF NC THEN ;AN020;IF next char numeric THEN could be a date
  2532. ;(deleted) CLC ;AN020;reset CF so "/" not treated as a delimiter
  2533. ;(deleted) .ENDIF ;AN026;
  2534. ; .ENDIF ;AN020;ENDIF looks like date (number/number)
  2535. $P_STRUC_L7: ;AN000;
  2536. POP AX ;AN020;restore AL to input char
  2537. ENDIF ;AN020;DateSw
  2538. ; .ELSE ;AN020;
  2539. jmp short $P_STRUC_L1 ;AN000;
  2540. $P_STRUC_L5: ;AN000;
  2541. CLC ;AN020;not a slash
  2542. ; .ENDIF ;AN020;
  2543. ; .ELSE ;AN020;is first char in the buffer, ZF=0
  2544. jmp short $P_STRUC_L1 ;AN000;
  2545. $P_STRUC_L2: ;AN000;
  2546. ; .IF <AL EQ $P_Switch> THEN ;AN020;
  2547. cmp AL,$P_Switch ;AN000;
  2548. jne $P_STRUC_L12 ;AN000;
  2549. OR psdata_seg:$P_Flags2,$P_SW ;AN020;AC034;;could be valid switch, first char and is slash
  2550. ; .ENDIF ;AN020;
  2551. $P_STRUC_L12: ;AN000;
  2552. CLC ;AN020;CF=0 indicating first char
  2553. ; .ENDIF ;AN020;
  2554. $P_STRUC_L1: ;AN000;
  2555. ret ;AN000;
  2556. $P_Chk_Switch endp ;AN000;
  2557. PAGE ;AN000;
  2558. ;**************************************************************************
  2559. ; $P_Chk_DBCS:
  2560. ;
  2561. ; Function: Check if a specified byte is in ranges of the DBCS lead bytes
  2562. ;
  2563. ; Input:
  2564. ; AL = Code to be examineed
  2565. ;
  2566. ; Output:
  2567. ; If CF is on then a lead byte of DBCS
  2568. ;
  2569. ; Use: INT 21h w/AH=63
  2570. ;
  2571. ; Vars: $P_DBCSEV_Seg(RW), $P_DBCSEV_Off(RW)
  2572. ;***************************************************************************
  2573. $P_Chk_DBCS PROC ;AN000;
  2574. ;
  2575. PUSH DS ;AN000;
  2576. PUSH SI ;AN000;
  2577. PUSH bx ;AN000; (tm11)
  2578. CMP psdata_seg:$P_DBCSEV_SEG,0 ;AC034; ALREADY SET ?
  2579. JNE $P_DBCS00 ;AN000;
  2580. PUSH AX ;AN000;
  2581. ; PUSH BX ;AN000; (tm11)
  2582. PUSH ds ;AN000; (tm11)
  2583. PUSH CX ;AN000;
  2584. PUSH DX ;AN000;
  2585. PUSH DI ;AN000;
  2586. PUSH BP ;AN000;
  2587. PUSH ES ;AN000;
  2588. XOR SI,SI ;AN000;
  2589. MOV DS,SI ;AN000;
  2590. MOV AX,$P_DOS_GetEV ;AN000; GET DBCS EV CALL
  2591. INT 21H ;AN000;
  2592. ; MOV AX,DS ;AN000; (tm11)
  2593. ; OR AX,AX ;AN000; (tm11)
  2594. MOV bx,DS ;AN000; (tm11)
  2595. OR bx,bx ;AN000; (tm11)
  2596. POP ES ;AN000;
  2597. POP BP ;AN000;
  2598. POP DI ;AN000;
  2599. POP DX ;AN000;
  2600. POP CX ;AN000;
  2601. ; POP BX ;AN000; (tm11)
  2602. POP ds ;AN000; (tm11)
  2603. POP AX ;AN000;
  2604. JE $P_NON_DBCS ;AN000;
  2605. $P_DBCS02: ;AN000;
  2606. MOV psdata_seg:$P_DBCSEV_OFF,SI ;AC034; save EV offset
  2607. ; MOV psdata_seg:$P_DBCSEV_SEG,DS ;AC034; save EV segment
  2608. MOV psdata_seg:$P_DBCSEV_SEG,bx ;AC034; save EV segment (tm11)
  2609. $P_DBCS00: ;AN000;
  2610. MOV SI,psdata_seg:$P_DBCSEV_OFF ;AC034; load EV offset
  2611. MOV DS,psdata_seg:$P_DBCSEV_SEG ;AC034; and segment
  2612. $P_DBCS_LOOP: ;AN000;
  2613. CMP WORD PTR [SI],0 ;AN000; zero vector ?
  2614. JE $P_NON_DBCS ;AN000; then exit
  2615. CMP AL,[SI] ;AN000;
  2616. JB $P_DBCS01 ;AN000; Check if AL is in
  2617. CMP AL,[SI+BYTE] ;AN000; range of
  2618. JA $P_DBCS01 ;AN000; the vector
  2619. STC ;AN000; if yes, indicate DBCS and exit
  2620. JMP short $P_DBCS_EXIT ;AN000;
  2621. $P_DBCS01: ;AN000;
  2622. INC SI ;AC035; add '2' to
  2623. INC SI ;AC035; SI reg
  2624. ;AN000; get next vector
  2625. ;(changed ;AC035;) ADD SI,2 ;AN000; get next vector
  2626. JMP short $P_DBCS_LOOP ;AN000; loop until zero vector found
  2627. $P_NON_DBCS: ;AN000;
  2628. CLC ;AN000; indicate SBCS
  2629. $P_DBCS_EXIT: ;AN000;
  2630. POP bx ;AN000; (tm11)
  2631. POP SI ;AN000;
  2632. POP DS ;AN000;
  2633. RET ;AN000;
  2634. $P_Chk_DBCS ENDP ;AN000;