]> wirehaze git hosting - MS-DOS.git/blob - v4.0/src/DOS/MACRO2.ASM

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0 / src / DOS / MACRO2.ASM
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