diff options
Diffstat (limited to 'v4.0/src/DOS/MACRO2.ASM')
| -rw-r--r-- | v4.0/src/DOS/MACRO2.ASM | 1281 |
1 files changed, 1281 insertions, 0 deletions
diff --git a/v4.0/src/DOS/MACRO2.ASM b/v4.0/src/DOS/MACRO2.ASM new file mode 100644 index 0000000..a3ff4cc --- /dev/null +++ b/v4.0/src/DOS/MACRO2.ASM | |||
| @@ -0,0 +1,1281 @@ | |||
| 1 | ; SCCSID = @(#)macro2.asm 1.2 85/07/23 | ||
| 2 | TITLE MACRO2 - Pathname and macro related internal routines | ||
| 3 | NAME MACRO2 | ||
| 4 | ; | ||
| 5 | ; TransFCB written | ||
| 6 | ; TransPath written | ||
| 7 | ; TransPathSet written | ||
| 8 | ; TransPathNoSet Written | ||
| 9 | ; Canonicalize written | ||
| 10 | ; PathSep written | ||
| 11 | ; SkipBack written | ||
| 12 | ; CopyComponent written | ||
| 13 | ; Splice written | ||
| 14 | ; $NameTrans written | ||
| 15 | ; DriveFromText | ||
| 16 | ; TextFromDrive | ||
| 17 | ; PathPref | ||
| 18 | ; ScanPathChar | ||
| 19 | ; | ||
| 20 | ; Revision history: | ||
| 21 | ; | ||
| 22 | ; Created: MZ 4 April 1983 | ||
| 23 | ; MZ 18 April 1983 Make TransFCB handle extended FCBs | ||
| 24 | ; AR 2 June 1983 Define/Delete macro for NET redir. | ||
| 25 | ; MZ 3 Nov 83 Fix InitCDS to reset length to 2 | ||
| 26 | ; MZ 4 Nov 83 Fix NetAssign to use STRLEN only | ||
| 27 | ; MZ 18 Nov 83 Rewrite string processing for subtree | ||
| 28 | ; aliasing. | ||
| 29 | ; BAS 3 Jan 85 ScanPathChar to search for path separator | ||
| 30 | ; in null terminated string. | ||
| 31 | ; | ||
| 32 | ; MSDOS performs several types of name translation. First, we maintain for | ||
| 33 | ; each valid drive letter the text of the current directory on that drive. | ||
| 34 | ; For invalid drive letters, there is no current directory so we pretend to | ||
| 35 | ; be at the root. A current directory is either the raw local directory | ||
| 36 | ; (consisting of drive:\path) or a local network directory (consisting of | ||
| 37 | ; \\machine\path. There is a limit on the point to which a .. is allowed. | ||
| 38 | ; | ||
| 39 | ; Given a path, MSDOS will transform this into a real from-the-root path | ||
| 40 | ; without . or .. entries. Any component that is > 8.3 is truncated to | ||
| 41 | ; this and all * are expanded into ?'s. | ||
| 42 | ; | ||
| 43 | ; The second part of name translation involves subtree aliasing. A list of | ||
| 44 | ; subtree pairs is maintained by the external utility SUBST. The results of | ||
| 45 | ; the previous 'canonicalization' are then examined to see if any of the | ||
| 46 | ; subtree pairs is a prefix of the user path. If so, then this prefix is | ||
| 47 | ; replaced with the other subtree in the pair. | ||
| 48 | ; | ||
| 49 | ; A third part involves mapping this "real" path into a "physical" path. A | ||
| 50 | ; list of drive/subtree pairs are maintained by the external utility JOIN. | ||
| 51 | ; The output of the previous translation is examined to see if any of the | ||
| 52 | ; subtrees in this list are a prefix of the string. If so, then the prefix | ||
| 53 | ; is replaced by the appropriate drive letter. In this manner, we can | ||
| 54 | ; 'mount' one device under another. | ||
| 55 | ; | ||
| 56 | ; The final form of name translation involves the mapping of a user's | ||
| 57 | ; logical drive number into the internal physical drive. This is | ||
| 58 | ; accomplished by converting the drive number into letter:CON, performing | ||
| 59 | ; the above translation and then converting the character back into a drive | ||
| 60 | ; number. | ||
| 61 | ; | ||
| 62 | ; curdir_list STRUC | ||
| 63 | ; curdir_text DB DIRSTRLEN DUP (?) ; text of assignment and curdir | ||
| 64 | ; curdir_flags DW ? ; various flags | ||
| 65 | ; curdir_devptr DD ? ; local pointer to DPB or net device | ||
| 66 | ; curdir_ID DW ? ; cluster of current dir (net ID) | ||
| 67 | ; DW ? | ||
| 68 | ; curdir_end DW ? ; end of assignment | ||
| 69 | ; curdir_list ENDS | ||
| 70 | ; curdir_netID EQU DWORD PTR curdir_ID | ||
| 71 | ; ;Flag word masks | ||
| 72 | ; curdir_isnet EQU 1000000000000000B | ||
| 73 | ; curdir_inuse EQU 0100000000000000B | ||
| 74 | ; | ||
| 75 | ; | ||
| 76 | ; There are two main entry points: TransPath and TransFCB. TransPath will | ||
| 77 | ; take a path and form the real text of the pathname with all . and .. | ||
| 78 | ; removed. TransFCB will translate an FCB into a path and then invoke | ||
| 79 | ; TransPath. | ||
| 80 | ; | ||
| 81 | ; Implementation note: CURDIR_End field points to the point in the text | ||
| 82 | ; string where the user may back up to via .. It is the location of a | ||
| 83 | ; separator character. For the root, it points at the leading /. For net | ||
| 84 | ; assignments it points at the end (nul) of the initial assignment: | ||
| 85 | ; A:/ \\foo\bar \\foo\bar\blech\bozo | ||
| 86 | ; ^ ^ ^ | ||
| 87 | ; A: -> d: /path/ path/ text | ||
| 88 | ; | ||
| 89 | ; A000 version 4.00 Jan. 1988 | ||
| 90 | |||
| 91 | .xlist | ||
| 92 | ; | ||
| 93 | ; get the appropriate segment definitions | ||
| 94 | ; | ||
| 95 | include dosseg.asm | ||
| 96 | |||
| 97 | CODE SEGMENT BYTE PUBLIC 'CODE' | ||
| 98 | ASSUME SS:DOSGroup,CS:DOSGroup | ||
| 99 | |||
| 100 | .xcref | ||
| 101 | INCLUDE DOSSYM.INC | ||
| 102 | INCLUDE DEVSYM.INC | ||
| 103 | .cref | ||
| 104 | .list | ||
| 105 | .sall | ||
| 106 | |||
| 107 | Installed = TRUE | ||
| 108 | |||
| 109 | I_need Splices,BYTE ; TRUE => splices are being done. | ||
| 110 | I_need WFP_Start,WORD ; pointer to beginning of expansion | ||
| 111 | I_need Curr_Dir_End,WORD ; offset to end of current dir | ||
| 112 | I_need ThisCDS,DWORD ; pointer to CDS used | ||
| 113 | I_need ThisDPB,DWORD ; pointer to DPB used | ||
| 114 | I_need NAME1,11 ; Parse output of NameTrans | ||
| 115 | I_need OpenBuf,128 ; ususal destination of strings | ||
| 116 | I_need ExtFCB,BYTE ; flag for extended FCBs | ||
| 117 | I_need Sattrib,BYTE ; attribute of search | ||
| 118 | I_need fSplice,BYTE ; TRUE => do splice after canonicalize | ||
| 119 | I_need fSharing,BYTE ; TRUE => no redirection allowed | ||
| 120 | I_Need NoSetDir,BYTE ; TRUE => syscall is interested in | ||
| 121 | ; entry, not contents. We splice only | ||
| 122 | ; inexact matches | ||
| 123 | I_Need cMeta,BYTE ; count of meta chars in path | ||
| 124 | I_Need Temp_Var,WORD ;AN000; variable for temporary use 3/31/KK | ||
| 125 | I_Need DOS34_FLAG,WORD ;AN000; variable for dos34 | ||
| 126 | I_Need NO_FILTER_PATH,DWORD ;AN000; pointer to orignal path | ||
| 127 | Table SEGMENT | ||
| 128 | EXTRN CharType:BYTE | ||
| 129 | Table ENDS | ||
| 130 | |||
| 131 | BREAK <TransFCB - convert an FCB into a path, doing substitution> | ||
| 132 | |||
| 133 | ; | ||
| 134 | ; TransFCB - Copy an FCB from DS:DX into a reserved area doing all of the | ||
| 135 | ; gritty substitution. | ||
| 136 | ; | ||
| 137 | ; Inputs: DS:DX - pointer to FCB | ||
| 138 | ; ES:DI - point to destination | ||
| 139 | ; Outputs: Carry Set - invalid path in final map | ||
| 140 | ; Carry Clear - FCB has been mapped into ES:DI | ||
| 141 | ; Sattrib is set from possibly extended FCB | ||
| 142 | ; ExtFCB set if extended FCB found | ||
| 143 | ; Registers modified: most | ||
| 144 | |||
| 145 | Procedure TransFCB,NEAR | ||
| 146 | ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 147 | PUBLIC MACRO001S,MACRO001E | ||
| 148 | MACRO001S: | ||
| 149 | LocalVar FCBTmp,15 | ||
| 150 | MACRO001E: | ||
| 151 | Enter | ||
| 152 | Context ES ; get DOSGroup addressability | ||
| 153 | SaveReg <ES,DI> ; save away final destination | ||
| 154 | LEA DI,FCBTmp ; point to FCB temp area | ||
| 155 | MOV [ExtFCB],0 ; no extended FCB found | ||
| 156 | MOV [Sattrib],0 ; default search attributes | ||
| 157 | invoke GetExtended ; get FCB, extended or not | ||
| 158 | JZ GetDrive ; not an extended FCB, get drive | ||
| 159 | MOV AL,[SI-1] ; get attributes | ||
| 160 | MOV [SAttrib],AL ; store search attributes | ||
| 161 | MOV [ExtFCB],-1 ; signal extended FCB | ||
| 162 | GetDrive: | ||
| 163 | LODSB ; get drive byte | ||
| 164 | invoke GetThisDrv | ||
| 165 | jc BadPack | ||
| 166 | CALL TextFromDrive ; convert 0-based drive to text | ||
| 167 | ; | ||
| 168 | ; Scan the source to see if there are any illegal chars | ||
| 169 | ; | ||
| 170 | MOV BX,OFFSET DOSGroup:CharType | ||
| 171 | IF DBCS ;AN000; | ||
| 172 | ;----------------------------- Start of DBCS 2/13/KK | ||
| 173 | SaveReg <SI> ;AN000;; back over name, ext | ||
| 174 | MOV CX,8 ;AN000;; 8 chars in main part of name | ||
| 175 | FCBScan:LODSB ;AN000;; get a byte | ||
| 176 | invoke testkanj ;AN000; | ||
| 177 | jz notkanj2 ;AN000; | ||
| 178 | DEC CX ;AN000; | ||
| 179 | JCXZ VolidChck ;AN000;; Kanji half char screw up | ||
| 180 | LODSB ;AN000;; second kanji byte | ||
| 181 | jmp short Nextch ;AN000; | ||
| 182 | VolidChck: ;AN000; | ||
| 183 | TEST [SAttrib],attr_volume_id ;AN000;; volume id ? | ||
| 184 | JZ Badpack ;AN000;; no, error | ||
| 185 | OR [DOS34_FLAG],DBCS_VOLID ;AN000;; no, error | ||
| 186 | DEC CX ;AN000;; cx=-1 | ||
| 187 | INC SI ;AN000;; next char | ||
| 188 | JMP SHORT FCBScango ;AN000; | ||
| 189 | notkanj2: ;AN000; | ||
| 190 | XLAT ES:CharType ;AN000;;get bits | ||
| 191 | TEST AL,fFCB ;AN000; | ||
| 192 | JZ BadPack ;AN000; | ||
| 193 | NextCh: ;AN000; | ||
| 194 | LOOP FCBScan ;AN000; | ||
| 195 | FCBScango: ;AN000; | ||
| 196 | ADD CX,3 ;AN000;; Three chars in extension | ||
| 197 | FCBScanE: ;AN000; | ||
| 198 | LODSB ;AN000; | ||
| 199 | invoke testkanj ;AN000; | ||
| 200 | jz notkanj3 ;AN000; | ||
| 201 | DEC CX ;AN000; | ||
| 202 | JCXZ BadPack ;AN000;; Kanji half char problem | ||
| 203 | LODSB ;AN000;; second kanji byte | ||
| 204 | jmp short NextChE ;AN000; | ||
| 205 | notkanj3: ;AN000; | ||
| 206 | XLAT ES:CharType ;AN000;; get bits | ||
| 207 | TEST AL,fFCB ;AN000; | ||
| 208 | JZ BadPack ;AN000; | ||
| 209 | NextChE: ;AN000; | ||
| 210 | LOOP FCBScanE ;AN000; | ||
| 211 | ;----------------------------- End of DBCS 2/13/KK | ||
| 212 | ELSE | ||
| 213 | |||
| 214 | MOV CX,11 | ||
| 215 | SaveReg <SI> ; back over name, ext | ||
| 216 | FCBScan:LODSB ; get a byte | ||
| 217 | XLAT ES:CharType ; get bits | ||
| 218 | TEST AL,fFCB | ||
| 219 | JZ BadPack | ||
| 220 | NextCh: LOOP FCBScan | ||
| 221 | ENDIF | ||
| 222 | RestoreReg <SI> | ||
| 223 | MOV BX,DI | ||
| 224 | invoke PackName ; crunch the path | ||
| 225 | RestoreReg <DI,ES> ; get original destination | ||
| 226 | Context DS ; get DS addressability | ||
| 227 | LEA SI,FCBTmp ; point at new pathname | ||
| 228 | CMP BYTE PTR [BX],0 | ||
| 229 | JZ BadPack | ||
| 230 | SaveReg <BP> | ||
| 231 | CALL TransPathSet ; convert the path | ||
| 232 | RestoreReg <BP> | ||
| 233 | JNC FCBRet ; bye with transPath error code | ||
| 234 | BadPack: | ||
| 235 | STC | ||
| 236 | MOV AL,error_path_not_found | ||
| 237 | FCBRet: Leave | ||
| 238 | return | ||
| 239 | EndProc TransFCB,NoCheck | ||
| 240 | |||
| 241 | BREAK <TransPath - copy a path, do string sub and put in current dir> | ||
| 242 | |||
| 243 | ; | ||
| 244 | ; TransPath - copy a path from DS:SI to ES:DI, performing component string | ||
| 245 | ; substitution, insertion of current directory and fixing . and .. | ||
| 246 | ; entries. Perform splicing. Allow input string to match splice | ||
| 247 | ; exactly. | ||
| 248 | ; | ||
| 249 | ; TransPathSet - Same as above except No splicing is performed if input path | ||
| 250 | ; matches splice. | ||
| 251 | ; | ||
| 252 | ; TransPathNoSet - No splicing/local using is performed at all. | ||
| 253 | ; | ||
| 254 | ; The following anomalous behaviour is required: | ||
| 255 | ; | ||
| 256 | ; Drive letters on devices are ignored. (set up DummyCDS) | ||
| 257 | ; Paths on devices are ignored. (truncate to 0-length) | ||
| 258 | ; Raw net I/O sets ThisCDS => NULL. | ||
| 259 | ; fSharing => dummyCDS and no subst/splice. Only canonicalize. | ||
| 260 | ; | ||
| 261 | ; Other behaviour: | ||
| 262 | ; | ||
| 263 | ; ThisCDS set up. | ||
| 264 | ; FatRead done on local CDS. | ||
| 265 | ; ValidateCDS done on local CDS. | ||
| 266 | ; | ||
| 267 | ; Brief flowchart: | ||
| 268 | ; | ||
| 269 | ; if fSharing then | ||
| 270 | ; set up DummyCDS (ThisCDS) | ||
| 271 | ; canonicalize (sets cMeta) | ||
| 272 | ; splice | ||
| 273 | ; fatRead | ||
| 274 | ; return | ||
| 275 | ; if \\ or d:\\ lead then | ||
| 276 | ; set up null CDS (ThisCDS) | ||
| 277 | ; canonicalize (sets cMeta) | ||
| 278 | ; return | ||
| 279 | ; if device then | ||
| 280 | ; set up dummyCDS (ThisCDS) | ||
| 281 | ; canonicalize (sets cMeta) | ||
| 282 | ; return | ||
| 283 | ; if file then | ||
| 284 | ; getCDS (sets (ThisCDS) from name) | ||
| 285 | ; validateCDS (may reset current dir) | ||
| 286 | ; Copy current dir | ||
| 287 | ; canonicalize (set cMeta) | ||
| 288 | ; splice | ||
| 289 | ; generate correct CDS (ThisCDS) | ||
| 290 | ; if local then | ||
| 291 | ; fatread | ||
| 292 | ; return | ||
| 293 | ; | ||
| 294 | ; Inputs: DS:SI - point to ASCIZ string path | ||
| 295 | ; DI - point to buffer in DOSGroup | ||
| 296 | ; Outputs: Carry Set - invalid path specification: too many .., bad | ||
| 297 | ; syntax, etc. or user FAILed to I 24. | ||
| 298 | ; WFP_Start - points to beginning of buffer | ||
| 299 | ; Curr_Dir_End - points to end of current dir in path | ||
| 300 | ; DS - DOSGroup | ||
| 301 | ; Registers modified: most | ||
| 302 | |||
| 303 | Procedure TransPath,NEAR | ||
| 304 | ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 305 | XOR AL,AL | ||
| 306 | JMP SHORT SetSplice | ||
| 307 | Entry TransPathSet | ||
| 308 | MOV AL,-1 | ||
| 309 | SetSplice: | ||
| 310 | MOV NoSetDir,AL ; NoSetDir = !fExact; | ||
| 311 | MOV AL,-1 | ||
| 312 | Entry TransPathNoSet | ||
| 313 | MOV WORD PTR [NO_FILTER_PATH],SI ;AN000;;IFS. save old path for IFS | ||
| 314 | MOV WORD PTR [NO_FILTER_PATH+2],DS ;AN000;;IFS. | ||
| 315 | |||
| 316 | MOV fSplice,AL ; fSplice = TRUE; | ||
| 317 | MOV cMeta,-1 | ||
| 318 | MOV WFP_Start,DI | ||
| 319 | MOV Curr_Dir_End,-1 ; crack from start | ||
| 320 | Context ES | ||
| 321 | LEA BP,[DI+TEMPLEN] ; end of buffer | ||
| 322 | ; | ||
| 323 | ; if this is through the server dos call, fsharing is set. We set up a | ||
| 324 | ; dummy cds and let the operation go. | ||
| 325 | ; | ||
| 326 | TEST fSharing,-1 ; if no sharing | ||
| 327 | JZ CheckUNC ; skip to UNC check | ||
| 328 | ; | ||
| 329 | ; ES:DI point to buffer | ||
| 330 | ; | ||
| 331 | CALL DriveFromText ; get drive and advance DS:SI | ||
| 332 | invoke GetThisDrv ; Set ThisCDS and convert to 0-based | ||
| 333 | jc NoPath | ||
| 334 | CALL TextFromDrive ; drop in new | ||
| 335 | LEA BX,[DI+1] ; backup limit | ||
| 336 | CALL Canonicalize ; copy and canonicalize | ||
| 337 | retc ; errors | ||
| 338 | ; | ||
| 339 | ; Perform splices for net guys. | ||
| 340 | ; | ||
| 341 | Context DS | ||
| 342 | MOV SI,wfp_Start ; point to name | ||
| 343 | TEST fSplice,-1 | ||
| 344 | JZ NoServerSplice | ||
| 345 | CALL Splice | ||
| 346 | NoServerSplice: | ||
| 347 | Context DS ; for FATREAD | ||
| 348 | LES DI,ThisCDS ; for fatread | ||
| 349 | EnterCrit critDisk | ||
| 350 | Invoke FatRead_CDS | ||
| 351 | LeaveCrit critDisk | ||
| 352 | NoPath: | ||
| 353 | MOV AL,error_path_not_found ; Set up for possible bad path error | ||
| 354 | return ; any errors are in Carry flag | ||
| 355 | ASSUME DS:NOTHING | ||
| 356 | ; | ||
| 357 | ; Let the network decide if the name is for a spooled device. It will map | ||
| 358 | ; the name if so. | ||
| 359 | ; | ||
| 360 | CheckUnc: | ||
| 361 | MOV WORD PTR ThisCDS,-1 ; NULL thisCDS | ||
| 362 | CallInstall NetSpoolCheck,multNet,35 | ||
| 363 | JNC UNCDone | ||
| 364 | ; | ||
| 365 | ; At this point the name is either a UNC-style name (prefixed with two leading | ||
| 366 | ; \\s) or is a local file/device. Remember that if a net-spooled device was | ||
| 367 | ; input, then the name has been changed to the remote spooler by the above net | ||
| 368 | ; call. Also, there may be a drive in front of the \\. | ||
| 369 | ; | ||
| 370 | NO_CHECK: | ||
| 371 | CALL DriveFromText ; eat drive letter | ||
| 372 | PUSH AX ; save it | ||
| 373 | MOV AX,WORD PTR [SI] ; get first two bytes of path | ||
| 374 | Invoke PathChrCmp ; convert to normal form | ||
| 375 | XCHG AH,AL ; swap for second byte | ||
| 376 | Invoke PathChrCmp ; convert to normal form | ||
| 377 | JNZ CheckDevice ; not a path char | ||
| 378 | CMP AH,AL ; are they same? | ||
| 379 | JNZ CheckDevice ; nope | ||
| 380 | ; | ||
| 381 | ; We have a UNC request. We must copy the string up to the beginning of the | ||
| 382 | ; local machine root path | ||
| 383 | ; | ||
| 384 | |||
| 385 | POP AX | ||
| 386 | MOVSW ; get the lead \\ | ||
| 387 | UNCCpy: LODSB ; get a byte | ||
| 388 | IF DBCS ;AN000; | ||
| 389 | ;----------------------------- Start of DBCS 2/23/KK | ||
| 390 | invoke testkanj ;AN000; | ||
| 391 | jz notkanj1 ;AN000; | ||
| 392 | STOSB ;AN000; | ||
| 393 | LODSB ;AN000; | ||
| 394 | OR AL,AL ;AN000; | ||
| 395 | JZ UNCTerm ;AN000;; Ignore half kanji error for now | ||
| 396 | STOSB ;AN000; | ||
| 397 | jmp UNCCpy ;AN000; | ||
| 398 | notkanj1: ;AN000; | ||
| 399 | ;----------------------------- End of DBCS 2/23/KK | ||
| 400 | ENDIF ;AN000; | ||
| 401 | invoke UCase ;AN000;; convert the char | ||
| 402 | OR AL,AL | ||
| 403 | JZ UNCTerm ; end of string. All done. | ||
| 404 | Invoke PathChrCmp ; is it a path char? | ||
| 405 | MOV BX,DI ; backup position | ||
| 406 | STOSB | ||
| 407 | JNZ UNCCpy ; no, go copy | ||
| 408 | CALL Canonicalize ; wham (and set cMeta) | ||
| 409 | UNCDone: | ||
| 410 | Context DS | ||
| 411 | IF DBCS | ||
| 412 | ;----------------------------- Start of DBCS 2/23/KK | ||
| 413 | retc ;AN000; Return if error from Canonicalize | ||
| 414 | |||
| 415 | ; Although Cononicalize has done lots of good things for us it may also have | ||
| 416 | ; done e5 to 05 conversion on the fisrt char following a path sep char which is | ||
| 417 | ; not wanted on a UNC request as this should be left for the remote station. | ||
| 418 | ; The simplest thing to do is check for such conversions and convert them back | ||
| 419 | ; again. | ||
| 420 | ; This check loop is also called from the DoFile section of TransPath if the | ||
| 421 | ; file is a remote file. Entry point when called is TP_check05 with the | ||
| 422 | ; inputs/outputs as follows; | ||
| 423 | ; Inputs : ES:DI = Buffer to check for re-conversion | ||
| 424 | ; Outputs: None | ||
| 425 | ; Used : DI,AX | ||
| 426 | |||
| 427 | |||
| 428 | MOV DI,WFP_start ;AN000;; ES:DI points to converted string | ||
| 429 | TP_check05: ;AN000; | ||
| 430 | MOV AL,BYTE PTR ES:[DI] ;AN000;; Get character from path | ||
| 431 | OR AL,AL ;AN000;; End of null terminated path? | ||
| 432 | JZ TP_end05 ;AN000;; Finished, CF =0 from OR (ret success) | ||
| 433 | invoke testkanj ;AN000;; Kanji lead character? | ||
| 434 | JZ TP_notK ;AN000;; Check for path seperator if not | ||
| 435 | INC DI ;AN000;; Bypass Kanji second byte | ||
| 436 | JMP TP_nxt05 ;AN000;; Go to check next character | ||
| 437 | TP_notK: ;AN000; | ||
| 438 | invoke PathChrCmp ;AN000;; Is it a path seperator char? | ||
| 439 | JNZ TP_nxt05 ;AN000;; Check next character if not | ||
| 440 | CMP BYTE PTR ES:[DI+1],05 ;AN000;; 05 following path sep char? | ||
| 441 | JNZ TP_nxt05 ;AN000;; Check next character if not | ||
| 442 | MOV BYTE PTR ES:[DI+1],0E5h ;AN000;; Convert 05 back to E5 | ||
| 443 | TP_nxt05: ;AN000; | ||
| 444 | INC DI ;AN000;; Point to next char in path | ||
| 445 | JMP TP_check05 ;AN000;; Test all chars in path | ||
| 446 | TP_end05: | ||
| 447 | ;----------------------------- End of DBCS 2/23/KK | ||
| 448 | ENDIF ;AN000; | ||
| 449 | return ; return error code | ||
| 450 | |||
| 451 | ASSUME DS:NOTHING | ||
| 452 | UNCTerm: | ||
| 453 | STOSB ;AN000; | ||
| 454 | JMP UNCDone ;AN000; | ||
| 455 | |||
| 456 | CheckDevice: | ||
| 457 | ; | ||
| 458 | ; Check DS:SI for device. First eat any path stuff | ||
| 459 | ; | ||
| 460 | POP AX ; retrieve drive info | ||
| 461 | CMP BYTE PTR DS:[SI],0 ; check for null file | ||
| 462 | JNZ CheckPath | ||
| 463 | MOV AL,error_file_not_found ; bad file error | ||
| 464 | STC ; signal error on null input | ||
| 465 | RETURN ; bye! | ||
| 466 | CheckPath: | ||
| 467 | SaveReg <AX,BP> ; save drive number | ||
| 468 | Invoke CheckThisDevice ; snoop for device | ||
| 469 | RestoreReg <BP,AX> ; get drive letter back | ||
| 470 | JNC DoFile ; yes we have a file. | ||
| 471 | ; | ||
| 472 | ; We have a device. AX has drive letter. At this point we may fake a CDS ala | ||
| 473 | ; sharing DOS call. We know by getting here that we are NOT in a sharing DOS | ||
| 474 | ; call. | ||
| 475 | ; | ||
| 476 | MOV fSharing,-1 ; simulate sharing dos call | ||
| 477 | invoke GetThisDrv ; set ThisCDS and init DUMMYCDS | ||
| 478 | MOV fSharing,0 ; | ||
| 479 | ; | ||
| 480 | ; Now that we have noted that we have a device, we put it into a form that | ||
| 481 | ; getpath can understand. Normally getpath requires d:\ to begin the input | ||
| 482 | ; string. We relax this to state that if the d:\ is present then the path | ||
| 483 | ; may be a file. If D:/ (note the forward slash) is present then we have | ||
| 484 | ; a device. | ||
| 485 | ; | ||
| 486 | CALL TextFromDrive | ||
| 487 | MOV AL,'/' ; path sep. | ||
| 488 | STOSB | ||
| 489 | invoke StrCpy ; move remainder of string | ||
| 490 | CLC ; everything OK. | ||
| 491 | Context DS ; remainder of OK stuff | ||
| 492 | return | ||
| 493 | ; | ||
| 494 | ; We have a file. Get the raw CDS. | ||
| 495 | ; | ||
| 496 | DoFile: | ||
| 497 | ASSUME DS:NOTHING | ||
| 498 | invoke GetVisDrv ; get proper CDS | ||
| 499 | MOV AL,error_path_not_found ; Set up for possible bad file error | ||
| 500 | retc ; CARRY set -> bogus drive/spliced | ||
| 501 | ; | ||
| 502 | ; ThisCDS has correct CDS. DS:SI advanced to point to beginning of path/file. | ||
| 503 | ; Make sure that CDS has valid directory; ValidateCDS requires a temp buffer | ||
| 504 | ; Use the one that we are going to use (ES:DI). | ||
| 505 | ; | ||
| 506 | SaveReg <DS,SI,ES,DI> ; save all string pointers. | ||
| 507 | invoke ValidateCDS ; poke CDS amd make everything OK | ||
| 508 | RestoreReg <DI,ES,SI,DS> ; get back pointers | ||
| 509 | MOV AL,error_path_not_found ; Set up for possible bad path error | ||
| 510 | retc ; someone failed an operation | ||
| 511 | ; | ||
| 512 | ; ThisCDS points to correct CDS. It contains the correct text of the | ||
| 513 | ; current directory. Copy it in. | ||
| 514 | ; | ||
| 515 | SaveReg <DS,SI> | ||
| 516 | LDS SI,ThisCDS ; point to CDS | ||
| 517 | MOV BX,DI ; point to destination | ||
| 518 | ADD BX,[SI].curdir_end ; point to backup limit | ||
| 519 | ; LEA SI,[SI].curdir_text ; point to text | ||
| 520 | LEA BP,[DI+TEMPLEN] ; regenerate end of buffer | ||
| 521 | IF DBCS ;AN000; | ||
| 522 | ;------------------------ Start of DBCS 2/13/KK | ||
| 523 | Kcpylp: ;AN000; | ||
| 524 | LODSB ;AN000; | ||
| 525 | invoke TestKanj ;AN000; | ||
| 526 | jz Notkanjf ;AN000; | ||
| 527 | STOSB ;AN000; | ||
| 528 | MOVSB ;AN000; | ||
| 529 | CMP BYTE PTR [SI],0 ;AN000; | ||
| 530 | JNZ Kcpylp ;AN000; | ||
| 531 | MOV AL, '\' ;AN000; | ||
| 532 | STOSB ;AN000; | ||
| 533 | JMP SHORT GetOrig ;AN000; | ||
| 534 | Notkanjf: ;AN000; | ||
| 535 | STOSB ;AN000; | ||
| 536 | OR AL,AL ;AN000; | ||
| 537 | JNZ Kcpylp ;AN000; | ||
| 538 | DEC DI ;AN000;; point to NUL byte | ||
| 539 | |||
| 540 | ;------------------------ End of DBCS 2/13/KK | ||
| 541 | ELSE ;AN000; | ||
| 542 | invoke FStrCpy ; copy string. ES:DI point to end | ||
| 543 | DEC DI ; point to NUL byte | ||
| 544 | ENDIF ;AN000; | ||
| 545 | ; | ||
| 546 | ; Make sure that there is a path char at end. | ||
| 547 | ; | ||
| 548 | MOV AL,'\' | ||
| 549 | CMP ES:[DI-1],AL | ||
| 550 | JZ GetOrig | ||
| 551 | STOSB | ||
| 552 | ; | ||
| 553 | ; Now get original string. | ||
| 554 | ; | ||
| 555 | GetOrig: | ||
| 556 | DEC DI ; point to path char | ||
| 557 | RestoreReg <SI,DS> | ||
| 558 | ; | ||
| 559 | ; BX points to the end of the root part of the CDS (at where a path char | ||
| 560 | ; should be) . Now, we decide whether we use this root or extend it with the | ||
| 561 | ; current directory. See if the input string begins with a leading \ | ||
| 562 | ; | ||
| 563 | CALL PathSep ; is DS:SI a path sep? | ||
| 564 | JNZ PathAssure ; no, DI is correct. Assure a path char | ||
| 565 | OR AL,AL ; end of string? | ||
| 566 | JZ DoCanon ; yes, skip. | ||
| 567 | ; | ||
| 568 | ; The string does begin with a \. Reset the beginning of the canonicalization | ||
| 569 | ; to this root. Make sure that there is a path char there and advance the | ||
| 570 | ; source string over all leading \'s. | ||
| 571 | ; | ||
| 572 | MOV DI,BX ; back up to root point. | ||
| 573 | SkipPath: | ||
| 574 | LODSB | ||
| 575 | invoke PathChrCmp | ||
| 576 | JZ SkipPath | ||
| 577 | DEC SI | ||
| 578 | OR AL,AL | ||
| 579 | JZ DoCanon | ||
| 580 | ; | ||
| 581 | ; DS:SI start at some file name. ES:DI points at some path char. Drop one in | ||
| 582 | ; for yucks. | ||
| 583 | ; | ||
| 584 | PathAssure: | ||
| 585 | MOV AL,'\' | ||
| 586 | STOSB | ||
| 587 | ; | ||
| 588 | ; ES:DI point to the correct spot for canonicalization to begin. | ||
| 589 | ; BP is the max extent to advance DI | ||
| 590 | ; BX is the backup limit for .. | ||
| 591 | ; | ||
| 592 | DoCanon: | ||
| 593 | CALL Canonicalize ; wham. | ||
| 594 | retc ; badly formatted path. | ||
| 595 | IF DBCS ;AN000; | ||
| 596 | ;--------------------- Start of DBCS 2/13/KK | ||
| 597 | ; Although Cononicalize has done lots of good things for us it may also have | ||
| 598 | ; done e5 to 05 conversion on the fisrt char following a path sep char which is | ||
| 599 | ; not wanted if this a remote file as this should be left for the remote | ||
| 600 | ; station. Check for a leading \\ in the path buffer and call TP_check05 to | ||
| 601 | ; reconvert if found. | ||
| 602 | |||
| 603 | MOV DI,WFP_start ;AN000;; ES:DI points to string | ||
| 604 | MOV AX,WORD PTR ES:[DI] ;AN000;; Get leading 2 chars from path buffer | ||
| 605 | invoke PathChrCmp ;AN000;; First char a path char? | ||
| 606 | JNZ TP_notremote ;AN000;; Not remote if not. | ||
| 607 | invoke PathChrCmp ;AN000;; Second char a path char? | ||
| 608 | JNZ TP_notremote ;AN000;; Not remote if not | ||
| 609 | CALL TP_check05 ;AN000;; Remote so convert 05 back to e5 | ||
| 610 | TP_notremote: ;AN000; | ||
| 611 | ;--------------------- End of DBCS 2/13/KK | ||
| 612 | ENDIF | ||
| 613 | ; | ||
| 614 | ; The string has been moved to ES:DI. Reset world to DOS context, pointers | ||
| 615 | ; to wfp_start and do string substitution. BP is still the max position in | ||
| 616 | ; buffer. | ||
| 617 | ; | ||
| 618 | Context DS | ||
| 619 | MOV DI,wfp_start ; DS:SI point to string | ||
| 620 | LDS SI,ThisCDS ; point to CDS | ||
| 621 | ASSUME DS:NOTHING | ||
| 622 | ; LEA SI,[SI].curdir_text ; point to text | ||
| 623 | CALL PathPref ; is there a prefix? | ||
| 624 | JNZ DoSplice ; no, do splice | ||
| 625 | ; | ||
| 626 | ; We have a match. Check to see if we ended in a path char. | ||
| 627 | ; | ||
| 628 | IF DBCS ;AN000; | ||
| 629 | ;---------------------------- Start of DBCS 2/13/KK | ||
| 630 | PUSH BX ;AN000; | ||
| 631 | MOV BX,SI ;AN000; | ||
| 632 | MOV SI,WORD PTR ThisCDS ;AN000;; point to CDS | ||
| 633 | LOOKDUAL: ;AN000; | ||
| 634 | MOV AL,BYTE PTR [SI] ;AN000; | ||
| 635 | invoke TESTKANJ ;AN000; | ||
| 636 | JZ ONEINC ;AN000; | ||
| 637 | INC SI ;AN000; | ||
| 638 | INC SI ;AN000; | ||
| 639 | CMP SI,BX ;AN000; | ||
| 640 | JB LOOKDUAL ;AN000; | ||
| 641 | POP BX ;AN000;; Last char was KANJI, don't look back | ||
| 642 | JMP SHORT Pathline ;AN000;; for path sep, there isn't one. | ||
| 643 | ;AN000; | ||
| 644 | ONEINC: ;AN000; | ||
| 645 | INC SI ;AN000; | ||
| 646 | CMP SI,BX ;AN000; | ||
| 647 | JB LOOKDUAL ;AN000; | ||
| 648 | POP BX ;AN000; | ||
| 649 | ;------------------------ End of DBCS 2/13/KK | ||
| 650 | ENDIF ;AN000; | ||
| 651 | MOV AL,DS:[SI-1] ; last char to match | ||
| 652 | Invoke PathChrCmp ; did we end on a path char? (root) | ||
| 653 | JZ DoSplice ; yes, no current dir here. | ||
| 654 | Pathline: ; 2/13/KK | ||
| 655 | CMP BYTE PTR ES:[DI],0 ; end at NUL? | ||
| 656 | JZ DoSplice | ||
| 657 | INC DI ; point to after current path char | ||
| 658 | MOV Curr_Dir_End,DI ; point to correct spot | ||
| 659 | ; | ||
| 660 | ; Splice the result. | ||
| 661 | ; | ||
| 662 | DoSplice: | ||
| 663 | Context DS ; back to DOSGROUP | ||
| 664 | MOV SI,wfp_Start ; point to beginning of string | ||
| 665 | XOR CX,CX | ||
| 666 | TEST fSplice,-1 | ||
| 667 | JZ SkipSplice | ||
| 668 | CALL Splice ; replaces in place. | ||
| 669 | SkipSplice: | ||
| 670 | ASSUME DS:NOTHING | ||
| 671 | ; | ||
| 672 | ; The final thing is to assure ourselves that a FATREAD is done on the local | ||
| 673 | ; device. | ||
| 674 | ; | ||
| 675 | Context DS | ||
| 676 | LES DI,ThisCDS ; point to correct drive | ||
| 677 | TEST ES:[DI].curdir_flags,curdir_isnet | ||
| 678 | retnz ; net, no fatread necessary | ||
| 679 | JCXZ Done | ||
| 680 | EnterCrit critDisk | ||
| 681 | invoke FatRead_CDS | ||
| 682 | LeaveCrit critDisk | ||
| 683 | MOV AL,error_path_not_found ; Set up for possible bad path error | ||
| 684 | Done: return ; any errors in carry flag. | ||
| 685 | EndProc TransPath | ||
| 686 | |||
| 687 | BREAK <Canonicalize - copy a path and remove . and .. entries> | ||
| 688 | |||
| 689 | ; | ||
| 690 | ; Canonicalize - copy path removing . and .. entries. | ||
| 691 | ; | ||
| 692 | ; Inputs: DS:SI - point to ASCIZ string path | ||
| 693 | ; ES:DI - point to buffer | ||
| 694 | ; BX - backup limit (offset from ES) points to slash | ||
| 695 | ; BP - end of buffer | ||
| 696 | ; Outputs: Carry Set - invalid path specification: too many .., bad | ||
| 697 | ; syntax, etc. | ||
| 698 | ; Carry Clear - | ||
| 699 | ; DS:DI - advanced to end of string | ||
| 700 | ; ES:DI - advanced to end of canonicalized form after nul | ||
| 701 | ; Registers modified: AX CX DX (in addition to those above) | ||
| 702 | |||
| 703 | Procedure Canonicalize,NEAR | ||
| 704 | ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 705 | ; | ||
| 706 | ; We copy all leading path separators. | ||
| 707 | ; | ||
| 708 | LODSB ; while (PathChr (*s)) | ||
| 709 | Invoke PathChrCmp | ||
| 710 | IF DBCS | ||
| 711 | JNZ CanonDec0 ; 2/19/KK | ||
| 712 | ELSE | ||
| 713 | JNZ CanonDec | ||
| 714 | ENDIF | ||
| 715 | CMP DI,BP ; if (d > dlim) | ||
| 716 | JAE CanonBad ; goto error; | ||
| 717 | STOSB | ||
| 718 | JMP Canonicalize ; *d++ = *s++; | ||
| 719 | IF DBCS ;AN000; | ||
| 720 | CanonDec0: ;AN000; 2/19/KK | ||
| 721 | ; mov cs:Temp_Var,di ;AN000; 3/31/KK | ||
| 722 | ENDIF ;AN000; | ||
| 723 | CanonDec: | ||
| 724 | DEC SI | ||
| 725 | ; | ||
| 726 | ; Main canonicalization loop. We come here with DS:SI pointing to a textual | ||
| 727 | ; component (no leading path separators) and ES:DI being the destination | ||
| 728 | ; buffer. | ||
| 729 | ; | ||
| 730 | CanonLoop: | ||
| 731 | ; | ||
| 732 | ; If we are at the end of the source string, then we need to check to see that | ||
| 733 | ; a potential drive specifier is correctly terminated with a path sep char. | ||
| 734 | ; Otherwise, do nothing | ||
| 735 | ; | ||
| 736 | XOR AX,AX | ||
| 737 | CMP [SI],AL ; if (*s == 0) { | ||
| 738 | JNZ DoComponent | ||
| 739 | IF DBCS ;AN000; | ||
| 740 | call chk_last_colon ;AN000; 2/18/KK | ||
| 741 | ELSE ;AN000; | ||
| 742 | CMP BYTE PTR ES:[DI-1],':' ; if (d[-1] == ':') | ||
| 743 | ENDIF ;AN000; | ||
| 744 | JNZ DoTerminate | ||
| 745 | MOV AL,'\' ; *d++ = '\'; | ||
| 746 | STOSB | ||
| 747 | MOV AL,AH | ||
| 748 | DoTerminate: | ||
| 749 | STOSB ; *d++ = 0; | ||
| 750 | CLC ; return (0); | ||
| 751 | return | ||
| 752 | IF DBCS ;AN000; | ||
| 753 | ;---------------- Start of DBCS 2/18/KK | ||
| 754 | chk_last_colon proc ;AN000; | ||
| 755 | push si ;AN000; | ||
| 756 | push ax ;AN000; | ||
| 757 | push bx ;AN000; | ||
| 758 | mov si,[WFP_START] ;AN000;;PTM. for cd .. use beginning of buf | ||
| 759 | cmp si,di ;AN000;; no data stored ? | ||
| 760 | jb CLC02 ;AN000;;PTM. for cd .. | ||
| 761 | inc si ;AN000;; make NZ flag | ||
| 762 | JMP SHORT CLC09 ;AN000; | ||
| 763 | CLC02: ;AN000; | ||
| 764 | mov bx,di ;AN000; | ||
| 765 | dec bx ;AN000; | ||
| 766 | CLC_lop: ;AN000; | ||
| 767 | cmp si,bx ;AN000; | ||
| 768 | jb CLC00 ;AN000; | ||
| 769 | jne CLC09 ;AN000; | ||
| 770 | CLC01: ;AN000; | ||
| 771 | CMP BYTE PTR ES:[DI-1],':' ;AN000;; if (d[-1] == ':') | ||
| 772 | jmp CLC09 ;AN000; | ||
| 773 | CLC00: ;AN000; | ||
| 774 | mov al,es:[si] ;AN000; | ||
| 775 | inc si ;AN000; | ||
| 776 | invoke testkanj ;AN000; | ||
| 777 | je CLC_lop ;AN000; | ||
| 778 | inc si ;AN000; | ||
| 779 | jmp CLC_lop ;AN000; | ||
| 780 | CLC09: ;AN000; | ||
| 781 | pop bx ;AN000; | ||
| 782 | pop ax ;AN000; | ||
| 783 | pop si ;AN000; | ||
| 784 | ret ;AN000; | ||
| 785 | chk_last_colon endp ;AN000; | ||
| 786 | ;---------------- Endt of DBCS 2/18/KK | ||
| 787 | ENDIF ;AN000; | ||
| 788 | |||
| 789 | CanonBad: | ||
| 790 | CALL ScanPathChar ; check for path chars in rest of string | ||
| 791 | MOV AL,error_path_not_found ; Set up for bad path error | ||
| 792 | JZ PathEnc ; path character encountered in string | ||
| 793 | MOV AL,error_file_not_found ; Set bad file error | ||
| 794 | PathEnc: | ||
| 795 | STC | ||
| 796 | return | ||
| 797 | ; | ||
| 798 | ; We have a textual component that we must copy. We uppercase it and truncate | ||
| 799 | ; it to 8.3 | ||
| 800 | ; | ||
| 801 | DoComponent: ; } | ||
| 802 | CALL CopyComponent ; if (!CopyComponent (s, d)) | ||
| 803 | retc ; return (-1); | ||
| 804 | ; | ||
| 805 | ; We special case the . and .. cases. These will be backed up. | ||
| 806 | ; | ||
| 807 | CMP WORD PTR ES:[DI],'.' + (0 SHL 8) | ||
| 808 | JZ Skip1 | ||
| 809 | CMP WORD PTR ES:[DI],'..' | ||
| 810 | JNZ CanonNormal | ||
| 811 | DEC DI ; d--; | ||
| 812 | Skip1: CALL SkipBack ; SkipBack (); | ||
| 813 | MOV AL,error_path_not_found ; Set up for possible bad path error | ||
| 814 | retc | ||
| 815 | JMP CanonPath ; } | ||
| 816 | ; | ||
| 817 | ; We have a normal path. Advance destination pointer over it. | ||
| 818 | ; | ||
| 819 | CanonNormal: ; else | ||
| 820 | ADD DI,CX ; d += ct; | ||
| 821 | ; | ||
| 822 | ; We have successfully copied a component. We are now pointing at a path | ||
| 823 | ; sep char or are pointing at a nul or are pointing at something else. | ||
| 824 | ; If we point at something else, then we have an error. | ||
| 825 | ; | ||
| 826 | CanonPath: | ||
| 827 | CALL PathSep | ||
| 828 | JNZ CanonBad ; something else... | ||
| 829 | ; | ||
| 830 | ; Copy the first path char we see. | ||
| 831 | ; | ||
| 832 | LODSB ; get the char | ||
| 833 | Invoke PathChrCmp ; is it path char? | ||
| 834 | JNZ CanonDec ; no, go test for nul | ||
| 835 | CMP DI,BP ; beyond buffer end? | ||
| 836 | JAE CanonBad ; yep, error. | ||
| 837 | STOSB ; copy the one byte | ||
| 838 | ; | ||
| 839 | ; Skip all remaining path chars | ||
| 840 | ; | ||
| 841 | CanonPathLoop: | ||
| 842 | LODSB ; get next byte | ||
| 843 | Invoke PathChrCmp ; path char again? | ||
| 844 | JZ CanonPathLoop ; yep, grab another | ||
| 845 | DEC SI ; back up | ||
| 846 | JMP CanonLoop ; go copy component | ||
| 847 | EndProc Canonicalize | ||
| 848 | |||
| 849 | BREAK <PathSep - determine if char is a path separator> | ||
| 850 | |||
| 851 | ; | ||
| 852 | ; PathSep - look at DS:SI and see if char is / \ or NUL | ||
| 853 | ; Inputs: DS:SI - point to a char | ||
| 854 | ; Outputs: AL has char from DS:SI (/ => \) | ||
| 855 | ; Zero set if AL is / \ or NUL | ||
| 856 | ; Zero reset otherwise | ||
| 857 | ; Registers modified: AL | ||
| 858 | |||
| 859 | Procedure PathSep,NEAR | ||
| 860 | ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 861 | MOV AL,[SI] ; get the character | ||
| 862 | entry PathSepGotCh ; already have character | ||
| 863 | OR AL,AL ; test for zero | ||
| 864 | retz ; return if equal to zero (NUL) | ||
| 865 | invoke PathChrCmp ; check for path character | ||
| 866 | return ; and return HIS determination | ||
| 867 | EndProc PathSep | ||
| 868 | |||
| 869 | BREAK <SkipBack - move backwards to a path separator> | ||
| 870 | |||
| 871 | ; | ||
| 872 | ; SkipBack - look at ES:DI and backup until it points to a / \ | ||
| 873 | ; Inputs: ES:DI - point to a char | ||
| 874 | ; BX has current directory back up limit (point to a / \) | ||
| 875 | ; Outputs: ES:DI backed up to point to a path char | ||
| 876 | ; AL has char from output ES:DI (path sep if carry clear) | ||
| 877 | ; Carry set if illegal backup | ||
| 878 | ; Carry Clear if ok | ||
| 879 | ; Registers modified: DI,AL | ||
| 880 | |||
| 881 | Procedure SkipBack,NEAR | ||
| 882 | ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 883 | IF DBCS ;AN000; | ||
| 884 | ;-------------------------- Start of DBCS 2/13/KK | ||
| 885 | PUSH DS ;AN000; | ||
| 886 | PUSH SI ;AN000; | ||
| 887 | PUSH CX ;AN000; | ||
| 888 | PUSH ES ;AN000; | ||
| 889 | POP DS ;AN000; | ||
| 890 | MOV SI,BX ;AN000;; DS:SI -> start of ES:DI string | ||
| 891 | MOV CX,DI ;AN000;; Limit of forward scan is input DI | ||
| 892 | MOV AL,[SI] ;AN000; | ||
| 893 | invoke PathChrCmp ;AN000; | ||
| 894 | JNZ SkipBadP ;AN000;; Backup limit MUST be path char | ||
| 895 | CMP DI,BX ;AN000; | ||
| 896 | JBE SkipBadP ;AN000; | ||
| 897 | MOV DI,BX ;AN000;; Init backup point to backup limit | ||
| 898 | Skiplp: ;AN000; | ||
| 899 | CMP SI,CX ;AN000; | ||
| 900 | JAE SkipOK ;AN000;; Done, DI is correct backup point | ||
| 901 | LODSB ;AN000; | ||
| 902 | invoke Testkanj ;AN000; | ||
| 903 | jz Notkanjv ;AN000; | ||
| 904 | lodsb ;AN000;; Skip over second kanji byte | ||
| 905 | JMP Skiplp ;AN000; | ||
| 906 | NotKanjv: ;AN000; | ||
| 907 | invoke PathChrCmp ;AN000; | ||
| 908 | JNZ Skiplp ;AN000;; New backup point | ||
| 909 | MOV DI,SI ;AN000;; DI point to path sep | ||
| 910 | DEC DI ;AN000; | ||
| 911 | jmp Skiplp ;AN000; | ||
| 912 | SkipOK: ;AN000; | ||
| 913 | MOV AL,ES:[DI] ;AN000;; Set output AL | ||
| 914 | CLC ;AN000;; return (0); | ||
| 915 | POP CX ;AN000; | ||
| 916 | POP SI ;AN000; | ||
| 917 | POP DS ;AN000; | ||
| 918 | return ;AN000; | ||
| 919 | ;AN000; | ||
| 920 | SkipBadP: ;AN000; | ||
| 921 | POP CX ;AN000; | ||
| 922 | POP SI ;AN000; | ||
| 923 | POP DS ;AN000; | ||
| 924 | ;-------------------------- End of DBCS 2/13/KK | ||
| 925 | ELSE ;AN000; | ||
| 926 | CMP DI,BX ; while (TRUE) { | ||
| 927 | JB SkipBad ; if (d < dlim) | ||
| 928 | DEC DI ; goto err; | ||
| 929 | MOV AL,ES:[DI] ; if (pathchr (*--d)) | ||
| 930 | invoke PathChrCmp ; break; | ||
| 931 | JNZ SkipBack ; } | ||
| 932 | CLC ; return (0); | ||
| 933 | return ; | ||
| 934 | ENDIF ;AN000; | ||
| 935 | SkipBad: ;err: | ||
| 936 | MOV AL,error_path_not_found ; bad path error | ||
| 937 | STC ; return (-1); | ||
| 938 | return ; | ||
| 939 | EndProc SkipBack | ||
| 940 | |||
| 941 | Break <CopyComponent - copy out a file path component> | ||
| 942 | |||
| 943 | ; | ||
| 944 | ; CopyComponent - copy a file component from a path string (DS:SI) into ES:DI | ||
| 945 | ; | ||
| 946 | ; Inputs: DS:SI - source path | ||
| 947 | ; ES:DI - destination | ||
| 948 | ; ES:BP - end of buffer | ||
| 949 | ; Outputs: Carry Set - too long | ||
| 950 | ; Carry Clear - DS:SI moved past component | ||
| 951 | ; CX has length of destination | ||
| 952 | ; Registers modified: AX,CX,DX | ||
| 953 | |||
| 954 | Procedure CopyComponent,NEAR | ||
| 955 | ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 956 | CopyBP EQU WORD PTR [BP] | ||
| 957 | CopyD EQU DWORD PTR [BP+2] | ||
| 958 | CopyDoff EQU WORD PTR [BP+2] | ||
| 959 | CopyS EQU DWORD PTR [BP+6] | ||
| 960 | CopySoff EQU WORD PTR [BP+6] | ||
| 961 | CopyTemp EQU BYTE PTR [BP+10] | ||
| 962 | SUB SP,14 ; room for temp buffer | ||
| 963 | SaveReg <DS,SI,ES,DI,BP> | ||
| 964 | MOV BP,SP | ||
| 965 | MOV AH,'.' | ||
| 966 | LODSB | ||
| 967 | STOSB | ||
| 968 | CMP AL,AH ; if ((*d++=*s++) == '.') { | ||
| 969 | JNZ NormalComp | ||
| 970 | CALL PathSep ; if (!pathsep(*s)) | ||
| 971 | JZ NulTerm | ||
| 972 | TryTwoDot: | ||
| 973 | LODSB ; if ((*d++=*s++) != '.' | ||
| 974 | STOSB | ||
| 975 | CMP AL,AH | ||
| 976 | JNZ CopyBad | ||
| 977 | CALL PathSep | ||
| 978 | JNZ CopyBad ; || !pathsep (*s)) | ||
| 979 | NulTerm: ; return -1; | ||
| 980 | XOR AL,AL ; *d++ = 0; | ||
| 981 | STOSB | ||
| 982 | MOV CopySoff,SI | ||
| 983 | JMP SHORT GoodRet ; } | ||
| 984 | NormalComp: ; else { | ||
| 985 | MOV SI,CopySoff | ||
| 986 | Invoke NameTrans ; s = NameTrans (s, Name1); | ||
| 987 | CMP SI,CopySOff ; if (s == CopySOff) | ||
| 988 | JZ CopyBad ; return (-1); | ||
| 989 | TEST fSharing,-1 ; if (!fSharing) { | ||
| 990 | JNZ DoPack | ||
| 991 | AND DL,1 ; cMeta += fMeta; | ||
| 992 | ADD cMeta,DL ; if (cMeta > 0) | ||
| 993 | JG CopyBad ; return (-1); | ||
| 994 | JNZ DoPack ; else | ||
| 995 | OR DL,DL ; if (cMeta == 0 && fMeta == 0) | ||
| 996 | JZ CopyBadPath ; return (-1); | ||
| 997 | DoPack: ; } | ||
| 998 | MOV CopySoff,SI | ||
| 999 | Context DS | ||
| 1000 | MOV SI,OFFSET DOSGroup:NAME1 | ||
| 1001 | LEA DI,CopyTemp | ||
| 1002 | SaveReg <DI> | ||
| 1003 | Invoke PackName ; PackName (Name1, temp); | ||
| 1004 | RestoreReg <DI> | ||
| 1005 | Invoke StrLen ; if (strlen(temp)+d > bp) | ||
| 1006 | DEC CX | ||
| 1007 | ADD CX,CopyDoff | ||
| 1008 | CMP CX,CopyBP | ||
| 1009 | JAE CopyBad ; return (-1); | ||
| 1010 | MOV SI,DI ; strcpy (d, temp); | ||
| 1011 | LES DI,CopyD | ||
| 1012 | Invoke FStrCpy | ||
| 1013 | GoodRet: ; } | ||
| 1014 | CLC | ||
| 1015 | JMP SHORT CopyEnd ; return 0; | ||
| 1016 | CopyBad: | ||
| 1017 | STC | ||
| 1018 | CALL ScanPathChar ; check for path chars in rest of string | ||
| 1019 | MOV AL,error_file_not_found ; Set up for bad file error | ||
| 1020 | JNZ CopyEnd | ||
| 1021 | CopyBadPath: | ||
| 1022 | STC | ||
| 1023 | MOV AL,error_path_not_found ; Set bad path error | ||
| 1024 | CopyEnd: | ||
| 1025 | RestoreReg <BP,DI,ES,SI,DS> | ||
| 1026 | LAHF | ||
| 1027 | ADD SP,14 ; reclaim temp buffer | ||
| 1028 | Invoke Strlen | ||
| 1029 | DEC CX | ||
| 1030 | SAHF | ||
| 1031 | return | ||
| 1032 | EndProc CopyComponent,NoCheck | ||
| 1033 | |||
| 1034 | Break <Splice - pseudo mount by string substitution> | ||
| 1035 | |||
| 1036 | ; | ||
| 1037 | ; Splice - take a string and substitute a prefix if one exists. Change | ||
| 1038 | ; ThisCDS to point to physical drive CDS. | ||
| 1039 | ; Inputs: DS:SI point to string | ||
| 1040 | ; NoSetDir = TRUE => exact matches with splice fail | ||
| 1041 | ; Outputs: DS:SI points to thisCDS | ||
| 1042 | ; ES:DI points to DPB | ||
| 1043 | ; String at DS:SI may be reduced in length by removing prefix | ||
| 1044 | ; and substituting drive letter. | ||
| 1045 | ; CX = 0 If no splice done | ||
| 1046 | ; CX <> 0 otherwise | ||
| 1047 | ; ThisCDS points to proper CDS if spliced, otherwise it is | ||
| 1048 | ; left alone | ||
| 1049 | ; ThisDPB points to proper DPB | ||
| 1050 | ; Registers modified: DS:SI, ES:DI, BX,AX,CX | ||
| 1051 | |||
| 1052 | Procedure Splice,NEAR | ||
| 1053 | ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 1054 | TEST Splices,-1 | ||
| 1055 | JZ AllDone | ||
| 1056 | SaveReg <<WORD PTR ThisCDS>,<WORD PTR ThisCDS+2>> ; TmpCDS = ThisCDS | ||
| 1057 | SaveReg <DS,SI> | ||
| 1058 | RestoreReg <DI,ES> | ||
| 1059 | XOR AX,AX ; for (i=1; s = GetCDSFromDrv (i); i++) | ||
| 1060 | SpliceScan: | ||
| 1061 | invoke GetCDSFromDrv | ||
| 1062 | JC SpliceDone | ||
| 1063 | INC AL | ||
| 1064 | TEST [SI.curdir_flags],curdir_splice | ||
| 1065 | JZ SpliceScan ; if ( Spliced (i) ) { | ||
| 1066 | SaveReg <DI> | ||
| 1067 | CALL PathPref ; if (!PathPref (s, d)) | ||
| 1068 | JZ SpliceFound ; | ||
| 1069 | SpliceSkip: | ||
| 1070 | RestoreReg <DI> | ||
| 1071 | JMP SpliceScan ; continue; | ||
| 1072 | SpliceFound: | ||
| 1073 | CMP BYTE PTR ES:[DI],0 ; if (*s || NoSetDir) { | ||
| 1074 | JNZ SpliceDo | ||
| 1075 | TEST NoSetDir,-1 | ||
| 1076 | JNZ SpliceSkip | ||
| 1077 | SpliceDo: | ||
| 1078 | MOV SI,DI ; p = src + strlen (p); | ||
| 1079 | SaveReg <ES> | ||
| 1080 | RestoreReg <DS,DI> | ||
| 1081 | CALL TextFromDrive1 ; src = TextFromDrive1(src,i); | ||
| 1082 | MOV AX,Curr_Dir_End | ||
| 1083 | OR AX,AX | ||
| 1084 | JS NoPoke | ||
| 1085 | ADD AX,DI ; curdirend += src-p; | ||
| 1086 | SUB AX,SI | ||
| 1087 | MOV Curr_Dir_End,AX | ||
| 1088 | NoPoke: | ||
| 1089 | CMP BYTE PTR [SI],0 ; if (*p) | ||
| 1090 | JNZ SpliceCopy ; *src++ = '\\'; | ||
| 1091 | MOV AL,"\" | ||
| 1092 | STOSB | ||
| 1093 | SpliceCopy: ; strcpy (src, p); | ||
| 1094 | invoke FStrCpy | ||
| 1095 | ADD SP,4 ; throw away saved stuff | ||
| 1096 | OR CL,1 ; signal splice done. | ||
| 1097 | JMP SHORT DoSet ; return; | ||
| 1098 | SpliceDone: ; } | ||
| 1099 | ASSUME DS:NOTHING ; ThisCDS = TmpCDS; | ||
| 1100 | RestoreReg <<WORD PTR ThisCDS+2>,<WORD PTR ThisCDS>> | ||
| 1101 | AllDone: | ||
| 1102 | XOR CX,CX | ||
| 1103 | DoSet: | ||
| 1104 | LDS SI,ThisCDS ; ThisDPB = ThisCDS->devptr; | ||
| 1105 | LES DI,[SI].curdir_devptr | ||
| 1106 | MOV WORD PTR ThisDPB,DI | ||
| 1107 | MOV WORD PTR ThisDPB+2,ES | ||
| 1108 | return | ||
| 1109 | EndProc Splice | ||
| 1110 | |||
| 1111 | Break <$NameTrans - partially process a name> | ||
| 1112 | |||
| 1113 | ; | ||
| 1114 | ; $NameTrans - allow users to see what names get mapped to. This call | ||
| 1115 | ; performs only string substitution and canonicalization, not splicing. Due | ||
| 1116 | ; to Transpath playing games with devices, we need to insure that the output | ||
| 1117 | ; has drive letter and : in it. | ||
| 1118 | ; | ||
| 1119 | ; Inputs: DS:SI - source string for translation | ||
| 1120 | ; ES:DI - pointer to buffer | ||
| 1121 | ; Outputs: | ||
| 1122 | ; Carry Clear | ||
| 1123 | ; Buffer at ES:DI is filled in with data | ||
| 1124 | ; ES:DI point byte after nul byte at end of dest string in buffer | ||
| 1125 | ; Carry Set | ||
| 1126 | ; AX = error_path_not_found | ||
| 1127 | ; Registers modified: all | ||
| 1128 | |||
| 1129 | Procedure $NameTrans,Near | ||
| 1130 | ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 1131 | SaveReg <DS,SI,ES,DI> | ||
| 1132 | MOV DI,OFFSET DOSGroup:OpenBuf | ||
| 1133 | CALL TransPath ; to translation (everything) | ||
| 1134 | RestoreReg <DI,ES,SI,DS> | ||
| 1135 | JNC TransOK | ||
| 1136 | transfer SYS_Ret_Err | ||
| 1137 | TransOK: | ||
| 1138 | MOV SI,OFFSET DOSGroup:OpenBuf | ||
| 1139 | Context DS | ||
| 1140 | GotText: | ||
| 1141 | Invoke FStrCpy | ||
| 1142 | Transfer SYS_Ret_OK | ||
| 1143 | EndProc $NameTrans | ||
| 1144 | |||
| 1145 | Break <DriveFromText - return drive number from a text string> | ||
| 1146 | |||
| 1147 | ; | ||
| 1148 | ; DriveFromText - examine DS:SI and remove a drive letter, advancing the | ||
| 1149 | ; pointer. | ||
| 1150 | ; | ||
| 1151 | ; Inputs: DS:SI point to a text string | ||
| 1152 | ; Outputs: AL has drive number | ||
| 1153 | ; DS:SI advanced | ||
| 1154 | ; Registers modified: AX,SI. | ||
| 1155 | |||
| 1156 | Procedure DriveFromText,NEAR | ||
| 1157 | ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 1158 | XOR AL,AL ; drive = 0; | ||
| 1159 | CMP BYTE PTR [SI],0 ; if (*s && | ||
| 1160 | retz | ||
| 1161 | CMP BYTE PTR [SI+1],':' ; s[1] == ':') { | ||
| 1162 | retnz | ||
| 1163 | IF DBCS ;AN000; | ||
| 1164 | ;--------------------- Start of DBCS 2/18/KK | ||
| 1165 | push ax ;AN000; | ||
| 1166 | mov al,[si] ;AN000; | ||
| 1167 | invoke testkanj ;AN000; | ||
| 1168 | pop ax ;AN000; | ||
| 1169 | retnz ;AN000; | ||
| 1170 | ;--------------------- End of DBCS 2/18/KK | ||
| 1171 | ENDIF ;AN000; | ||
| 1172 | LODSW ; drive = (*s | 020) - 'a'+1; | ||
| 1173 | OR AL,020h | ||
| 1174 | SUB AL,'a'-1 ; s += 2; | ||
| 1175 | retnz | ||
| 1176 | MOV AL,-1 ; nuke AL... | ||
| 1177 | return ; } | ||
| 1178 | EndProc DriveFromText | ||
| 1179 | |||
| 1180 | Break <TextFromDrive - convert a drive number to a text string> | ||
| 1181 | |||
| 1182 | ; | ||
| 1183 | ; TextFromDrive - turn AL into a drive letter: and put it at es:di with | ||
| 1184 | ; trailing :. TextFromDrive1 takes a 1-based number. | ||
| 1185 | ; | ||
| 1186 | ; Inputs: AL has 0-based drive number | ||
| 1187 | ; Outputs: ES:DI advanced | ||
| 1188 | ; Registers modified: AX | ||
| 1189 | |||
| 1190 | Procedure TextFromDrive,NEAR | ||
| 1191 | ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 1192 | INC AL | ||
| 1193 | Entry TextFromDrive1 | ||
| 1194 | ADD AL,'A'-1 ; *d++ = drive-1+'A'; | ||
| 1195 | MOV AH,":" ; strcat (d, ":"); | ||
| 1196 | STOSW | ||
| 1197 | return | ||
| 1198 | EndProc TextFromDrive | ||
| 1199 | |||
| 1200 | Break <PathPref - see if one path is a prefix of another> | ||
| 1201 | |||
| 1202 | ; | ||
| 1203 | ; PathPref - compare DS:SI with ES:DI to see if one is the prefix of the | ||
| 1204 | ; other. Remember that only at a pathchar break are we allowed to have a | ||
| 1205 | ; prefix: A:\ and A:\FOO | ||
| 1206 | ; | ||
| 1207 | ; Inputs: DS:SI potential prefix | ||
| 1208 | ; ES:DI string | ||
| 1209 | ; Outputs: Zero set => prefix found | ||
| 1210 | ; DI/SI advanced past matching part | ||
| 1211 | ; Zero reset => no prefix, DS/SI garbage | ||
| 1212 | ; Registers modified: CX | ||
| 1213 | |||
| 1214 | Procedure PathPref,NEAR | ||
| 1215 | Invoke DStrLen ; get length | ||
| 1216 | DEC CX ; do not include nul byte | ||
| 1217 | IF DBCS ;AN000; | ||
| 1218 | ;----------------------- Start of DBCS 2/13/KK | ||
| 1219 | SaveReg <AX> ;AN000;; save char register | ||
| 1220 | CmpLp: ;AN000; | ||
| 1221 | MOV AL,[SI] ;AN000; | ||
| 1222 | invoke Testkanj ;AN000; | ||
| 1223 | jz NotKanj9 ;AN000; | ||
| 1224 | CMPSW ;AN000; | ||
| 1225 | JNZ Prefix ;AN000; | ||
| 1226 | DEC CX ;AN000; | ||
| 1227 | LOOP CmpLp ;AN000; | ||
| 1228 | JMP SHORT NotSep ;AN000; | ||
| 1229 | NotKanj9: ;AN000; | ||
| 1230 | CMPSB ;AN000; | ||
| 1231 | JNZ Prefix ;AN000; | ||
| 1232 | LOOP CmpLp ;AN000; | ||
| 1233 | ;----------------------- End of DBCS 2/13/KK | ||
| 1234 | ELSE ;AN000; | ||
| 1235 | REPZ CMPSB ; compare | ||
| 1236 | retnz ; if NZ then return NZ | ||
| 1237 | SaveReg <AX> ; save char register | ||
| 1238 | ENDIF ;AN000; | ||
| 1239 | MOV AL,[SI-1] ; get last byte to match | ||
| 1240 | Invoke PathChrCmp ; is it a path char (Root!) | ||
| 1241 | JZ Prefix ; yes, match root (I hope) | ||
| 1242 | NotSep: ; 2/13/KK | ||
| 1243 | MOV AL,ES:[DI] ; get next char to match | ||
| 1244 | CALL PathSepGotCh ; was it a pathchar? | ||
| 1245 | Prefix: | ||
| 1246 | RestoreReg <AX> ; get back original | ||
| 1247 | return | ||
| 1248 | EndProc PathPref | ||
| 1249 | |||
| 1250 | Break <ScanPathChar - see if there is a path character in a string> | ||
| 1251 | |||
| 1252 | ; | ||
| 1253 | ; ScanPathChar - search through the string (pointed to by DS:SI) for | ||
| 1254 | ; a path separator. | ||
| 1255 | ; | ||
| 1256 | ; Input: DS:SI target string (null terminated) | ||
| 1257 | ; Output: Zero set => path separator encountered in string | ||
| 1258 | ; Zero clear => null encountered | ||
| 1259 | ; Registers modified: SI | ||
| 1260 | |||
| 1261 | Procedure ScanPathChar,NEAR | ||
| 1262 | LODSB ; fetch a character | ||
| 1263 | IF DBCS ;AN000; | ||
| 1264 | invoke TestKanj ;AN000;; 2/13/KK | ||
| 1265 | jz NotKanjr ;AN000;; 2/13/KK | ||
| 1266 | LODSB ;AN000;; 2/13/KK | ||
| 1267 | OR AL,AL ;AN000;; 2/13/KK 3/31/removed | ||
| 1268 | JNZ ScanPathChar ;AN000;; 2/13/KK 3/31/removed | ||
| 1269 | INC AL ;AN000;; 2/13/KK | ||
| 1270 | return ;AN000;; 2/13/KK | ||
| 1271 | ;AN000; | ||
| 1272 | NotKanjr: ;AN000;; 2/13/KK | ||
| 1273 | ENDIF ;AN000; | ||
| 1274 | call PathSepGotCh | ||
| 1275 | JNZ ScanPathChar ; not \, / or NUL => go back for more | ||
| 1276 | invoke PathChrCmp ; path separator? | ||
| 1277 | return | ||
| 1278 | EndProc ScanPathChar | ||
| 1279 | |||
| 1280 | CODE ends | ||
| 1281 | END | ||