filename.asm
上传用户:xiaoan1112
上传日期:2013-04-11
资源大小:19621k
文件大小:19k
源码类别:

操作系统开发

开发平台:

Visual C++

  1. TITLE FILENAME - filename scanning routines
  2. ;***
  3. ; FILENAME - filename scanning routines
  4. ;
  5. ; Copyright <C> 1987, Microsoft Corporation
  6. ;
  7. ; Contains functions:
  8. ; B$IValidatePath
  9. ; B$GET_PATHNAME
  10. ; B$ADD_EXT
  11. ; B$GET_CUR_DRIVE
  12. ; B$GET_CUR_DIR
  13. ; B$GET_DEV_NUM
  14. ;
  15. ;******************************************************************************
  16. INCLUDE switch.inc
  17. INCLUDE rmacros.inc
  18. USESEG CONST
  19. USESEG _DATA
  20. USESEG _BSS
  21. USESEG DK_TEXT
  22. INCLUDE seg.inc
  23. INCLUDE baslibma.inc
  24. INCLUDE devdef.inc
  25. INCLUDE files.inc
  26. INCLUDE idmac.inc
  27. INCLUDE rtps.inc ; constants shared with QBI
  28. ; Device Name Generator
  29. DEVMAC MACRO ARG
  30. DB '&ARG'
  31. DB DN_&ARG
  32. ENDM
  33. externFP OpenCheckDrive
  34. sBegin CONST
  35. staticB BAD_CHAR_TBL,<34,"+,:;<=>[]|"> ; illegal filename chars
  36. BAD_CHAR_CNT EQU ($ - BAD_CHAR_TBL) ; table length (w/o space)
  37. staticB ,<" ">,1 ; reject spaces for B$IValidatePath
  38. sEnd CONST
  39. sBegin _DATA
  40. globalB szWildDefault,<"*"> ; "*.bas" (MUST be before b$BAS_EXT!!!)
  41. globalB b$BAS_EXT,<".BAS",0>
  42. globalB b$EXE_EXT,<".EXE",0>
  43. EVEN ; sd's must be word-aligned
  44. staticW fakeSD,0,2 ; phoney SD for B$IValidatePath QB5 code.
  45. sEnd _DATA
  46. sBegin _BSS
  47. globalW b$PN_NAME,,1 ; addr of first char in filename.ext
  48. staticW FIRST_SLASH,?,1 ; address of first "" in pathname, for
  49. ; underflow checking
  50. staticW b$BadCharCnt,,1 ; # of bytes of BAD_CHAR_TBL to use
  51. sEnd _BSS
  52. ; special flag values
  53. SLASH_SEEN = FILNAML + 1 ; last char was a ""
  54. SLASHDOT_SEEN = FILNAML + 2 ; last chars were "."
  55. SLASHDOTDOT_SEEN = FILNAML + 3 ; last chars were ".."
  56. assumes CS,DK_TEXT
  57. sBegin DK_TEXT
  58. externNP B$UPCASE
  59. externNP B$ERR_BFN
  60. externNP B$ERR_DNA
  61. DEVICE_NAME_TABLE LABEL BYTE
  62. DEVNAM
  63. DB 0
  64. ;*** 
  65. ;B$IValidatePath -- interpreter filename parser (FAR)
  66. ;
  67. ;Purpose:
  68. ; Interpreter reachable routine to call B$GET_PATHNAME and B$ADD_EXT.
  69. ; Added with revision [9].
  70. ;Entry:
  71. ; pSource  = DGROUP offset of filename to be parsed
  72. ; cbSource = length of filename to be parsed
  73. ; pDestBuf = DGROUP offset of destination buffer for parsed filename
  74. ; pExt  = DGROUP offset of extension to add (if none present)
  75. ;Exit:
  76. ; AX = length of parsed filename (NOT including null terminator)
  77. ;Uses:
  78. ; per conv.
  79. ;Preserves:
  80. ; per conv.
  81. ;Exceptions:
  82. ; Invalid file name, Device unavailable 
  83. ;******************************************************************************
  84. cProc B$IValidatePath,<FAR,PUBLIC>,<ES,SI,DI>
  85. ParmW pSource  ;offset of filename to be parsed
  86. ParmW cbSource ;length of filename to be parsed
  87. ParmW pDestBuf ;offset of dest buffer
  88. ParmW pExt ;offset of extension to add
  89. cBegin
  90. PUSH DS ;ES=DS
  91. POP ES
  92. MOV AX,[pSource] ; AX = ptr to filename string
  93. MOV CX,[cbSource] ; CX = length of filename
  94. MOV BX,OFFSET DGROUP:fakeSD ; BX = ptr to filename SD
  95. MOV [BX],CX ; set up phony SD
  96. MOV [BX+2],AX
  97. MOV DI,[pDestBuf] ;[DI] = ptr to destination buffer
  98. MOV b$BadCharCnt,BAD_CHAR_CNT+1 ; reject spaces in filenames
  99. CALL B$GET_PATHNAME_CORE ; returns CX=length (includes null)
  100. ; and AL = flags
  101. MOV SI,[pExt] ;[SI] = ptr to extension
  102. CALL B$ADD_EXT ;add extension if one not already there
  103. XCHG AX,CX ;[AX] = length of parsed filename
  104. DEC AX ; don't include null byte in count
  105. cEnd
  106. ERBFN3:
  107. JMP ERBFN2
  108. SUBTTL General File Name Parser
  109. ;*** 
  110. ; B$GET_PATHNAME
  111. ;
  112. ;Purpose:
  113. ;
  114. ; Generates the fully-qualified pathname from a filename.
  115. ; Converts name to upper case, and removes ".." and "." from the
  116. ; pathname.  Resulting pathname is null-terminated.  Appends the drive
  117. ; letter and a ":" to the front if it doesn't have one already.
  118. ;
  119. ; Names within pathname do not have '*'s expanded to '?'s.  No checks
  120. ; are done for too many slashes or length.  These checks are not
  121. ; necessary, since the DOS calls that take as input this processed
  122. ; pathname should perform those checks.  Both forward and backward
  123. ; slashes are accepted as path characters.
  124. ;
  125. ; An error is given if a filename has more than one dot.
  126. ; Filenames without extensions that are longer than 8 characters have
  127. ; a "." inserted after the 8th position. 
  128. ; The extension portion is truncated to 3 chars.
  129. ;
  130. ;Algorithm:
  131. ;
  132. ;
  133. ;Entry:
  134. ; BX    = pointer to filename string descriptor
  135. ; DI    = address to place processed pathname (DGROUP offset)
  136. ;
  137. ;Exit:
  138. ; AL = FLAGS -- bits FN_HAS_EXT and FN_WILD set appropriately.
  139. ; CX = length of pathname (including the null byte)
  140. ; Upper case, fully-specified pathname filled in.
  141. ;
  142. ;Uses:
  143. ; none
  144. ;
  145. ;Preserves:
  146. ; BX,DX
  147. ;
  148. ;Exceptions:
  149. ; Invalid file name.
  150. ;
  151. ;******************************************************************************
  152. labelNP <PUBLIC,B$GET_PATHNAME>
  153. mov b$BadCharCnt,BAD_CHAR_CNT ; use default # of bad chars
  154. cProc B$GET_PATHNAME_CORE,<NEAR>,<ES,SI,BX,DX>
  155. cBegin
  156. PUSH DS ; ES=DS
  157. POP ES
  158. MOV SI,[BX+2] ; DS:SI = pointer to filename
  159. MOV CX,[BX] ; CX = length of filename
  160. ; ES:DI = pointer to destination buffer
  161. PUSH DI ; save start of processed pathname
  162. LEA BX,[DI+FILNAML] ; BX = address for overflow check
  163. ; place the drive letter into pathname
  164. DEC CX ; filename length < 2?
  165. JLE NO_DRIVE_SPEC ; brif so -- no drive specified
  166. CMP BYTE PTR [SI+1],':' ; is next filename char a ":"?
  167. JNE NO_DRIVE_SPEC ; brif not -- no drive specified
  168. LODSW ; get first two chars of filename into AX
  169. DEC CX ; adjust count
  170. CALL B$UPCASE ; convert drive letter to upper case
  171. JMP SHORT GOT_DRIVE ; store specified drive in pathname
  172. NO_DRIVE_SPEC: ; no drive specified at start of filename
  173. INC CX ; restore filename length
  174. CALL B$GET_CUR_DRIVE ; put current DRIVE_LETTER: into AX
  175. GOT_DRIVE: ; AX contains "DRIVE_LETTER:"
  176. STOSW ; store "DRIVE_LETTER:" into pathname
  177. MOV FIRST_SLASH,DI ; save address for underflow check
  178. cCall OpenCheckDrive,<ax> ; put up a message box if we are
  179. ; switching logical drives
  180. ; PRESERVES ALL REGISTERS
  181. SUB AX,':' SHL 8 + 'A'-1 ; convert AX to drive number (A=1,B=2,etc)
  182. XCHG DX,AX ; DX = drive number (DH = 0)
  183. JCXZ USE_CURDIR ; brif end of filename -- use current directory
  184. MOV AL,[SI] ; get next char into AL
  185. CALL CHK_FOR_SLASH ; slash char?
  186. JE PROCESS_NAME ; brif so -- don't use current directory
  187. USE_CURDIR:
  188. CALL B$GET_CUR_DIR ; get current directory for the proper drive,
  189. ; and store it into the pathname buffer
  190. XOR AL,AL ; search for null byte
  191. PUSH CX ; save count
  192. MOV CX,-1 ; search for up to 64K chars
  193. REPNE SCASB ; set DI to position past null byte
  194. DEC DI ; [DI] = null byte at end of pathname
  195. CMP BYTE PTR [DI-1],'' ; root directory?
  196. JE Not_Root_Dir ; brif so -- don't add a ""
  197. MOV AL,'' ; place a "" between the current directory
  198. STOSB ; and the filename
  199. Not_Root_Dir:
  200. POP CX ; restore count
  201. PROCESS_NAME:
  202. CALL SLASH_END ; indicate slash char seen, and set b$PN_NAME.
  203. JCXZ CheckDir ; brif end of filename -- just return the
  204. ; current directory for the proper drive
  205. ; Register usage:
  206. ;    DS:SI = pointer to next char in filename
  207. ;    ES:DI = pointer to next char in processed pathname
  208. ; AL = next char in filename
  209. ; AH = KANJI Flags
  210. ; 0  => not Double Byte Character
  211. ; 1  => Double Byte Character
  212. ; BX = pathname buffer end address (for overflow check)
  213. ; CX = number of remaining chars in filename
  214. ; DH = flags:
  215. ; FN_WILD -- name portion of pathname contains a wildcard
  216. ; FN_HAS_EXT -- name portion of pathname has extension
  217. ; DL = last char(s) flag:
  218. ; SLASH_SEEN -- last char in path is ""
  219. ; SLASHDOT_SEEN -- last chars in path are "."
  220. ; SLASHDOTDOT_SEEN - last chars in path are ".."
  221. ; otherwise -- number of chars since last ""
  222. ; On stack:
  223. ; pathname buffer address
  224. ; Now add specified filename to current drive:path, processing "." and ".."
  225. NAME_LOOP:
  226. ; get next filename char
  227. LODSB ; AL = next filename character
  228. CALL B$UPCASE ; convert to upper case
  229. STOSB ; store char from filename into pathname
  230. CMP DI,BX ; are we now past the end of the buffer?
  231. JA ERBFN2 ;brif so -- illegal pathname
  232. ; process the char
  233. CMP AL,'.' ; is char a DOT?
  234. JNE CHK_SLASH ; brif not -- check for slash
  235. CMP DL,SLASHDOTDOT_SEEN ; seen "..."?
  236. JAE ERBFN2 ;brif so -- invalid pathname
  237. CMP DL,SLASH_SEEN ; seen "." or ".."?
  238. JAE INC_COUNT ; brif so -- advance state
  239. TEST DH,FN_HAS_EXT ; seen two dots since last ""? ("x.y.z")
  240. JNZ ERBFN2 ; brif so -- invalid pathname.
  241. ; This handles name of the form "xxxxxxxxy.z" too, since "xxxxxxxxy"
  242. ; gets changed to "xxxxxxxx.y" before the ".z" is added.
  243. DOT_EXIT:
  244. OR DH,FN_HAS_EXT ; set extension present flag
  245. JMP SHORT ResetCount ; reset count to 1 (just the ".")
  246. CHK_SLASH:
  247. CALL CHK_FOR_SLASH ; is it a slash?
  248. DJMP JNE CHK_BAD_CHAR ; brif not -- check for invalid char
  249. CALL PROCESS_SLASH
  250. JMP SHORT END_LOOP ; go to the end of the loop
  251. ERBFN2: ; centrally located
  252. DJMP JMP SHORT ERBFN
  253. VALID_CHAR:
  254. CMP AL,'*' ; is it an asterix?
  255. JE IS_WILD_CHAR ; brif so
  256. CMP AL,'?' ; is it a question mark?
  257. JNZ CHK_DEFAULT ; brif not -- perform default char processing
  258. IS_WILD_CHAR:
  259. OR DH,FN_WILD ; flag wild card present
  260. CHK_DEFAULT:
  261. CMP DL,SLASHDOT_SEEN ; seen ".x" (ext w/o name) or "..x"?
  262. JAE ERBFN ; brif so -- illegal pathname
  263. CMP DL,SLASH_SEEN ; have we seen "x"?
  264. JNE INC_COUNT ; brif not -- just increment count
  265. ResetCount:
  266. XOR DL,DL ; reset char count/last char flag to 0
  267. INC_COUNT:
  268. INC DX ; have seen another char
  269. CMP DL,SLASH_SEEN ; processing name portion?
  270. JAE END_LOOP ; brif not -- process next char
  271. CMP DL,4 ; valid length for either extension or name?
  272. JBE END_LOOP ; brif so
  273. TEST DH,FN_HAS_EXT ; seen a dot already?
  274. JNZ BackUpChar ; brif so -- truncate extension to 3 chars
  275. CMP DL,9 ; 9 characters in name now?
  276. JB END_LOOP ; brif < -- process next char
  277. MOV AL,'.' ; pretend we now have a '.'
  278. XCHG AL,[DI-1] ; turn "xxxxxxxxy" into "xxxxxxxx.y"
  279. STOSB
  280. INSERTED_DOT:
  281. OR DH, FN_HAS_EXT ; Indicate the presence of the DOT
  282. MOV DL, 1 ; extenstion has 1 character (the DOT)
  283. JMP SHORT INC_COUNT ; Include the new character in the count
  284. ; here if truncating extension
  285. BackUpChar: ; back up 1 char in output fname
  286. dec di ; back up over char
  287. dec dx ; one less char
  288. END_LOOP:
  289. LOOP NAME_LOOP ; process next char, if any
  290. ; filename has now been almost completely processed
  291. CMP DL,SLASH_SEEN ; does current pathname end with "." or ".."?
  292. JBE CheckDir ; brif not -- add the null byte
  293. ;Special code to handle directory names
  294. INC DI ; pretend there's another "" on the end
  295. CALL PROCESS_SLASH ; and process as if there is a slash char,
  296. ; removing the dots.
  297. CheckDir:
  298. CMP DL,SLASH_SEEN ; does it end with a ''?
  299. JNE ADD_NULL ; brif not -- just add the null byte
  300. OR DH,FN_IS_DIR ; set directory flag so B$ADD_EXT won't
  301. ; try to add an extension to directory name
  302. ADD_NULL:
  303. XCHG AX,CX ; set AX = 0, since CX will always = 0 here
  304. STOSB ; store terminating null byte
  305. ; complete null-terminated pathname without "." or ".." is now in buffer.
  306. MOV CX,DI ; one past the last position (past null byte)
  307. POP DI ; restore DI to point to the processed pathname
  308. SUB CX,DI ; and set CX to the count of chars in pathname
  309. ; (including the null)
  310. MOV AL,DH ; return flags in AL
  311. cEnd
  312. ERBFN: ; centrally located
  313. jmp B$ERR_BFN ; give bad filename error
  314. CHK_BAD_CHAR: ; Check if char is a valid filename character.
  315. CMP AL,' ' ; control character?
  316. JB ERBFN ; brif so -- bad filename
  317. ; search table of invalid chars for current char
  318. PUSH DI ; save registers
  319. PUSH CX
  320. MOV DI,OFFSET DGROUP:BAD_CHAR_TBL ; table to search
  321. MOV CX,b$BadCharCnt ; number of chars to search (changes)
  322. REPNE SCASB ; search for char in table
  323. JZ ERBFN ; brif char found -- bad filename
  324. POP CX ; restore registers
  325. POP DI
  326. JMP VALID_CHAR ; valid char -- continue processing
  327. ;*** 
  328. ;PROCESS_SLASH -- perform processing for a "" in the pathname
  329. ;
  330. ;Purpose:
  331. ; Eliminates "." and "dir.." from pathname string, and checks
  332. ; for underflow (".." at the root directory level).
  333. ;
  334. ;Entry: (same conditions as within pathname processing loop)
  335. ; ES:DI = pointer to next char in processed pathname
  336. ; DH    = flags:
  337. ;     FN_WILD -- name portion of pathname contains a wildcard
  338. ;     FN_HAS_EXT -- name portion of pathname has extension
  339. ; DL    = last char(s) flag:
  340. ;     SLASH_SEEN     -- last char in path is ""
  341. ;     SLASHDOT_SEEN   -- last chars in path are "."
  342. ;     SLASHDOTDOT_SEEN - last chars in path are ".."
  343. ;Exit:
  344. ; DI updated
  345. ; DH = NOT FN_WILD and NOT FN_HAS_EXT
  346. ; DL = SLASH_SEEN
  347. ; b$PN_NAME = address of last "" in pathname.
  348. ;
  349. ;Uses:
  350. ; AL
  351. ;
  352. ;Preserves:
  353. ;
  354. ;Exceptions:
  355. ; Bad File Name
  356. ;
  357. ;******************************************************************************
  358. PROCESS_SLASH: ;Transform "." or "dir_name.." to ""
  359. CMP DL,SLASHDOT_SEEN ; seen "."?
  360. JNE CHK_SLASHDOTDOT ; brif not -- check for ".."
  361. DEC DI ; remove the last ""
  362. DEC DI ; remove the "."
  363. JMP SHORT SLASH_END ; indicate slash char seen
  364. CHK_SLASHDOTDOT:
  365. CMP DL,SLASHDOTDOT_SEEN ; seen ".."?
  366. JNE SLASH_END ; brif not -- indicate slash char seen
  367. SUB DI,4 ; get rid of the ".."
  368. ; [DI] = addr of the first ""
  369. REMOVE_SLASHES:
  370. DEC DI ; remove another char
  371. MOV AL,[DI] ; get deleted char
  372. CALL CHK_FOR_SLASH ; just removed a previous ""?
  373. JE REMOVE_SLASHES ; remove another char
  374. CMP DI,FIRST_SLASH ; have we deleted the first ""?
  375. JB ERBFN ; brif so -- underflow -- too many ".."'s
  376. REMOVE_NAME:
  377. DEC DI ; remove another char of the name
  378. MOV AL,[DI] ; get deleted char
  379. CALL CHK_FOR_SLASH ; just removed a previous ""?
  380. JNE REMOVE_NAME ; brif not -- delete another character
  381. INC DI ; put back the last ""
  382. SLASH_END:
  383. MOV DX,SLASH_SEEN ; indicate slash character seen, no wildcards,
  384. ; and no extension
  385. MOV b$PN_NAME,DI ; set address of name.ext in pathname
  386. RET ; return to caller
  387. ;*** 
  388. ; CHK_FOR_SLASH -- check if char is "" or "/"
  389. ;
  390. ;Purpose:
  391. ; Since we're to allow both forward and backwards slashes in the
  392. ; pathname, check if char is "" or "/".  Extracted to save code.
  393. ;
  394. ;Entry:
  395. ; AL = char to check.
  396. ;Exit:
  397. ; ZF if AL = "" or "/", NZ otherwise.
  398. ;Uses:
  399. ; None
  400. ;Preserves:
  401. ; All
  402. ;Exceptions:
  403. ; None
  404. ;
  405. ;******************************************************************************
  406. CHK_FOR_SLASH: ; check for forward slash and back slash
  407. CMP AL,'' ; is it a back slash?
  408. JE CHK_SLASH_EXIT ; brif so -- return to caller
  409. CMP AL,'/' ; is it a forward slash?
  410. CHK_SLASH_EXIT:
  411. RET ; return to caller
  412. ;*** 
  413. ; B$ADD_EXT -- add extension to pathname
  414. ;
  415. ;Purpose:
  416. ; Adds a 4-byte extension to a name, updating the count and checking
  417. ; for overflow.  It first checks to see that there is not already an
  418. ; extension on the last name of the file.
  419. ;
  420. ;Entry:
  421. ; ES:DI = address of null-terminated pathname to append extension to
  422. ; CX = index into the pathname of the char past the char to overwrite
  423. ; (usually the pathname length returned from B$GET_PATHNAME)
  424. ; DS:SI = address of 4-bytes to be appended to name
  425. ; AL = flags returned from B$GET_PATHNAME
  426. ;
  427. ;Exit:
  428. ; if not already an extension
  429. ;     extension appended to name at ES:DI
  430. ;     CX = new length of name (INCLUDING the NULL)
  431. ;
  432. ;Uses:
  433. ; SI,AX
  434. ;
  435. ;Preserves:
  436. ; BX,DX
  437. ;
  438. ;Exceptions:
  439. ; Bad file name
  440. ;
  441. ;******************************************************************************
  442. cProc B$ADD_EXT,<NEAR,PUBLIC>,<DI>
  443. cBegin
  444. TEST AL,FN_HAS_EXT or FN_IS_DIR ; does the filename already have
  445. ; an extension (or end with a '')?
  446. JNZ NO_EXTENSION ; brif so -- don't add an extension
  447. DEC CX ; CX = # chars w/o the null
  448. ADD DI,CX ; set destination pointer to point to null byte
  449. NextChar:
  450. INC cx ; advance count
  451. CMP CX,FILNAML ; will we overflow with this char?
  452. JA ERBFN ; brif so -- Bad file name error
  453. LODSB ; get char
  454. STOSB ; store it
  455. OR AL,AL ; got the null yet?
  456. JNZ NextChar
  457. NO_EXTENSION:
  458. cEnd
  459. ;*** 
  460. ; B$GET_CUR_DRIVE -- get current drive letter and number
  461. ;
  462. ;Purpose:
  463. ;
  464. ; get current drive number (1-26) and letter (A-Z) from DOS
  465. ;
  466. ;Entry:
  467. ; none
  468. ;
  469. ;Exit:
  470. ; AL    = current drive letter (A-Z)
  471. ; AH    = ':'
  472. ;
  473. ;Uses:
  474. ; DX
  475. ;
  476. ;Preserves:
  477. ; BX,CX
  478. ;
  479. ;Exceptions:
  480. ; None
  481. ;
  482. ;******************************************************************************
  483. cProc B$GET_CUR_DRIVE,<NEAR,PUBLIC>
  484. cBegin
  485. CALLOS GDRV ; AL = default drive  (A=0, B=1, etc)
  486. CBW ; clear high byte
  487. ADD AX,':' SHL 8 + 'A' ; return drive letter in AL and ':' in AH
  488. cEnd
  489. ;*** 
  490. ; B$GET_CUR_DIR -- return current directory for a given drive number.
  491. ;
  492. ;Purpose:
  493. ;
  494. ;Algorithm:
  495. ; Add "" to string
  496. ; Get current directory from DOS into string
  497. ;
  498. ;Entry:
  499. ; ES:DI = address of area to place current directory
  500. ; DX = drive number (1-26)
  501. ; ES=DS
  502. ;
  503. ; Note: IF FV_FARSTR, DS is not necessarily DGROUP on entry.
  504. ;
  505. ;Exit:
  506. ; current directory (null-terminated) loaded into buffer
  507. ;
  508. ;Uses:
  509. ; AX,DX
  510. ;
  511. ;Preserves:
  512. ; BX,CX
  513. ;
  514. ;Exceptions:
  515. ; Device not available
  516. ;
  517. ;******************************************************************************
  518. cProc B$GET_CUR_DIR,<NEAR,PUBLIC>,<CX>
  519. cBegin
  520. MOV AL,'' ; add a beginning ""
  521. STOSB
  522. PUSH SI ; save register
  523. MOV SI,DI ; set SI to current location in buffer
  524. CALLOS CURDIR,ERDNA ; load current directory into DS:SI
  525. POP SI ; restore register
  526. cEnd
  527. ERDNA:
  528. jmp B$ERR_DNA ; give Device unavailable error
  529. ;*** 
  530. ; B$GET_DEV_NUM
  531. ;
  532. ;Purpose:
  533. ; Checks if the first 5 chars of a string are equal to some BASIC
  534. ; device, and if so, returns the device number for that device.
  535. ; Accepts names of the form "XXXX:yyyyyy" as a valid devices, and
  536. ; copies the options string for valid devices into the specified buffer.
  537. ;
  538. ;Entry:
  539. ; BX    = pointer to filename string descriptor
  540. ;
  541. ;Exit:
  542. ; AL = device number if device, or 0 if not a valid BASIC device
  543. ; FLAGS = result of "OR AL,AL"
  544. ;
  545. ;Uses:
  546. ; None
  547. ;
  548. ;Preserves:
  549. ; BX,CX,DX
  550. ;
  551. ;Exceptions:
  552. ; none
  553. ;
  554. ;******************************************************************************
  555. cProc B$GET_DEV_NUM,<NEAR,PUBLIC>,<ES,SI,DI,CX>
  556. cBegin
  557. MOV SI,[BX+2] ; [DS:SI] = pointer to string data
  558. CMP WORD PTR [BX],5 ; length < 5?
  559. JB NOT_DEV ; brif so -- not a valid BASIC device
  560. CMP BYTE PTR [SI+4],':' ; name of the form "xxxx:" ?
  561. JNZ NOT_DEV ; brif not -- not a BASIC device
  562. ; No checks will need to be done for KANJI characters, because there are
  563. ; none in our tables.  The call to B$UPCASE will not matter, as it can not
  564. ; do anything to make a match succeed. (The first byte of a KANJI character
  565. ; will not be converted, nor will it be in the table.)
  566. MOV DI,OFFSET DEVICE_NAME_TABLE
  567. PUSH CS ; set ES = CS for table reference
  568. POP ES
  569. DEV_LOOP: ; for each device in table
  570. CMP BYTE PTR ES:[DI],0 ; end of table?
  571. JZ NOT_DEV ; brif so -- not a valid BASIC device
  572. PUSH SI ; save start of name
  573. MOV CX,4 ; compare 4 chars
  574. CMP_LOOP:
  575. LODSB ; get character from the name into AL
  576. CALL B$UPCASE ; convert to upper case
  577. SCASB ; does it match char in the device table?
  578. JE NEXT_CHAR ; brif so -- try next char
  579. ADD DI,CX ; skip over remaining chars and dev # in table
  580. POP SI ; retrieve start of name
  581. JMP SHORT DEV_LOOP ; and try to match the next entry
  582. NEXT_CHAR:
  583. LOOP CMP_LOOP ; falls through if device matched
  584. POP SI ; clean off stack
  585. MOV AL,ES:[DI] ; return device number in AL
  586. OR AL,AL ; set flags for calling routine
  587. JMP SHORT DEV_EXIT
  588. NOT_DEV:
  589. XOR AL,AL ; not a device -- clear AL and flags
  590. DEV_EXIT:
  591. cEnd
  592. sEnd DK_TEXT
  593. END