summaryrefslogtreecommitdiff
path: root/v4.0/src/DOS/MACRO2.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/DOS/MACRO2.ASM')
-rw-r--r--v4.0/src/DOS/MACRO2.ASM1281
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
2TITLE MACRO2 - Pathname and macro related internal routines
3NAME 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;
95include dosseg.asm
96
97CODE SEGMENT BYTE PUBLIC 'CODE'
98 ASSUME SS:DOSGroup,CS:DOSGroup
99
100.xcref
101INCLUDE DOSSYM.INC
102INCLUDE DEVSYM.INC
103.cref
104.list
105.sall
106
107Installed = 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
127Table SEGMENT
128 EXTRN CharType:BYTE
129Table ENDS
130
131BREAK <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
145Procedure TransFCB,NEAR
146 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
147PUBLIC MACRO001S,MACRO001E
148MACRO001S:
149 LocalVar FCBTmp,15
150MACRO001E:
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
162GetDrive:
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
175FCBScan: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;
182VolidChck: ;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;
189notkanj2: ;AN000;
190 XLAT ES:CharType ;AN000;;get bits
191 TEST AL,fFCB ;AN000;
192 JZ BadPack ;AN000;
193NextCh: ;AN000;
194 LOOP FCBScan ;AN000;
195FCBScango: ;AN000;
196 ADD CX,3 ;AN000;; Three chars in extension
197FCBScanE: ;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;
205notkanj3: ;AN000;
206 XLAT ES:CharType ;AN000;; get bits
207 TEST AL,fFCB ;AN000;
208 JZ BadPack ;AN000;
209NextChE: ;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
216FCBScan:LODSB ; get a byte
217 XLAT ES:CharType ; get bits
218 TEST AL,fFCB
219 JZ BadPack
220NextCh: 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
234BadPack:
235 STC
236 MOV AL,error_path_not_found
237FCBRet: Leave
238 return
239EndProc TransFCB,NoCheck
240
241BREAK <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
303Procedure 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
309SetSplice:
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
346NoServerSplice:
347 Context DS ; for FATREAD
348 LES DI,ThisCDS ; for fatread
349 EnterCrit critDisk
350 Invoke FatRead_CDS
351 LeaveCrit critDisk
352NoPath:
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;
360CheckUnc:
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;
370NO_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 \\
387UNCCpy: 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;
398notkanj1: ;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)
409UNCDone:
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
429TP_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
437TP_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
443TP_nxt05: ;AN000;
444 INC DI ;AN000;; Point to next char in path
445 JMP TP_check05 ;AN000;; Test all chars in path
446TP_end05:
447;----------------------------- End of DBCS 2/23/KK
448 ENDIF ;AN000;
449 return ; return error code
450
451 ASSUME DS:NOTHING
452UNCTerm:
453 STOSB ;AN000;
454 JMP UNCDone ;AN000;
455
456CheckDevice:
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!
466CheckPath:
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;
496DoFile:
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
523Kcpylp: ;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;
534Notkanjf: ;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;
555GetOrig:
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.
573SkipPath:
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;
584PathAssure:
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;
592DoCanon:
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
610TP_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
633LOOKDUAL: ;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;
644ONEINC: ;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.
654Pathline: ; 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;
662DoSplice:
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.
669SkipSplice:
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
684Done: return ; any errors in carry flag.
685EndProc TransPath
686
687BREAK <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
703Procedure 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;
720CanonDec0: ;AN000; 2/19/KK
721; mov cs:Temp_Var,di ;AN000; 3/31/KK
722 ENDIF ;AN000;
723CanonDec:
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;
730CanonLoop:
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
748DoTerminate:
749 STOSB ; *d++ = 0;
750 CLC ; return (0);
751 return
752 IF DBCS ;AN000;
753;---------------- Start of DBCS 2/18/KK
754chk_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;
763CLC02: ;AN000;
764 mov bx,di ;AN000;
765 dec bx ;AN000;
766CLC_lop: ;AN000;
767 cmp si,bx ;AN000;
768 jb CLC00 ;AN000;
769 jne CLC09 ;AN000;
770CLC01: ;AN000;
771 CMP BYTE PTR ES:[DI-1],':' ;AN000;; if (d[-1] == ':')
772 jmp CLC09 ;AN000;
773CLC00: ;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;
780CLC09: ;AN000;
781 pop bx ;AN000;
782 pop ax ;AN000;
783 pop si ;AN000;
784 ret ;AN000;
785chk_last_colon endp ;AN000;
786;---------------- Endt of DBCS 2/18/KK
787 ENDIF ;AN000;
788
789CanonBad:
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
794PathEnc:
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;
801DoComponent: ; }
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--;
812Skip1: 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;
819CanonNormal: ; 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;
826CanonPath:
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;
841CanonPathLoop:
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
847EndProc Canonicalize
848
849BREAK <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
859Procedure 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
867EndProc PathSep
868
869BREAK <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
881Procedure 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
898Skiplp: ;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;
906NotKanjv: ;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;
912SkipOK: ;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;
920SkipBadP: ;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;
935SkipBad: ;err:
936 MOV AL,error_path_not_found ; bad path error
937 STC ; return (-1);
938 return ;
939EndProc SkipBack
940
941Break <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
954Procedure CopyComponent,NEAR
955 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
956CopyBP EQU WORD PTR [BP]
957CopyD EQU DWORD PTR [BP+2]
958CopyDoff EQU WORD PTR [BP+2]
959CopyS EQU DWORD PTR [BP+6]
960CopySoff EQU WORD PTR [BP+6]
961CopyTemp 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
972TryTwoDot:
973 LODSB ; if ((*d++=*s++) != '.'
974 STOSB
975 CMP AL,AH
976 JNZ CopyBad
977 CALL PathSep
978 JNZ CopyBad ; || !pathsep (*s))
979NulTerm: ; return -1;
980 XOR AL,AL ; *d++ = 0;
981 STOSB
982 MOV CopySoff,SI
983 JMP SHORT GoodRet ; }
984NormalComp: ; 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);
997DoPack: ; }
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
1013GoodRet: ; }
1014 CLC
1015 JMP SHORT CopyEnd ; return 0;
1016CopyBad:
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
1021CopyBadPath:
1022 STC
1023 MOV AL,error_path_not_found ; Set bad path error
1024CopyEnd:
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
1032EndProc CopyComponent,NoCheck
1033
1034Break <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
1052Procedure 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++)
1060SpliceScan:
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 ;
1069SpliceSkip:
1070 RestoreReg <DI>
1071 JMP SpliceScan ; continue;
1072SpliceFound:
1073 CMP BYTE PTR ES:[DI],0 ; if (*s || NoSetDir) {
1074 JNZ SpliceDo
1075 TEST NoSetDir,-1
1076 JNZ SpliceSkip
1077SpliceDo:
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
1088NoPoke:
1089 CMP BYTE PTR [SI],0 ; if (*p)
1090 JNZ SpliceCopy ; *src++ = '\\';
1091 MOV AL,"\"
1092 STOSB
1093SpliceCopy: ; 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;
1098SpliceDone: ; }
1099 ASSUME DS:NOTHING ; ThisCDS = TmpCDS;
1100 RestoreReg <<WORD PTR ThisCDS+2>,<WORD PTR ThisCDS>>
1101AllDone:
1102 XOR CX,CX
1103DoSet:
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
1109EndProc Splice
1110
1111Break <$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
1129Procedure $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
1137TransOK:
1138 MOV SI,OFFSET DOSGroup:OpenBuf
1139 Context DS
1140GotText:
1141 Invoke FStrCpy
1142 Transfer SYS_Ret_OK
1143EndProc $NameTrans
1144
1145Break <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
1156Procedure 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 ; }
1178EndProc DriveFromText
1179
1180Break <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
1190Procedure 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
1198EndProc TextFromDrive
1199
1200Break <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
1214Procedure 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
1220CmpLp: ;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;
1229NotKanj9: ;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)
1242NotSep: ; 2/13/KK
1243 MOV AL,ES:[DI] ; get next char to match
1244 CALL PathSepGotCh ; was it a pathchar?
1245Prefix:
1246 RestoreReg <AX> ; get back original
1247 return
1248EndProc PathPref
1249
1250Break <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
1261Procedure 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;
1272NotKanjr: ;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
1278EndProc ScanPathChar
1279
1280CODE ends
1281END