summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/COMMAND/PATH2.ASM
diff options
context:
space:
mode:
authorGravatar Mark Zbikowski2024-04-25 21:24:10 +0100
committerGravatar Microsoft Open Source2024-04-25 22:32:27 +0000
commit2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch)
tree80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/CMD/COMMAND/PATH2.ASM
parentMerge pull request #430 from jpbaltazar/typoptbr (diff)
downloadms-dos-main.tar.gz
ms-dos-main.tar.xz
ms-dos-main.zip
MZ is back!HEADmain
Diffstat (limited to 'v4.0/src/CMD/COMMAND/PATH2.ASM')
-rw-r--r--v4.0/src/CMD/COMMAND/PATH2.ASM458
1 files changed, 458 insertions, 0 deletions
diff --git a/v4.0/src/CMD/COMMAND/PATH2.ASM b/v4.0/src/CMD/COMMAND/PATH2.ASM
new file mode 100644
index 0000000..8f8d8b8
--- /dev/null
+++ b/v4.0/src/CMD/COMMAND/PATH2.ASM
@@ -0,0 +1,458 @@
1 page 80,132
2; SCCSID = @(#)path2.asm 1.1 85/05/14
3; SCCSID = @(#)path2.asm 1.1 85/05/14
4.sall
5.xlist
6.xcref
7INCLUDE DOSSYM.INC
8 include comsw.asm
9 include comseg.asm
10 include comequ.asm
11.list
12.cref
13
14
15DATARES SEGMENT PUBLIC BYTE
16 EXTRN FORFLAG:BYTE
17DATARES ENDS
18
19
20break <Path.Asm>
21;----------------------------------------------------------------------------
22; PATH.ASM contains the routines to perform pathname incovation. Path and
23; Parse share a temporary buffer and argv[] definitions. <Path_Search>,
24; given a pathname, attempts to find a corresponding executable or batch
25; file on disk. Directories specified in the user's search path will be
26; searched for a matching file, if a match is not found in the current
27; directory and if the pathname is actually only an MSDOS filename.
28; <Path_Search> assumes that the parsed command name can be found in
29; argv[0] -- in other words, <Parseline> should be executed prior to
30; <Path_Search>. Alternatively, the command name and appropriate
31; information could be placed in argv[0], or <Path_Search> could be
32; (easily) modified to make no assumptions about where its input is found.
33; Please find enclosed yet another important routine, <Save_Args>, which
34; places the entire arg/argv[]/argbuf structure on a piece of newly
35; allocated memory. This is handy for for-loop processing, and anything
36; else that wants to save the whole shebang and then process other command
37; lines.
38;
39; Alan L, OS/MSDOS August 15, 1983
40;
41; ENTRY:
42; <Path_Search>: argv[0].
43; <Save_Args>: bytes to allocate in addition to arg structure
44; EXIT:
45; <Path_Search>: success flag, best pathname match in EXECPATH.
46; <Save_Args>: success flag, segment address of new memory
47; NOTE(S):
48; * <Argv_calc> handily turns an array index into an absolute pointer.
49; The computation depends on the size of an argv[] element (arg_ele).
50; * <Parseline> calls <cparse> for chunks of the command line. <Cparse>
51; does not function as specified; see <Parseline> for more details.
52; * <Parseline> now knows about the flags the internals of COMMAND.COM
53; need to know about. This extra information is stored in a switch_flag
54; word with each command-line argument; the switches themselves will not
55; appear in the resulting arg structure.
56; * With the exception of CARRY, flags are generally preserved across calls.
57;---------------
58; CONSTANTS:
59;---------------
60 DEBUGx equ FALSE ; prints out debug info
61;---------------
62; DATA:
63;---------------
64
65TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
66 EXTRN arg:byte
67 EXTRN BADPMES_ptr:word
68 EXTRN curdrv:byte
69 EXTRN EXECPATH:byte
70 EXTRN ext_entered:byte ;AN005;
71 EXTRN fbuf:byte
72 EXTRN pathinfo:word
73 EXTRN psep_char:byte
74 EXTRN string_ptr_2:word
75 EXTRN tpbuf:byte
76TRANSPACE ENDS
77
78TRANCODE SEGMENT PUBLIC BYTE ;AC000;
79
80assume cs:trangroup, ds:trangroup, es:trangroup, ss:nothing
81
82
83break <Search>
84;----------------------------------------------------------------------------
85; SEARCH, when given a pathname, attempts to find a file with
86; one of the following extensions: .com, .exe, .bat (highest to
87; lowest priority). Where conflicts arise, the extension with
88; the highest priority is favored.
89; ENTRY:
90; DX -- pointer to null-terminated pathname
91; fbuf -- dma buffer for findfirst/next
92; EXIT:
93; AX -- 8) file found with .com extension
94; 4) file found with .exe extension
95; 2) file found with .bat extension
96; 0) no such file to be found
97; (if AX is non-zero:)
98; [search_best] identical to AX
99; [search_best_buf] null-terminated filename
100; NOTES:
101; 1) Requires caller to have allocated a dma buffer and executed a setdma.
102;---------------
103; CONSTANTS:
104;---------------
105search_file_not_found equ 0
106search_com equ 8
107search_exe equ 4
108search_bat equ 2
109fname_len equ 8
110fname_max_len equ 13
111dot equ '.'
112wildchar equ '?'
113
114;---------------
115; DATA:
116;---------------
117TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
118 EXTRN search_best:byte
119 EXTRN search_best_buf:byte
120 EXTRN search_curdir_buf:byte
121 EXTRN search_error:word
122TRANSPACE ENDS
123
124;---------------
125Procedure Search,NEAR
126;---------------
127 push CX
128 push DX
129 push DI
130 push SI
131 pushf
132
133 push DX ; check drivespec (save pname ptr)
134 mov DI, DX ; working copy of pathname
135 mov SI, OFFSET TRANGROUP:search_curdir_buf
136 xor DX, DX ; zero means current drive
137 cmp BYTE PTR [DI+1],':' ; is there a drive spec?
138 jne search_dir_check
139 mov DL, [DI] ; get the drive byte
140 and DL, NOT 20H ; uppercase the sucker
141 sub DL, '@' ; and convert to drive number
142
143search_dir_check:
144 trap Current_Dir ; can we get the drive's current
145 pop DX ; directory? If we can't we'll
146 jc search_invalid_drive ; assume it's a bad drive...
147
148 mov CX, search_attr ; filetypes to search for
149 trap Find_First ; request first match, if any
150 jc search_no_file
151 mov search_best, search_file_not_found
152 mov [search_best_buf], ANULL ; nothing's been found, yet
153
154search_loop:
155 call search_ftype ; determine if .com, &c...
156 cmp AL, search_best ; better than what we've found so far?
157 jle search_next ; no, look for another
158 mov search_best, AL ; found something... save its code
159 mov SI, OFFSET TRANGROUP:fbuf.find_buf_pname
160 mov DI, OFFSET TRANGROUP:search_best_buf
161 mov CX, fname_max_len
162 cld
163 rep movsb ; save complete pathname representation
164 cmp AL, search_com ; have we found the best of all?
165 je search_done
166
167search_next: ; keep on looking
168 mov CX, search_attr
169 trap Find_Next ; next match
170 jnc search_loop
171
172search_done: ; it's all over with...
173 mov AL, search_best ; pick best to return with
174 cmp ext_entered,1 ;AN005; Did user request a specific ext?
175 jz search_exit ;AN005; no - exit
176 mov al,ext_entered ;AN005; yes - get the real file type back
177 mov search_best,al ;AN005; save the real file type
178 jmp short search_exit
179
180search_invalid_drive: ; Tell the user path/drive
181 mov DX, [search_error] ; appropriate error message
182 invoke std_printf ; and pretend no file found
183
184search_no_file: ; couldn't find a match
185 mov AX, search_file_not_found
186
187search_exit:
188 popf
189 pop SI
190 pop DI
191 pop DX
192 pop CX
193 ret
194;---------------
195EndProc Search
196;----------------------------------------------------------------------------
197
198
199break <Search_Ftype>
200;----------------------------------------------------------------------------
201; SEARCH_FTYPE determines the type of a file by examining its extension.
202; ENTRY:
203; fbuf -- dma buffer containing filename
204; EXIT:
205; AX -- file code, as given in search header
206; NOTE(S):
207; * Implicit assumption that NULL == search_file_not_found
208;---------------
209; DATA:
210;---------------
211TRANDATA SEGMENT PUBLIC BYTE ;AC000;
212 extrn comext:byte,exeext:byte,batext:byte
213trandata ends
214;---------------
215Procedure Search_Ftype,NEAR
216;---------------
217 push DI
218 push si
219 mov AX, ANULL ; find the end of the filename
220 mov DI, OFFSET TRANGROUP:fbuf.find_buf_pname
221 mov CX, fname_max_len
222 cld
223 repnz scasb ; search for the terminating null
224 jnz ftype_exit ; weird... no null byte at end
225 sub di,5 ; . + E + X + T + NULL
226;
227; Compare .COM
228;
229 mov si,offset trangroup:comext
230 mov ax,di
231 cmpsw
232 jnz ftype_exe
233 cmpsw
234 jnz ftype_exe
235 mov AX, search_com ; success!
236 jmp short ftype_exit
237;
238; Compare .EXE
239;
240
241ftype_exe: ; still looking... now for '.exe'
242 mov di,ax
243 mov si,offset trangroup:exeext
244 cmpsw
245 jnz ftype_bat
246 cmpsw
247 jnz ftype_bat
248 mov AX, search_exe ; success!
249 jmp short ftype_exit
250;
251; Compare .BAT
252;
253
254ftype_bat: ; still looking... now for '.bat'
255 mov di,ax
256 mov si,offset trangroup:batext
257 cmpsw
258 jnz ftype_fail
259 cmpsw
260 jnz ftype_fail
261 mov AX, search_bat ; success!
262 jmp short ftype_exit
263
264ftype_fail: ; file doesn't match what we need
265 mov ax,ANULL
266
267ftype_exit:
268 cmp ext_entered,1 ;AN005; was an extension entered?
269 jz ftype_done ;AN005; no - exit
270 cmp ax,ANULL ;AN005; was any match found
271 jz ftype_done ;AN005; no - exit
272 mov ext_entered,al ;AN005; save the match type found
273 mov AX, search_com ;AN005; send back best was found to stop search
274
275ftype_done: ;AN005;
276 pop SI
277 pop DI
278 ret
279
280;---------------
281EndProc Search_Ftype
282;----------------------------------------------------------------------------
283
284
285break <Strip>
286;----------------------------------------------------------------------------
287; STRIP copies the source string (argv[0]) into the destination buffer,
288; replacing any extension with wildcards.
289; ENTRY:
290; BX -- maximum length of destination buffer
291; DS:SI -- address of destination buffer
292; argv[0] -- command name to be stripped
293; EXIT:
294; CF -- set if failure, clear if successful
295; NOTE(S):
296;---------------
297Procedure Strip,NEAR
298;---------------
299 push AX
300 push BX
301 push CX
302 push DX
303 push DI
304 push SI
305 pushf
306
307 mov ext_entered,1 ;AN005; assume no extension on file name
308 mov DX, DS:arg.argv[0].argpointer ; save pointer to beginning of argstring
309 mov DI, DS:arg.argv[0].argstartel ; beginning of last pathname element
310 cmp BYTE PTR [DI], 0 ; *STARTEL == NULL means no command
311 jz strip_error
312 mov CX, DX ; compute where end of argstring lies
313 add CX, DS:arg.argv[0].arglen
314 sub CX, DI ; and then find length of last element
315 inc CX ; include null as well
316 mov AL, dot ; let's find the filetype extension
317 cld
318 repnz scasb ; wind up pointing to either null or dot
319 jcxz process_ext ;AN005; if no extension found, just continue
320 mov ext_entered,0 ;AN005; we found an extension
321 mov al,ANULL ;AN005; continue scanning until the
322 repnz scasb ;AN005; end of line is reached.
323
324process_ext: ;AN005;
325 mov CX, DI ; pointer to end of argstring yields
326 sub CX, DX ; number of bytes to be copied
327 sub BX, 4 ; can argstring fit into dest. buffer?
328 cmp CX, BX
329 jg strip_error ; if not, we must have a bad pathname
330 mov DI, SI ; destination buffer
331 mov SI, DX ; source is beginning of pathname
332 cld
333 rep movsb ; SI=arg,DI=buffer,CX=argend-argbeg
334 cmp ext_entered,1 ;AN005; if an extension was entered
335 jnz skip_wilds ;AN005; don't set up wildcard ext.
336
337 dec DI ; overwrite null or dot
338 stosb ; with a dot
339 mov AL, wildchar ; now add wildcards
340 stosb
341 stosb
342 stosb
343 mov AL, ANULL ; and a terminating null
344 stosb
345
346skip_wilds: ;AN005;
347 popf
348 clc ; chill out...
349 jmp short strip_exit
350
351strip_error:
352 popf
353 stc
354
355strip_exit:
356 pop SI
357 pop DI
358 pop DX
359 pop CX
360 pop BX
361 pop AX
362 ret
363;---------------
364EndProc Strip
365;----------------------------------------------------------------------------
366
367
368break <Save_Args>
369;----------------------------------------------------------------------------
370; SAVE_ARGS attempts to preserve the existing argv[]/argvcnt/argbuffer
371; structure in newly allocated memory. The argv[] structure is found at the
372; beginning of this area. The caller indicates how much extra space is
373; needed in the resulting structure; Save_Args returns a segment number and
374; an offset into that area, indicating where the caller may preserve its own
375; data. Note that <argvcnt> can be found at <offset-2>.
376; ENTRY:
377; BX -- size (in bytes) of extra area to allocate
378; EXIT:
379; AX -- segment of new area.
380; CF -- set if unable to save a copy.
381; NOTE(S):
382; 1) The allocated area will be AT LEAST the size requested -- since
383; the underlying MSDOS call, <alloc> returns an integral number of
384; paragraphs.
385; 2) It is an error if MSDOS can't allocate AT LEAST as much memory
386; as the caller of Save_Args requests.
387; 3) AX is undefined if CF indicates an error.
388;---------------
389Procedure Save_Args,NEAR
390;---------------
391 push BX
392 push CX
393 push DX
394 push DI
395 push SI
396 push BP
397 pushf
398 add BX, SIZE arg_unit + 0FH ; space for arg structure, round up
399 mov CL, 4 ; to paragraph size and convert
400 shr BX, CL ; size in bytes to size in paragraphs
401 trap Alloc
402 jc save_error
403 mov BP, AX ; save segment id
404 push ES ; save TRANGROUP address
405 mov ES, AX ; switch to new memory segment
406assume ES:nothing
407 mov CX, SIZE arg_unit ; get back structure size
408 xor DI, DI ; destination is new memory area
409 mov SI, OFFSET TRANGROUP:arg ; source is arg structure
410 rep movsb ; move that sucker!
411 mov CX, arg.argvcnt ; adjust argv pointers
412 xor AX, AX ; base address for argv_calc
413 mov SI, OFFSET TRANGROUP:arg.argbuf - OFFSET arg_unit.argbuf
414
415save_ptr_loop:
416 dec CX ; exhausted all args?
417 jl save_done
418 mov BX, CX ; get arg index and
419 invoke argv_calc ; convert to a pointer
420 mov DX, DS:arg.argv[BX].argpointer
421 sub DX, SI ; adjust argpointer
422 mov ES:argv[BX].argpointer, DX
423 mov DX, DS:arg.argv[BX].argstartel
424 sub DX, SI ; and adjust argstartel
425 mov ES:argv[BX].argstartel, DX
426 mov DX, DS:arg.argv[BX].arg_ocomptr
427 sub DX, SI ; and adjust arg_ocomptr
428 mov ES:argv[BX].arg_ocomptr, DX
429 jmp save_ptr_loop
430
431save_done:
432 pop ES ; back we go to TRANGROUP
433assume ES:trangroup
434 mov AX, BP ; restore segment id
435 jmp short save_ok
436
437save_error:
438 popf
439 stc
440 jmp short save_exit
441
442save_ok:
443 popf
444 clc
445save_exit:
446 pop BP
447 pop SI
448 pop DI
449 pop DX
450 pop CX
451 pop BX
452 ret
453;---------------
454EndProc Save_Args
455;----------------------------------------------------------------------------
456
457trancode ends
458END